知識庫 / Spring / Spring MVC RSS 訂閱

Spring處理器映射指南

Spring MVC
HongKong
4
02:41 PM · Dec 06 ,2025

1. 引言

在 Spring MVC 中,<em >DispatcherServlet</em> 作為前置控制器,負責接收所有傳入的 HTTP 請求並進行處理。

簡單來説,處理是通過將請求傳遞給相關的組件,藉助 <em >handler mappings</em> 實現的。

<em >HandlerMapping</em> 是一個定義請求與處理器對象之間映射關係的接口。雖然 Spring MVC 框架提供了一些現成的實現,但開發者也可以通過實現該接口來提供自定義的映射策略。

本文將討論 Spring MVC 提供的幾種實現,包括 <em >BeanNameUrlHandlerMapping</em><em >SimpleUrlHandlerMapping</em><em >ControllerClassNameHandlerMapping</em>,以及它們的配置以及它們之間的差異。

2.BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping 是默認的 HandlerMapping 實現。 BeanNameUrlHandlerMapping 將請求 URL 映射到具有相同名稱的 Bean。

此映射實現支持直接名稱匹配,以及使用“*”模式的模式匹配。

例如,傳入的 URL “/foo” 映射到名為 “/foo” 的 Bean。 模式匹配的示例是,將請求映射到 “/foo*” 到以 “/foo” 開頭的 Bean,例如 “/foo2/”“/fooOne/”

讓我們在這裏配置此示例並註冊一個處理請求到 “/beanNameUrl” 的 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" />

需要注意的是,在兩種配置中,定義 BeanNameUrlHandlerMapping 的 Bean 並不會產生影響,因為 Spring MVC 已經提供了它。刪除此 Bean 定義不會導致任何問題,請求仍然會被映射到已註冊的 Handler Bean。

現在,所有指向 “/beanNameUrl” 的請求都將由 DispatcherServlet 轉發到 WelcomeControllerWelcomeController 返回一個名為 “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 配置中,必須建立一個與 “<value>” 標籤的映射,該映射必須符合 java.util.Properties 類的接受格式,並且應遵循以下語法:path= Handler_Bean_Name

URL 通常應包含前導斜槓,但是如果路徑沒有以斜槓開頭,Spring MVC 會自動添加它。

配置上述示例的另一種方式是在 XML 中使用 “props” 屬性而不是 “value” 屬性。Props 具有一個 “prop” 標籤列表,其中每個標籤定義一個映射,其中 “key” 指向映射的 URL,該標籤的值是 bean 的名稱。

<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 從 Spring 4.3 版本開始已棄用,取而代之的是註解驅動的處理器方法。

另一個重要的注意事項是,控制器名稱始終以小寫形式返回(不包括“Controller”後綴)。因此,如果我們的控制器名為 “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”處理。

以下代碼確保對“/welcome*”請求,例如“/welcometest”的處理由“WelcomeController”完成,該“WelcomeController”返回一個名為“welcome”的視圖。

public class ControllerClassNameHandlerMappingTest {
    // ...

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

5. 配置優先級

Spring MVC 框架允許同時使用多個 HandlerMapping 接口的實現。

讓我們創建一個配置並註冊兩個控制器,它們都映射到 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"));
}

如果明確註冊了不同的映射器,則默認映射器將被覆蓋。然而,當明確註冊兩個映射器時,會產生有趣的結果:

@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)方法設置優先級。此方法接受一個 int參數,其中較低的值表示較高的優先級。

在XML配置中,可以通過名為 “order”的屬性來配置優先級。

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

讓我們為處理映射 Bean 添加 order 屬性,通過使用 beanNameUrlHandlerMapping.setOrder(1) simpleUrlHandlerMapping.setOrder(0) 。較低的 order 屬性值表示更高的優先級。讓我們通過測試來驗證新的行為:

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

在對上述配置進行測試時,您會發現請求到 “/welcome” 會被 SimpleUrlHandlerMapping bean 處理,該 bean 調用 SimpleUrlHandlerController 並返回 simple-url-handler-mapping view。 我們可以通過調整 BeanNameHandlerMappingorder 屬性值來使其優先級更高。

6. 結論

在本文中,我們探討了 Spring MVC 框架中 URL 映射的處理方式,通過研究框架中不同的實現來深入瞭解。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.