前言
在我們的實際開發中,經常要寫路徑,不管是鏈接,重定向還是轉發,這都是需要路徑的。那這一篇我給大家詳細的分享一下Web中的各種路徑問題。
世界上一切東西都是相對的,對於這點而言,相信大家並不陌生,由於這篇文章是針對於WEB階段來講的,所以以下絕對路徑和相對路徑都是針對於整個互聯網而言的。
在JavaWeb中需要寫的路徑大概分為四大類:
1)客戶端路徑
超鏈接、表單、重定向
2)服務端路徑
轉發、包含
3)獲取資源路徑
servletContext獲取資源、ClassLoader獲取資源、Class獲取資源
4)<url-pattern>路徑
在本文中使用下圖構建Web項目的目錄:
一、客戶端路徑
客戶端路徑是指運行在瀏覽器上的路徑。
比如:表單、超鏈接、js(location.href)、Ajax(url)、CSS和JS的引入以及重定向等。路徑分為絕對路徑和相對路徑,相對路徑又分為相對主機的路徑和相對於當前請求的路徑。
1.1、超鏈接
超鏈接有三種書寫路徑的方式
1)絕對路徑
2)以"/"開頭的相對路徑
3)不以"/"開頭的相對路徑
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>頁面A</title> </head> <body> <!-- 超鏈接有三種書寫路徑的方式 1,絕對地址 2,以"/"開頭的相對地址 3,不以"/"開頭的相對地址 --> <!-- 1.絕對地址 --> <!-- 完整的URL --> <a href="http://localhost:8080/javaee/jsp/b.jsp">這是絕對地址超鏈接</a><br/> <!-- 2.以"/"開頭的相對地址 --> <!-- /代表了整個web項目,即:http://localhost:8080/ --> <a href="/javaee/jsp/b.jsp">這是以"/"開頭的相對地址超鏈接</a><br/> <!-- 3.不以"/"開頭的相對地址 --> <!-- 不以/開頭,則相對於當前資源的路徑 當前資源的路徑為:http://localhost:8080/javaee/jsp/ 而b.jsp也在此路徑下 所以直接書寫b.jsp --> <a href="b.jsp">這是不以"/"開頭的相對地址超鏈接</a><br/> </body> </html>
分析:
1)絕對路徑(以協議開頭的路徑):最終請求路徑為:http://localhost:8080/javaee/jsp/b.jsp
2)相對路徑:
2.1) 相對於主機的路徑(以“/”開頭):相對於當前主機(可以簡單理解為ip地址,如果想深入了解請研究tomcat的Server.xml文件。這里是localhost)的路徑,請求的最終路徑為:http://localhost:8080/javaee/jsp/b.jsp
2.2)相對於請求的路徑(不以“/”開頭):相對於當前請求(瀏覽器的請求)的路徑。
1.2、表單
表單有三種書寫路徑的方式
1)絕對路徑
2)以"/"開頭的相對路徑
3)不以"/"開頭的相對路徑
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 表單提交到jsp中 --> <!-- 表當提交路徑有三種書寫方式 1,絕對地址 2,以"/"開頭的相對地址 3,不以"/"開頭的相對地址 --> <form action="http://localhost:8080/javaee/jsp/b.jsp" methoe="get"> username:<input type="text" name="username" value=""> <input type="submit" value="提交---絕對地址 "> </form> <!-- 以/開頭的相對地址 此時的/代表整個web項目,即:http://localhost:8080/ --> <form action="/javaee/jsp/b.jsp" methoe="get"> username:<input type="text" name="username" value=""> <input type="submit" value="提交---以/開頭的相對地址"> </form> <form action="b.jsp" methoe="get"> username:<input type="text" name="username" value=""> <input type="submit" value="提交---不以/開頭的相對地址 "> </form> <!-- 表單提交到Servlet --> <!-- 表單提交到Servlet有三種書寫方式 1,絕對路徑 2,以"/"開頭的相對地址 3,不以"/"開頭的相對地址 --> <!-- 1.絕對地址 --> <!-- 完整的URL --> <form action="http://localhost:8080/javaee/PathServlet" methoe="get"> username:<input type="text" name="username" value=""> <input type="submit" value="表單提交到Servlet---絕對地址"> </form> <!-- 2.以/開頭的相對地址 --> <!-- 此時的/代表整個web項目,即:http://localhost:8080/ --> <form action="/javaee/PathServlet" methoe="get"> username:<input type="text" name="username" value=""> <input type="submit" value="表單提交到Servlet---以/開頭的相對地址"> </form> <!-- 3.不以/開頭的相對地址 --> <!-- 不以/開頭的相對路徑是相對於當前資源的路徑 此時form.jsp的地址為:http://localhost:8080/javaee/jsp/form.jsp 所以當前資源路徑為:http://localhost:8080/javaee/jsp 而要提交的Servlet的路徑為Http://localhost:8080/javaee/PathServlet 所以路徑為當前路徑的上一級路徑下 即路徑為:../PathServlet 注:.代表當前路徑 ..代表當前路徑的上一級路徑 --> <form action="../PathServlet" methoe="get"> username:<input type="text" name="username" value=""> <input type="submit" value="表單提交到Servlet---不以/開頭的相對地址"> </form> </body> </html>
1.3、重定向
表單有三種書寫路徑的方式
1)絕對路徑
2)以"/"開頭的相對路徑
3)不以"/"開頭的相對路徑
注意:在這里中我們一般只會用相對路徑,不會去用絕對路徑
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RedirectServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendRedirect("http://localhost:8080/javaee/jsp/b.jsp"); /* * 2.以"/"開頭的相對路徑 * 此時,/代表整個web工程的路徑,即http://localhost:8080/ */ // response.sendRedirect("/javaee/jsp/b.jsp"); /* * 3.不以"/"開頭的相對路徑 * 此時是相對於當前資源的相對路徑 * 當前資源路徑為:http://localhost:8080/javaee/RedirectServlet * 即表示:RedirectServlet在路徑http://localhost:8080/javaee之下 * 而b.jsp在http://localhost:8080/javaee/jsp/b.jsp * 所以最終地址寫為:jsp/b.jsp */ // response.sendRedirect("jsp/b.jsp"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
二、服務端路徑
服務端路徑是指在服務器上面運行的請求,比如請求轉發(常用)、請求包含等。服務端的路徑有兩種:相對於當前應用的路徑和相對於當前請求的路徑。
2.1、請求轉發
請求轉發有兩種書寫路徑的方式
2)以"/"開頭的相對路徑
3)不以"/"開頭的相對路徑
注意:服務器端的路徑不能是絕對路徑,只能是相對路徑,也分為以/開頭和不以/開頭兩種
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* * 1.以"/"開頭的相對路徑 * 2.不以"/"開頭的相對路徑 */ public class DispatcherServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1.以"/"開頭的相對路徑 * 此時,/代表當前web項目,即:http://localhost:8080/javaee */ // request.getRequestDispatcher("/jsp/b.jsp").forward(request, response); /* * 2.不以"/"開頭的相對路徑 * 相對於當前資源的相對路徑 * 此時,當前資源的路徑為:http://localhost:8080/javaee/DispatcherServlet * 所以要轉發去的資源的路徑以:http://localhost:8080/javaee開頭 */ request.getRequestDispatcher("jsp/b.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
注意:所有Web層框架的底層使用的都是Web的基礎Filter(Struts)或Servlet(SpringMVC),請求都是request,響應都是response,所以各個Web層框架的轉發或重定向底層都是利用request和response進行的。
2.2、請求包含
請求包含和上面的請求轉發路徑方式一樣的
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /* * 請求包含不能書寫絕對地址,只能書寫相對地址 * 1.以"/"開頭的相對路徑 * 2.不以"/"開頭的相對路徑 */ public class IncludeServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1.以"/"開頭的相對路徑 * 此時,/代表當前web項目,即:http://localhost:8080/javaee */ // request.getRequestDispatcher("/jsp/b.jsp").include(request, response); /* * 2.不以"/"開頭的相對路徑 * 相對於當前資源的相對路徑 * 此時,當前資源的路徑為:http://localhost:8080/javaee/IncludeServlet * 所以要轉發去的資源的路徑以:http://localhost:8080/javaee開頭 */ request.getRequestDispatcher("jsp/b.jsp").include(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
三、資源獲取路徑
獲取資源的路徑主要有3種,分別是ServletContext、Class和ClassLoader。其中ServletContext是WEB階段的,Tomcat提供的一種獲取資源的方式;Class和ClassLoader獲取資源主要是JavaAPI提供的一種獲取流的方式,
由於這是JDK提供的,所以不僅局限於Web,在普通Java類中也可以使用,主要用於獲取src目錄及其子目錄下的文件流。
3.1、ServletContext獲取資源
這里ServletContext獲取資源的路徑是相對系統的絕對路徑(在Windows中是帶盤符的,可以用來獲取上傳或下載文件的具體路徑)。
基本語法:servletContext.getRealPath("路徑");參數中的路徑必須是相對路徑,可以“/”開頭,也可以不使用“/”開頭,但無論是否使用“/”開頭都是相對當前應用路徑,建議以"/"開頭(這樣可以盡量統一)。
另外獲取ServletContext的方法如下:
1)使用request獲取: request.getSession().getServletContext();
2)在Servlet中獲取:this.getServletContext();
3)使用FilterConfig對象獲取(在Filter中使用):config.getServletContext();
ServletContext獲取資源必須是相對路徑,不能是絕對路徑,但不管是以/開頭,還是不以/開頭, 都是相對於當前資源的相對路徑 。
import java.io.IOException; import java.io.InputStream; import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletContextServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path1 = this.getServletContext().getRealPath("/a.properties"); String path2 = this.getServletContext().getRealPath("a.properties"); System.out.println(path1); System.out.println(path2); //輸出的地址一樣 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3.2、ClassLoader獲取資源
和Class獲取資源類似。只是不同的寫法而已,也是用於獲取文件流的。
用法:classLoader.getResourceAsStream("路徑")。參數中的路徑可以以“/”開頭,也可以不以“/”開頭(建議)。但帶不帶“/”的都表示相對於當前類的路徑。
ClassLoader類加載器不能通過絕對地址來加載資源,只能通過相對地址來加載資源 但相對地址不管前面加不加/都是相當於類路徑的相對地址
public class ClassLoaderServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 加了/,其地址是相對於類路徑的相對地址 */ // InputStream in = this.getClass().getClassLoader().getResourceAsStream("/cn/ccnu/classloaderpath/c.properties"); // Properties prop = new Properties(); // prop.load(in); // System.out.println(prop.getProperty("url")); /* * 不加/,其地址是相對於類路徑的相對地址 */ InputStream in = this.getClass().getClassLoader().getResourceAsStream("cn/ccnu/classloaderpath/c.properties"); Properties prop = new Properties(); prop.load(in); System.out.println(prop.getProperty("url")); /* * 總結:不能使用絕對地址,而只能只用相對地址 * 且不管加不加/的相對地址,都是相對於類路徑的相對地址 * */ } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3.3、Class獲取資源
Class獲取資源主要是用作自己寫的配置文件,用來讀取內容。
用法:clazz.getResourceAsStream("路徑")。參數中的路徑可以以“/”開頭,也可以不以“/”開頭。其中帶“/”的表示相對於當前類的路徑,不以“/”開頭表示相對於當前class所在目錄的路徑。
Class讀取資源不能是絕對路徑,只能是相對路徑,又分為以/開頭或者是不以/開頭 。
public class ClassServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 1.以/開頭的相對路徑 * 此時的/代表類路徑,即:/javaee/WEB-INF/classes */ // InputStream in = ClassServlet.class.getResourceAsStream("/cn/ccnu/classpath/b.properties"); // Properties porp = new Properties(); // porp.load(in); // System.out.println(porp.getProperty("url")); /* * 2.不以/開頭的相對路徑 * 此時相對的是:類ClassServlet.class的路徑,即:\javaee\WEB-INF\classes\cn\ccnu\classpath * 即:/javaee/WEB-INF/classes/cn/ccnu/classpath */ InputStream in = ClassServlet.class.getResourceAsStream("b.properties"); Properties porp = new Properties(); porp.load(in); System.out.println(porp.getProperty("url")); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
四、<url-pattern>路徑
這里的路徑僅僅是指web.xml文件中的標簽內容。這個路徑是虛擬的路徑,只有相對路徑(相對於當前應用的路徑),但相對路徑的寫法可以是精確查詢和模糊查詢。
要么以“*”開關,要么為“/”開頭,當通常情況看下,我們都會以"/"開頭。
<!—精確查詢,是相對於當前應用--> <url-pattern>/servlet/testPath</url-pattern> <!—模糊查詢,表示匹配servlet目錄下的所有文件或請求。/*表示匹配所有--> <url-pattern>/servlet/*</url-pattern> <!—模糊查詢,表示匹配所有后綴名為do的文件或請求--> <url-pattern>*.do</url-pattern>
五、總結
1)客戶端是帶“/”相對當前主機。
2)服務端(包括上述的服務端、url-pattern路徑和ServletContext路徑)帶不帶“/”都是相對當前應用(建議帶上)。
3)Class帶“/”是相對當前類路徑。不帶“/”是相對於當前位置。
4)ClassLoader無論帶不帶“/”都是當前類路徑(建議帶上)。
喜歡就點個“推薦”哦!