目录
Spring中
过滤器
监听器
拦截器
springboot中
过滤器
监听器
拦截器
搞明白监听器、过滤器、拦截器的作用和使用方式,首先需要了解spring对于这三个的加载时机是在怎么样的,如下图:
spring对于这三者依次是先执行过滤器(多个过滤器采用责任链模式依次调用执行),紧接着是监听器,最后才是拦截器。
而这三者的作用:
过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(不更改对象的行为和属性)
监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程,这就要用到监听器。 (不更改对象的行为和属性)
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(更改对象的行为和属性)
能力逐渐增强:过滤器-->监听器-->拦截器
需要在项目的web.xml中配置过滤器和过滤请求:如下图
public class CrosFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("启动时初始化???");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("新的请求每次都会执行请求时机????");
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
//允许跨域的域
response.setHeader("Access-Control-Allow-Origin", "*");
//允许携带脚本程序
response.setHeader("Access-Control-Allow-Credentials","true");
//允许的跨域请求
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT,PATCH");
//允许脚本访问返回的头
response.setHeader("Access-Control-Expose-Headers", "true");
//缓存此请求秒数
response.setHeader("Access-Control-Max-Age", "3600");
//自定义的头部
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, content-type");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("服务器停止时销毁??");
}
}
监听器的使用跟过滤器类似,也需要在web.xml中配置你的监听类
拦截器配置在MVC的配置文件中
@Component
public class UserInterceptor implements HandlerInterceptor {
/**
* 每次请求之前执行
* @param request
* @param response
* @param handler
* @return true表示继续流程(如调用下一个拦截器或处理器);
* false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("新的请求:"+handler);
return true;
}
/**
* 请求处理结束,(但在渲染视图之前)执行,此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("请求处理后视图前:"+handler+"==="+modelAndView);
}
/**
* 请求处理结束,渲染视图结束后执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("请求完全执行完成:"+handler+"--"+ex);
}
}
过滤器不需要额外的配置,直接交由spring管理即可,或者使用@WebFilter,二者选其一,使用@WebFilter,需要在启动类上开启对servlet注解的支持
在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码
/**
* @ClassName CrosFilter
* @Description 跨域过滤器,springboot直接交由spring管理就可直接使用,spring需要在web.xml中配置此过滤器
* @Date 2021/9/7 11:13
*/
@Component
//@WebFilter(urlPatterns = "/api/*", filterName = "loginFilter") //配置过滤请求等参数
public class CrosFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("启动时初始化???");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("新的请求每次都会执行请求时机????");
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
//允许跨域的域
response.setHeader("Access-Control-Allow-Origin", "*");
//允许携带脚本程序
response.setHeader("Access-Control-Allow-Credentials","true");
//允许的跨域请求
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT,PATCH");
//允许脚本访问返回的头
response.setHeader("Access-Control-Expose-Headers", "true");
//缓存此请求秒数
response.setHeader("Access-Control-Max-Age", "3600");
//自定义的头部
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, content-type");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("服务器停止时销毁??");
}
}
监听器在类上使用@WebListener标注,并且启动类上使用了@ServletComponentScan
@WebListener
public class MyRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("销毁。。。");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("初始化、、、");
}
}
拦截器的使用需要添加配置类,注册拦截器,不然不生效
@Component
public class UserInterceptor implements HandlerInterceptor {
/**
* 每次请求之前执行
* @param request
* @param response
* @param handler
* @return true表示继续流程(如调用下一个拦截器或处理器);
* false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("新的请求:"+handler);
return true;
}
/**
* 请求处理结束,(但在渲染视图之前)执行,此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("请求处理后视图前:"+handler+"==="+modelAndView);
}
/**
* 请求除磷结束,渲染视图结束后执行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("请求完全执行完成:"+handler+"--"+ex);
}
}
/**
* @ClassName InterceptorConfig
* @Description 拦截器的注册和配置 extends WebMvcConfigurerAdapter过时了
* 1、继承WebMvcConfigurationSupport
* 2、实现WebMvcConfigurer
* 但是继承WebMvcConfigurationSupport会让Spring-boot对mvc的自动配置失效。根据项目情况选择。
* 现在大多数项目是前后端分离,并没有对静态资源有自动配置的需求所以继承WebMvcConfigurationSupport也未尝不可。
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 创建拦截器对象
* @return
*/
@Bean
public HandlerInterceptor getMyInterceptor(){
return new UserInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration interceptor = registry.addInterceptor(getMyInterceptor());
// 拦截所有、排除
interceptor.addPathPatterns("/**")
.excludePathPatterns("/user/login");
}
}
运行结果:
总结至此