1、相對路徑和絕對路徑
絕對路徑:以 “ / ” 開頭的路徑,是完整的路徑。
相對路徑:不以 “ / ” 開頭的路徑,是相對於當前web資源目錄的路徑。
在絕對路徑中, “ / ” 的含義有兩種解釋:
(1)如果是服務器端解析, “ / ” 代表相對於當前web應用的絕對路徑,即:協議名://服務器名(主機地址):端口號/項目名/,例如:http://localhost:8080/MyTest/。
(2)如果是瀏覽器端解析(出現在地址欄里的路徑), “ / ” 代表相對於當前服務器的絕對路徑,即:協議名://服務器名(主機地址):端口號/,例如:http://localhost:8080/。
常見的兩種絕對路徑的例子就是轉發和重定向。
| 轉發:當瀏覽器向服務器發送請求的時候,服務器自己不處理,而是調用其他的web資源進行處理。 | ||||
| 重定向:當瀏覽器向服務器發送請求的時候,服務器返回給瀏覽器一個特殊的響應,這個特殊的響應告訴瀏覽器再向另一個地址發送一個請求。 | ||||
| 轉發和重定向的區別: | 發生在瀏覽器還是服務器 | 瀏覽器的請求次數 | 瀏覽器地址欄是否發生變化 | 瀏覽器能否感知到 |
| 轉發[request] | 發生在服務器端 | 1 | 不發生變化 | 感知不到 |
| 重定向[response] | 發生在瀏覽器端 | 2 | 發生變化 | 能感知到 |
假設在當前動態web項目MyTest中,項目根目錄webContent下有兩個頁面src.html和des.html。
src.html中,通過超鏈接訪問項目中的Servlet,此時a標簽的地址有瀏覽器端解析,路徑的第一個 “ / ” 代表http://localhost:8080/,如果直接寫 " /MyServlet " 就會報404錯誤。
<a href="/MyTest/MyServlet">主頁</a><!-- /MyTest/MyServlet等價於http://llocalhost:8080/MyTest/MyServlet -->
在MyServlet中做如下處理,將請求轉發到des.html做處理,此時轉發器中的地址由服務器解析,路徑的第一個 “ / ” 代表http://localhost:8080/MyTest/。
如果是重定向,重定向中的地址由瀏覽器解析,路徑的第一個 “ / ” 代表http://localhost:8080/,如果直接寫 " /des.html " 就會報404錯誤。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/des.html").forward(request, response); // /des.html 等價於 http://localhost:8080/MyTest/des.html
// response.sendRedirect("/MyTest/des.html"); // /MyTest/des.html 等價於 http://localhost:8080/MyTest/des.html
}
如果是相對路徑的話較簡單些,但相比絕對路徑,相對路徑更容易出錯,當頁面更換位置時,鏈接容易失效。
<a href="MyServlet">主頁</a>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("des.html").forward(request, response); // response.sendRedirect("des.html"); }
但是無論是相對路徑還是絕對路徑,都容易出問題。
2、動態獲取路徑(最不容易出錯的方法)
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <body> <!-- 獲取當前鏈接使用的協議;一般應用返回http;SSL返回https; --> request.getScheme()===<%=request.getScheme() %><!-- http --> <br> <!-- 獲取當前頁面所在的服務器的名字,如果是在本地的話就是localhost --> request.getServerName()===<%=request.getServerName() %><!-- localhost --> <br> <!-- 獲得服務器的端口號 --> request.getServerPort()===<%=request.getServerPort() %><!-- 8080 --> <br> <!-- 獲取當前web應用的根目錄 --> request.getContextPath()===<%=request.getContextPath() %><!-- /MyTest --> <br> basePath===<%=basePath %><!-- http://localhost:8080/MyTest/ --> <br> </body>
在java后台同樣可以這樣獲取到路徑,但是更多的用於前台的訪問路徑和js、css、img等靜態資源的訪問路徑問題。
注意:如果在web.xml中配置了
1 <servlet> 2 <servlet-name>springDispatcherServlet</servlet-name> 3 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 4 <init-param> 5 <param-name>contextConfigLocation</param-name> 6 <param-value>classpath:springmvc.xml</param-value> 7 </init-param> 8 <load-on-startup>1</load-on-startup> 9 </servlet> 10 <servlet-mapping> 11 <servlet-name>springDispatcherServlet</servlet-name> 12 <url-pattern>/</url-pattern> 13 </servlet-mapping>
優雅的REST風格的資源URL不希望帶.html或.do等后綴,若將DispatcherServlet請求映射配置為“/”,
則SpringMVC將捕獲WEB容器的所有請求,包括靜態資源的請求,SpringMVC會將他們當成一個普通請求處理,因此找不到對應處理器將導致錯誤。
解決方法:在SpringMVC的配置文件springmvc.xml中配置
<mvc:default-servlet-handler/> <mvc:annotation-driven></mvc:annotation-driven>
