Servlet、Jsp路径问题汇总
目录
环境
tomcat9
servlet4.0
jdk1.8
新建一个Java Web项目,名称为PathTest。
如果着急使用,可以直接跳过测试,看最后的总结即可。
常用变量
新建一个servlet, 路径配置为servlet01
HttpServletRequest中有各种Path,整理如下:
//上下文路径,所有servlet共享,所以和servlet本身的路径无关,默认情况下是项目名
String contextPath = request.getContextPath();
//当前项目在本地的路径,图片存储的时候会用到
String realPath =request.getSession().getServletContext().getRealPath("/");
//servlet的路径,@WebServlet注解里面的路径(或者是xml配置的路径)
String servletPath = request.getServletPath();
//请求的uri,上下文路径 + 当前servlet的路径
String requestURI = request.getRequestURI();
//当前servlet的网络访问路径(地址复制到浏览器可以访问到),不带参数
String requestURL = request.getRequestURL().toString();
System.out.println("ContextPath: " + contextPath);
System.out.println("RealPath: " + realPath);
System.out.println("ServletPath: " + servletPath);
System.out.println("RequestURI: " + requestURI);
System.out.println("RequestURL: " + requestURL);
运行结果:
ContextPath: /PathTest
RealPath: E:\personcode\eclipse\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\PathTest\
ServletPath: /servlet01
RequestURI: /PathTest/servlet01
RequestURL: http://localhost:8080/PathTest/servlet01
这边的realPath在.metadata文件里是因为eclipse的问题,进入该目录可以发现是编译后的项目。
Servlet
相对路径
绝对路径:以斜杠开头
相对路径:字母开头
相对路径在使用的过程中,可能会出现一些问题,项目里最好用绝对路径。
下面来演示一下可能会出现的问题。
新建三个servlet,名称随意,配置路径如下(servlet高版本可以直接使用注解,而不需要配额外的xml)
注意:servlet的路径必须斜杠开头,否则tomcat都启动不了。
@WebServlet("/servlet01")
@WebServlet("/admin/servlet02")
@WebServlet("/servlet03")
servlet01转发到servlet02
System.out.println("到 servlet01 了");
request.getRequestDispatcher("admin/servlet02").forward(request, response);
servlet02转发到servlet03
System.out.println("到 servlet02 了");
request.getRequestDispatcher("servlet03").forward(request, response);;
servlet03打印输出
System.out.println("到 servlet03 了");
response.getWriter().append("servlet03 Served at: ").append(request.getContextPath());
启动tomcat,访问servlet01,报错如下
控制台打印
到 servlet01 了
到 servlet02 了
servlet01转发到servlet02成功了,servlet02转发到servlet03时失败了。servlet03的地址应该是 /PathTest/servlet03,多加了个admin。
使用相对路径进行转发时,他只会在当前的层级进行转发。例如当前的servlet路径为,/admin/test,那么他只会转发给/admin/**的servlet。
我们尝试将servlet02的路径改一下
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("到 servlet02 了");
request.getRequestDispatcher("../servlet03").forward(request, response);
}
跳转成功!不过相对路径确实不够清晰,使用起来不怎么方便。
绝对路径
绝对路径以斜杠开头,/表示上下文路径,后面直接加servlet路径即可,简单粗暴。
测试:
servlet01
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("到 servlet01 了");
request.getRequestDispatcher("/admin/servlet02").forward(request, response);
}
servlet02
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("到 servlet02 了");
request.getRequestDispatcher("/servlet03").forward(request, response);;
}
servlet03
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("到 servlet03 了");
response.getWriter().append("servlet03 Served at: ").append(request.getContextPath());
}
启动运行,可以正确跳转!
JSP
前置知识:
WEB-INF目录下的文件不能直接通过浏览器访问,需要后台servlet转发。
目录结构:
相对路径
servlet跳转WEB-INF下的jsp(使用相对路径)
新建一个servlet
@WebServlet("/servlet01")
跳转到jsp
request.getRequestDispatcher("WEB-INF/world.jsp").forward(request, response);
成功!
但是同样的,我们把servlet路径改一下就不行了。
@WebServlet("/admin/servlet01")
想要访问还是得加两个点
绝对路径
@WebServlet("/admin/servlet01")
public class Servlet01 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Servlet01() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/world.jsp").forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
可以访问。
这里的/和上面的一样,也是指上下文路径。
还记得上面的realPath吗?我们进入该目录,这是编译后的项目。
进入WEB-INF,发现了world.jsp。/表示PathTest目录,也就是项目根目录,/WEB-INF/world.jsp可以定位到资源。
静态资源
静态资源存放位置
应该避免放在WEB-INF下面
在jsp中引用的时候,使用绝对路径
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>
<link rel="stylesheet" href="<%=basePath%>/css/bootstrap.css">
<link rel="stylesheet" href="<%=basePath%>/css/main.css">
JSP跳转Servlet
jsp跳转servlet,写绝对路径要加上项目名。
例如,项目名为StudentManage,servlet名为mainUrl,可以这么写
<li><a href="/StudentManage/mainUrl">主页</a></li>
总结
1、servlet跳转servlet
不管怎么跳转,尽量用绝对路径,也就是斜杠开头,可以避免很多莫名其妙的错误。
servlet之间跳转,直接写servlet路径即可。
例如有两个servlet,路径分别为
/user
/admin/user
跳转的时候直接写这个路径即可,一定要/开头
2、servlet跳转到jsp
如果是在WEB-INF下,则是/WEB-INF/XXX文件
request.getRequestDispatcher("/WEB-INF/pages/main.jsp").forward(request, response);
斜杠表示WebContent的路径,如果是在WebContent下的jsp,例如index.jsp,
那么直接 /index.jsp即可
3、jsp引用静态资源
1、静态资源不要放在Web-INF下
2、jsp引入静态资源的时候,使用绝对路径
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
%>
<link rel="stylesheet" href="<%=basePath%>/css/bootstrap.css">
<link rel="stylesheet" href="<%=basePath%>/css/main.css">
4、jsp跳转到servlet
绝对路径、且需要加上项目名
例如我的项目叫StudentManage,servlet路径为mainUrl,那么应该这么写
<li><a href="/StudentManage/mainUrl">主页</a></li>