在工作中我们经常需要做登录拦截验证或者其他拦截认证功能,基于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 (outputStream != 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再次请求就可以访问到

到此这篇关于springboot拦截器无法注入redisTemplate的解决方法的文章就介绍到这了,更多相关springboot拦截器无法注入redisTemplate内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!