On the container of the wrapper packaging device thinking:
Tomcat introduced the connector Connector, container container, the idea of the container in many frameworks can be seen, such as the Xwork container in Struts2, spring in the container. The containers in Tomcat include:
①engine: The servlet engine that represents the entire Catalina
②host: Represents a virtual host with several contexts
③context: Represents a Web application in which a context contains one or more wrapper
④wrapper: Represents a separate servlet
The following is a brief description of the wrapper that contains only the wrapper container, and the following figure represents the flow of a request within a single container wrapper:
After starting the server, the listener in the connector has been ready to send, waiting for the client to connect, when the client sent the request, the connector will request to the container, if we need to deal with a servlet, container should do.
The ① container must have a class loader that can load the servlet
② container to know which class to load
③ container to be introduced into the pipeline pipeline
④ for the assembly line with the valve
⑤ Connectors and Containers on
Why is Tomcat designed this way, the master design is certainly justified, and I can only find life examples to convince myself that this is really good.
The client's request is like a bottle of muddy water, which has everything, this bottle of water needs to be processed. Finally get pure water, the connector is like a transporter, always on standby, to send these shipping to the designated factory (container), the factory to get the material, in order to efficiency and norms, there will be many lines, because the raw materials contain a lot of impurities, There will be many valves on the assembly line, like filters, every valve you can handle, but, must pass through all valves, when the last valve, pure water will be produced.
So many frameworks are convenient to introduce containers, for example, I want to record in what time the water is processed in turn (like a log), then we can introduce a log component in the container, so that he specifically to log ...
So, based on the above containing only one container, that wrapper how to implement:
The following code is quoted in "How Tomcatwork"
Based on the steps above, let's look at the startup class:
public static void Main (string[] args) {/
* call by using Http://localhost:8080/ModernServlet,
but could is invoke D by the Any name *
/HttpConnector connector = new HttpConnector ();
Wrapper wrapper = new Simplewrapper ();
Wrapper.setservletclass ("Modernservlet");
Loader Loader = new Simpleloader ();
Valve valve1 = new Headerloggervalve ();
Valve valve2 = new Clientiploggervalve ();
Wrapper.setloader (loader);
((Pipeline) wrapper). Addvalve (valve1);
((Pipeline) wrapper). Addvalve (valve2);
Connector.setcontainer (wrapper);
try {
connector.initialize ();
Connector.start ();
Make the application wait until we press a key.
System.in.read ();
}
catch (Exception e) {
e.printstacktrace ();
}
}
This is the main method of the startup class, which first declares the connector, declares the container, the loader of the class, declares the valve, puts the loader of the class, the valve into the container, and the last connector starts. When the container is invoked, the code that looks at the connector can find the code:
try {(
(httpservletresponse) response). SetHeader
("Date", Fasthttpdateformat.getcurrentdate ());
if (OK) {
connector.getcontainer (). Invoke (request, response);
Connector.getcontainer (). Invoke (Request,response);
The container invokes the Invoke method.
So what is the invoke of the wrapper container:
public void invoke (Request request, Response Response)
throws IOException, servletexception {
Pipeline.invoke ( request, response);
}
Obviously, the container invokes the assembly line pipeline Invoke method.
public void invoke (Request request, Response Response)
throws IOException, servletexception {
//Invoke the FIR St Valve in this pipeline for this request
(new Simplepipelinevalvecontext ()). Invokenext (request, response);
The pipeline Invoke method also calls its internal class Simplepipelinevalvecontext Invokenext method.
public void Invokenext (Request request, Response Response)
throws IOException, servletexception {
int subscript = stage;
stage = stage + 1;
Invoke the requested Valve for the ' current request thread
if (Subscript < valves.length) {
Valves[subscript] . Invoke (Request, response, this);
}
else if ((subscript = = valves.length) && (basic!= null)) {
Basic.invoke (request, response, this);
}
else {
throw new servletexception ("No valve");
}
}
Then we look at how each valve is defined:
public void Invoke (Request request, Response Response, Valvecontext valvecontext) throws IOException , servletexception {//pass this request on to the next valve at our pipeline Valvecontext.invokenext (request, R
Esponse);
System.out.println ("Header Logger Valve");
ServletRequest sreq = Request.getrequest ();
if (sreq instanceof httpservletrequest) {httpservletrequest hreq = (httpservletrequest) sreq;
Enumeration headernames = Hreq.getheadernames ();
while (Headernames.hasmoreelements ()) {String headername = Headernames.nextelement (). toString ();
String Headervalue = Hreq.getheader (headername);
System.out.println (Headername + ":" + headervalue);
' Else System.out.println (' not ' an HTTP Request ');
System.out.println ("------------------------------------"); }
The valve is called first to invoke Valvecontext.invokenext (Request,response), which is the next valve invoke method, and finally, when the most basic valve (i.e. the last valve) is invoked, the process of the container is terminated.
Therefore the basic valve is finally executed, the previous methods are in the stack, the front two valves first into the stack, into the stack after the first call to the Invokenext, the next valve into the stack, the next valve is called Invokenext, the basic valve into the stack, because he is the last valve, the implementation of the stack.