0. 問題: 如何改mvc中項目的歡迎頁,或者叫做根路徑
一個東西快弄完了,就剩下一個問題,應該是個小問題。就是mvc項目的歡迎頁,怎么給改下呢。
這個項目是通過mvn建立的,整個項目的原型就是spring_mvc_jpa_deom_archetype。框架早早建成,即可看到效果。假如項目名稱叫做mvn_mvc,其效果如下:
訪問根路徑
http://localhost:8080/mvn_mvc/
自動跳轉到如下路徑
http://localhost:8080/mvn_mvc/spring/
接下來的訪問都是帶着"spring"這個前綴的
http://localhost:8080/mvn_mvc/spring/person/list
很顯然不想帶着這個“spring”前綴,改名或干掉,直接位於/ 下
問題就是怎么修改這個默認的路徑!
1. 缺省的流程
先看看缺省的根路徑流程:
web.xml 中什么沒有配置任何有關歡迎頁的信息!其實這時等效於如下配置:這個會由Web容器最先訪問!
//-未指定歡迎頁時,缺省等於如下配置。這個應該不同的Web服務器可以設置,但大多數都如此-
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
而項目目錄下,有個index.html文件,進行了跳轉:
<html>
<head>
<metahttp-equiv="Refresh"content="0; URL=spring/">
</head>
</html>
跳轉到的url全路徑就相當於 http://localhost:8080/mvn_mvc/spring/。這個路徑就會由mvc 的DispatcherServlet來處理。為什么呢,是因為web.xml中進行了如下url配置:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/app/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
此時, http://localhost:8080/mvn_mvc/spring/,根據此規則,就會對應為MVC 路徑路由中的 /。也就是HomeController。
@Controller
publicclassHomeController
{
@RequestMapping(value ="/", method =RequestMethod.GET)
publicString home(Model model)
{
return"home";
}
}
然后找到對應的home.jsp。
整個流程如此。其實缺省為什么設置這么一個spring路徑。主要目的是為了提升spring對url的處理效率。spring/下的分支都交由spring來處理,其它的就可以交由web 服務器。
如果一切都交給spring處理,我們就要將 / 進行攔截。嗯,一定會由很多靜態資源、或者其它動態jsp是另有用途,也會先被spring攔截,然后再當做另外來處理。可以是可以,但是效率上就會覺得多了一步。
但是,另一方面,我們在規划url時,可能會盡可能的減短,以方便用戶的輸入;同時,規划url時,才不會考慮spring的效率呢,也就是url設計先行。這個時候,通常不會有spring這個特定的路徑;也就是spring要將就url的規划。也就是要對 / 進行攔截了。
2. 如何直接對根路徑進行攔截
還是直接說流程吧:
必須在web.xml中加入如下:
<welcome-file-list>
<welcome-file></welcome-file>
</welcome-file-list>
此時,web服務器就知道,根路徑不要web服務器來處理,而是由程序自身來處理。這時,index.html也就不起作用了。
然后,根路徑就被 HomeCtroller攔截了;因為其中配置了對"/"的映射。
或者,沒有controller,只有view,也可以簡化,在servlet的配置文件中加入:
<mvc:view-controllerpath="/"view-name="index"/>
如果同時都有。反正只會有一個起作用。一般是先掃描的起作用。誰會先掃描到,就是看和<mvc:annotation-driven />比較,誰在前面。
3. 為什么要去他大爺的
終於明白事后諸葛亮真的很容易當,完全忘記了事前豬一樣!
這個流程很簡單,但是在弄清楚之前卻浪費了一個周末去解決。還記得到處網上找,或者下源代碼斷點研究,或者參考例子對照配置。直到今天上午都沒有頭緒。始終找不到規律,沒有把對根路徑的攔截給實現。然后中午按時出去吃個飯,吃完飯回來又擺弄下電腦,發現正在運行的那個項目,一切都盡隨心所欲,正常的太不正常。
難道是mvn tomcat:run 運行時,存在緩存!!!所以每次修改配置文件時,並沒有立刻生效。記得之前用mvn tomcat:run或者mvn jetty:run 或者eclipse中的mavent調試,都試過,都不正常的!這次就直接發布到Tomcat6中,每次直接改配置文件,重啟,查看。居然就全好了。
得出如此結論,第一句話,就是maven的大爺遭殃了。
不過其它一些東西也值得借鑒:
- maven jetty:run運行時,改web.xml 不知道是否會有緩存影響,不能立刻生效;多刷新瀏覽器。
- 可以看看項目啟動日志,里面每個url映射到哪個controller,都有輸出。
- <mvc:annotation-driven />最好不要多次調用,調用一次,全包掃描一次,會發現日志中出現一遍掃描映射紀錄
- 對路徑攔截,/ 和 /* 還是有什么區別。參考:http://bluxte.net/musings/2006/03/29/servletpath-and-pathinfo-servlet-api-weirdness。
爽了,原諒他大爺了!
