第六章 SpringBoot拦截器实战和Servlet3.0自定义Filter和Listener
06-4 SpringBoot2.x自定义拦截器实战以及新旧配置对比
1.过滤器与拦截器的区别
- 过滤器与拦截器触发时机不一样,过滤器是在请求进入容器后,在请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。
- 过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射
- Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射) 的方式来执行。
- Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
应用场景区别
过滤器应用场景:
- 过滤敏感词汇(防止sql注入)
- 设置字符编码
- URL级别的权限访问控制
- 压缩响应信息
拦截器应用场景:
- 登录验证,判断用户是否登录。
- 权限验证,判断用户是否有权限访问资源,如校验token
- 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
- 处理cookie、本地化、国际化、主题等。
- 性能监控,监控请求处理时长等。
- 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现)
2.Spring拦截器新旧版本的区别
当前目录结构
先定义好一个拦截器LoginIntercepter.java
.
package com.lcz.demo.intercepter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author : codingchao
* @date : 2021-11-23 14:29
* @Description:
**/
public class LoginIntercepter implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("LoginIntercepter--->preHandle");
return HandlerInterceptor.super.preHandle(request,response,handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("LoginIntercepter--->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("LoginIntercepter--->afterHandle");
}
}
(1)Spring2.x之前
package com.lcz.demo.intercepter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @author : codingchao
* @date : 2021-11-23 14:36
* @Description:
**/
@Configuration
public class CustomOldWebMvcConfigure extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/");
super.addInterceptors(registry);
}
}
package com.lcz.demo.intercepter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author : codingchao
* @date : 2021-11-23 14:34
* @Description:
**/
@Configuration
public class CustomWebMvcConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/*/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
(2)Spring2.x之后
package com.lcz.demo.intercepter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author : codingchao
* @date : 2021-11-23 14:34
* @Description:
**/
@Configuration
public class CustomWebMvcConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/*/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
(3)小结
测试结果:
3.Spring拦截器顺序问题
在上述的基础上再添加一个拦截器,输出查看一下拦截器顺序。
package com.lcz.demo.intercepter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class TwoIntercepter implements HandlerInterceptor{
/**
* 进入对应的controller方法之前
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("TwoIntercepter------>preHandle");
return HandlerInterceptor.super.preHandle(request, response, handler);
}
/**
* controller处理之后,返回对应的视图之前
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("TwoIntercepter------>postHandle");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 整个请求结束后调用,视图渲染后,主要用于资源的清理
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("TwoIntercepter------>afterCompletion");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
package com.lcz.demo.intercepter;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author : codingchao
* @date : 2021-11-23 14:34
* @Description:
**/
@Configuration
public class CustomWebMvcConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/*/**");
registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api/*/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
测试结果如下:
小结:
按照注册顺序进行拦截,先注册,先被拦截
拦截器不生效常见问题:
1)是否有加@Configuration
2)拦截路径是否有问题 ** 和 *
3)拦截器最后路径一定要 “/**”, 如果是目录的话则是 /*/