Spring Bootプロジェクトの実戦ブロックとフィルタ


一、ブロックとフィルタ
Spring bootを話す前に、フィルターとブロックについて調べてみます。この両者は機能的には似ていますが、具体的な技術の実現には大きな差があります。両者の違いを分析する前に、まずAOPの概念を理解します。AOPは具体的な技術ではなく、プログラミング思想です。オブジェクト指向プログラミングのプロセスでは、縦方向の拡張は継承、多状態によって容易に解決できます。しかし、横の機能については、例えば、すべてのサービス方法でビジネスを開始したり、ログを統一したりする機能では、対象に向けることはできません。だから、AOP――表面に向かってプログラミングするのは、実は対象に向かってプログラミングする思想の一つです。今日私達が話したフィルタとスクリーンはすべて面に向かってプログラミングする具体的な実現に属します。両者の主な違いは以下のいくつかの態様を含む。
1、FilterはServlet容器に依存しており、Servlet仕様の一部であり、ブロッキングは独立して存在し、どのような状況でも使用できる。
2、Filterの実行はServlet容器によってフィードバックされたが、ブロックは通常動的エージェントによって実行される。
3、FilterのライフサイクルはServlet容器で管理されていますが、ブロックはIoC容器で管理されていますので、注入などによって他のBenのインスタンスを取得することができますので、より便利です。
二、フィルタの配置
ここではフィルタを通して記録要求実行時間の機能を実現します。

public class LogCostFilter implements Filter {
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
 }
 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  long start = System.currentTimeMillis();
  filterChain.doFilter(servletRequest,servletResponse);
  System.out.println("Execute cost="+(System.currentTimeMillis()-start));
 }
 @Override
 public void destroy() {

 }
}

このコードの論理的な比較は簡単で、方法実行前にタイムスタンプを記録し、フィルタチェーンを介して要求の実行を完了し、結果を返す間に実行時間を計算することである。ここではメインが必要です。このクラスはFilterクラスを継承しなければなりません。これはServletの仕様です。これは以前のWebプロジェクトと変わりません。しかし、フィルタ類があったら、以前のウェブプロジェクトはweb.xmlに配置できますが、spring boot項目はweb.xmlというファイルがありません。どう配置しますか?Spring bootでは、FilterRegistration Beanが配置を完了するために必要です。その実現過程は以下の通りである。

@Configuration
public class FilterConfig {
 @Bean
 public FilterRegistrationBean registFilter() {
  FilterRegistrationBean registration = new FilterRegistrationBean();
  registration.setFilter(new LogCostFilter());
  registration.addUrlPatterns("/*");
  registration.setName("LogCostFilter");
  registration.setOrder(1);
  return registration;
 }
}
このように配置が完了しました。必要なオプションは主に実用化Filter類を含み、urlのマッチングモードを指定し、フィルタ名と実行順序を設定します。このプロセスはweb.xmlに配置されているものと大して違いがありません。形式が違っています。サーバーを起動して任意のURLにアクセスできます。
 
上の配置が有効になりました。FilterRegistration Beanを通して配置する以外に、より直接的な方法があります。

@WebFilter(urlPatterns = "/*", filterName = "logFilter2")
public class LogCostFilter2 implements Filter {
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
 }
 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  long start = System.currentTimeMillis();
  filterChain.doFilter(servletRequest, servletResponse);
  System.out.println("LogFilter2 Execute cost=" + (System.currentTimeMillis() - start));
 }
 @Override
 public void destroy() {

 }
}
ここで直接@WebFilterを使って配置することができます。同様に、urlマッチングモード、フィルタ名などを設定することができます。ここで注意したいのは、@WebFilterという注釈はServlet 3.0の仕様であり、Spring bootが提供したものではない。この注釈以外に、私達は構成類にもう一つの注釈を加えます。@ServletComponetScan、スキャンのカバンを指定します。

@SpringBootApplication
@MapperScan("com.pandy.blog.dao")
@ServletComponentScan("com.pandy.blog.filters")
public class Application {
 public static void main(String[] args) throws Exception {
  SpringApplication.run(Application.class, args);
 }
}
私達はまた任意のURLを訪問します。
 
私たちが配置した二つのフィルタが有効になりました。注意深い読者は、第二のFilterは実行の順序を指定していませんが、第一のFilterの前に実行します。ここで説明したいのですが、@WebFilterという注釈は実行順序の属性を指定していません。その実行順序はFilterの名前に依存しています。Filterクラス名(配置のfilterの名前ではないことに注意してください。)のアルファベット順に並べられ、@WebFilterで指定されたフィルタ優先度はFilterRegistration Bernよりも高いフィルタです。興味のある友達は自分で実験してもいいです。
三、スクリーンの配置
上でフィルタの配置方法を紹介しましたが、次にブロックの配置を見てみます。上のような機能を実現するためにスクリーンセーバを使って、要求の実行時間を記録します。まず、ブロック類を実現します。

public class LogCostInterceptor implements HandlerInterceptor {
 long start = System.currentTimeMillis();
 @Override
 public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
  start = System.currentTimeMillis();
  return true;
 }
 @Override
 public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
 }
 @Override
 public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
 }
}
ここでは、Handler Interceptorというインターフェースを実現したいです。このインターフェースは三つの方法を含んでいます。preHandleは実行前に実行してください。postHandlerは実行終了を要求しますが、preHandle方法がtrueに戻る時だけ実行します。afterCompletionはビューレンダリング完了後に実行します。preHandleがtrueに戻る必要です。この方法は通常、リソースなどの作業を整理するために用いられる。上記のインターフェースを実現する以外に、私達はそれを構成する必要があります。

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

 @Override
 public void addInterceptors(InterceptorRegistry registry) {
  registry.addInterceptor(new LogCostInterceptor()).addPathPatterns("/**");
  super.addInterceptors(registry);
 }
}
ここでWebMVCConfigrer Adapterを継承しました。前の記事を見た友達はもうこの種類を見たはずです。静的な資源カタログの配置をする時にこの種類を使ったことがあります。ここではaddInterceptorsという方法を書き直して、ブロックの構成を行います。主な構成項目は二つです。一つは指定ブロックで、二つ目は指定ブロックのURLです。今からシステムを起動して任意のURLにアクセスします。
 
私たちはスクリーンを通して同じ機能を実現していることが分かります。しかし、ここでもう一つ説明したいのは、実はこの実装に問題があります。preHandleとpostHandleは二つの方法なので、ここでは共有変数startを設定して開始値を記憶しなければなりませんが、スレッドの安全問題があります。もちろん、他の方法で解決できます。例えば、ThreadLocalを通じてこの問題をうまく解決できます。興味のある学生は自分で実現できます。しかし、この点によって、スクリーンはフィルタよりも多くのシーンで優れていますが、このようなシーンでは、フィルタはスクリーンよりも簡単に実現されます。
四、まとめ
本文は主にSpring bootに基づいてフィルタとスクリーンの構成を説明する。フィルタにしてもブロックにしても、AOP思想の具体的な実現に属します。これらの2つの実装に加えて、他のより柔軟なAOP実現技術、すなわちAsppectを見ました。Asppectを通じてより強力な機能を達成することができます。この続きを皆さんに分かち合います。