上周学习了springboot集成websocket就使用了过滤器 (Filter
),对指定的请求进行拦截设置响应头,所有借这个机会重新学习下总结拦截器和过滤器。
目录
一、过滤器(Filter)
1.1 基本概念
1.2 定义过滤器
1.3 过滤器的拦截路径配置
1.4 过滤器的执行流程
1.5 过滤器遇到的坑
二、拦截器(Interceptor)
2.1 基本概念
2.2 定义拦截器
2.3 注册拦截器
2.4 拦截器的拦截路径配置
2.5 拦截器的执行流程
2.6 拦截器遇到的坑
三、过滤器(Filter)和 拦截器(Interceptor)的区别
文章语:
第一种:@WebFilter+@ServletComponentScan(可以自定义拦截路径,无法控制多个过滤器顺序)
测试接口:
// 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() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter1());
registrationBean.addUrlPatterns("/*");
registrationBean.setOrder(2);
return registrationBean;
}
@Bean
public FilterRegistrationBean DemoFilter2() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter2());
registrationBean.addUrlPatterns("/*"); // 设置过滤器的URL模式
registrationBean.setOrder(1);
return registrationBean;
}
@Bean
public FilterRegistrationBean DemoFilter3() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter3());
registrationBean.addUrlPatterns("/*"); // 设置过滤器的URL模式
registrationBean.setOrder(3);
return registrationBean;
}
}
测试结果成功!!!
把第三个过滤器的拦截路径调整下,看配置拦截路径是否失效 改成只拦截/aaa 的请求
@Bean
public FilterRegistrationBean DemoFilter3() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new DemoFilter3());
registrationBean.addUrlPatterns("/aaa"); // 设置过滤器的URL模式
registrationBean.setOrder(3);
return registrationBean;
}
请求的的路径:
测试成功!!! 所以 FilterRegistrationBean 即可定义拦截顺序 也可以定义拦截路径
1、使用@WebFilter,启动类不加@ServletComponentScan,@WebFilter描述的过滤器将扫描不到,对应的过滤器也无法注入及生效
2、请不要在过滤器实现类上同时加@WebFilter和@Component并且还在启动类上加@ServletComponentScan,这会导致过滤器拦截两次!!!
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");
}
}
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("/**");
}
}
我看到有部分文章在注册拦截器的时候是这样的
@Configuration public class MyMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } }
这种new的方式注入,要注意MyInterceptor类里面,如果有用spring注入的属性将无法注入,属性将为null。
总结不易觉得有用的话,还请各位大佬动动发财的小手
给小瞿扣个三连:⛳️ 点赞⭐️收藏 ❤️ 关注
这个对我真的非常重要,拜托啦!
本人水平有限,如有纰漏,欢迎各位大佬评论指正!