springboot项目快速实现过滤器功能

凡夫贩夫 凡夫贩夫     2023-03-31     615

关键词:

前言

很多时候,当你以为掌握了事实真相的时间,如果你能再深入一点,你可能会发现另外一些真相。比如面向切面编程的最佳编程实践是AOP,AOP的主要作用就是可以定义切入点,并在切入点纵向织入一些额外的统一操作,避免与业务代码过度耦合。熟悉java web项目的都知道,另外还有过滤器(filter)、拦截器(interceptor)也有类似AOP的功能特性,那么问题来了:为什么一般说面向切面编程就是指AOP,而不是过滤器和拦截器?过滤器和拦截器在Spring boot中怎么实现?这三者之间有什么区别?Springboot项目快速实现Aop功能中分享了AOP的相关实现,下面将再用两到三篇文章,分别和大家分享一下过滤器、拦截器的实现,以及AOP、过滤器、拦截器之间的横向对比,以便在业务开发中,能够快速、正确选对具体实现方法。

环境配置

jdk版本:1.8

开发工具:Intellij iDEA 2020.1

springboot:2.3.9.RELEASE

Filter简介

Filter, 中文意思是过滤器,Filter的全限定类名是javax.servlet.Filter,可以看出这是与servelt相关的一个接口;SpringMVC核心是DispatcherServlet,而DispatcherServlet又继承了Servlet,进而可以推测出Filter与SpringMVC也是关联关系。

事实上这样的推测也是正确的,在SpringMVC项目中,filter在浏览器与服务器之间起过滤的作用,可以截取客户端和服务端之间的请求和响应信息,并根据这些请求-响应信息作一些其他的操作,但是要注意,filter并不能改变请求-响应信息;

核心类

Filter

Filter接口的全限定类名是javax.servlet.Filter,该接口有三个方法,分别是

1、init(...):用于初始化Filter;

2、doFilter(...):过滤请求和拦截响应信息的具体实现在这个方法里;

3、destroy(...):Filter对象被销毁时触发,主要用于做一些收尾工作,如资源的释放等;

FilterConfig

FilterConfig接口的全限定类名是javax.servlet.FilterConfig,该接口主要有四个方法,分别是:

1、getFilterName() 获取Filter的名字;

2、getServletContext() 获取ServletContext对象(即application);

3、getInitParameter() 获取Filter的初始化参数;

4、getInitParameterNames() 获取所有初始化参数的名字;

FilterChain

FilterChainr接口的全限定类名是javax.servlet.FilterChain,该接口只有一个方法,是doFilter()方法,用于调用Filter链上的下一个过滤器,如果当前过滤器为最后一个或只有一个过滤器,则该过滤器则将请求发送到目标资源。

MyFilter2是自己实现的过滤器,实现了Filter接口;Filter接口依赖FilterChain接口和FilterConfig接口,其中FilterChain接口的实现类是org.apache.catalina.core.ApplicationFilterChain,FilterConfig接口的实现类是org.apache.catalina.core.ApplicationFilterConfig;

工作原理

1、项目启动的时候,先执行Filter的构造方法,完成相关Filter对象的注册;

2、紧接着,Filter对象的init()方法被调用,开始对Filter做一些初始化操作;

3、项目启动完成后,客户端每次向服务端发起请求时,如果请求地址与过滤器定义的地址匹配,则会执行Filter的doFilter();如果匹配上多个过滤器,则会形成一个链路,依次调用各个过滤器对象的doFilter();服务端作出响应后,也会再次执行到各个过滤器对象的doFilter();请求和响应时,过滤器链的执行顺序是先进后出;

4、服务器停止时调用Filter的destroy()方法,用来释放资源。

实现方式

Springboot项目中一般有两种方式:

1、@WebFilter注解,即javax.servlet.annotation.WebFilter;

2、FilterRegistrationBean,即org.springframework.boot.web.servlet.FilterRegistrationBean;

两种方式,都需要在启动类上增加注解@ServletComponentScan,用于开启servlet相关bean的扫描,其中包含有过滤器(Filter);

@SpringBootApplication
@ServletComponentScan
public class FanfuApplication 
    public static void main(String[] args) 
        SpringApplication.run(FanfuApplication.class, args);
    

代码实现

