当前位置: 首页 > 科技观察

SpringBoot使用Filter的正确姿势!

时间:2023-03-13 02:09:10 科技观察

Filter是JavaEE中Servlet规范的一个组件,位于包javax.servlet中,在HTTP请求到达Servlet之前,它可以被一个或多个Filter处理。其工作流程如图:Filter的这个特性在生产环境中有着广泛的应用,比如:修改请求和响应,防止xss攻击,打包二进制流使其可以被多次读取等等.在实际工作中,我们都是使用SpringBoot进行业务开发。本文总结了三种Filter用法。SpringBoot版本采用最新的v2.3.1.RELEASE1。编写Filter只需要实现javax.servlet.Filter接口即可。.publicclassMyFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{System.out.println("MyFilter");//要继续处理请求,必须添加filterChain,doservinletReponseFilter()filter}Filter接口有3个方法:init()、doFilter()、destroy()。其中doFilter()需要自己实现,另外两个是默认的,不需要自己实现。SpringBoot的基础就不介绍了,推荐这个实用教程:https://github.com/javastacks/spring-boot-best-practice注意:如果Filter想要继续处理请求,必须调用filterChain.doFilter()!2.配置Filter由Spring管理,让自定义的Filter由Spring的IOC容器管理。共有三种实现方法,各有优缺点。下面类代表为大家总结一下:(1)使用@Component+@Order为刚刚定义的MyFilter类添加@Component和@Order注解,可以通过Spring管理@Component@Order(1)publicclassMyFilterimplementsFilter{@OverridepublicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{System.out.println("MyFilter");//要继续处理请求,必须添加filterChain.doFilter()filterChain.doFilter(servletRequest,servletResponse);}}是的,就这么简单,让MyFilter生效,写个Controller调用看看效果。当有多个Filter时,这里的@Order(1)注解会指定执行顺序。数字越小,执行优先级越高。如果只写@Order,默认的订单值为Integer.MAX_VALUE。@Component+@Order注解方式配置方便,支持自定义Filter顺序。缺点是只能拦截所有的url,不能通过配置拦截指定的url。(2)@WebFilter+@ServletComponentScan在MyFilter中添加@WebFilter注解,在启动类中添加@ServletComponentScan("com.zhengxl.filterdemo.filter")注解。参数是Filter所在的包路径,相当于告诉SpringBoot去哪里扫描.out.println(必须添加"My/Filter"才能继续处理)doFilter()filterChain.doFilter(servletRequest,servletResponse);}}@SpringBootApplication@ServletComponentScan("com.zhengxl.filterdemo.filter")publicclassFilterDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(FilterDemoApplication.class,args)}}@WebFilter+@ServletComponentScan注解支持为Filter匹配指定的URL,不支持指定Filter的执行顺序。(3)JavaConfig配置方法@ConfigurationpublicclassFilterConfig{@BeanpublicFilterRegistrationBeanregisterMyFilter(){FilterRegistrationBeanbean=newFilterRegistrationBean<>();bean.setOrder(1);bean.setFilter(newMyFilter());//匹配"/hello/"以下所有urlbean.addUrlPatterns("/hello/*");returnbean;}@BeanpublicFilterRegistrationBeanregisterMyAnotherFilter(){FilterRegistrationBeanbean=newFilterRegistrationBean<>();bean.setOrder(2);bean.setFilter(newMyAnotherFilter());//匹配所有urlbean.addUrlPatterns("/*");returnbean;}}通过Java代码显式配置Filter,功能强大,灵活。你只需要将每一个自定义的Filter声明为一个bean,交给Spring管理即可。您还可以设置匹配的URL并指定Filter的顺序。3、三种方法的比较SpringBoot中三种Filter的使用姿势非常简单。总结如下表:使用方法排序指定URL@Component@Order10@WebFilter@ServletComponentScan01JavaConfig11实际使用过程中,可以根据业务需要选择合适的使用方法。比如你写一个过滤器拦截所有没有指定URL的请求,那么选择最简单的@Component+@Order是非常合适的。PS:其实还有第四种,web.xml配置,不过这都2020年了,用SpringBoot的自动组装或者JavaConfig不是更方便吗?