Springboot プロジェクトはフィルター機能を迅速に実装します

序文

多くの場合、真実を把握したと思っても、もう少し深く掘り下げることができれば、別の真実を発見できるかもしれません。たとえば、アスペクト指向プログラミングのベスト プログラミング プラクティスは AOP です. AOP の主な機能は、エントリ ポイントを定義し、追加の統一された操作をエントリ ポイントで垂直に織り込んで、ビジネス コードとの過度の結合を回避することです。Java Web プロジェクトに精通している人なら誰でも、AOP のような機能を持つフィルターやインターセプターも存在することを知っているので、疑問が生じます: なぜアスペクト指向プログラミングは一般的にフィルターやインターセプターではなく AOP を参照するのでしょうか? デバイス? フィルターとインターセプターは Spring ブートにどのように実装されていますか? これら3つの違いは何ですか?関連する AOP の実装は、Springboot プロジェクトの Aop 関数の迅速な実装で共有されます. 次に、2 つから 3 つの記事を使用して、フィルターとインターセプターの実装、および AOP、フィルター、インターセプター間の水平比較を共有します.、ビジネス開発において、具体的な実装方法を迅速かつ正確に選択できるようにします。

環境構成

jdk バージョン: 1.8

開発ツール: Intellij iDEA 2020.1

springboot:2.3.9.RELEASE

フィルターの概要

Filter、中国語はフィルターを意味し、Filter の完全修飾クラス名は javax.servlet.Filter であり、これはサーブレットに関連するインターフェースであることがわかります; SpringMVC のコアは DispatcherServlet であり、DispatcherServlet は Servlet を継承しているため、 Filter It は SpringMVC にも関連付けられていると推測されます。

実際、この憶測も正しい. SpringMVC プロジェクトでは、フィルターはブラウザーとサーバーの間のフィルターとして機能します. クライアントとサーバーの間の要求と応答の情報を傍受し、これらの要求に基づいて決定を下すことができます.応答情報. 他の操作もありますが、フィルターは要求応答情報を変更できないことに注意してください。

コアクラス

フィルター

Filter インターフェースの完全修飾クラス名は javax.servlet.Filter で、次の 3 つのメソッドがあります。

1. init(...): Filter の初期化に使用されます。

2. doFilter(...): リクエストのフィルタリングとレスポンス情報のインターセプトの特定の実装は、このメソッドにあります。

3. destroy(...): Filter オブジェクトが破棄されたときにトリガーされ、主にリソースの解放などの仕上げ作業を行うために使用されます。

FilterConfig

FilterConfig インターフェースの完全修飾クラス名は javax.servlet.FilterConfig です。これには、次の 4 つの主要なメソッドがあります。

1. getFilterName() フィルターの名前を取得します。

2. getServletContext() ServletContext オブジェクト (アプリケーション) を取得します。

3. getInitParameter() Filter の初期化パラメータを取得します。

4. getInitParameterNames() すべての初期化パラメータの名前を取得します。

フィルターチェーン

FilterChainr インターフェイスの完全修飾クラス名は、javax.servlet.FilterChain です。このインターフェイスには、フィルタ チェーンの次のフィルタを呼び出すために使用される doFilter() メソッドという 1 つのメソッドしかありません。現在のフィルタが最後または 1 つのフィルターのみ、フィルターはリクエストをターゲット リソースに送信します。

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、过滤器可以过滤请求和拦截响应,但是不能改变请求值和响应值;

おすすめ

転載: blog.csdn.net/fox9916/article/details/129672773