javaweb項目中有不少場景的路徑
客戶端的POST/GET請求,服務器的請求轉發,資源獲取須要設置路徑等
這些路徑表達的含義都有不一樣,因此想要更好的書寫規範有用的路徑代碼 須要對路徑有一個清晰地認知java
路徑基本上分三類
路徑相關的操做類型
- 超連接
- 表單
- 重定向
- 轉發
- 包含
- <url-pattern>
- ServletContext獲取資源
- Class獲取資源
- ClassLoader獲取資源
客戶端路徑形式上能夠分爲三種方式:
- 絕對路徑;
- 以「/」開頭的相對路徑;
- 不以「/」開頭的相對路徑;
超連接/表單
好比:
http://127.0.0.1:8080/servlet/NewFile.jsp
絕對路徑:
<a href="http://127.0.0.1:8080/servlet/ServletA">連接1</a>
以「/」開頭的相對路徑:
<a href="/servlet/ServletB">連接2</a>
相對路徑:
<a href="ServletB">連接3</a>
<hr />
絕對路徑:
<form action="http://127.0.0.1:8080/servlet/ServletA">
<input type="submit" value="表單1" />
</form>
以「/」開頭的相對路徑:
<form action="/servlet/ServletB">
<input type="submit" value="表單2" />
</form>
相對路徑:
<form action="ServletB">
<input type="submit" value="表單3" />
</form>
連接1和表單1:沒什麼可說的,它使用絕對路徑;
連接2和表單2:以「/」開頭,相對主機,與當前jsp頁面的主機相同
即最終訪問的頁面爲http://localhost:8080/servlet/ServletB;
連接3和表單3:不以「/」開頭,相對當前頁面的路徑,即頁面jsp全部的路徑
即最終訪問的路徑爲:http://localhost:8080/servlet/ServletB;
重定向
兩種形式
帶/開頭的 相對路徑
不帶/開頭的 相對路徑
ServletA中
response.sendRedirect("/servlet/ServletB");
http://127.0.0.1:8080/servlet/ServletA
由於路徑以「/」開頭,因此相對當前主機
http://127.0.0.1:8080/servlet/ServletB
ServletA中
response.sendRedirect("ServletB");
相對於當前ServletA的路徑
當前ServletA的路徑爲http://127.0.0.1:8080/servlet/
因此請求的是:
http://127.0.0.1:8080/servlet/ServletB
上面的例子若是寫成
response.sendRedirect("/ServletB");
將是相對於主機http://127.0.0.1:8080/ServletB 就找不到了
強烈建議使用「/」開頭的路徑,這說明在頁面中的超連接和表單都要以「/」開頭
後面是當前應用的名稱,再是訪問路徑
/servlet/ServletB
在Servlet中的重定向也建議使用「/」開頭,同理,也要給出應用的名稱
應用名稱能夠使用request.getContextPath()獲取
response.sendRedirect(request.getContextPath() + "/BServlet");
服務端路徑
請求轉發 請求
服務器端路徑必須是相對路徑,不能是絕對路徑。但相對路徑有兩種形式
其中請求轉發、請求包含都是服務器端路徑 request.getRequestDispatcher()的參數 |
服務器端路徑與客戶端路徑的區別是:
- 客戶端路徑以「/」開頭:相對當前主機;
- 服務器端路徑以「/」開頭:相對當前應用;
例如
ServletA中
request.getRequestDispatcher("/BServlet").forward(request, response);
相對於ServletA http://127.0.0.1:8080/servlet/ServletA 的當前應用 http://127.0.0.1:8080/servlet
也就是http://127.0.0.1:8080/servlet/BServlet
若是是
request.getRequestDispatcher("BServlet").forward(request, response);
那麼則是相對於當前路徑
相對於ServletA http://127.0.0.1:8080/servlet/ServletA 的當前路徑 http://127.0.0.1:8080/servlet/
也就是http://127.0.0.1:8080/servlet/BServlet
例子不是很明顯,由於只有一層路徑,應用名下面就是ServletB了 能夠再多加一層路徑嘗試
好比:
假設訪問AServlet的路徑爲:http://localhost:8080/hello/servlet/AServlet
由於路徑不以「/」開頭,因此相對當前應用,即http://localhost:8080/hello/servlet/BServlet。
其餘web
url-pattern
<url-pattern>必須使用「/」開頭,而且相對的是當前應用。服務器
ServletContext獲取資源
必須是相對路徑,能夠「/」開頭,也能夠不使用「/」開頭,但不管是否使用「/」開頭都是相對當前應用路徑
String path1 = this.getServletContext().getRealPath("a.txt");
String path2 = this.getServletContext().getRealPath("/a.txt");
path1和path2是相同的結果
Class獲取資源
import java.io.InputStream;
public class Demo {
public void fun1() {
InputStream in = Demo.class.getResourceAsStream("/a.txt");
}
public void fun2() {
InputStream in = Demo.class.getResourceAsStream("a.txt");
}
}
其中fun1()方法獲取資源時以「/」開頭,那麼相對的是當前類路徑,即 /應用名/WEB-INF/classes/a.txt文件;
其中fun2()方法獲取資源時沒有以「/」開頭,那麼相對當前Demo.class所在路徑,
由於Demo類在com.test 包下,因此資源路徑爲:/應用名/WEB-INF/classes/com/test/a.txt
Class獲取資源也必須是相對路徑,能夠「/」開頭,也能夠不使用「/」開頭。
以「/」開頭,那麼相對的是當前類路徑,即 /應用名/WEB-INF/classes/
沒有以「/」開頭,那麼相對當前.class所在路徑,由於類通常都在包下面好比com.demo
因此/應用名/WEB-INF/classes/...包路徑.../
ClassLoader獲取資源
ClassLoader獲取資源也必須是相對路徑,能夠「/」開頭,也能夠不使用「/」開頭。
但不管是否以「/」開頭,資源都是相對當前類路徑。
public class Demo {
public void fun1() {
InputStream in = Demo.class.getClassLoader().getResourceAsStream("/a.txt");
}
public void fun2() {
InputStream in = Demo.class.getClassLoader().getResourceAsStream("a.txt");
}
}
fun1()和fun2()方法的資源都是相對類路徑,即classes目錄,即/應用名/WEB-INF/classes/a.txt