前陣子整合 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