1. 序章

Spring MVCでは、 DispatcherServlet フロントコントローラーとして機能し、すべての着信HTTPリクエストを受信して処理します。

簡単に言えば、処理は、ハンドラーマッピングの助けを借りて関連するコンポーネントにリクエストを渡すことによって行われます。

HandlerMapping は、リクエストとハンドラーオブジェクトの間のマッピングを定義するインターフェースです。 Spring MVCフレームワークはいくつかの既成の実装を提供しますが、開発者はインターフェースを実装して、カスタマイズされたマッピング戦略を提供できます。

この記事では、Spring MVCによって提供されるいくつかの実装、つまり BeanNameUrlHandlerMapping SimpleUrlHandlerMapping ControllerClassNameHandlerMapping 、それらの構成、およびそれらの違いについて説明します。

2. BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping は、デフォルトのHandlerMapping実装です。 BeanNameUrlHandlerMapping は、リクエストURLを同じ名前のBeanにマップします。

この特定のマッピングは、直接の名前マッチングと、「*」パターンを使用したパターンマッチングをサポートしています。

たとえば、着信URL “ / foo” は、“ / foo”というBeanにマップされます。 パターンマッピングの例は、“ / foo *” へのリクエストを、“ / foo2 /”やのように“ / foo”で始まる名前のBeanにマッピングすることです。 X146X]「/fooOne/」。

ここでこの例を構成し、“ / bean NameUrl”への要求を処理するbeanコントローラーを登録しましょう。

@Configuration
public class BeanNameUrlHandlerMappingConfig {
    @Bean
    BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() {
        return new BeanNameUrlHandlerMapping();
    }

    @Bean("/beanNameUrl")
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

これは、上記のJavaベースの構成に相当するXMLです。

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean name="/beanNameUrl" class="com.baeldung.WelcomeController" />

これらの構成の両方で、Spring MVCによって提供されるため、BeanNameUrlHandlerMappingのbeanを定義する必要はありません。 このBean定義を削除しても問題は発生せず、リクエストは引き続き登録済みのハンドラーBeanにマップされます。

これで、「/ beanNameUrl」へのすべてのリクエストは、DispatcherServletによって「WelcomeController」に転送されます。 WelcomeController は、「welcome」という名前のビュー名を返します。

次のコードは、この構成をテストし、正しいビュー名が返されることを確認します。

public class BeanNameMappingConfigTest {
    // ...

    @Test
    public void whenBeanNameMapping_thenMappedOK() {
        mockMvc.perform(get("/beanNameUrl"))
          .andExpect(status().isOk())
          .andExpect(view().name("welcome"));
    }
}

3. SimpleUrlHandlerMapping

次に、 SimpleUrlHandlerMapping は、最も柔軟なHandlerMapping実装です。 これにより、BeanインスタンスとURLの間、またはBean名とURLの間の直接かつ宣言的なマッピングが可能になります。

リクエスト「/simpleUrlWelcome」「/*/simpleUrlWelcome」「welcome」beanにマッピングしましょう。

@Configuration
public class SimpleUrlHandlerMappingConfig {

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping
          = new SimpleUrlHandlerMapping();
        
        Map<String, Object> urlMap = new HashMap<>();
        urlMap.put("/simpleUrlWelcome", welcome());
        simpleUrlHandlerMapping.setUrlMap(urlMap);
        
        return simpleUrlHandlerMapping;
    }

    @Bean
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

または、同等のXML構成は次のとおりです。

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <value>
            /simpleUrlWelcome=welcome
            /*/simpleUrlWelcome=welcome
        </value>
    </property>
</bean>
<bean id="welcome" class="com.baeldung.WelcomeController" />

XML構成では、 「「 タグは、によって受け入れられた形式で実行する必要があります java .util.Properties クラスとそれは構文に従う必要があります: path = Handler_Bean_Name

通常、URLは先頭にスラッシュを付ける必要がありますが、パスがスラッシュで始まらない場合は、SpringMVCが自動的に追加します。

上記の例をXMLで構成する別の方法は、「value」の代わりに「props」プロパティを使用することです。 Props には、“ prop” タグのリストがあり、それぞれがマッピングを定義します。ここで、“ key” はマッピングされたURLを参照し、タグの値は名前です。豆の。

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/simpleUrlWelcome">welcome</prop>
            <prop key="/*/simpleUrlWelcome">welcome</prop>
        </props>
    </property>
</bean>

次のテストケースでは、「/ simpleUrlWelcome」へのリクエストが「WelcomeController」によって処理され、「welcome」というビュー名が返されることを確認します。

public class SimpleUrlMappingConfigTest {
    // ...

    @Test
    public void whenSimpleUrlMapping_thenMappedOK() {
        mockMvc.perform(get("/simpleUrlWelcome"))
          .andExpect(status().isOk())
          .andExpect(view().name("welcome"));
    }
}

4. ControllerClassNameHandlerMapping (Spring 5で削除)

ControllerClassNameHandlerMapping は、URLを、同じ名前を持つ、または同じ名前で始まる登録済みコントローラーBean(または @Controller アノテーションが付けられたコントローラー)にマップします。

多くのシナリオでは、特に単一の要求タイプを処理する単純なコントローラーの実装の場合に、より便利な場合があります。 Spring MVCで使用される規則は、クラスの名前を使用して“ Controller” サフィックスを削除し、名前を小文字に変更して、先頭に“/を付けたマッピングとして返すことです。 」

たとえば、“ WelcomeController” は、“ / welcome *”へのマッピングとして返されます。 「welcome」で始まる任意のURLに。

ControllerClassNameHandlerMappingを構成しましょう。

@Configuration
public class ControllerClassNameHandlerMappingConfig {

