过滤器
过滤器的定义
在客户端将请求发送到服务器端之前,拦截这些请求;在服务器端的响应返回给客户端之前,处理这些响应。
比如字符编码过滤器CharacterEncodingFilter,就是设置request和response中的字符编码方式。
过滤器的实现
方式一 利用WebFilter注解配置
@Slf4j
@WebFilter(filterName = "filter1", urlPatterns = {"/*"})
public class MyFirstFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("filter1 init method invoke....");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("filter1 doFilter method invoke....");
//让过滤器继续往下执行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
log.info("filter1 destroy method invoke....");
}
}
在SpringBoot主程序类上添加Servlet组件扫描的注解@ServletComponentScan,运行程序即可看到控制台输出的init方法的调用输出内容,访问任意请求,都可以看到doFilter的方法内容输出。
以上代码可以实现过滤器的配置和使用,但是存在一个问题,当项目中有多个过滤器同时存在时,不能设置这些过滤器的执行顺序,需要借助FilterRegistrationBean类型的对象设置过滤器,可以再添加一个过滤器查看运行效果。
方式二:FilterRegistrationBean方式
将前面的两个过滤器类上的@WebFilter注解去掉,其他都不变,在项目中添加一个配置类专门针对过滤器配置,代码如下:
public class MyFilterRegistration {
//注册第一个filter
@Bean
public FilterRegistrationBean registerMyFirstFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//注册Filter
filterRegistrationBean.setFilter(new MyFirstFilter());
//配置过滤器的名字
filterRegistrationBean.setName("filter1");
//配置过滤器过滤的url
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(2);
return filterRegistrationBean;
}
//注册第二个filter
@Bean
public FilterRegistrationBean registerMySecondFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//注册filter
filterRegistrationBean.setFilter(new MySecondFilter());
//配置过滤器的名字
filterRegistrationBean.setName("filter2");
//配置过滤器过滤的url
filterRegistrationBean.addUrlPatterns("/*");
//设置执行顺序
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
在使用setOrder()方法可以设置多个过滤器的执行顺序,其中值越小,优先级越高。
其他代码不变,再看代码的运行效果,会发现,doFilter方式是先执行MySecondFilter再执行MyFirstFilter。
拦截器
拦截器的定义
在Servlet的规范中并没有拦截器的概念,是在Spring框架中衍生出来的。
拦截器的处理:
拦截器中有三个方法:
1、 preHandle:表示被拦截的URL 对应的控制层方法执行前的自定义处理逻辑
2、 postHandle:表示被拦截的URL对应的控制层方法执行后的自定义处理逻辑,此时还没有对ModelAndView进行渲染
3、 afterCompletion:表示此时ModelAndView已经做了页面渲染,执行拦截器的自定义处理逻辑。
拦截器的实现
添加一个类,实现HandlerInterceptor接口
@Slf4j
public class MyFirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("preHandle method invoke....");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("postHandle method invoke....");
log.info("要跳转的页面是:" + modelAndView.getViewName());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("afterCompletion method invoke....");
}
}
接着,配置该拦截器,在之前写的WebMvcConfigurer接口的实现类中添加拦截器的注册信息:
`
拦截器和过滤器的区别
从请求处理的生命周期上看,拦截器和过滤器的作用是类似的,区别是:
过滤器使用的是Filter接口,实现的是init、doFilter和destroy方法
拦截器使用的是HandlerInterceptor接口,实现的是preHandle、postHandle、afterCompletion方法。
过滤器和拦截器的执行位置
过滤器和拦截器的使用场景:
规范不同的:Filter是Servlet规范中定义的组件,在Servlet容器内生效,而拦截器时Spring框架定义的,在Spring上下文中生效;
拦截器可以获取并使用Spring IOC容器中的bean,但过滤器不行。
拦截器可以访问Spring上下文值对象,如ModelAndView,过滤器不行。
过滤器的力度比拦截器的力度大,因为过滤器是在进入Servlet容器之前处理请求,拦截器则是在进入到Servlet容器之内处理请求,过滤器比较适合系统级别的处理动作,比如权限认证之类的。
拦截器比过滤器力度小,更适合分模块、分范围的统一业务逻辑处理。