spring boot中 拦截器和过滤器
拦截器
拦截器的执行流程
直接上代码,代码有注释
package com.hjx.config;
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;
/**
* 拦截器的实现
*/
@Component
public class MyInterceptor implements HandlerInterceptor {
/**
*
* 预处理回调方法,实现处理器的预处理
* 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
* 在方法处理前执行
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Controller中的方法执行前执行");
return true; //返回值:true表示继续向下执行;false表示流程中断,不会继续调用其他的拦截器或即将执行的Controller中的方法
}
/**
* 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
* 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Controller中的方法执行后执行");
}
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
* 如性能监控中我们可以在此记录结束时间并输出消耗时间,
* 还可以进行一些资源清理,类似于try-catch-finally中的finally,
* 但仅调用处理器执行链中
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("视图生成后执行");
}
}
实现拦截器的方式有:
1.实现接口HandlerInterceptor,重写preHandle、postHandle、afterCompletion方法。最后将拦截器进行注册
2.继承HandlerInterceptorAdapter类(HandlerInterceptor接口的实现类)。
3.实现WebRequestInterceptor接口 或 继承该接口的实现类。
注意点:
1.当我们使用 继承 WebMvcConfigurationSupport 类的方式注册拦截器时,默认会对静态资源(包括templates下的资源)进行拦截,导致静态资源时出现:No mapping for GET xxxx的问题
在使用拦截器时,在配置拦截器的时候,由于在 Spring Boot 2.0 之前,我们都是直接继承 WebMvcConfigurerAdapter 类,然后重写 addInterceptors 方法来实现拦截器的配置。但是在 Spring Boot 2.0 之后,该方法已经被废弃了(当然,也可以继续用),取而代之的是 WebMvcConfigurationSupport 方法,如下
解决方案1:最简单的方式,实现WebMvcConfigurer接口注册拦截器即可对静态资源放行。如下:
@Configuration
public class ViewConfig implements WebMvcConfigurer {
@Autowired
// 过滤器配置 实现HandlerInterceptor接口
private MyInterceptor myInterceptor;
//对拦截器的配置
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 实现WebMvcConfigurer不会导致静态资源被拦截
registry.addInterceptor(myInterceptor).addPathPatterns("/**");
}
}
解决方案2
依然使用继承类WebMvcConfigurationSupport 方法注册拦截器,但是还需重写其中一个方法addResourceHandlers用于对静态资源进行放行,如下:
/**
* 用来指定静态资源不被拦截,否则继承WebMvcConfigurationSupport这种方式会导致静态资源无法直接访问
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
super.addResourceHandlers(registry);
}
不过,最好使用方案一:便于管理,代码更加轻巧。
多个拦截时的执行流程
preHandle会按照配置文件中的执行顺序执行。
但他们的postHandle和afterCompletion方法会按照配置文件中的顺序反序执行
过滤器
实现方式1
1.使用组件注册的方式整合Filter,具体做法如下:
1.定义一个类实现Filter接口,重写init、doFilter、destory方法。并将该类使用@Component注解修饰。
2.新建一个配置类,使用@Configuration 修饰该类。声明一个方法,并用@Bean注解修饰(将该注解修饰的方法的返回值注入到Bean中),具体如下:
Component
public class Myfilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
@Bean
public FilterRegistrationBean FilterRegister(Myfilter myfilter){
FilterRegistrationBean registrationBean=new FilterRegistrationBean(myfilter);
registrationBean.setUrlPatterns(Arrays.asList("/login","/a"));
return registrationBean;
}
实现方式2
通过路径扫描的方式,具体如下:
// 主启动类开启包扫描(要扫描的过滤器)
@ServletComponentScan("com.hjx.Controller.Filter")
// 对指定的路径进行拦截
@WebFilter(value = {"/a","/b"})
public class Myfilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
过滤器和拦截器的区别
区别
1.过滤器Filter基于Servlet实现,过滤器的主要应用场景是对字符编码、跨域等问题进行过滤。Servlet的工作原理是拦截配置好的客户端请求,然后对Request和Response进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。
3.拦截器是SpringMVC中实现的一种基于Java反射(动态代理)机制的方法增强工具
4.过滤器属于Servlet级别,拦截器属于Spring级别
Filter是在javax.servlet包中定义的,要依赖于网络容器,因此只能在web项目中使用。
Interceptor是SpringMVC中实现的,归根揭底拦截器是一个Spring组件,由Spring容器进行管理。
5.过滤器基于函数回调方式实现,拦截器基于Java反射机制实现
相同点
1、拦截器与过滤器都是体现了AOP的思想,对方法实现增强,都可以拦截请求方法。
2、拦截器和过滤器都可以通过Order注解设定执行顺序
拦截器和过滤器执行路径图
应用场景
拦截器的应用场景:权限控制,日志打印,参数校验
过滤器的应用场景:跨域问题解决,编码转换