1.概要

この記事では、新しい


@ServletComponentScan


アノテーションについて説明します。

Spring Boot.

目的は、以下の

Servlet 3.0

アノテーションをサポートすることです。


  • javax.servlet.annotation.WebFilter


  • javax.servlet.annotation.WebListener


  • javax.servlet.annotation.WebServlet


@ WebServlet



@ WebFilter

、および

@ WebListener

のアノテーション付きクラスは、

@ Configuration

クラスに

@ ServletComponentScan

をアノテーションしてパッケージを指定することで、自動的に埋め込み

Servlet

コンテナに登録できます。

リンク内の

@ WebServlet

の基本的な使用法を紹介しました。/intro-to-servlets[Javaサーブレットの紹介]およびリンク内の

@ WebFilter

の基本的な使い方:/intercepting-filter-pattern-in-java]。

@ WebListener

については、リンク:/httpsessionlistener

with

metrics[この記事]でのぞき見をすることができます。これは、Webリスナーの典型的な使用例を示しています。

2.

Servlets



Filters

、および

Listeners


@ ServletComponentScan

に飛び込む前に、

@ ServletComponentScan

が登場する前に、アノテーション

@ WebServlet



@ WebFilter

、および

@ WebListener

がどのように使用されていたかを見てみましょう。

2.1.

@ WebServlet

それでは、最初に

GET

要求を処理して応答する

Servlet

を定義します。

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        try {
            response
              .getOutputStream()
              .write("hello");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

2.2.

@ WebFilter

次に、ターゲット「

“/hello”

への要求をフィルター処理し、出力の先頭に

“filtering”

を付加します。

@WebFilter("/hello")
public class HelloFilter implements Filter {

   //...
    @Override
    public void doFilter(
      ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
      throws IOException, ServletException {
        servletResponse
          .getOutputStream()
          .print("filtering ");
        filterChain.doFilter(servletRequest, servletResponse);
    }
   //...

}

2.3.

@ WebListener

最後に、

ServletContext

にカスタム属性を設定するリスナーです。

@WebListener
public class AttrListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        servletContextEvent
          .getServletContext()
          .setAttribute("servlet-context-attr", "test");
    }
   //...
}

2.4.

Servlet

コンテナにデプロイする

単純なWebアプリケーションの基本コンポーネントを構築したので、それをパッケージ化して

Servlet

コンテナにデプロイします。パッケージ化されたwarファイルを


Jetty





Tomcat


、または

Servlet

3.0をサポートする任意の

Servlet

コンテナに展開することで、各コンポーネントの動作を簡単に検証できます。

3.

Spring Boot



@ ServletComponentScan

を使う

私たちは何の設定もせずにほとんどの

Servlet

コンテナでそれらのアノテーションを使うことができるのであなたは不思議に思うかもしれません、なぜ我々は

@ ServletComponentScan

を必要としますか?問題は組み込みの

Servlet

コンテナにあります。

組み込みコンテナは

@ WebServlet



@ WebFilter

、および

@ WebListener

アノテーション、

Spring Boot、

組み込みコンテナに大きく依存していないため、これらの3つのアノテーションを使用するいくつかの依存jarをサポートするためにこの新しいアノテーションを導入しました。

詳細な議論はhttps://github.com/spring-projects/spring-boot/issues/2290[このGithubに関する問題]にあります。

3.1. Mavenの依存関係


@ ServletComponentScan

を使用するには、バージョン1.3.0以降の

Spring Boot

が必要です。


spring-boot-starter-parent

の最新バージョンを追加しましょう。

およびhttps://search.maven.org/classic/#artifactdetails%7Corg.springframework.boot%7Cspring-boot-starter-web%7C1.5.1.RELEASE%7Cjar[

spring-boot-starter-web

]を

pom

に:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>1.5.1.RELEASE</version>
    </dependency>
</dependencies>

3.2.

