1.Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理。例如通过拦截器可以进行权限验证、判断用户是否已登录等。
2. 执行先后顺序:Filter前处理 --> Interceptor前处理 --> controller--> Interceptor后处理 --> Filter后处理
3. HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前(preHandle)、request被响应之后(postHandle)、视图渲染之前以及request全部结束之后(afterCompletion)。
4. Filter 的 doFilter(ServletRequest request,ServletResponse response,FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。该方法可以实现对用户请求进行预处理(ServletRequest request),也可实现对服务器响应进行后处理(ServletResponse response)—它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理
public class LogFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("----项目启动----");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//拦截请求
String reqPath = ((HttpServletRequest)servletRequest).getServletPath();
if(!(reqPath.contains(".js") || reqPath.contains(".css"))){
logger.info("----请求url:"+reqPath+"----");
}
//拦截继续传递
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
logger.info("----项目关闭----");
}
}
/**
* @author ngLee
* @version 1.0
* @Desc 如果用户信息存在,就不拦截请求
* @date 2021/3/25 22:05
*/
@Component
public class AuthIntercepteror implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取用户信息,session里面取
User user = UserContext.getUser();
if(user == null){
String target = URLEncoder.encode(request.getRequestURI(),"UTF-8");
String reqType = request.getMethod();
if("GET".equalsIgnoreCase(reqType)){
response.sendRedirect("/account/login.vw?target="+target);
}else {
response.sendRedirect("/account/login.vw");
}
}
return false;
}
@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 {
}
}
/**
* @author ngLee
* @version 1.0
* @Desc 如果用户信息存在,就不拦截请求
* 用户信息不存在,重定向到登录页面
* @date 2021/3/25 22:05
*/
@Component
public class AuthIntercepteror implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
User user = UserContext.getUser();
if(user == null){
String target = URLEncoder.encode(request.getRequestURI(),"UTF-8");
String reqType = request.getMethod();
if("GET".equalsIgnoreCase(reqType)){
response.sendRedirect("/account/login.vw?target="+target);
}else {
response.sendRedirect("/account/login.vw");
}
}
return false;
}
@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 {
}
}
//存储用户信息 公用
public class UserContext {
public static ThreadLocal<User> USER_LOCAL = new ThreadLocal<>();
/**
* @desc 存储用户
* @author ngLee
* @date 2021/3/25 21:56
*/
public static void setUser(User user){
USER_LOCAL.set(user);
}
public static User getUser(){
return USER_LOCAL.get();
}
public static void remove(){
USER_LOCAL.remove();
}
}
注意:拦截器的执行是有一定顺序的,该顺序与我们拦截器的注册顺序有关,例如上问实现的两个拦截器,工作顺序应该是AuthIntercepter拦截请求,判断是否有用户信息,有信息则放到当前线程进行存储,然后存储的信息供AuthIntercepteror使用,然后根据请求的方式,进行重定向。流程图如下
/**
* @author ngLee
* @version 1.0
* @Desc
* @date 2021/3/25 22:17
*/
@Configuration
public class WebMvcConf implements WebMvcConfigurer {
@Autowired
private AuthIntercepter authIntercepter;
@Autowired
private AuthIntercepteror authIntercepteror;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//所有请求
registry.addInterceptor(authIntercepter).excludePathPatterns("/static").addPathPatterns("/**");
//涉及到个人信息需要登录
registry.addInterceptor(authIntercepteror).addPathPatterns("/account/profile**");
}
}
[拦截器]spring 中 HandlerInterceptor 与 javax.servlet.Filter区别及使用
原文:https://www.cnblogs.com/ngLee/p/14588079.html