Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
238 views
in Technique[技术] by (71.8m points)

java - Where does getRequestDispatcher("path") look?

Using embedded tomcat, this code:

System.out.println("getServletPath: " + request.getServletPath());
System.out.println("getServletContext: " + request.getServletContext().getContextPath());
System.out.println("getServerName: " + request.getServerName());
System.out.println("getServerPort: " + request.getServerPort());

Prints out:

getServletPath: /example
getServletContext: 
getServerName: localhost
getServerPort: 9090

Does that mean that:

request.getRequestDispatcher("/example/read.jsp").forward(request, response);

Will look at this URL to forward(request, response) to the JSP:

http://localhost:9090/example/read.jsp?

Is there a way to print out what absolute URL getRequestDispatcher("relativePath") is addressing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

  1. 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.
  2. 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.
  3. 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.
  4. 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:

  1. Remove all the addWebapp definitions.
  2. 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());

  1. 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".

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...