Introduction
forward and include
The Servlet object is created by the servlet container, and the service () method of the Servlet object is also called by the container. Can a Servlet object directly invoke the service () method of another Servlet object? The answer is no, because one servlet object cannot get a reference to another Servlet object.
In the previous version of the Servlet API, the Getservlet (Stringname) method in the ServletContext interface returns a reference to the corresponding Servlet object based on the name given by the parameter. Starting with servlet API2.1, this method is discarded. For servlet containers that support servlet API2.1 or later, the Getservlet (String name) method of the ServletContext implementation class will always return null. Therefore, one Servlet object can no longer obtain a reference to another Servlet object.
When a Web application responds to a request from a client, it is possible that the response process is complex and requires multiple Web components to work together to produce a response result. Although one Servlet object cannot directly invoke the service () method of another Servlet object, the servlet specification provides two ways to collaborate between Web Components.
· Request Forwarding: The Servlet (source component) does some preprocessing on the customer request, then forwards the request to the other Web Component (the target component) to complete the subsequent operations including generating the response result.
· include: The Servlet (source component) contains the response results generated by other Web components (the target component) into the response result of the asset itself.
Request forwarding and inclusion have the following common characteristics:
· Both the source and target components handle the same customer request, and the source and target components share the same ServletRequest object and the Servletresponse object.
· the target component can be a servlet, JSP, or HTML document.
· are dependent on the Javax.servlet.RequestDispatcher interface.
The Javax.servlet.RequestDispatcher interface represents a request dispatcher, which has two methods.
Public void forward (servletrequest request,servletresponse response)
throws Servletexception, IOException;
Forwards the request to the target component.
Public void include (servletrequest request,servletresponse response)
throws Servletexception, IOException;
Contains the response result of the target component.
When the servlet component calls RequestDispatcher's ForWord () or include () method, it passes the current ServletRequest object and the Servletresponse object as arguments to forward () or include () method, which enables the source and target components to share the same ServletRequest object and the Servletresponse object .
A servlet can get Resquestdispatcher objects in two ways:
Call ServletContext's Getrequestdispatcher (Stringpath) method, which specifies the path to the target component.
Call ServletRequest's Getrequestdispatcher (Stringpath) method, which specifies the path to the target component.
The difference between the two methods is that the path path of the former must be an absolute path, while the latter's path parameter can be either an absolute or a relative path. The so-called absolute path refers to the path that begins with the symbol "/" and "/" represents the URL entry for the current web app. The so-called relative path, which is relative to the current source servlet component path, does not begin with the symbol "/".
Request Forwarding
Processing flow for Request forwarding:
(1) Empties the buffer used to hold the response body data.
(2) If the target component is a servlet or JSP, call their service () method, send the response result of the method to the client, if the target component is a static HTML document in the file system, read the data in the document and send it to the client.
Request Forwarding Features:
(1) because the ForWord () method empties the buffer used to hold the response body, the result of the response generated by the servlet source component is not sent to the client, and only the response results generated by the target component are sent to the client.
(2) If the source component has submitted a response result (such as calling Servletresponse's Flushbuffer () method, or calling the close () method of the output stream associated with the Servletresponse) before the request is forwarded, the Forwar The D () method throws IllegalStateException. In order to avoid this exception, the response result should not be submitted in the source component.
Performance:
The address does not change, and the settings of the request object before forwarding can be passed to the forwarded Web Component. Request forwarding is a chain, in which the same request object is always the same regardless of how many times it is forwarded.
include
The process flow for the include () method of the RequestDispatcher object is as follows:
(1) If the target component is a servlet or JSP, call their corresponding service () method to add the response body generated by the method to the response result of the source component, and if the target component is an HTML document, add the contents of the document directly to the response result of the source component.
(2) Return to the source component's service method and proceed with the subsequent code block.
Contains the following features compared to request forwarding:
(1) The output data of the source component and the contained target component will be added to the response result.
(2) Changes made to the response status Code or response header in the target component are ignored.
redirect
The HTTP protocol specifies a redirection mechanism in which the redirection process is as follows:
(1) The user enters a specific URL on the browser side, requesting access to a component on the server side.
(2) The server-side component returns a response result with a status code of 302, which means:
Allows the browser to request access to another Web component, providing the URL of another Web component in the response result. Another Web component might be on the same Web server, or it might not be on the same Web server.
(3) When the browser side receives this response, it automatically requests access to another Web component immediately.
(4) The browser side receives response results from another Web component.
The method used for redirection is Sendredirect (String location), which has the following characteristics:
(1) The result of the response generated by the servlet source component is not sent to the client. The Response.sendredirect (String location) method returns the result of the response with a status code of 302. After the browser receives this response, it immediately requests the target Web component of the home redirect, and the client finally receives the response result of the target Web component.
(2) If the source component has submitted a response result (such as calling Servletresponse's Flushbuffer () method, or calling the close () method of the output stream associated with the Servletresponse) before the redirect is made, Then the Sendredirect () method throws IllegalStateException. In order to avoid this exception, the response result should not be submitted in the source component.
(3) The code block after calling the Response.sendredirect () method in the Servlet source component will also be executed.
(4) The source and target components do not share the same ServletRequest object, so shared data within the requested scope is not shared.
(5) for the parameter location in the Response.sendredirect (String position) method, if beginning with "/", represents the URL relative to the root path of the current server, if starting with http://, represents a full URL.
(6) The target component does not have to be a component in the same web app on the same server, it can be any valid Web page on the Internet.
access other web apps within the servlet container
In a servlet container process, you can run multiple Web apps at the same time, so is it possible to communicate between these web apps? The answer is yes. Each Web application has a large servletcontext. For a servlet in web App A, you can access the various resources of web App B as long as you get the ServletContext object for Web App B.
The GetContext (Stringuripath) method in the ServletContext interface is used to obtain ServletContext objects for other Web applications. The parameter uripath specifies the URL entry for the other web app.
A web App is free to access a variety of resources from another web app, which can lead to security issues. Therefore, for security reasons, most servlet container implementations let the user set whether to allow web apps to get ServletContext objects for other web apps. The Crosscontext property of the,<context> element in Tomcat is used to set this option:
If the Crosscontext property is False, the Web app that corresponds to the <Context> element cannot get the ServletContext object for the other web app. When a servlet in this Web application calls the GetContext (Stringuripath) method, the method always returns null. The value of the Crosscontext property defaults to False.
If the Crosscontext property is true, the Web app that corresponds to the <Context> element can get ServletContext objects for other web apps. When a servlet in this Web application calls the GetContext (String Uripath) method, the method returns the ServletContext object for the other web app that the parameter Uripath corresponds to.
Example of differences between request forwarding and redirection (demonstrating the difference)
public class MyServlet1 extends HttpServlet {private static final long serialversionuid = 1l;protected void Doget (Httpserv Letrequest request, HttpServletResponse response) throws Servletexception, IOException {this.dopost (request, response) ;} protected void DoPost (HttpServletRequest req, httpservletresponse Res) throws Servletexception, IOException { Req.setattribute ("username", "Jack"); PrintWriter out = Res.getwriter (); Out.println ("Hello");//out.close ();//res.flushbuffer (); req.getrequestdispatcher ("MyServlet2"). Forward (req, res),//res.sendredirect ("MyServlet2");//res.sendredirect ("http://blog.csdn.net/ Goskalrie ");//ok//req.getrequestdispatcher (" Http://blog.csdn.net/goskalrie "). Forward (req, res);//http Status 404- /webdemo/http://blog.csdn.net/goskalrie}}
public class MyServlet2 extends HttpServlet {private static final long serialversionuid = 1L; protected void doget (HttpServletRequest request, httpservletresponse response) throws Servletexception, IOException { This.dopost (request, response);} protected void DoPost (HttpServletRequest req, httpservletresponse Res) throws Servletexception, IOException { Res.setcontenttype ("Text/html;charset=utf-8"); PrintWriter out = Res.getwriter (); Out.println ("
<! DOCTYPE html>
Follow these steps to experiment
(1) Start the server, access the login login.html, fill in the user name after login, you can see the browser address bar address becomes http://localhost:8080/webdemo/MyServlet2, the page print two null, The Username property is not read to the original request, nor does it read the value of setattribute ("username", "Jack") from the request processed in the source component.
(2) The Res.sendredirect ("MyServlet2") in the MyServlet1, the code is commented out, and the Req.getrequestdispatcher ("MyServlet2"). Forward (req , Res), unpack the comment, repeat step one, print out the xiaoming and Jack two names on the page, and the address bar's address does not change, but only after the request parameters, but the actual address has not changed.
2. redirectionredirect Address bar changes, two requests appear in the browser Debug interface:
The response to the first request contains the redirected address, such as the Last:
In redirection mode, the request is a page resend, so the original data to be submitted is not available in the request. It is futile to deal with the original request even before the redirect. The reason is that the life cycle of the object that requests the object and the response exists only in one request and response. The client makes the first request, at which time the request is request a, the server receives the request, generates the corresponding response, and the program encounters the redirect statement, regardless of the request and response at that time, the response becomes fixed: The status code is 302, and the response data contains the redirected component address. After the browser responds, both the request a and the response are gone, and then the browser automatically makes a new request--Request B. In the test code contains two lines of code in different ways to request the outer domain name:
Res.sendredirect ("Http://blog.csdn.net/goskalrie");//ok
Req.getrequestdispatcher ("Http://blog.csdn.net/goskalrie"). Forward (req,res);//http Status 404-/Webdemo /Http://blog.csdn.net/goskalrie
As shown in the comments, the use of redirection has been successfully accessed and an exception has occurred using request forwarding.
Example (cross-domain access, system maintenance Tips)There may be situations in the actual project where company A and company B share a single Web application in a server, but each has its own database, and employee A of company A and Company B's staff B are required to load information from different databases when they sign in to the Web App. If the Web application Webdemo is a common application, it includes the functions of login, information display and so on. Web App Webdemoa is a Web application where company a interacts with the database. Web App Webdemob is a Web application where company B interacts with the database. The above Web application distribution model application should say a lot, for example, when a site for maintenance, customers visit the site, you will receive a "Site maintenance" page information prompts, also in the following example will simulate the feature. As described in the analysis, Webdemo, Webdemoa, and Webdemob are all in one server, using redirection to implement the requirements.
The login page is included in the Webdemo:
<! DOCTYPE html>
The login page also requests MyServlet1, in MyServlet1 to determine whether the currently logged-in employee is a company or B company, if it is an employee in company A, redirect to the Web Component MyServlet2 in Webdemoa, if it is an employee in company B, Redirect to Web Component MyServlet3 in Webdemob, attempt to connect Webdemoa or Webdemob in Webdemo, connection failure indicates WEBDEMOA or webdemob is being maintained, inaccessible, At this point, the request is forwarded to the Web Component error.jsp in Webdemo. Try-catch control procedures should not be used in actual projects, where Try-catch is used instead of cross-domain requests such as webservice,ajax. In the actual project, there are many ways to implement the system maintenance hints, which is only a simple simulation of one of these situations.
Identify employee-owned companies in Webdemo and control redirected MyServlet1:
public Class MyServlet1 extends HttpServlet {private static final long serialversionuid = 1l;protected void Doget (httpservletrequ EST request,httpservletresponse response) throws Servletexception, IOException {this.dopost (request, response);} protected void DoPost (HttpServletRequest req, httpservletresponse Res) throws Servletexception, IOException {String Company = Req.getparameter ("Company"); String username = req.getparameter ("username"); URL Urla = new URL ("Http:localhost:8080/webdemoa"), try {urlconnection ConA = urla.openconnection (); Cona.connect ();} catch (Exception e) {req.getrequestdispatcher ("error.jsp"). Forward (req, res);} if (Company.equals ("CompanyA")) {Res.sendredirect ("/webdemoa/myservlet2?username=" + username + "&company=" + Company);} else if (company.equals ("Companyb")) {Res.sendredirect ("/webdemob/myservlet3?username=" + username + "&company=" + Company);}}}
In Webdemoa and Webdemob as the target component for redirection, the data is read from the corresponding company's database and validated, and the Web Components processed are MyServlet2, MyServlet3:
public class MyServlet2 extends HttpServlet {private static final long serialversionuid = 1L; protected void doget (HttpServletRequest request, httpservletresponse response) throws Servletexception, IOException { This.dopost (request, response);} protected void DoPost (HttpServletRequest req, httpservletresponse Res) throws Servletexception, IOException { Res.setcontenttype ("Text/html;charset=utf-8"); PrintWriter out = Res.getwriter (); Out.println ("
public class MyServlet3 extends HttpServlet {private static final long serialversionuid = 1l;protected void Doget (Httpserv Letrequest request, HttpServletResponse response) throws Servletexception, IOException {this.dopost (request, response) ;} protected void DoPost (HttpServletRequest req, httpservletresponse Res) throws Servletexception, IOException { Res.setcontenttype ("Text/html;charset=utf-8"); PrintWriter out = Res.getwriter (); Out.println ("and error.jsp that prompt for server maintenance:<%@ page language= "java" contenttype= "text/html; Charset=utf-8 " pageencoding=" Utf-8 "%><! DOCTYPE HTML PUBLIC "-//w3c//dtd HTML 4.01 transitional//en" "Http://www.w3.org/TR/html4/loose.dtd" >
the code of the trial downloads [test code. 7z], after download, unzip will get three *.war files, directly put these three files in the Tomcat installation directory in the WebApps folder can follow the following steps to experiment:
(1) Put the package files of Webdemo, Webdemoa, webdemob three items into the WebApps folder under the Tomcat installation directory and start the server access localhost:8080/webdemo/ login.html, enter xiaoming in the username, enter CompanyA in the company (must), click Login, login success, observe the address bar, request Webdemoa/myservlet2 success, address bar display http://localhost : 8080/webdemoa/myservlet2?username=xiaoming&company=companya, page display:
(2) Visit localhost:8080/webdemo/login.html, enter Zhanghua in the username, enter COMPANYB (must) in the company, click Login, log in successfully, observe the address bar, request webdemob/ MyServlet3 success, the Address bar displays Http://localhost:8080/webdemoB/MyServlet3?username=zhanghua&company=companyB, page display:
(3) To access the Tomcat Management page http://localhost:8080/manager/html, manually stop the Webdemoa app:
(4) Once again visit localhost:8080/webdemo/login.html, enter the user name and the company login, this will appear in the system maintenance prompts:
There is also an include () method in the Javax.servlet.RequestDispatcher interface, which can also forward requests and responses, except as described in the previous section, include () The response returned by the method to the client contains all of the responses in the request chain, such as login.html making a request to MyServlet1, Includemyservlet2,include myservlet3,include hello.jsp. Where MyServlet1, MyServlet2, MyServlet3 in the simple print servlet name, hello.jsp print Hello, the page displays the results:
MyServlet1
MyServlet2
MyServlet3
Hello
SummarizeWhether the request is forwarded or redirected, or contained, is to send the request to other Web Components for processing, some of the components are control process, some of the components are data processing, in order to make the component function-oriented, in the control process type of the Web component can not respond to the client, Instead, the Web component of the data processing class responds to the client request, and in the control Flow class Web component only determines which data processing class The Web component of the current request is being processed. In some cases, such as the example code above, in the current app, you need to access resources for other web apps. In general, when a Web component is not suitable, does not want, or cannot handle a request, it needs to use redirection or request forwarding for other Web Components to respond.
Request forwarding and redirection (implementation of hints in simulation system maintenance)