本文以idea中利用maven模板创建web项目下的路径进行介绍,在写这篇博客前,作者在eclipse、idea等工具下都进行了web项目的路径测试。经过测试工具的不同会产生一些细微的差异,基本原理是一样的,无论是哪种编程工具,javaweb的路径问题这一篇就够了!
目录:
前置知识点:
在JavaWeb中,路径分为相对路径和绝对路径两种:
相对路径(不以/ 斜杠开头,不可以确定唯一资源):
规则:找到当前资源和目标资源的位置关系
- .表示当前目录
- ..表示上一级目录
- 资源名表示当前目录(相当于省略了./)
绝对路径(以/ 斜杠开头,会把斜杠解析为参照路径,唯一确定资源)
http://ip:port/工程路径(服务器访问到这个项目的路径)/资源路径
对于工程路径,不一定仅仅有/…/这样一段还有可能是/…/…/…
例(完整的):
在tomcat中我将我的演示项目访问路径设置为http://localhost:8080/url,即/url能访问到我的项目(这里的url仅仅代表访问我项目的映射,可以理解为我的项目名,跟URL是两码事!)
http://localhost:8080/url(访问到此项目、工程的路径)/servlet01
Web中 / 的不同表示含义:
在web中 / 斜杠 是一种绝对路径
/ 斜杠 如果被浏览器解析(前台路径),得到的地址是:http://ip:port/,即/等价于http://ip:port/
例:
/ 斜杠 如果被服务器解析(后台路径), 得到的地址是:http://ip:port/工程路径,即/等价于http://ip:port/工程路径
例:
- <url-pattern>/servlet1</url-pattern>
- servletContext.getRealPath("/");
- request.getRequestDispatcher("/");//请求转发
特殊情况: response.sendRediect("/"); 把斜杠发给浏览器解析。得到http://ip:port/
对于Web路径中的必要说明:
在 Web 应用中,浏览器或服务器会自动为不同的相对路径添加不同的参照路径,将相对路径转换为绝对路径,以定位这个资源。
URL,统一资源定位符,用于定位资源的一种方式。通常的URL资源访问路径由两部分构成:资源路径与资源名称。资源名称指的是要访问资源的直接名称,如show.html,或与要访问资源存在映射关系的间接名称,如show.do。而资源路径,则是通过该路径则可以定位到指定的资源,即资源路径是指在URL资源访问路径中除了资源名称以外的其它部分。
在此我们约定:
以下面路径为例(不必纠结结尾有无斜杠) http://localhost:8080/url/servlet01 http://localhost:8080/url为资源路径 /servlet01为资源名称 一般情况下,在URL或URI中,最后一个斜杠后的部分为资源名称,而其它部分则为资源路径 例: <a href=“xxx/ooo/jjj(资源路径)/register(资源名称)”>
web中的路径转化公式:
绝对路径=参照路径(我们上文分析的web中 /斜杠的含义)+相对路径
概念加强(前、后台路径均以/斜杠开头):
前台路径(浏览器解析的路径):
所谓前台路径是指,由浏览器解析执行的代码中所包含的路径。例如,html、css、js中的路径,jsp文件中静态部分的路径(HTML标签中的路径)。例如,html 及jsp文件中的 、、等标签中的路径﹔再如,css 文件中的 background:img("")等属性中的路径,js文件中的window.location.href=""等属性中的路径,都属于前台路径。
前台路径的参照路径是web服务器的根路径,即http://ip:port/
将前台路径转换为绝对路径的工作,是由浏览器自动完成的。该路径的作用是要为用户提交对某种资源的请求,是要查找并定位服务器中的某资源简单来说,前台路径的作用是“查找”。
后台路径(服务器解析的路径)
所谓后台路径是指由服务器解析执行的代码及文件中所包含的路径。例如,java 代码中的路径、jsp文件动态部分〈 java代码块〉中的路径、xml等配置文件中的路径(配置文件是要被java代码解析后加载到内存的,其中的路径会出现在Java代码中)等。 后台路径的参照路径是web应用的根路径。如http://ip:port/工程路径,例:http://localhost:8080/url(url为项目的访问名称,可简单理解为工程路径) 将后台路径转换为绝对路径的工作,是由服务器自动完成的。该路径的作用是标识出该资源在服务器中的路径,以便客户端能够按照这个设定路径来查找相应资源。简单来说,后台路径的作用是“标识”。
后台路径特例:
对于后台路径的参照路径有一个特例:当代码中使用response的sendRedirect()方法进行重定向时,若其参照路径是以斜杠开头,则其参照路径不是web应用的根路径,而是web服务器的根路径。 例如,执行response.sendRedirect("/show.jsp);将会报404 错误。因为其参照路径是Tomcat的根,而非当前项目的根。所以若要使用重定向,就需要在路径上添加上项目名称: response.sendRedirect("/项目名称/show.jsp" ); 或: response.sendRedirect(request.getContextPath +"/show.jsp" ); 为什么这里是特例? 因为sendRedirect()方法可以重定向到其它应用,若不指定要跳转的应用,其将无法确定跳转方向。
以路径名称开头的相对路径
以路径名称开头的相对路径,无论是出现在前台页面,还是出现在后台Java 代码或配置文件中,其参照路径都是当前访问路径的资源路径即使是response的sendRedirect()方法的参数路径,若不以斜杠开头,其也属于“以路径名称开头的相对路径”类,参照路径为当前访问路径的资源路径。
总结:

两个方法:
1.动态获取虚拟目录(获取的格式为:/工程路径)
request.getContextPath()
举例:
<servlet>
<servlet-name>servlet01</servlet-name>
<servlet-class>com.tz.servlet.servlet01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet01</servlet-name>
<url-pattern>/servlet01</url-pattern>
</servlet-mapping>
访问此servlet的绝对路径为: http://localhost:8080/url/servlet01
PrintWriter out = resp.getWriter();
out.print(req.getContextPath());
结果为:
/url
2.获取工程部署在服务器硬盘上的绝对路径(常用作获取文件路径)
ServletContext context = this.getServletContext();
String realpath=context.getRealPath("/");
代码举例:(在servlet中进行代码实现):
ServletContext context = this.getServletContext();
String realpath=context.getRealPath("/");
结果: C:\Users\86199\IdeaProjects\JavaProject\test-url\target\test-url 将此路径复制到我的电脑进行查找:  对应idea中(maven模板创建的web项目) 
注意:src目录下的文件,会被放到WEB-INF下的classes目录下
前、后台路径、相对路径代码深度解析(实战)
解析前提:绝对路径=参照路径+相对路径
前台路径分析(以/开头):
以在webapp下的index.jsp访问在同样在webapp下的main.jsp 此时main.jsp的访问路径为: http://localhost:8080/url/main.jsp(也就是只有输入这个路径才能访问到main.jsp)
代码:
<form action="/url/main.jsp">
提交内容:<input type="text">
<input type="submit">
</form>
对于form中action路径的解析 已知此路径为前台路径 参照路径:/斜杠(由浏览器解析为)http://localhost:8080/ 相对路径:url/main.jsp 绝对路径=参照路径+相对路径=http://localhost:8080/url/main.jsp 所以可以提交到main.jsp页面
后台路径分析(以/开头)
以servlet在web.xml中的配置为例:
代码:
<servlet>
<servlet-name>servlet01</servlet-name>
<servlet-class>com.tz.servlet.servlet01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet01</servlet-name>
<url-pattern>/servlet01</url-pattern>
</servlet-mapping>
对于<url-pattern>/servlet01</url-pattern>的解析 url-pattern是个虚拟映射 已知此路径为后台路径 参照路径:/斜杠(由服务器解析为)http://localhost:8080/url 相对路径:servlet01 绝对路径=参照路径+相对路径=http://localhost:8080/url/servlet01 经过以上分析访问servlet01通过上述路径即可访问到
注意:不论是servlet访问servlet还是jsp访问servlet,跟servlet存在于哪个包,哪个文件夹下没有关系,只跟servlet设置的虚拟路径有关系!
以/开头的重定向特例:
以servlet01访问servlet02为例 两者的url-pattern分别为:/servlet01和/servlet02
代码:在servlet01中进行书写
- 注意:对于response的sendRedirect()方法完成的重定向,若其参数路径以/斜杠开头的相对路径”这个后台路径是个特例。只所以其为特例,是由sendRedirect()方法的本质决定的。这个方法不仅可以完成在当前项目中资源的跳转,还可以跳转到其它项目中的资源。所以这个后台路径的参照路径为“当前Web服务器的根”。
- 注意,只有这一种重定向是特例,将来我们还会学习到其它方式实现的重定向,但那里的重定向就不是特例,而是遵循我们之前的路径转换埋论
resp.sendRedirect("/url/servlet02");
对于<url-pattern>/servlet01</url-pattern>的解析 参照路径:http://localhost:8080/ 相对路径:url/servlet02 绝对路径=参照路径+相对路径=http://localhost:8080/url/servlet02 经过以上分析访问servlet02通过上述路径即可访问到
以上写法不太好,可以参照下种写法
request.getContextPath(),在此例中等价于/url,解析后为http://localhost:8080/url更加方便
resp.sendRedirect(req.getContextPath()+"/servlet02");
以路径名开头的相对路径分析
其参照路径是“当前访问路径的资源路径”
以servlet01访问servlet02为例 两者的url-pattern分别为:/servlet01和/servlet02
代码:在servlet01中书写
req.getRequestDispatcher("servlet02").forward(req,resp);
对于req.getRequestDispatcher(“servlet02”).forward(req,resp);的解析 其参照路径是:当前访问路径的资源路径,在本例中如下: 参照路径:http://localhost:8080/url 相对路径:servlet02 绝对路径=参照路径+相对路径=http://localhost:8080/url/servlet02 经过以上分析访问servlet02通过上述路径即可访问到
在web下创建文件夹的相对路径访问
如下图所示,并没有像index.jsp一样直接建立在webapp下面  对于此时hello.jsp的访问路径为: http://localhost:8080/url/jsp/hello.jsp http://localhost:8080/url/直接映射到webapp目录下 关于http://localhost:8080/url/等价于http://localhost:8080/url/index.jsp的问题需要联系tomcat的相关配置,这里不再进行阐述。 本例以jsp文件下的hello.jsp访问servlet01为例 此时servlet的虚拟映射路径为:/servlet01
代码方式一:
<form action="../servlet01">
name:<input type="text">
<input type="submit" value="提交">
</form>
对于action="…/servlet01"的解析 其参照路径是:当前访问路径的资源路径,在本例中如下: 参照路径:http://localhost:8080/url/jsp 因为servlet在url目录下面而不在jsp目录下面,所以需要先跳出来 相对路径:servlet01 绝对路径=参照路径+相对路径=http://localhost:8080/url/servlet02 经过以上分析访问servlet01通过上述路径即可访问到
代码方式二:使用request.getContextPath()
因为request.getContextPath() 等价于 /工程名称 在本例中 /工程名称等价于 /url
<form action="<%=request.getContextPath() %>/servlet01">
name:<input type="text">
<input type="submit" value="提交">
</form>
servlet的url-pattern问题
对于上文中的servlet01在web.xml中配置的为/servlet01是一个访问的映射url ,仅仅是一个映射罢了,也可以写成/hello/servlet01,这仅仅是一个映射关系,并不是说servlet在hello这个文件夹下什么的,此时的访问路径为http://localhost:8080/url/hello/servlet01
关于获取项目中的文件路径
ServletContext context = this.getServletContext();
String realpath=context.getRealPath("/");
我们设置的三个文件的位置为src下的不同目录:  但部署在本地后我们通过方法获取的路径是对应于下图所示的文件夹:  所以我们在获取文件的地址时看着target目录即可。
代码如下:
获取工程部署后在服务嚣硬盘上的绝对路径
ServletContext context = this.getServletContext();
String realpath=context.getRealPath("/");
PrintWriter out = resp.getWriter();
out.println(realpath);
String a_realpath=context.getRealPath("/a.txt");
out.println(a_realpath);
String b_realpath=context.getRealPath("/WEB-INF/b.txt");
out.println(b_realpath);
String c_realpath=context.getRealPath("/WEB-INF/classes/c.txt");
out.println(c_realpath);
结果为:(经验证均正确)
C:\Users\86199\IdeaProjects\JavaProject\test-url\target\test-url\
C:\Users\86199\IdeaProjects\JavaProject\test-url\target\test-url\a.txt
C:\Users\86199\IdeaProjects\JavaProject\test-url\target\test-url\WEB-INF\b.txt
C:\Users\86199\IdeaProjects\JavaProject\test-url\target\test-url\WEB-INF\classes\c.txt
常用路径格式:
以下格式仅作参考,希望读者能理解原理,不要死记硬背!  
结束,因作者水平有限,如有错误还请指出!
|