问题
在Filter过滤器中,添加成员变量,并通过Spring的@Autowired和@Resource注解进行依赖注入失败。
代码如下:
package com.wnkj.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wnkj.entity.User;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
@Component
public class LoginFilter implements Filter {
@Autowired
private JedisPool jedisPool;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String servletPath = httpServletRequest.getServletPath();
if (servletPath.contains("login") || servletPath.contains("index")) {
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
String token = null;
for (int i = 0; i < cookies.length; i++) {
Cookie c = cookies[i];
String name = c.getName();
if ("tokenCookie".equals(name)) {
token = c.getValue();
}
}
if (token != null && ! "".equals(token) && ! token.trim().isEmpty()) {
Jedis jedis = null;
String userJsonString = null;
try {
jedis = jedisPool.getResource();
userJsonString = jedis.get(token);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (jedis != null) {
jedis.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (userJsonString != null && ! "".equals(token) && ! token.trim().isEmpty()) {
JSONObject userJsonObject = JSON.parseObject(userJsonString);
User user = new User();
try {
BeanUtils.populate(user, userJsonObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
HttpSession session = httpServletRequest.getSession();
session.setAttribute("user", user);
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
}
}
@Override
public void destroy() {
}
}
分析问题
在Web项目启动过程中,三大组件初始化顺序是:Listener ->> Filter ->> Serlvet
注:SpringMVC的前端控制器DispatcherServlet是一个Servlet。
当Filter初始化的时候,DispatcherServlet仍未开始初始化。而DispatcherServlet未开始初始化,就导致IOC容器未完成初始化,所以Filter中通过依赖注入给成员变量注入实例的方式明显不行。
解决问题
可以在Filter过滤器的init()初始化方法中,手动加载XML配置文件,并得到想得到的类的实例,完成成员变量的实例化。
如下:
package com.wnkj.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wnkj.entity.User;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class LoginFilter implements Filter {
private JedisPool jedisPool;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
ServletContext servletContext = filterConfig.getServletContext();
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
if (webApplicationContext != null) {
jedisPool = webApplicationContext.getBean(JedisPool.class);
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String servletPath = httpServletRequest.getServletPath();
if (servletPath.contains("login") || servletPath.contains("index")) {
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
String token = null;
for (int i = 0; i < cookies.length; i++) {
Cookie c = cookies[i];
String name = c.getName();
if ("tokenCookie".equals(name)) {
token = c.getValue();
}
}
if (token != null) {
Jedis jedis = null;
String userJsonString = null;
try {
jedis = jedisPool.getResource();
userJsonString = jedis.get(token);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (jedis != null) {
jedis.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (userJsonString != null) {
JSONObject userJsonObject = JSON.parseObject(userJsonString);
User user = new User();
try {
BeanUtils.populate(user, userJsonObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
HttpSession session = httpServletRequest.getSession();
session.setAttribute("user", user);
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
}
}
@Override
public void destroy() {
}
}
补充
为了使得以后在Filter中更便捷的完成成员变量的实例化,可以创建一个类,专门用于处理该问题。
package com.wnkj.utils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (ApplicationContextUtils.applicationContext == null) {
ApplicationContextUtils.applicationContext = applicationContext;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 根据XML中<bean id=""></bean>的id属性值
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 根据类型
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 根据name和类型
* @param name
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
因此,上面Filter中init()方法中的代码,就可以修改为如下:
package com.wnkj.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wnkj.entity.User;
import com.wnkj.utils.ApplicationContextUtils;
import org.apache.commons.beanutils.BeanUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class LoginFilter implements Filter {
private JedisPool jedisPool;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
jedisPool = ApplicationContextUtils.getBean(JedisPool.class);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String servletPath = httpServletRequest.getServletPath();
if (servletPath.contains("login") || servletPath.contains("index")) {
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
String token = null;
for (int i = 0; i < cookies.length; i++) {
Cookie c = cookies[i];
String name = c.getName();
if ("tokenCookie".equals(name)) {
token = c.getValue();
}
}
if (token != null) {
Jedis jedis = null;
String userJsonString = null;
try {
jedis = jedisPool.getResource();
userJsonString = jedis.get(token);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (jedis != null) {
jedis.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (userJsonString != null) {
JSONObject userJsonObject = JSON.parseObject(userJsonString);
User user = new User();
try {
BeanUtils.populate(user, userJsonObject);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
HttpSession session = httpServletRequest.getSession();
session.setAttribute("user", user);
chain.doFilter(httpServletRequest, httpServletResponse);
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
} else {
httpServletRequest.getRequestDispatcher("/login.jsp").forward(httpServletRequest, httpServletResponse);
}
}
}
@Override
public void destroy() {
}
}