springboot拦截器无法注入redisTemplate的解决方法

网友投稿 460 2022-10-16


springboot拦截器无法注入redisTemplate的解决方法

在工作中我们经常需要做登录拦截验证或者其他拦截认证功能,基于springboot项目下我们很容易想到结合redis做的分布式拦截,把用户登录或者需要验证的信息放到redis里面。但是在写拦截器的时候发现redisTemplate一直无法注入进来,最后查资料才发现springboot拦截器是在Bean实例化之前执行的,所以Bean实例无法注入。

先看下问题,新建一个拦截器,然后注入redisTemplate

/**

* @author: lockie

* @Date: 2019/8/13 16:16

* @Description: 接口限流拦截器

*/

@Component

public class AccessLimitIntercept implements HandlerInterceptor {

private static final Logger logger = LoggerFactory.getLogger(AccessLimitIntercept.class);

@Autowired

private StringRedisTemplate redisTemplate;

/**

* 接口调用前检查对方ip是否频繁调用接口

* @param request

* @param response

* @param handler

* @return

* @throws Exception

*/

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

try {

String test = redisTemplate.opsForValue().get("test");

logger.info(test);

} catch (Exception e) {

logger.error("API请求限流拦截异常,异常原因:", e);

throw new ParameterException(e);

}

return true;

}

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

}

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

}

private boolean setResponse(Results results, HttpServletResponse response) throws IOException {

ServletOutputStream outputStream = null;

try {

response.setHeader("Content-type", "application/json; charset=utf-8");

outputStream = response.getOutputStream();

outputStream.write(JsonUtil.toJson(results).getBytes("UTF-8"));

} catch (Exception e) {

logger.error("setResponse方法报错", e);

return false;

} finally {

if (outputStreamhttp:// != null) {

outputStream.flush();

outputStream.close();

}

}

return true;

}

}

然后配置拦截器,新建一个拦截器config类,我们这里让所有的url都拦截

@Configuration

public class WebFilterConfig implements WebMvcConfigurer {

/**

* 多个拦截器组成一个拦截器链

* @param registry

*/

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new AccessLimitIntercept()).addPathPatterns("/**");

}

}

新建一个controller里面增加一个接口,使用postman调用接口

@RestController

@RequestMapping("/")

public class PingController extends BaseController {

@GetMapping(value = "/ping")

public Results ping() {

return succeed("pong", "");

}

}

使用postman调用/ping接口,发现返回系统错误

控制台发现是空指针的错误,定位错误发现当我们想获取redis里面key是test的值时,发现redisTemplate没有是空的没有注入进来

解决问题:

知道拦截器执行在bean实例化前执行的,那么我们就让拦截器执行的时候实例化拦截器Bean,在拦截器配置类里面先实例化拦截器,然后再获取

@Configuration

public class WebFilterConfig implements WebMvcConfigurer {

/**

* 这里需要先将限流拦截器入住,不然无法获取到拦截器中的redistemplate

* @return

*/

@Bean

public AccessLimitIntercept getAccessLimitIntercept() {

return new AccessLimitIntercept();

}

/**

* 多个拦截器组成一个拦截器链

* @param registry

*/

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(getAccessLimitIntercept()).addPathPatterns("/**");

}

}

使用postman再次请求就可以访问到


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:RFC4862 IPV6无状态地址自动配置 阅读记录2
下一篇:RFC4862 IPV6无状态地址自动配置 阅读记录
相关文章

 发表评论

暂时没有评论,来抢沙发吧~