Servlet Specification 解释了这一点
getRequestDispatcher 方法采用 String 参数描述
ServletContext 范围内的路径。 此路径必须是
相对于 ServletContext 的根并以“/”开头,或者
为空。该方法使用路径查找 servlet,使用
第 12 章中的 servlet 路径匹配规则,“将请求映射到
Servlets”, 用 RequestDispatcher 对象包装它,并返回
结果对象。如果没有 servlet 可以基于给定的解析
路径,提供了一个 RequestDispatcher 来返回内容
那条路。
这些规则如下
- 容器将尝试查找请求路径与 servlet 路径的完全匹配。成功的匹配选择
servlet。
- 容器将递归地尝试匹配最长的路径前缀。这是通过将路径树下移到一个目录来完成的
一次,使用“/”字符作为路径分隔符。最长的
match 确定选择的 servlet。
- 如果 URL 路径中的最后一段包含扩展名(例如 .jsp),则 servlet 容器将尝试匹配处理
延期申请。扩展被定义为
最后一个 '.' 字符之后的最后一段。
- 如果前三个规则都没有导致 servlet 匹配,则容器将尝试提供适合
请求的资源。如果为
应用程序,它将被使用。许多容器提供了隐含的
提供内容的默认 servlet。
你问
这是否意味着:
request.getRequestDispatcher("/example/display.jsp").forward(request,
回复);将查看此 URL 以转发(请求、响应)到
JSP:
http://localhost:9090/example/display.jsp?
不,它不发送 HTTP 请求,因此路径与 URI 无关。它更像是一个内部路径,Servlet 容器将尝试与它的各种 Servlet url-mappings 匹配。
你也问
有没有办法打印出 getRequestDispatcher("relativePath") 正在寻址的绝对 URL?
没有。它并不完全是一个绝对 URL。它是一个可由 Web 应用程序上下文中的某些资源处理的路径。
编辑后,您将addWebapp 转到您的Tomcat 实例。
tomcat.addWebapp(null, "/view2/example2", new File("src/com/example/view/example").getAbsolutePath());
然后你发送一个请求到
/view2/example2/read.jsp
我将假设read.jsp 在
src/com/example/view/example/
我相信它位于 Web 应用程序的可公开访问部分,因此 Servlet 容器可以呈现它并用它做出响应。
您还添加了一个带有 addContext 的 webapp,它似乎类似于 addWebapp
context = tomcat.addContext("", base.getAbsolutePath());
并将 servlet 映射添加到 this 上下文。
Tomcat.addServlet(context, "example", new ExampleController());
context.addServletMapping("/example/*", "example");
我错了 /example/* 无法处理 /example。
当您发送请求时
/example
由于上下文路径是“”,所以将使用上面的Context,并且映射将匹配上面注册的ExampleController。您的Servlet 代码将执行并到达
request.getRequestDispatcher("/view2/example2/read.jsp").forward(request, response);
注意ServletRequest#getRequestDispatcher(String)的javadoc
指定的路径名可以是相对的,尽管它不能扩展
在当前 servlet 上下文之外。
也就是说,这个Servlet,ExampleController注册在映射到上下文路径""的ServletContext中,即。根。路径/view2/example2/read.jsp 指的是另一个上下文。由于此上下文没有对应的映射,因此它以 404 响应。
您可以在不同的上下文中获取对另一个 Web 应用程序的引用。你必须使用ServletContext#getContext(String)。例如
ServletContext otherContext = request.getServletContext().getContext("/view2/example2");
现在您有了ServletContext,您可以在那个上下文中为资源获取RequestDispatcher。
otherContext.getRequestDispatcher("/read.jsp").forward(request, response);
因为ServletContext#getRequestDispatcher(String) 状态
路径名必须以 / 开头,并被解释为相对于当前上下文根。
最终答案:
getRequestDispatcher("path") 在引用 JSP 文件时将查看在 addWebapp 方法中设置的目录。如果显示空白页或NullPointerException,请确保您已完成以下操作:
- 删除所有
addWebapp 定义。
- 像这样运行
addContext 然后addWebApp,这样它们都指向ROOT:
File base = new File("src/com/example/view");
context = tomcat.addContext("", base.getAbsolutePath());
tomcat.addWebapp(null, "/", base.getAbsolutePath());
- 在 servlet 中使用
request.getRequestDispatcher("/example/read.jsp").forward(request, response); 指向 jsp,前提是目录 /example 存在于 "src/com/example/view" 中。