一篇文章看懂拦截器和过滤器的执行顺序和区别,全!
上周学习了springboot集成websocket就使用了过滤器 (Filter
),对指定的请求进行拦截设置响应头,所有借这个机会重新学习下总结拦截器和过滤器。
目录
三、过滤器(Filter)和 拦截器(Interceptor)的区别
一、过滤器(Filter)
1.1 基本概念
- Filter 过滤器,是JavaWeb 三大组件(Servlet、Filter、Listener)之一
- 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
- 过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。
1.2?定义过滤器
第一种:@WebFilter+@ServletComponentScan(可以自定义拦截路径,无法控制多个过滤器顺序)
- 1.定义Filter:定义一个类,实现 Filter 接口,并重写其所有方法
- 2.配置Filter: Filter类上加 @WebFilter 注解,配置拦截资源的路径
- 3.启动类上加 @ServletComponentScan 开启Servlet组件支持
测试接口:
// http://127.0.0.1:8080/hello?name=lisi
@RequestMapping("/hello")
@ResponseBody
public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {
System.out.println("Hello " + name);
return "Hello " + name;
}
启动类加@ServletComponentScan
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@ServletComponentScan
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
Filter实现?:?
package com.example.demo.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author qujingye
* @Classname Demofilter
* @Description TODO
* @Date 2023/12/26 21:16
*/
@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {
//初始化方法,Web服务器启动,创建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 {
System.out.println("拦截方法执行,拦截到了请求 ...");
System.out.println("执行放行前逻辑 ...");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("执行放行后逻辑 ...");
}
//销毁方法,服务器关闭时调用,只调用一次
@Override
public void destroy() {
Filter.super.destroy();
}
}
测试成功!!!
第二种:@Component+@Order() 这种无法自定义拦截路径,但是可以设置过滤器链的执行顺序,order挎号里面的值越小,越先拦截
package com.example.demo.filter;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author qujingye
* @Classname DemoFilter2
* @Description TODO
* @Date 2023/12/26 21:42
*/
@Order(1)
@Component
public class DemoFilter2 extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
System.out.println("DemoFilter2拦截");
filterChain.doFilter(request,response);
}
}
?第三种:定义一个配置类,使用FilterRegistrationBean 可定义拦截器顺序和拦截路径
定义三个过滤器:
package com.example.demo.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @author qujingye
* @Classname DemoFilter1
* @Description TODO
* @Date 2023/12/26 21:42
*/
public class DemoFilter1 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 {
System.out.println("DemoFilter1拦截");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
package com.example.demo.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @author qujingye
* @Classname DemoFilter2
* @Description TODO
* @Date 2023/12/26 21:42
*/
public class DemoFilter2 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 {
System.out.println("DemoFilter2拦截");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
package com.example.demo.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @author qujingye
* @Classname DemoFilter3
* @Description TODO
* @Date 2023/12/26 21:42
*/
public class DemoFilter3 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 {
System.out.println("DemoFilter3拦截");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
?过滤器配置类:
package com.example.demo.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author qujingye
* @Classname WebFilterConfig
* @Description TODO
* @Date 2023/12/26 22:06
*/
@Configuration
public class WebFilterConfig {
@Bean
public FilterRegistrationBean<DemoFilter1> DemoFilter1() {
FilterRegistrationBean<DemoFilter1> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter1());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(2);
return registrationBean;
}
@Bean
public FilterRegistrationBean<DemoFilter2> DemoFilter2() {
FilterRegistrationBean<DemoFilter2> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter2());
registrationBean.addUrlPatterns("/*"); // 设置过滤器的URL模式
registrationBean.setOrder(1);
return registrationBean;
}
@Bean
public FilterRegistrationBean<DemoFilter3> DemoFilter3() {
FilterRegistrationBean<DemoFilter3> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter3());
registrationBean.addUrlPatterns("/*"); // 设置过滤器的URL模式
registrationBean.setOrder(3);
return registrationBean;
}
}
?测试结果成功!!!
把第三个过滤器的拦截路径调整下,看配置拦截路径是否失效? 改成只拦截/aaa 的请求
@Bean
public FilterRegistrationBean<DemoFilter3> DemoFilter3() {
FilterRegistrationBean<DemoFilter3> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter3());
registrationBean.addUrlPatterns("/aaa"); // 设置过滤器的URL模式
registrationBean.setOrder(3);
return registrationBean;
}
?请求的的路径:
测试成功!!! 所以 FilterRegistrationBean 即可定义拦截顺序 也可以定义拦截路径
1.3?过滤器的拦截路径配置
1.4?过滤器的执行流程
1.5?过滤器遇到的坑
1、使用@WebFilter,启动类不加@ServletComponentScan,@WebFilter描述的过滤器将扫描不到,对应的过滤器也无法注入及生效
2、请不要在过滤器实现类上同时加@WebFilter和@Component并且还在启动类上加@ServletComponentScan,这会导致过滤器拦截两次!!!
二、拦截器(Interceptor)
2.1 基本概念
- 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行
- 作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。
2.2?定义拦截器
- 定义拦截器,实现Handlerlnterceptor接口,并重写其所有方法。
package com.example.demo.interceptor;
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;
/**
* @author qujingye
* @Classname demoInterceptor
* @Description TODO
* @Date 2023/12/26 22:44
*/
@Component
public class DemoInterceptor implements HandlerInterceptor {
//目标资源方法执行前执行,放回true: 放行,返回false: 不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("目标资源方法执行前执行 == preHandle");
return true;
}
//目标资源方法执行后执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("目标资源方法执行后执行 == postHandle");
}
//视图渲染完毕后执行,最后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("视图渲染完毕后执行最后执行 == afterCompletion");
}
}
2.3?注册拦截器
package com.example.demo.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author qujingye
* @Classname Webconfig
* @Description TODO
* @Date 2023/12/26 22:51
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private DemoInterceptor demoInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(demoInterceptor).addPathPatterns("/**");
}
}
2.4?拦截器的拦截路径配置
2.5?拦截器的执行流程
2.6 拦截器遇到的坑
我看到有部分文章在注册拦截器的时候是这样的
@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } }
这种new的方式注入,要注意MyInterceptor类里面,如果有用spring注入的属性将无法注入,属性将为null。
三、过滤器(Filter)和 拦截器(Interceptor)的区别
- 接口规范不同: 过滤器需要实现Fiter接口,而拦截器需要实现Handlerlnterceptor接口。
- 拦截范围不同:过滤器Filter会拦截所有的资源,而interceptor只会拦截Spring环境中的资源。
- 拦截顺序不同:先拦截的是过滤器Filter然后是拦截器interceptor。
📝结束语:
总结不易😄觉得有用的话,还请各位大佬动动发财的小手
给小瞿扣个三连:?? 点赞??收藏 ?? 关注
这个对我真的非常重要,拜托啦!
本人水平有限,如有纰漏,欢迎各位大佬评论指正!💞
?
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!