目录
1拦截器与过滤器区别
1.1 实现原理
过滤器和拦截器 底层实现方式大不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。 思想都是 aop
1.2 使用范围不同
过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。
而拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。所以它可以使用spring管理的类。过滤器不行。
tomcat-->filter--->servlet-->Interceptor-->controller
Springboot过滤器和拦截器详解及使用场景_头顶假发的博客-CSDN博客_springboot什么情况使用过滤器
1.3 场景
过滤器:拦截web请求,请求编码,xss攻击 包括css js image 等资源文件。不能使用spring管理的类
拦截器:绝大多数的情况都是使用拦截器。权限,日志打印,参数校验。能使用spring管理的类
2 代码
拦截器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @创建人 赵伟
* @创建时间 2022/12/10
* @描述
*/
@Component
public class TestIntercepter implements HandlerInterceptor {
@Autowired
UserService UserService;
@Override
//在将请求发送到控制器controller之前执行操作,若返回true就进入控制器,若返回false就不进入控制器了
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
//拦截器能调用 spring 管理的类
String token1 = UserService.getToken();
System.out.println("自定义拦截器1-----开始拦截,在进入控制器之前,拦截器进行拦截该请求,拦截到的token值为:"+token);
return null != token;
}
@Override
//用于在将响应发送到客户端之前执行操作,就是控制器执行完之后返回数据时执行。
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable
ModelAndView modelAndView) throws Exception {
System.out.println("自定义拦截器1-----控制器执行完毕,返回数据");
}
@Override
//在完成请求和响应后执行操作
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("自定义拦截器1-----响应结束");
}
}
多个拦截器按照 order 从小到大顺序执行
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* @创建人 赵伟
* @创建时间 2022/12/10
* @描述
*/
//老版本是通过继承WebMvcConfigurerAdapter类,新版本是通过实现WebMvcConfigurer接口
@Configuration
public class TestIntercepterConfig implements WebMvcConfigurer {
//引入自定义拦截器对象
@Resource
private TestIntercepter testIntercepter;
@Resource
private TestIntercepter2 testIntercepter2;
/**
* 重写addInterceptors方法注册拦截器 order 从小到大顺序执行
* @param registry
*
*/
@Override
public void addInterceptors(InterceptorRegistry registry){
//addInterceptor方法向拦截器注册器添加拦截器,addPathPatterns方法添加拦截路径匹配规则("/**"是拦截所有),excludePathPatterns方法是设置白名单,放行哪些路径
registry.addInterceptor(testIntercepter).addPathPatterns("/**").excludePathPatterns("/login/*").order(1);
registry.addInterceptor(testIntercepter2).addPathPatterns("/**").excludePathPatterns("/login/*").order(2);
}
}
filter:
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @创建人 赵伟
* @创建时间 2022/12/11
* @描述 过滤器 无法使用spring管理的类
*/
public class TestFilter implements Filter {
/**
* 启动项目的时候会执行这个方法
* 初始化一些属性或对象等
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String initParameter = filterConfig.getInitParameter("name");
Filter.super.init(filterConfig);
System.out.println("启动项目的时候就会执行-初始化一些属性对象等");
}
/**
*
* @param servletRequest 请求
* @param servletResponse 响应
* @param filterChain 当前Filter链的对象
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
//这里为了使用getHeader方法获取token,转型成HttpServletRequest
System.out.println("token:"+req.getHeader("token"));
System.out.println(servletRequest.getParameter("id"));
String token = req.getHeader("token");
//再判断token是否正确
if(null==token){
throw new RuntimeException("token为空");
}
//无法调用 spring管理的类 来查询 token 是否正确
//调用doFilter方法,正常返回servletResponse
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("过滤器被销毁TestFilter");
}
}
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @创建人 赵伟
* @创建时间 2022/12/11
* @描述
*/
@Configuration
public class TestFilterConfig {
@Autowired
Environment Environment;
@Bean
public FilterRegistrationBean filterRegistrationBean(){
//创建一个注册过滤器对象
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
设置自定义过滤器 执行完整个 filterRegistrationBean方法 才会执行 new TestFilter()里的方法 init初始化东西;
registrationBean.setFilter(new TestFilter());
String name = Environment.getProperty("name");
registrationBean.addInitParameter("name",name);
//设置过滤拦截匹配规则,/*是匹配所有
registrationBean.addUrlPatterns("/*");
//只拦截userController下面的接口
// registrationBean.addUrlPatterns("/userController/*");
//存在多个过滤器时,设置执行顺序,值越大,执行顺序越靠后
registrationBean.setOrder(5);
//返回这个注册过滤器对象
return registrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean2(){
//创建一个注册过滤器对象
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
//设置自定义过滤器
registrationBean.setFilter(new TestFilter2());
//设置过滤拦截匹配规则,/*是匹配所有
registrationBean.addUrlPatterns("/*");
//只拦截userController下面的接口
// registrationBean.addUrlPatterns("/userController/*");
//存在多个过滤器时,设置执行顺序,值越大,执行顺序越靠后
registrationBean.setOrder(6);
//返回这个注册过滤器对象
return registrationBean;
}
}