1、WebFilter注解里,定义一下过滤器的名字,以及要对哪些请求进行过滤,“/*”表示对所有的请求都过滤,在实际业务中,可具体对待;如果在初始化的时候,需要携带一些初始化的参数,可以在initParams属性上,使用@WebInitParam注解来定义初始化参数名称和具体的值,这些参数可以在filter对象初始化的时候获取到;MyFIlter1和MyFIlter2使用的注解方式定义的过滤器;

@Slf4j
@WebFilter(filterName = "myFilter1", urlPatterns = "/*", initParams = @WebInitParam(name = "creator", value = "fanfu"))
public class MyFilter1 implements Filter 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        log.info("//myFilter1初始化开始");
        String creator = filterConfig.getInitParameter("creator");
        log.info("//初始化参数creator:",creator);
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        log.info("//myFilter1开始执行");
        chain.doFilter(request, response);
        log.info("//myFilter1结束执行");
    

    @Override
    public void destroy() 
        log.info("//myfilter1被销毁");
    
@Slf4j
@WebFilter(filterName = "myFilter2", urlPatterns = "/*")
public class MyFilter2 implements Filter 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        log.info("//myFilter2初始化开始");
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        log.info("//myFilter2开始执行");
        chain.doFilter(request, response);
        log.info("//myFilter2结束执行");
    

    @Override
    public void destroy() 
        log.info("//myFilter2被销毁");
    

2、FilterRegistrationBean方式

在Springboot项目的配置类中,使用FilterRegistrationBean来包装自定义的过滤器,这种方式的最大好处就是可以自定义过滤器的执行顺序,数字越小,执行时的优先级就越高;MyFIlter3和MyFIlter4是使用FilterRegistrationBean方式定义的过滤器;

@Configuration
public class WebConfig 

    @Bean
    public FilterRegistrationBean filterRegistration1() 
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MyFilter3());
        filterRegistrationBean.addUrlPatterns("/*");//定义过滤器对哪些请求路径进行过滤,/*表示对所有请求都过滤
        filterRegistrationBean.setOrder(2);//定义过滤器的执行优先级,数据越小优先级越高
        return filterRegistrationBean;
    

    @Bean
    public FilterRegistrationBean filterRegistration2() 
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MyFilter4());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    
@Slf4j
public class MyFilter3 implements Filter 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
    log.info("//MyFilter3初始化开始");
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        log.info("//MyFilter3开始执行");
        chain.doFilter(request,response);
        log.info("//MyFilter3结束执行");
    

    @Override
    public void destroy() 
        log.info("//MyFilter3被销毁");
    
@Slf4j
public class MyFilter4 implements Filter 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        log.info("//MyFilter4初始化开始");
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
        log.info("//MyFilter4开始执行");
        chain.doFilter(request,response);
        log.info("//MyFilter4结束执行");
    

    @Override
    public void destroy() 
        log.info("//MyFilter4被销毁");
    

未定义myFilter3、myFilter4的执行优先级,即采取自然排序时的执行结果:在请求前myFilter3的执行时机早于myFilter4,响应后myFilter3的执行时机要晚于myFilter4;

定义myFilter4的优先级高于myFilter3时,执行结果:在请求前myFilter4的执行时机早于myFilter3,响应后的myFilter4的执行时机要晚于myFilter3;

总结

过滤器的实现是比较简单,通过梳理这个过程,我get到以下几个点:

1、过滤器是用于SpringMVC项目中,即与servlet相关的项目;

2、过滤器的执行时机是在请求前和响应后,有两种实现方式,即@WebFilter注解和FilterRegistrationBean;如果对过滤器的执行顺序没有限制要求,则可以使用第一种;如果对过滤器的执行顺序有明确限制,则可以使用第二种;

3、如果有多个过滤器对象时,会形成一个过滤器链,过滤器的执行顺序是先进后出;

4、过滤器可以过滤请求和拦截响应,但是不能改变请求值和响应值;

手写springboot项目xss攻击过滤器实现

一、先来个简介什么是XSS?百度百科的解释: XSS又叫CSS (CrossSiteScript),跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊... 查看详情

docker实现springboot项目的快速构建

...Docker2.2.Docker的使用2.2.1.Docker常用命令2.2.2搞个容器玩玩3.SpringBoot项目制作镜像3.1.创建Springboot项目3.1.1.liquibase解释3.2.制作Doc 查看详情

docker实现springboot项目的快速构建(代码片段)

...Docker2.2.Docker的使用2.2.1.Docker常用命令2.2.2搞个容器玩玩3.SpringBoot项目制作镜像3.1.创建Springboot项目3.1.1.liquibase解释3.2.制作Doc 查看详情

springboot系列:4.session和鉴权—过滤器和拦截器

参考技术A本文主要介绍下,SpringBoot的web项目中,使用redis保存并共享session,可以实现集群内的登录信息共享。SpringBoot项目中,通过在application.yml增加redis的配置,即可实现对session的存储和修改。那么session是在何时被处理的?se... 查看详情

springboot快速整合springsecurity,新手都会的详细步骤(代码片段)

一、什么是SpringSecurity?SpringSecurity是一个基于Spring框架的安全性框架,提供了一组轻量级的API和工具,用于实现身份验证、授权、防止攻击等常见的安全性功能。它支持各种身份验证方式,例如基本身份验证、表... 查看详情

开发指南专题七jeecg微云快速开发平台查询hql过滤器

开发指南专题七:JEECG微云快速开发平台HQL过滤器 1. 查询HQL过滤器 1.1. 数据过滤现状分析项目开发的查询页面都会有很多查询条件,开发追加查询条件的工作繁琐又很浪费时间。这块工作量主要在:页面加查询字段... 查看详情

springboot快速入门(代码片段)

2、SpringBoot原理分析2.1、SpringBoot自动配置ConditionCondition是在Spring4.0增加的条件判断功能,通过这个可以功能可以实现选择性的创建Bean操作自定义条件:定义条件类:自定义类实现Condition接口,重写matches方法,在matches方法中进行... 查看详情

springboot.11.idea中如何快速复制当前父项目中的一个module为新的项目

SpringBoot.11.IDEA中如何快速复制当前父项目中的一个Module为新的项目实现步骤1.复制项目2.引入项目3.配置项目4.测试IDEA中如何快速复制当前父项目中的一个Module为新的项目呢?这个做法其实跟我们之前的文章Springboot.10.IDEA中如... 查看详情

有了springboot,为什么还要懂springmvc?

01什么是SpringBoot?首先,SpringBoot是现在比较流行的框架,可以实现快速开发,包括我自己也在用它开发项目。其优点是简化了Spring相关组件的配置,实现自动配置,降低了项目搭建的复杂度,使开发变得更加简便,从而提升开... 查看详情

springboot实战项目--用户批量删除功能实现

页面构建--批量删除功能事件实现1<!DOCTYPEhtml>2<htmlclass="x-admin-sm"xmlns:th="http://www.thymeleaf.org">3<head>4<metacharset="UTF-8">5<title>欢迎页面-X-admin2.2</title>6<headerth 查看详情

springboot如何快速改造老项目?

...候,受限于spring低版本的限制,故索性将整个模块升级为springboot,在这里做个记录,希望能帮助到有相同场景的朋友。整个改造过程非常简单,耗时大概在2个小时左右,主要解决项目中的各种版本冲突,不过下面我会介绍一个... 查看详情

springboot.11.idea中如何快速复制当前父项目中的一个module为新的项目(代码片段)

SpringBoot.11.IDEA中如何快速复制当前父项目中的一个Module为新的项目实现步骤1.复制项目2.引入项目3.配置项目4.测试IDEA中如何快速复制当前父项目中的一个Module为新的项目呢?这个做法其实跟我们之前的文章Springboot.10.IDEA中如... 查看详情

全网最细致springboot整合springsecurity+jwt实现用户认证(代码片段)

【全网最细致】SpringBoot整合SpringSecurity+JWT实现用户认证  登录和用户认证是一个网站最基本的功能,在这篇博客里,将介绍如何用SpringBoot整合SpringSecurity+JWT实现登录及用户认证文章目录【全网最细致】SpringBoot整... 查看详情

企业快速开发平台springcloud+springboot+mybatis创业必备企业架构,可开发任意项目

 鸿鹄云架构【系统管理平台】严格遵循Web安全规范,使用前后端双重验证,统一用户认证及密码安全策略,标准功能权限、数据权限过滤。使用防SQL脚本注入、跨站点脚本编制(XSS)、伪造请求(CSRF࿰... 查看详情

企业快速开发平台springcloud+springboot+mybatis创业必备企业架构,可开发任意项目

 鸿鹄云架构【系统管理平台】严格遵循Web安全规范,使用前后端双重验证,统一用户认证及密码安全策略,标准功能权限、数据权限过滤。使用防SQL脚本注入、跨站点脚本编制(XSS)、伪造请求(CSRF࿰... 查看详情

影院在线售票云平台(仿猫眼电影,附springboot项目源码)系统功能实现

...排名,财务报表,权限控制及系统日志等功能,系统采用SpringBoot,mybatis,easyui,ajax,mssql数据库等技术开发。提供项目源代码下载,系统功能完善,可直接运行。项目开发语言:Sprin 查看详情

企业快速开发平台springcloud+springboot+mybatis创业必备企业架构,可开发任意项目

鸿鹄云架构【系统管理平台】严格遵循Web安全规范,使用前后端双重验证,统一用户认证及密码安全策略,标准功能权限、数据权限过滤。使用防SQL脚本注入、跨站点脚本编制(XSS)、伪造请求(CSRF)... 查看详情

springboot快速上手——《一》:初始springboot,实现入门级程序

初识SpringBoot,实现入门级程序开发工具说明:idea可能有的同学很少使用idea,所以前两篇会比较多idea的截图操作!github源码:https://github.com/xivinChen/SpringBoot1.搭建父工程选中maven,下一步填写组织信息,下一步知道finish。选择打开... 查看详情