    @Bean
    public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() {
        return new ControllerClassNameHandlerMapping();
    }

    @Bean
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

ControllerClassNameHandlerMapping は、アノテーション駆動型ハンドラーメソッドを優先してSpring4.3から廃止されていることに注意してください。

もう1つの重要な注意点は、コントローラー名は常に小文字で返されることです(「コントローラー」サフィックスを除く)。 したがって、「 WelcomeBaeldungController 」というコントローラーがある場合、「/welcomebaeldung」へのリクエストのみを処理し、「/welcomeBaeldung」へのリクエストは処理しません。

以下のJava構成とXML構成の両方で、 ControllerClassNameHandlerMapping Beanを定義し、要求の処理に使用するコントローラーのBeanを登録します。 タイプ「WelcomeController」のBeanも登録し、そのBeanは「/welcome」で始まるすべてのリクエストを処理します。

同等のXML構成は次のとおりです。

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="com.baeldung.WelcomeController" />

上記の構成を使用する場合、「/welcome」へのリクエストは「WelcomeController」によって処理されます。

次のコードは、「/welcometest」などの「/welcome*」へのリクエストが「welcome[ X183X]“:

public class ControllerClassNameHandlerMappingTest {
    // ...

    @Test
    public void whenControllerClassNameMapping_thenMappedOK() {
        mockMvc.perform(get("/welcometest"))
          .andExpect(status().isOk())
          .andExpect(view().name("welcome"));
    }
}

5. 優先順位の構成

Spring MVCフレームワークでは、HandlerMappingインターフェースを同時に複数実装できます。

構成を作成し、2つのコントローラーを登録します。どちらもURL「/welcome」にマップされ、異なるマッピングのみを使用し、異なるビュー名を返します。

@Configuration
public class HandlerMappingDefaultConfig {

    @Bean("/welcome")
    public BeanNameHandlerMappingController beanNameHandlerMapping() {
        return new BeanNameHandlerMappingController();
    }

    @Bean
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

明示的なハンドラーマッパーが登録されていない場合、デフォルトのBeanNameHandlerMappingが使用されます。 テストでこの動作を主張しましょう:

@Test
public void whenConfiguringPriorities_thenMappedOK() {
    mockMvc.perform(get("/welcome"))
      .andExpect(status().isOk())
      .andExpect(view().name("bean-name-handler-mapping"));
}

別のハンドラマッパーを明示的に登録すると、デフォルトのマッパーが上書きされます。 ただし、2つのマッパーが明示的に登録されている場合に何が起こるかを確認するのは興味深いことです。

@Configuration
public class HandlerMappingPrioritiesConfig {

    @Bean
    BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() {
        BeanNameUrlHandlerMapping beanNameUrlHandlerMapping 
          = new BeanNameUrlHandlerMapping();
        return beanNameUrlHandlerMapping;
    }

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping
          = new SimpleUrlHandlerMapping();
        Map<String, Object> urlMap = new HashMap<>();
        urlMap.put("/welcome", simpleUrlMapping());
        simpleUrlHandlerMapping.setUrlMap(urlMap);
        return simpleUrlHandlerMapping;
    }

    @Bean
    public SimpleUrlMappingController simpleUrlMapping() {
        return new SimpleUrlMappingController();
    }

    @Bean("/welcome")
    public BeanNameHandlerMappingController beanNameHandlerMapping() {
        return new BeanNameHandlerMappingController();
    }
}

使用するマッピングを制御するには、 setOrder(int order)メソッドを使用して優先順位を設定します。 このメソッドは、1つの int パラメーターを取ります。値が小さいほど、優先度が高くなります。

XML構成では、「order」というプロパティを使用して優先順位を構成できます。

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
    <property name="order" value="2" />
</bean>

追加しましょう注文以下を介して、マッピングBeanをハンドラーするためのプロパティ beanNameUrlHandlerMapping.setOrder(1) simpleUrlHandlerMapping.setOrder(0)。 の低い方の値注文プロパティは、より高い優先順位を反映します。 テストで新しい動作を主張しましょう:

@Test
public void whenConfiguringPriorities_thenMappedOK() {
    mockMvc.perform(get("/welcome"))
      .andExpect(status().isOk())
      .andExpect(view().name("simple-url-handler-mapping"));
}

上記の構成をテストすると、“ / welcome” へのリクエストは、SimpleUrlHandlerControllerを呼び出してsimple-を返すSimpleUrlHandlerMappingBeanによって処理されることがわかります。 url-handler-mappingビュー。 order プロパティの値を適宜調整することで、BeanNameHandlerMappingが優先されるように簡単に構成できます。

6. 結論

この記事では、フレームワークのさまざまな実装を調査することにより、SpringMVCフレームワークでURLマッピングがどのように処理されるかについて説明しました。

この記事に付随するコードは、GitHubにあります。