1. 概要

この記事では、Springフレームワークで利用可能なさまざまなハンドラーアダプターの実装に焦点を当てます。

2. ハンドルラダプターとは何ですか?

HandlerAdapter は基本的に、SpringMVCで非常に柔軟な方法でHTTPリクエストの処理を容易にするインターフェイスです。

これは、メソッドを特定のURLにマップするHandlerMappingと組み合わせて使用されます。

次に、 DispatcherServlet は、HandlerAdapterを使用してこのメソッドを呼び出します。 サーブレットはメソッドを直接呼び出すことはありません。基本的に、サーブレットはそれ自体とハンドラオブジェクトの間のブリッジとして機能し、疎結合の設計につながります。

このインターフェースで利用可能なさまざまなメソッドを見てみましょう。

public interface HandlerAdapter {
    boolean supports(Object handler);
    
    ModelAndView handle(
      HttpServletRequest request,
      HttpServletResponse response, 
      Object handler) throws Exception;
    
    long getLastModified(HttpServletRequest request, Object handler);
}

supports APIは、特定のハンドラーインスタンスがサポートされているかどうかを確認するために使用されます。 ハンドラインスタンスがサポートされているかどうかを確認するために、このインターフェイスの handle()メソッドを呼び出す前に、このメソッドを最初に呼び出す必要があります。

handle APIは、特定のHTTPリクエストを処理するために使用されます。 このメソッドは、HttpServletRequestおよびHttpServletResponseオブジェクトをパラメーターとして渡すことによってハンドラーを呼び出す役割を果たします。 次に、ハンドラーはアプリケーションロジックを実行し、 ModelAndView オブジェクトを返します。このオブジェクトは、DispatcherServletによって処理されます。

3. Mavenの依存関係

pom.xmlに追加する必要のあるMaven依存関係から始めましょう。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

spring-webmvc アーティファクトの最新バージョンは、ここにあります。

4. HandlerAdapterの種類

4.1. SimpleControllerHandlerAdapter

これは、SpringMVCによって登録されたデフォルトのハンドラーアダプターです。 Controller インターフェイスを実装するクラスを処理し、要求をコントローラーオブジェクトに転送するために使用されます。

Webアプリケーションがコントローラーのみを使用する場合、フレームワークはこのクラスを要求を処理するためのデフォルトアダプターとして使用するため、HandlerAdapterを構成する必要はありません。

古いスタイルのコントローラー( Controller インターフェイスの実装)を使用して、単純なコントローラークラスを定義しましょう。

public class SimpleController implements Controller {
    @Override
    public ModelAndView handleRequest(
      HttpServletRequest request, 
      HttpServletResponse response) throws Exception {
        
        ModelAndView model = new ModelAndView("Greeting");
        model.addObject("message", "Dinesh Madhwal");
        return model;
    }
}

同様のXML構成:

<beans ...>
    <bean name="/greeting.html"
      class="com.baeldung.spring.controller.SimpleControllerHandlerAdapterExample"/>
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

BeanNameUrlHandlerMapping クラスは、このハンドラーアダプターのマッピングクラスです。

:カスタムハンドラーアダプターが BeanFactoryで定義されている場合、このアダプターは自動的に登録されません。 したがって、コンテキストで明示的に定義する必要があります。 定義されておらず、カスタムハンドラーアダプターを定義している場合、ハンドラーのアダプターが指定されていないことを示す例外が発生します。

4.2. SimpleServletHandlerAdapter

このハンドラアダプタを使用すると、サーブレットを使用してディスパッチサーブレットと連携して要求を処理できます。 [X11X] service() method を呼び出すことにより、DispatcherServletから適切なServletクラスにリクエストを転送します。

サーブレットインターフェースを実装するBeanは、このアダプターによって自動的に処理されます。 デフォルトでは登録されていないため、他の通常のBeanと同様に、DispatcherServletの構成ファイルに登録する必要があります。

<bean name="simpleServletHandlerAdapter" 
  class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter" />

4.3. AnnotationMethodHandlerAdapter

このアダプタクラスは、@RequestMappingアノテーションが付けられたメソッドを実行するために使用されます。 これは、HTTPメソッドとHTTPパスに基づいてメソッドをマップするために使用されます。

このアダプタのマッピングクラスはDefaultAnnotationHandlerMapping、はタイプレベルで @RequestMapping アノテーションを処理するために使用され、AnnotationMethodHandlerAdaptorはメソッドレベルで処理するために使用されます。

これらの2つのクラスは、 DispatcherServlet が初期化されるときに、フレームワークによってすでに登録されています。 ただし、他のハンドラーアダプターがすでに定義されている場合は、構成ファイルでもそれを定義する必要があります。

コントローラクラスを定義しましょう:

@Controller
public class AnnotationHandler {
    @RequestMapping("/annotedName")
    public ModelAndView getEmployeeName() {
        ModelAndView model = new ModelAndView("Greeting");        
        model.addObject("message", "Dinesh");       
        return model;  
    }  
}

@Controller アノテーションは、このクラスがcontrollerの役割を果たしていることを示しています。

