Spring MVC 專案用兩個以上 DispatcherServlet 時, url 映射不啟作用的問題

  • 1426
  • 0
  • 2018-08-21

前陣子整合 Spring MVC 與 Restful api 

符合送到 RestController 這個控制器的 url pattern 跟本來 Spring 用的前端控制器不同  

整合時發生了問題 ( RestController 的 url pattern 沒有起作用 )

設定檔裡面已經有本來的 dispatcherServlet 讓 url 導到 Spring 的 front controller ( 前端控制器 ) 

 此時又要多一組控制器處理 RestController

 需要用不同樣的 url pattern 來 mapping 到給 rest 用的 controller 

 

web.xml mapping rest 設定檔的部分我是寫這樣;

<servlet-mapping>
     <servlet-name>restful</servlet-name>
     <url-pattern>/restful/*</url-pattern>
</servlet-mapping>

<servlet>
     <servlet-name>rest</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
</servlet>

rest 設定檔的部分 

不在 init param 設定 contextConfigLocation 的話 

本例會 mapping 到 restful-servlet.xml

rest 是 <servlet-name> 中設定的 

也就是說如果你的<servlet-name> 設為 xxx

又不去設定 contextConfigLocation, 根據我自己的實測是會跑到 xxx-servlet.xml

P.S 如果在 web.xml 設定 contextConfigLocation 的話長這樣... 

<servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
		<init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/mvc-config.xml</param-value>
        </init-param>
</servlet>
<servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
</servlet-mapping>

 

 

前端 ajax 中往後端送的 url :

'/projectName/restful/test'

 

restcontroller 負責映射 url 的 annotation

@RestController
@RequestMapping(value = "/restful/test", produces = "application/json;charset=UTF-8")

 

上面的設定,

實際上當 ajax 觸發後發出的 url 無法找到我的 @RestController

發現要在 DispatcherServlet 的設定檔 ( 本例為 restful-servlet.xml ) 

加上

    <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
       <property name="alwaysUseFullPath" value="true"/>
    </bean>  

然後這個設定檔中的 namespace 要加上

xmlns:mvc="http://www.springframework.org/schema/mvc"

就能解決這個問題

 

原因?

首先我的 url 是 '/projectName/restful/test'

送到我的 server 端時的 url是 localhost:8080/projectName/restful/test 

這裡要注意...

 1. /projectName 是 contextPath , 環境路徑

    是 tomcat 容器用來挑選哪一個 web 應用程式的依據

2.  servlet-maping 是 /restful/*

     /restful 是 servlet path

      /* 是我的 path info

 

用 Spring 的時候, 有個alwaysUseFullPath參數預設是 default

它讓 servlet-mapping 中,  /restful/test  這一段 servletPath + pathInfo

扣掉 servletPath , 變成 /test

( 注意已經到 web 應用程式裡面了就只看 servletPath 跟 pathInfo )

如果設成 true, 就不會扣掉, 就能讓 servlet mapping 收的到了 

 

Spring 官方文件中, 16.4 Handler mappings 裡有寫這一段:

 

 

網址: https://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-handlermapping

其他參考網址:

https://stackoverflow.com/questions/12821079/servlet-mapping-with-spring

https://my.oschina.net/shishuifox/blog/215617

https://openhome.cc/Gossip/ServletJSP/URLPattern.html

 

修改紀錄:

2018.8.21  增加 contextConfigLocation 的說明, 只有文字很難讓閱讀的人想像設定的 code