zoukankan      html  css  js  c++  java
  • Filter使用@Autowired注解失败及解决办法

    filter中无法使用@Autowired 原因

    在Spring中,web应用启动的顺序是:listener->filter->servlet,先初始化listener,然后再来就filter的初始化,再接着才到我们的dispathServlet的初始化,因此,当我们需要在filter里注入一个注解的bean时,就会注入失败,因为filter初始化时,注解的bean还没初始化,没法注入。

    由一个简单filter的使用引发的“血案”

    前情回顾:项目需要一个filter过滤器来拦截所有请求,过滤器的内容很简单,就是过滤请求url判断用户是否登录。如果用户登录,则更新存在redis里的用户信息过期时间;如果未登录则返回信息给前端,跳转登录。

    <filter>
       <filter-name>ExtensionFilter</filter-name>
       <filter-class>com.extension.filters.ExtensionFilter</filter-class>
    </filter>
    <filter-mapping>
       <filter-name>ExtensionFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

    给自己挖的坑:

    首先在这个filter过滤器中,需要从请求头中获取token,根据token从redis中拿到用户信息。此时需要在filter中注入封装好的redis实体bean,我使用@Autowired注解,此时代码编译没有报错,看起来程序没问题。

    接下来就是在坑里转悠直到把坑填上:

    紧接着问题就来了,项目能正常跑起来,但是一请求就报NULLPOINTEREXCEPTION异常,debug调试也找不到原因。折磨了我将近半个小时,终于找到问题。细心阅读并且对Web容器初始化熟悉的朋友应该知道我犯了什么错误了。

    问题:在过滤器中采用@Autowired方式注入

    1 @Autowired
    2 rivate RedisCache redisCache;

    然鹅,实际证明注入失败。

    分析原因:Web容器初始化顺序是按照Listener-filter-servlet的顺序进行,因为dispatcherServlet是在filter之后才进行初始化,也就是这个时候我们要自动注入的bean才被初始化。所以此时在filter中自动注入的时候还没有bean,所以会注入失败。

    解决办法:

    1、采用xml配置方式

    • Web.xml这样配置
    <filter>
       <filter-name>ExtensionFilter</filter-name>
       <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
              <param-name>targetBeanName</param-name>
              <param-value>ExtensionFilter</param-value>
     </init-param>
     <init-param>
              <param-name>targetFilterLifecycle</param-name>
              <param-value>true</param-value>
      </init-param>
    </filter>
    <filter-mapping>
       <filter-name>DelegatingFilterProxy</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>
    • 在spring配置文件中使用bean标签配置serviceImpl和ExtensionFilter
    <bean id="ExtensionFilter" class="com.extension.filters.ExtensionFilter">
       <property name="redisCache" ref="redisCache"></property>
    </bean>
    
    <!--要注入的bean-->
    
    <bean id="redisCache" class="com.htjc.interceptor.redis.RedisCache">
    </bean>

    这种方式的重点是在web.xml中用到了DelegatingFilterProxy这个filter代理类。具体用法可以去看看DelegatingFilterProxy源码。

    2、使用ApplicationContext对象获取

    //要注入的对象
    
    private RedisCache redisCache;
    
    ServletContext context = request.getServletContext();
    
    ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
    redisCache = ctx.getBean(RedisCache.class);

    以上内容纯属个人总结,如有问题请在评论区留言!

  • 相关阅读:
    springboot项目在IDEA根据不同的开发人员读取不同的配置文件
    Idea中一个服务按多个端口同时启动
    修改feign解析器替换json
    Intellij IDEA中启动多个微服务--开启Run Dashboard管理
    解决springboot乱码和window cmd乱码
    调用远程linux服务器shell脚本
    cp复制命令详解
    ftp列出具体目录的所有目录,和目录按照文件类型列出
    Linux下Redis开机自启(Centos)
    vsftpd 配置上传失败553
  • 原文地址:https://www.cnblogs.com/panchanggui/p/14979829.html
Copyright © 2011-2022 走看看