@RequestMapping アノテーションは、 getEmployeeName()メソッドをURL /name。にマップします。

アプリケーションがJavaベースの構成を使用するかXMLベースの構成を使用するかに応じて、このアダプターを構成する2つの異なる方法があります。 Java構成を使用する最初の方法を見てみましょう。

@ComponentScan("com.baeldung.spring.controller")
@Configuration
@EnableWebMvc
public class ApplicationConfiguration implements WebMvcConfigurer {
    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

アプリケーションがXML構成を使用する場合、WebアプリケーションコンテキストXMLでこのハンドラーアダプターを構成するための2つの異なるアプローチがあります。 ファイルspring-servlet_AnnotationMethodHandlerAdapter.xmlで定義されている最初のアプローチを見てみましょう。

<beans ...>
    <context:component-scan base-package="com.baeldung.spring.controller" />
    <bean 
      class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean 
      class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

The タグは、スキャンするパッケージを指定するために使用されますコントローラクラス。

2番目のアプローチを見てみましょう。

<beans ...>
    <mvc:annotation-driven/>
    <context:component-scan base-package="com.baeldung.spring.controller" />
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

The tagは、これら2つのクラスをSpringMVCに自動的に登録します。 このアダプターはSpring3.2で非推奨になり、RequestMappingHandlerAdapterと呼ばれる新しいハンドラーアダプターがSpring3.1で導入されました。

4.4. RequestMappingHandlerAdapter

このアダプタクラスはSpring3.1で導入され、Spring3.2のAnnotationMethodHandlerAdaptorハンドラアダプタは廃止されました。

RequestMappingHandlerMapping クラスで使用され、は@RequestMappingでアノテーションが付けられたメソッドを実行します。

RequestMappingHandlerMapping は、リクエストURIのハンドラーへのマッピングを維持するために使用されます。 ハンドラーが取得されると、 DispatcherServlet が要求を適切なハンドラー・アダプターにディスパッチし、適切なハンドラー・アダプターが handlerMethod()。を呼び出します。

タイプレベルとメソッドレベルのマッピングは、3.1より前のSpringバージョンでは2つの異なる段階で処理されていました。

最初の段階はDefaultAnnotationHandlerMappingによってコントローラーを選択することであり、2番目の段階はAnnotationMethodHandlerAdapterによって実際のメソッドを呼び出すことでした。

Springバージョン3.1以降、ステージは1つだけです。これには、コントローラーの識別と、要求を処理するために呼び出す必要のあるメソッドの識別が含まれます。

簡単なコントローラークラスを定義しましょう。

@Controller
public class RequestMappingHandler {
    
    @RequestMapping("/requestName")
    public ModelAndView getEmployeeName() {
        ModelAndView model = new ModelAndView("Greeting");        
        model.addObject("message", "Madhwal");        
        return model;  
    }  
}

アプリケーションがJavaベースの構成を使用するかXMLベースの構成を使用するかに応じて、このアダプターを構成する2つの異なる方法があります。

Java構成を使用する最初の方法を見てみましょう。

@ComponentScan("com.baeldung.spring.controller")
@Configuration
@EnableWebMvc
public class ServletConfig implements WebMvcConfigurer {
    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

アプリケーションがXML構成を使用する場合、WebアプリケーションコンテキストXMLでこのハンドラーアダプターを構成するための2つの異なるアプローチがあります。 ファイルspring-servlet_RequestMappingHandlerAdapter.xmlで定義されている最初のアプローチを見てみましょう。

<beans ...>
    <context:component-scan base-package="com.baeldung.spring.controller" />
    
    <bean 
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    
    <bean
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

そして、これが2番目のアプローチです。

<beans ...>
    <mvc:annotation-driven />
    
    <context:component-scan base-package="com.baeldung.spring.controller" />
    
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

このタグは、これら2つのクラスをSpringMVCに自動的に登録します。

RequestMappingHandlerMapping、をカスタマイズする必要がある場合は、このタグをアプリケーションコンテキストXMLから削除し、アプリケーションコンテキストXMLで手動で構成する必要があります。

4.5. HttpRequestHandlerAdapter

このハンドラーアダプターは、HttpRequestを処理するハンドラーに使用されます。 これは、 HttpRequestHandler インターフェイスを実装します。このインターフェイスには、要求を処理して応答を生成するための単一の handleRequest()メソッドが含まれています。

このメソッドの戻り型はvoidであり、他のハンドラーアダプタによって生成されるModelAndView戻り型を生成しません。 これは基本的にバイナリ応答を生成するために使用され、レンダリングするビューを生成しません。

5. アプリケーションの実行

アプリケーションがポート番号8082localhostにデプロイされ、context-rootが spring-mvc-handlersである場合:

http://localhost:8082/spring-mvc-handlers/

6. 結論

この記事では、SpringFrameworkで使用できるさまざまなタイプのハンドラーアダプターについて説明しました。

ほとんどの開発者はおそらくデフォルトに固執するでしょうが、基本を超える必要がある場合にフレームワークがどれほど柔軟であるかを理解することは十分に価値があります。

このチュートリアルのソースコードは、GitHubプロジェクトにあります。