一、如何实现拦截器

在Spring Boot项目中,拦截器经常被用来做登陆验证,日志记录等操作。拦截器是Spring提供的,所以可以将拦截器注成bean,由IOC容器来管理。实现拦截器的方式很简单,主要由以下两个步骤:

  1. 自定义拦截器类实现HandlerInterceptor接口
  2. 自定义WebMvc配置类实现WebMvcConfigurer接口,添加自定义拦截器类

简要实现代码如下:

自定义拦截器 LoginInterceptor

public class LoginInterceptor implements HandlerInterceptor {

    @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token");
if(StringUtils.isEmpty(token)){
...
return false;
}
return true;
}
}

配置自定义拦截器:

@Configuration
public class WebConfiguration implements WebMvcConfigurer { @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
// 拦截的请求
.addPathPatterns("/**")
// 不用拦截的请求
.excludePathPatterns("/login");
}
}

这个拦截器的主要作用就是拦截所有访问请求,验证所带token是否有效,当token验证成功后,才能访问我们的业务接口。这时候就需要提供一个验证token有效性的接口,在拦截器中验证token,由于拦截器是Spring提供的,因此很容易想到使用@Component注解将拦截器注成一个 bean。然后使用@Autowired注解将验证token的类注入到拦截器进行验证。

改造完的代码如下:

验证token接口类:

@Component
public class TokenUtil {
/**
* 验证token 是否有效
*/
public boolean checkToken(String token){
...
}
}

改造完的拦截器代码如下:

@Component
public class LoginInterceptor implements HandlerInterceptor { @Autowired
private TokenUtil tokenUtil; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(!tokenUtil.checkToken(token)){
...
return false;
}
return true;
}
}

调用接口时发现,TokenUtil并没有被注入进来!明明代码写的没问题,为什么不能正常注入TokenUtil呢?

仔细观察我们自定义的配置类WebConfiguration,在添加拦截器的时候用的是new LoginInterceptor()如果想要拦截器生效,必须将拦截器配置到WebMvc的配置类中,就是我们自定义的WebConfiguration类。现在添加拦截器的时候是 new 了一个拦截器,也就是说并没有将拦截器托管给IOC容器,所以就无法引入Spring的bean对象

二、如何将拦截器托管给IOC容器

解决问题的思路也很简单,就是将拦截器也托管给IOC容器,这样容器内的对象就可以相互注入了。总共有以下三种方式进行处理上述问题。

2.1 在WebConfiguration注入拦截器

拦截器代码不变,在拦截器上使用@Component,同时在WebConfiguration中使用@Autowired注解将拦截器注入。

拦截器代码:

@Component
public class LoginInterceptor implements HandlerInterceptor {
}

配置类代码:

@Configuration
public class WebConfiguration implements WebMvcConfigurer { @Autowired
private LoginInterceptor loginInterceptor; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor);
}
}

2.2 在WebConfiguration将拦截器注成bean

拦截器无需增加@Component注解,在WebConfiguration类中使用@Bean注解将拦截器注成bean。

拦截器代码:

public class LoginInterceptor implements HandlerInterceptor {
}

配置类代码:

@Configuration
public class WebConfiguration implements WebMvcConfigurer { @Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
} @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor( loginInterceptor());
}
}

2.3 通过构造器处理

思路是在WebConfiguration类中注入需要的验证token的业务类,然后在初始化拦截器的时候将业务类通过构造器带入拦截器中,这样就不用把拦截器注成Spring Bean对象了。

拦截器代码:

public class LoginInterceptor implements HandlerInterceptor {

    private TokenUtil tokenUtil;

    public LoginInterceptor(TokenUtil tokenUtil) {
this.tokenUtil = tokenUtil;
}
}

配置类代码:

@Configuration
public class WebConfiguration implements WebMvcConfigurer { @Autowired
private TokenUtil tokenUtil; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor(tokenUtil));
}
}

三、总结

网上关于拦截器的代码基本都是通过new一个拦截器进行配置的,这时候就会出现无法注入其他bean的情况。很多人想当然地直接在拦截器加@Component注解使其成为一个bean对象。这是一种错误的做法。我们需要保证的是在WebMvc配置类中添加的拦截器是Spring 的一个bean对象,也就是说我们需要将拦截器注成一个bean,同时将这个bean添加的WebMvc配置类中。

四、点关注、不迷路

如果觉得文章不错,欢迎关注点赞收藏,你们的支持是我创作的动力,感谢大家。

如果文章写的有问题,请不要吝惜文笔,欢迎留言指出,我会及时核查修改。

