一、使用Interceptor拦截器
1.首先新建一个拦截器实现HandlerInterceptor接口
以一个简单的token验证为例,验证通过,将用户信息放入作用域,返回true
不通过返回false
@Service
public class UserTokenInterceptor implements HandlerInterceptor {
@Autowired
private SysusertokenMapper sysusertokenMapper;
@Autowired
private SysloginuserMapper sysloginuserMapper;
@Autowired
private SysuserMapper sysuserMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在请求处理之前进行调用(Controller方法调用之前),返回true才会继续往下执行,返回false取消当前请求
boolean isAccess = false;
String tokenCode = request.getHeader("Token");
if (tokenCode != null && !"".equals(tokenCode)) {
//查询未过期的
Sysusertoken sysusertoken = sysusertokenMapper.selectByTokenCode(tokenCode);
if (sysusertoken != null) {
Sysloginuser sysloginuser = sysloginuserMapper.selectByPrimaryKey(sysusertoken.getLoginid());
Sysuser sysuser = sysuserMapper.selectByPrimaryKey(sysloginuser.getUserid());
request.getSession().setAttribute("user",sysuser);
request.getSession().setAttribute("token",tokenCode);
isAccess = true;
}
}
return isAccess;
}
@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 {
}
}
2.新建一个配置类来管理拦截器,将你之前新建的拦截器注入进来
addPathPatterns("/**")是拦截所有请求
excludePathPatterns("","",...)配置无需拦截的请求
package com.gcexe.monitor.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Component
public class UserTokenAppConfigurer extends WebMvcConfigurationSupport{
@Autowired
private UserTokenInterceptor userTokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
// excludePathPatterns 用户排除拦截
registry.addInterceptor(userTokenInterceptor).addPathPatterns("/**")
.excludePathPatterns("/account/login","/account/register");
super.addInterceptors(registry);
}
}
注意加上@Component注解,使其可以被扫描到
二、使用servlet的filter过滤器
新建一个类实现javax.servlet.Filter接口,通过@WebFilter注解来配置要拦截的请求,doFilter方法是要进行的操作。
package com.gcexe.monitor.filter;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.gcexe.monitor.persistence.dao.SysloginuserMapper;
import com.gcexe.monitor.persistence.dao.SysuserMapper;
import com.gcexe.monitor.persistence.dao.SysusertokenMapper;
import com.gcexe.monitor.persistence.entity.Sysloginuser;
import com.gcexe.monitor.persistence.entity.Sysuser;
import com.gcexe.monitor.persistence.entity.Sysusertoken;
@Component
@WebFilter(urlPatterns = "/**", filterName = "monitorFilter")
public class TokenAuthorFilter implements Filter {
@Autowired
private SysusertokenMapper sysusertokenMapper;
@Autowired
private SysloginuserMapper sysloginuserMapper;
@Autowired
private SysuserMapper sysuserMapper;
private static final String[] excludePathPatterns = { "/monitor/account/login", "/monitor/account/register" };
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
// 在请求处理之前进行调用(Controller方法调用之前),返回true才会继续往下执行,返回false取消当前请求
boolean isFilter = false;
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 不拦截登陆和注册
String url = request.getRequestURI();
if (Arrays.asList(excludePathPatterns).contains(url)) {
chain.doFilter(request, response);
return;
}
String tokenCode = request.getHeader("Token");
if (tokenCode != null && !"".equals(tokenCode)) {
// 查询未过期的
Sysusertoken sysusertoken = sysusertokenMapper.selectByTokenCode(tokenCode);
if (sysusertoken != null) {
Sysloginuser sysloginuser = sysloginuserMapper.selectByPrimaryKey(sysusertoken.getLoginid());
Sysuser sysuser = sysuserMapper.selectByPrimaryKey(sysloginuser.getUserid());
request.getSession().setAttribute("user", sysuser);
request.getSession().setAttribute("token", tokenCode);
isFilter = true;
}
}
if (isFilter) {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
执行chain.doFilter(request,response)方法类似于上面的返回true,让程序继续往下执行
可以自己配置返回内容,无需拦截的请求,我这里是定义了一个数组,自行判断,对应地址直接执行chain.doFilter(reuqest.response),同样注意加上@Component注解
三、过滤器和拦截器区别
主要区别如下:
1、拦截器主要是基于java的反射机制的,而过滤器是基于函数回调
2、拦截器不依赖于servlet容器,过滤器依赖于servlet容器
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
两种方式均可以使用,相比较而言,第一种方式较为方便,我一开始也是使用的这种,但是后来需要集成Spring Boot Validator框架时,发现验证数据一直不生效,后来发现是和Inteceptor有冲突,去掉拦截就可以验证了,暂时还没找到解决的办法,所以改为使用第二种方法。