【Java】JavaWeb开发中路径的总结
- 引言
- Servlet中的路径
- 重定向
- 转发
- JSP中的路径
- web.xml中的路径
引言
Servlet和JSP中有很多需要使用路径的地方,有很多初学者搞不太清楚,为了方便自己和他人,写一篇文章来探讨一下,抛砖引玉。
该篇文章会持续更新和完善,如果发现作者有什么不对的地方,欢迎评论留言批评。
Servlet中的路径
Servlet中使用到路径的地方有两处:
- 转发
- 重定向
下面一个一个来看。
声明两个概念:
(1) 本地服务器:当前正在运行的项目(正在编码的项目)所处的计算机
(2) 服务器软件:Tomcat
重定向
重定向可以重定向至任何网站(项目)。
重定向不是一次请求,浏览器地址栏中的URL会改变
重定向的分类:
1、重定向至当前项目
比如说当前正在运行的项目context path为lp_resume
重定向至当前项目的其他资源或路径都有两种写法:
- 使用context_path
response.sendRedirect("/lp_resume/website.html");
由于context path有可能会修改,因此也可以使用动态路径写法:
response.sendRedirect(req.getContextPath() + "/website.html");
- 写全路径
response.sendRedirect("http://localhost:8080/lp_resume/website.html");
2、重定向至同一本地服务器同一服务器软件中的项目
重定向时,如果不给浏览器全路径(http://host:port/context/xxx
)的话,必须给浏览器(客户端)一个context path,比如下面这样:
response.sendRedirect("/lp_resume/website.html");
其中/lp_resume
就是context path。
原因在于:如果不给浏览器全路径的话,浏览器会自动推断出response.sendRedirect("path")
中path
所属的http://host:port
(主机和端口号)。
假设当前正在运行的项目(正在编码的项目)A和另外一个项目B一起被部署在同一计算机下的同一Tomcat中,那么这两个项目就处于同一http://host:port
因此我们就可以直接在A项目中,写如下代码重定向至B项目的webapp/public.html:
resp.sendRedirect("/B/public.html");
当然,你也可以写全路径。
3、重定向至其他网站(项目)
一般只有写全路径一种写法:
response.sendRedirect("https://www.baidu.com/");
转发
转发只能转发至当前自己的项目。
转发是一次请求,浏览器地址栏中的URL不会改变
牢记几点:
- 第1点:
http://host:port/context/
对应项目中的webapp目录
也就是:http://localhost:8080/lp_resume/
对应lp_resume项目下的webapp目录(根目录)。 - 第2点:转发只能使用相对路径
- 相对路径以“/”开头的话,是指直接相对于"webapp/"根目录。
- 相对路径不以“/”开头的话,是指相对于此时浏览器地址栏中的路径(浏览器地址栏中的路径此时处于哪个目录)。
举例验证:
在webapp目录下新建三个JSP文件:
- a.jsp
- b/b.jsp
- c/c/c.jsp
再新建三个Servlet:
AServlet:
@WebServlet("/a_servlet")
public class AServlet extends HttpServlet {
// ...
}
BServlet:
@WebServlet("/b/b_servlet")
public class BServlet extends HttpServlet {
// ...
}
CServlet:
@WebServlet("/c/c/c_servlet")
public class CServlet extends HttpServlet {
// ...
}
浏览器访问AServlet、BServlet、CServlet时,浏览器地址栏中的路径:
- 访问AServlet:
// 浏览器路径:http://localhost:8080/context_path/a.jsp
- 访问BServlet:
// 浏览器路径:http://localhost:8080/context_path/b/b_servlet
- 访问CServlet:
// 浏览器路径:http://localhost:8080/context_path/c/c/c_servlet
在AServlet中,使用如下代码就可以直接转发成功:
// 浏览器路径:http://localhost:8080/context_path/a.jsp
// 当前处于根目录/,因此可以直接访问根目录下的所有文件
req.getRequestDispatcher("a.jsp").forward(req, resp); // T
req.getRequestDispatcher("b/b.jsp").forward(req, resp); // T
req.getRequestDispatcher("c/c/c.jsp").forward(req, resp); // T
但是,BServlet和CServlet要想转发成功必须分别这样写:
BServlet:
// 浏览器路径:http://localhost:8080/context_path/b/b_servlet
// 处于/b/目录,可以直接访问b.jsp
req.getRequestDispatcher("b.jsp").forward(req, resp);
// 当前处于根目录下的b目录下,因此需要跳出b目录
// req.getRequestDispatcher("../a.jsp").forward(req, resp); // T
// req.getRequestDispatcher("../b/b.jsp").forward(req, resp); // T
// req.getRequestDispatcher("../c/c/c.jsp").forward(req, resp); // T
CServlet:
// 浏览器路径:http://localhost:8080/context_path/c/c/c_servlet
// 处于/c/c/目录
// 可以直接跳转至c.jsp
req.getRequestDispatcher("c.jsp").forward(req, resp);
// 当前处于 "根目录/c/c/"目录下,因此需要跳出/c/c目录
// req.getRequestDispatcher("../../a.jsp").forward(req, resp); // T
// req.getRequestDispatcher("../../b/b.jsp").forward(req, resp); // T
// req.getRequestDispatcher("../../c/c/c.jsp").forward(req, resp); // T
因此我们现在就可以得出:转发时,不以/
开头的相对路径是指相对于此时浏览器地址栏中的路径(在哪个目录里)。
也可以得出:http://localhost:8080/context_path/
对应webapp目录(webapp/)
。
推荐写法:
值得一提的是,转发时无论AServlet、BServlet还是CServlet都可以这样写:
相对路径(带/)(/代表webapp根目录)
req.getRequestDispatcher("/a.jsp").forward(req, resp); // T
req.getRequestDispatcher("/b/b.jsp").forward(req, resp); // T
req.getRequestDispatcher("/c/c/c.jsp").forward(req, resp); // T
因为如果相对路径以“/”开头的话,是指直接相对于“webapp/”根目录。
JSP中的路径
- JavaWeb开发中,jsp和html中的URL应该使用以
/context_path
开头的绝对路径 - 由于context path有可能会更改,所以应该使用动态的context path
'${pageContext.request.contextPath}/static/*'
- 或者这样:
- 指令中的路径使用相对路径
include指令的本质是copy
假设有个JSP文件处于webapp/common/
目录下,那么有两种写法:
写法一:
<!-- 相对于自身所处的目录下 -->
<%@ include file="head.jsp" %>
写法二:
<!-- ‘/’ 指直接相对于webapp根目录 -->
<%@ include file="/common/head.jsp" %>
web.xml中的路径
web.xml使用的是转发
例一:
<!-- 配置首页 -->
<welcome-file-list>
<welcome-file>user/front</welcome-file>
</welcome-file-list>
相当于:
// 假设现在浏览器地址栏是:http://localhost:8080/lp_resume/
// 那么下面就会转发到:http://localhost:8080/lp_resume/user/front
// 转发相对于此时浏览器地址栏中的URL进行转发
request.getRequestDispatcher("user/front").forward(request, response);
例二:
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/404.jsp</location>
</error-page>
相当于:
// 假设现在浏览器地址栏是:http://localhost:8080/lp_resume/
// 那么此时就会去访问webapp/WEB-INF/404.jsp
// 因为如果以"/"开头的话,是指直接相对于"webapp"根目录
request.getRequestDispatcher("/WEB-INF/404.jsp").forward(request, response);