如果你还想看到更多别的东西,可以微信搜索「Java旅途」进行关注。「Java旅途」目前已经整理各种中间件的使用教程及各类Java相关的面试题。扫描下方二维码进行关注就可以得到这些资料。

为什么你写的拦截器注入不了 Java bean?的更多相关文章

  1. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  2. SpringBoot开发案例之拦截器注入Bean

    前言 由于业务需要,需要在拦截器中操作Redis缓存,按照 controller,service层配置发现无法注入,一直报空指针异常. 解决方案 @Configuration public class ...

  3. springboot拦截器注入service为空

    一般都是因为除了在拦截器之外,还需要在拦截器的配置类中,注册拦截器时没有使用spring的bean,而是使用了new创建bean造成的. @Configuration public class Web ...

  4. 解决Spring Boot 拦截器注入service为空的问题

    问题:在自定义拦截器中,使用了@Autowaire注解注入了封装JPA方法的Service,结果发现无法注入,注入的service为空 0.原因分析 拦截器加载的时间点在springcontext之前 ...

  5. springboot的拦截器报错plicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]

    解决方案: spingboot的拦截器"index.html"少"/",太粗心了

  6. SpringBoot拦截器中无法注入bean的解决方法

    SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ...

  7. 拦截器HandlerInterceptor内部也可以注入bean,代码纠正补充

    原文地址https://www.jianshu.com/p/890c23a1b3d7 原文内容 1.拦截器内无法通过SpringBean的方式注入LoggerJPA,我只能通过另外一种形式. priv ...

  8. 写的太细了!Spring MVC拦截器的应用,建议收藏再看!

    Spring MVC拦截器 拦截器是Spring MVC中强大的控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作. 拦截器概述 对于任何优秀的MVC框架, ...

  9. 解决mybatis拦截器无法注入spring bean的问题

    公司要整合rabbitmq与mybatis拦截器做一个数据同步功能. 整合过程中大部分环节都没什么问题,就是遇到了mybatis拦截器 @Intercepts(@Signature(type = Ex ...

随机推荐

  1. spring-boot-route(二十)Spring Task实现简单定时任务

    Spring Task是Spring 3.0自带的定时任务,可以将它看作成一个轻量级的Quartz,功能虽然没有Quartz那样强大,但是使用起来非常简单,无需增加额外的依赖,可直接上手使用. 一 如 ...

  2. 【事件中心 Azure Event Hub】Event Hub Java SDK的消费端出现不消费某一个分区中数据的情况,出现IdleTimerExpired错误消息记录

    问题情形 使用Java SDK编写的Event Hub消费端应用,随机性遇见了某个分区没有消费消息的情况,在检查日志时候,有发现IdelTimeExpired的错误记录.在重启应用后,连接EventH ...

  3. 【计算几何 05】Pick定理

    什么是Pick定理(皮克定理) 来自wiki的介绍: 给定顶点座标均是整点(或正方形格子点)的简单多边形,皮克定理说明了其面积 \(A\)和内部格点数目 \(i\) .边上格点数目 \(b\) 的关系 ...

  4. final修饰注意事项

    StringBuilder , StringBuffer ,String 都是 final 的,但是为什么StringBuilder , StringBuffer可以进行修改呢,因为不可变包括的是,引 ...

  5. jQuery load() 中文乱码

    1.使用editplus创建了demo.txt (ANSI保存的), $("#div1").load("demo.txt");//div显示中文乱码---> ...

  6. 配置通过Console口登录交换机

    组网图形 图1 通过Console口登录交换机组网图 通过Console口登录交换机简介 通过Console口登录交换机是指使用专门的Console通信线缆将用户PC的串口与交换机的Console口相 ...

  7. OpenSpiel 随笔 05.14

    ------------恢复内容开始------------ 这两天年总算把自己的游戏写完了,也通过了所有的测试. 我将自己的代码上传到了我的github上, 地址是 https://github.c ...

  8. SpringMVC+Spring+MyBatis个人技术博客源码

    项目描述 Hi,大家好,又到了源码分享时间啦,今天我们分享的源码一个<个人技术博客>,该博客是基于SSM实现的一个个人博客系统,适合初学SSM和个人博客制作的同学学习.有了这个源码,直接买 ...

  9. Flutter 1.22版本新增的Button

    Flutter 1.22版本新增了3个按钮,TextButton.OutlinedButton.ElevatedButton,虽然以前的Button没有被废弃,但还是建议使用新的Button. 为什么 ...

  10. HashMap的初始化,到底都做了什么?

    HashMap的初始化,到底都做了什么? HashMap初始化参数都是什么?默认是多少? 为什么建议初始化设置容量? tableSizeFor方法是做什么的? 如何获取到一个key的hash值?及计算 ...