@ ServletComponentScan

を使用する


Spring Boot

アプリはとてもシンプルです。

@ WebFilter



@ WebListener

、および

@ WebServletのスキャンを有効にするために

@ ServletComponentScan__を追加します。

@ServletComponentScan
@SpringBootApplication
public class SpringBootAnnotatedApp {

    public static void main(String[]args) {
        SpringApplication.run(SpringBootAnnotatedApp.class, args);
    }

}

以前のWebアプリケーションを変更しなくても動作します。

@Autowired private TestRestTemplate restTemplate;

@Test
public void givenServletFilter__whenGetHello__thenRequestFiltered() {

    ResponseEntity<String> responseEntity =
      restTemplate.getForEntity("/hello", String.class);

    assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
    assertEquals("filtering hello", responseEntity.getBody());
}

@Autowired private ServletContext servletContext;

@Test
public void givenServletContext__whenAccessAttrs__thenFoundAttrsPutInServletListner() {

    assertNotNull(servletContext);
    assertNotNull(servletContext.getAttribute("servlet-context-attr"));
    assertEquals("test", servletContext.getAttribute("servlet-context-attr"));
}

3.3. スキャンするパッケージを指定する

デフォルトでは、

@ ServletComponentScan

はアノテーション付きクラスのパッケージからスキャンします。どのパッケージをスキャンするかを指定するために、その属性を使用できます。




  • basePackages


  • basePackageClasses

デフォルトの

value

属性は、

basePackages

のエイリアスです。


SpringBootAnnotatedApp



com.baeldung.annotation

パッケージの下にあり、上記のWebアプリケーションで作成された

com.baeldung.annotation.components

パッケージ内のクラスをスキャンするとします。次の構成は同じです。

@ServletComponentScan

@ServletComponentScan("com.baeldung.annotation.components")

@ServletComponentScan(basePackages = "com.baeldung.annotation.components")

@ServletComponentScan(
  basePackageClasses =
    {AttrListener.class, HelloFilter.class, HelloServlet.class})

4.フードの下


@ ServletComponentScan

アノテーションはhttps://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/によって処理されます。 web/servlet/ServletComponentRegisteringPostProcessor.java[

ServletComponentRegisteringPostProcessor

]。


@ WebFilter



@ WebListener

、および

@ WebServlet

アノテーションの指定されたパッケージをスキャンした後、https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-bootのリスト/src/main/java/org/springframework/boot/web/servlet/ServletComponentHandler.java[

ServletComponentHandlers

]はそれらの注釈属性を処理し、スキャンされたBeanを登録します。

class ServletComponentRegisteringPostProcessor
  implements BeanFactoryPostProcessor, ApplicationContextAware {

    private static final List<ServletComponentHandler> HANDLERS;

    static {
        List<ServletComponentHandler> handlers = new ArrayList<>();
        handlers.add(new WebServletHandler());
        handlers.add(new WebFilterHandler());
        handlers.add(new WebListenerHandler());
        HANDLERS = Collections.unmodifiableList(handlers);
    }

   //...

    private void scanPackage(
      ClassPathScanningCandidateComponentProvider componentProvider,
      String packageToScan){
       //...
        for (ServletComponentHandler handler : HANDLERS) {
            handler.handle(((ScannedGenericBeanDefinition) candidate),
              (BeanDefinitionRegistry) this.applicationContext);
        }
    }
}


official Javadoc

で述べられているように、**

@ ServletComponentScan

注釈はデフォルトでは

Spring Boot

に付属しているものです。

5.まとめ

この記事では、

@ ServletComponentScan

と、それがどのアノテーションに依存するアプリケーションをサポートするためにどのように使用できるかを紹介しました。


@ WebServlet



@ WebFilter



@ WebListener

例とコードの実装はhttps://github.com/eugenp/tutorials/tree/master/spring-boot/[GitHubプロジェクト]にあります。