Filter使用@Autowired注解失敗及解決辦法


由一個簡單filter的使用引發的“血案”

前情回顧:項目需要一個filter過濾器來攔截所有請求,過濾器的內容很簡單,就是過濾請求url判斷用戶是否登錄。如果用戶登錄,則更新存在redis里的用戶信息過期時間;如果未登錄則返回信息給前端,跳轉登錄。

 

1 <filter>
2    <filter-name>ExtensionFilter</filter-name>
3    <filter-class>com.extension.filters.ExtensionFilter</filter-class>
4 </filter>
5 <filter-mapping>
6    <filter-name>ExtensionFilter</filter-name>
7    <url-pattern>/*</url-pattern>
8 </filter-mapping>
View Code

 

給自己挖的坑:

首先在這個filter過濾器中,需要從請求頭中獲取token,根據token從redis中拿到用戶信息。此時需要在filter中注入封裝好的redis實體bean,我使用@Autowired注解,此時代碼編譯沒有報錯,看起來程序沒問題。

接下來就是在坑里轉悠直到把坑填上:

緊接着問題就來了,項目能正常跑起來,但是一請求就報NULLPOINTEREXCEPTION異常,debug調試也找不到原因。折磨了我將近半個小時,終於找到問題。細心閱讀並且對Web容器初始化熟悉的朋友應該知道我犯了什么錯誤了。

問題:在過濾器中采用@Autowired方式注入

1 @Autowired
2 rivate RedisCache redisCache;
View Code

然鵝,實際證明注入失敗。

分析原因:Web容器初始化順序是按照Listener-filter-servlet的順序進行,因為dispatcherServlet是在filter之后才進行初始化,也就是這個時候我們要自動注入的bean才被初始化。所以此時在filter中自動注入的時候還沒有bean,所以會注入失敗。

解決辦法:

1、采用xml配置方式

  • Web.xml這樣配置
 1 <filter>
 2    <filter-name>ExtensionFilter</filter-name>
 3    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 4 <init-param>
 5           <param-name>targetBeanName</param-name>
 6           <param-value>ExtensionFilter</param-value>
 7  </init-param>
 8  <init-param>
 9           <param-name>targetFilterLifecycle</param-name>
10           <param-value>true</param-value>
11   </init-param>
12 </filter>
13 <filter-mapping>
14    <filter-name>DelegatingFilterProxy</filter-name>
15    <url-pattern>/*</url-pattern>
16 </filter-mapping>
View Code
  • 在spring配置文件中使用bean標簽配置serviceImpl和ExtensionFilter
1 <bean id="ExtensionFilter" class="com.extension.filters.ExtensionFilter">
2    <property name="redisCache" ref="redisCache"></property>
3 </bean>
4 
5 <!--要注入的bean-->
6 
7 <bean id="redisCache" class="com.htjc.interceptor.redis.RedisCache">   
8 </bean>
View Code

這種方式的重點是在web.xml中用到了DelegatingFilterProxy這個filter代理類。具體用法可以去看看DelegatingFilterProxy源碼。

2、使用ApplicationContext對象獲取

1 //要注入的對象
2 
3 private RedisCache redisCache;
4 
5 ServletContext context = request.getServletContext();
6 
7 ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
8 redisCache = ctx.getBean(RedisCache.class);
View Code

以上內容純屬個人總結,如有問題請在評論區留言!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM