The Servlet Specification explains this
The getRequestDispatcher
method takes a String
argument describing a
path within the scope of the ServletContext. This path must be
relative to the root of the ServletContext and begin with a ‘/’, or
be empty. The method uses the path to look up a servlet, using the
servlet path matching rules in Chapter 12, “Mapping Requests to
Servlets”, wraps it with a RequestDispatcher object, and returns the
resulting object. If no servlet can be resolved based on the given
path, a RequestDispatcher is provided that returns the content for
that path.
Those rules are the following
- The container will try to find an exact match of the path of the request to the path of the servlet. A successful match selects the
servlet.
- The container will recursively try to match the longest path-prefix. This is done by stepping down the path tree a directory
at a time, using the ’/’ character as a path separator. The longest
match determines the servlet selected.
- If the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that handles
requests for the extension. An extension is defined as the part of
the last segment after the last ’.’ character.
- If neither of the previous three rules result in a servlet match, the container will attempt to serve content appropriate for the
resource requested. If a "default" servlet is defined for the
application, it will be used. Many containers provide an implicit
default servlet for serving content.
You ask
Does that mean that:
request.getRequestDispatcher("/example/display.jsp").forward(request,
response); Will look at this URL to forward(request, response) to the
JSP:
http://localhost:9090/example/display.jsp
?
No, it doesn't send an HTTP request, so the path has nothing to do with a URI. It's more of an internal path that the Servlet container will try to match with its various url-mappings for Servlets.
You also ask
Is there a way to print out what absolute URL getRequestDispatcher("relativePath") is addressing?
No. And it isn't exactly an absolute URL. It's a path that can be handled by some resource in the web application context.
After your edit, you addWebapp
to your Tomcat
instance.
tomcat.addWebapp(null, "/view2/example2", new File("src/com/example/view/example").getAbsolutePath());
You then send a request to
/view2/example2/read.jsp
I'm going to assume that read.jsp
is in
src/com/example/view/example/
I believe it's in the publicly accessible part of the web application and therefore the Servlet container can render it and respond with it.
You've also added a webapp with addContext
which seems to be similar to addWebapp
context = tomcat.addContext("", base.getAbsolutePath());
and added servlet mappings to this context.
Tomcat.addServlet(context, "example", new ExampleController());
context.addServletMapping("/example/*", "example");
I was wrong about the /example/*
not being able to handle /example
.
When you send a request to
/example
since the context path is "", the Context
above will be used and the mapping will match the ExampleController
registered above. Your Servlet
code will execute and reach
request.getRequestDispatcher("/view2/example2/read.jsp").forward(request, response);
Note the javadoc of ServletRequest#getRequestDispatcher(String)
The pathname specified may be relative, although it cannot extend
outside the current servlet context.
In other words, this Servlet
, ExampleController
was registered in the ServletContext
mapped to the context path ""
, ie. root. The path /view2/example2/read.jsp
is referring to another context. Since this context doesn't have a mapping for it, it responds with 404.
You can get a reference to another web applications in a different context. You have to use ServletContext#getContext(String)
. For example
ServletContext otherContext = request.getServletContext().getContext("/view2/example2");
Now that you have the ServletContext
, you can get a RequestDispatcher
for a resource in that context.
otherContext.getRequestDispatcher("/read.jsp").forward(request, response);
since ServletContext#getRequestDispatcher(String)
states
The pathname must begin with a / and is interpreted as relative to the current context root.
Final Answer:
getRequestDispatcher("path")
will look at the directory set in the addWebapp
method when referencing a JSP file. If a blank page or NullPointerException
is displayed, ensure that you have done the following:
- Remove all the
addWebapp
definitions.
- Run
addContext
then addWebApp
like this so they both point to ROOT
:
File base = new File("src/com/example/view");
context = tomcat.addContext("", base.getAbsolutePath());
tomcat.addWebapp(null, "/", base.getAbsolutePath());
- In the servlet point to the jsp using
request.getRequestDispatcher("/example/read.jsp").forward(request, response);
provided that the directory /example exists in "src/com/example/view"
.