How Tomcat works five servlet containers

Source: Internet
Author: User
The servlet container is a module used to process the requested servlet resources and populate the response object with the Web Client. In the previous article (chapter 4 of the book), we designed the simplecontainer class to implement the container interface, and basically completed the role of the container. However, we need to know that there are four types of containers in Tomcat:
Engine: indicates the entire Catalina servlet engine;
HOST: a virtual host that contains one or more context containers;
Context: indicates a web application. A context can contain multiple wrapper
Wrapper: An Independent servlet;
The UML diagram is as follows:



The container contains four methods: addchild (container con), removechild (container con), findchild (string name), and findchildren, wrapper indicates an independent servlet. Therefore, its addchild method body is empty.
In this section, we will mainly show the features of wrapper. Other containers will talk about it later.

First, let's look at the time sequence diagram (the first draw may have some problems with the time sequence diagram rules)


This section describes what happened after the connector called the servlet container's invoke method.
The pipeline contains the task to be executed by a servlet container (not related to its own servlet, which is an extra task)
One wrapper will contain one pipeline, and one pipeline will contain several valve (valves)
Public class simplewrapper implements wrapper, pipeline {// The servlet instance private servlet instance = NULL; private string servletclass; private loader; private string name; private simplepipeline pipeline = new simplepipeline (this); protected container parent = NULL ;...} public class simplepipeline implements pipeline {public simplepipeline (container) {setcontainer (container);} // The basic valve (if any) associated with this pipeline. protected valve basic = NULL; // the container with which this pipeline is associated. protected Container = NULL; // the array of valves protected valve valves [] = new valve [0]; // All valves}


In the valve, the request passes through every valve in the pipeline like water, and the valve N in will call the servlet class we requested.
After the container's invoke method is called, the following method is used:
Invokenext is a method in the standardpipelinevalvecontext class (standardpipelinevalvecontext is an internal class of the pipeline, so you can access all members of the pipeline) Public void invokenext (request, 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 (subscr ARIMA = valves. Length) & (Basic! = NULL) {basic. Invoke (request, response, this) ;}else {Throw new servletexception ("no valve") ;}}// end of inner class


OK? Flow like water. The following line of code is worth looking.

Valves [subscript]. Invoke (request, response, this );

For more information, see

<Let's talk about the request process of the interceptor in struts2 (simulate the general process)>
Http://blog.csdn.net/dlf123321/article/details/40078583


public class HeaderLoggerValve implements Valve, Contained {  protected Container container;  public void invoke(Request request, Response response, ValveContext valveContext)    throws IOException, ServletException {    // Pass this request on to the next valve in our pipeline    valveContext.invokeNext(request, response);    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("------------------------------------");  }}



This line of code is valvecontext. invokenext (request, response ).
On the other hand, we can see that all valves are reversely executed. Each time a valve is executed, the valve will be first passed to the back valve. After the execution is completed, to execute your own business logic.
When the last base valve in the channel is passed, the following code is executed naturally.
Basic. Invoke (request, response, this );
The question is, who is basic?
Let's wait.

The pipeline interface is simplepipeline, which implements the pipeline interface.
public interface Pipeline {public Valve getBasic();public void setBasic(Valve valve);public void addValve(Valve valve);public Valve[] getValves();public void invoke(Request request, Response response)throws IOException, ServletException;public void removeValve(Valve valve);}
There is a base valve in pipeline, which is called at last and is responsible for processing the response object of the request object. Therefore, the GetSet method is provided here.
The channels store valves, so you don't need to talk about the remaining methods.
In tomcat4, there is also a standardpipelinevalvecontext, which is an internal class of simplepipeline.

Valve Interface
public interface Valve {public String getInfo();public void invoke(Request request, Response response,ValveContext context) throws IOException, ServletException;}


Very clear, isn't it?

Contained Interface
public interface Contained {public Container getContainer();public void setContainer(Container container);}


The class that implements this interface, at most associated with a servlet container.

The wrapper interface was first mentioned at the beginning of the article. Wrapper wraps a basic servlet.
There are two important methods in this interface.
Public javax. servlet. servlet allocate () throws javax. servlet. servletexception;
Public void load () throws javax. servlet. servletexception;
Allocate allocates an initialized servlet instance,
Load will load it.


Wrapper Application

The class diagram is as follows:



Simpleloader class
public class SimpleLoader implements Loader {  public static final String WEB_ROOT =    System.getProperty("user.dir") + File.separator  + "webroot";  ClassLoader classLoader = null;  Container container = null;  public SimpleLoader() {    try {      URL[] urls = new URL[1];      URLStreamHandler streamHandler = null;      File classPath = new File(WEB_ROOT);      String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;      urls[0] = new URL(null, repository, streamHandler);      classLoader = new URLClassLoader(urls);    }    catch (IOException e) {      System.out.println(e.toString() );    }  }}


The constructor will initially load the class for simplewrapper to use.

The simplewrapper class implements the org. Apache. Catalina. Wrapper interface and implements the allocate and load methods.
The constructor is as follows:
Public simplewrapper (){
Pipeline. setbasic (New simplewrappervalve ());
}
We have asked where basic comes from!

The simplewrappervalve class uses the pipeline. setbasic (New simplewrappervalve () method. We know that the simplewrappervalve class is a base valve used to process servlet-passing parameters, as shown below:
public void invoke(Request request, Response response, ValveContext valveContext)    throws IOException, ServletException {    SimpleWrapper wrapper = (SimpleWrapper) getContainer();    ServletRequest sreq = request.getRequest();    ServletResponse sres = response.getResponse();    Servlet servlet = null;    HttpServletRequest hreq = null;    if (sreq instanceof HttpServletRequest)      hreq = (HttpServletRequest) sreq;    HttpServletResponse hres = null;    if (sres instanceof HttpServletResponse)      hres = (HttpServletResponse) sres;    // Allocate a servlet instance to process this request    try {      servlet = wrapper.allocate();      if (hres!=null && hreq!=null) {        servlet.service(hreq, hres);      }      else {        servlet.service(sreq, sres);      }    }    catch (ServletException e) {    }  }


There should be no problems.

The clientiploggervalve class is used to display the IP address of the client. The code is omitted, and headerloggervalve is also used to display the HTTP request header. The code is omitted.


Bootstrap1 startup class
public final class Bootstrap1 {  @SuppressWarnings("deprecation")public static void main(String[] args) {/* call by using http://localhost:8080/ModernServlet,   but could be invoked by 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();    }  }}


The running result is as follows:

As you can see, no matter which service you request, the returned results are the same. Why? Will this be explained by me?


There are many things in this chapter. We will put the use of context containers in the next section.

How Tomcat works five servlet containers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.