Springboot拦截器无法注入redisTemplate操作工具类问题

最近在做微服务间用户权限打通的时候,由于当初设计的问题,用户的信息没有存在Redis中,而是由请求头携带的,因此需要在用户首次访问的时候缓存用户信息到Redis中,但是redisTemplate却无法注入到拦截其中,核心代码如下所示:
SessionInterceptor.java


package cn.lz.conf.auth;

import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import cn.hutool.json.JSONUtil;
import cn.lz.dh.common.utils.effi.PipelineUtil;
import cn.lz.dh.feign.dragon.dto.User;


/**
 * 
* Copyright: Copyright (c) 2019 Jun_Zhou
* 
* @ClassName: SessionInterceptor.java
* @Description: Session拦截器,当用户首次访问的时候,
*                 根据用户名或者Id查询用户详情并缓存于Redis中[k(用户Id)->V(用户详情)];
* 
* @version: v1.0.0
* @author: JunZhou
* @Email: 1769676159@qq.com
* @Site: CERNO
* @date: 2019年5月14日 上午10:25:38
 */
public class SessionInterceptor implements HandlerInterceptor
{
    @Autowired
    RedisTemplate<String, String>    redisTemplate;

    //设置默认的额过期时间为15分钟;
    private Long                    timeout                = (long) (15 * 60);

    //缓存空间名称;
    private static final String        CACHE_NAME_SPACE    = "efffi:user:";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception
    {
        //当前服务不存在登陆请求,因此不用考虑登陆请求造成的死循环问题;
        String userId = request.getHeader("userid");
        String userName = request.getHeader("userName");
        Boolean hadCachedCurrentUserInfo = hadCachedCurrentUserInfo(userName, userId);
        if (!hadCachedCurrentUserInfo)
        {
            //当没有缓存当前用户详情的时候调用第三方服务查询用户详情;
            User userDetail = PipelineUtil.parseUserInfoFromResEntity(userId);
            ValueOperations<String, String> opsForValue = getValueOperations();
            if (userDetail != null)
            {
                String jsonPrettyStr = JSONUtil.toJsonPrettyStr(userDetail);
                //缓存用户信息到redis中;
                opsForValue.set(CACHE_NAME_SPACE + userId, jsonPrettyStr, timeout, TimeUnit.SECONDS);
            }
        }
        return true;
    }

    /**
     * 该方法将在Controller执行之后,返回视图之前执行,modelAndView表示请求Controller处理之后返回的Model和View对象,所以可以在
     * 这个方法中修改modelAndView的属性,从而达到改变返回的模型和视图的效果。
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception
    {}

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception
    {}

    /**
     *  判断当前用户信息是否被缓存,用于加快访问效率;
     * @param userName:用户名;
     * @param userid : 用户Id;
     * @return:用户信息是否被缓存的标志【true/false】;
     */
    public Boolean hadCachedCurrentUserInfo(String userName, String userid)
    {
        Boolean hadCachedCurrentUserInfo = true;
        //从Redis中获取指定key的值;
        ValueOperations<String, String> opsForValue = getValueOperations();
        Object object = opsForValue.get(CACHE_NAME_SPACE + userid);
        //根据请求头信息中的用户信息判断session中是否存在有效的用户信息;
        if (null == object)
        {
            hadCachedCurrentUserInfo = false;
        }
        return hadCachedCurrentUserInfo;
    }

    /**
     * 获取redis中的对象操作句柄;
     * @return
     */
    public ValueOperations<String, String> getValueOperations()
    {
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        return opsForValue;
    }
}

SessionConfiguration.java


package cn.lz.conf.auth;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;


/**
 * 
* Copyright: Copyright (c) 2019 Jun_Zhou
* 
* @ClassName: SessionConfiguration.java
* @Description: 用户信息Redis缓存相关的配置类;
* 
* @version: v1.0.0
* @author: JunZhou
* @Email: 1769676159@qq.com
* @Site: CERNO
* @date: 2019年5月14日 下午12:38:53
*/
@Configuration
public class SessionConfiguration extends WebMvcConfigurerAdapter
{
  【-->
        @Bean
        public SessionInterceptor getSessionInterceptor()
        {
            return new SessionInterceptor();
        }
    <--】
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(getSessionInterceptor()).addPathPatterns("/**");
    }
}

最终调试发现,由于拦截器加载的时间点在springcontext之前,所以在拦截器中注入自然为null 。
因此解决方法在配置拦截器链的类中先注入这个拦截器,代码如下:

【-->
        @Bean
        public SessionInterceptor getSessionInterceptor()
        {
            return new SessionInterceptor();
        }
    <--】

这样,就相当于将当前拦截器交给了Spring的IOC容器管理,因此拦截器中的属性注入自然就不会发生问题了。

参考文章:
记录解决一个springboot拦截器无法注入redisTemplate操作工具类问题
Spring boot整合redis过程中,发现自定义的拦截器注入不了redis接口service。


Previous
带权重的随机数算法的实现 带权重的随机数算法的实现
在做一个银行的网页游戏的时候,涉及到一个随机抽奖的模块。具体的需求是:当用户的积分可以抽奖的时候,点击抽奖则消耗指定的积分随机抽取奖品,各种奖品的概率如下:笔记本(10%),手机(20%),充值卡(30%),积分(40%)。因为,奖品的概率
2019-05-19
Next
软件开发中会用到的图 软件开发中会用到的图
转载 软件开发中会用到的图 阅读目录 背景 图为了解决什么问题 不同流程中适合运用的图 实际的运用 结语  一、背景 
2019-04-14