上周学习了springboot集成websocket就使用了过滤器 (Filter
),对指定的请求进行拦截设置响应头,所有借这个机会重新学习下总结拦截器和过滤器。
目录
三、过滤器(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> 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、使用@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。
总结不易😄觉得有用的话,还请各位大佬动动发财的小手
给小瞿扣个三连:?? 点赞??收藏 ?? 关注
这个对我真的非常重要,拜托啦!
本人水平有限,如有纰漏,欢迎各位大佬评论指正!💞
?