The doGet method of Tomcat source code analysis (1)

Welcome to click "The Beauty of Algorithms and Programming"↑Follow us!

This article was first published on the WeChat public account: "The Beauty of Algorithms and Programming", welcome to pay attention and learn more about this series of blogs in time.

Servlet is one of the most commonly used interfaces in Java Web development, especially the doGet() and doPost() methods in this interface. When we are doing web development, we often customize a servlet such as HelloServlet, and let this class inherit HttpServelt, and then rewrite the doGet() method to quickly implement our own request service.

So what is going on behind the scenes of the doGet() method? Some students may say that this problem is very simple, that is, HttpServlet does an encapsulation to determine the type of HTTP request. If it is a get request, call the doGet() method, and if it is a post request, call the doPost() method.

What we want is not this simple answer, but to explore what is going on behind the scenes?

HelloServlet ->HttpServlet-> ApplicationFilterChain -> WsFilter -> StandardWrapperValve -> StandardContextValve -> StandardHostValve -> StandardEngineValve -> CoyoteAdapter -> Http11Processor -> NioEndpoint -> ThreadPoolExecutor -> Worker -> TaskThread -> Thread -> Catalina -> Bootstrap.main()

This is the answer we want to get in the end, starting from the doGet method, and gradually exploring where it starts, where does this start end? The answer is undoubtedly the entry main function started by the Tomcat program. Only after completing such a process can we say that we fully understand the doGet() method and fully understand what is going on behind the scenes.

By reading this series of blogs, you will thoroughly understand what is happening behind the doGet() method, deeply understand the implementation mechanism of Tomcat from the perspective of source code, how the core components in Tomcat work together, and also learn about WEB Server design ideas.

1 target

The goal of this series of blog source code analysis is to gain an in-depth understanding of the implementation mechanism of the doGet method in Tomcat. The goal of this source code analysis is to understand Servlet.

2 Analysis methods

First write the test code, and then use the stack window, thread window and single-step debugging function of Intellij Idea to analyze its implementation ideas step by step.

The preparatory work is as follows:

1) Write the HelloServlet class.

public class HelloServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


        resp.getWriter().write("hello");
    }

}

2) Add servlet configuration to web.xml.

<servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

3) Test run

Browser address bar input: http://localhost:8080/hello

The final page displays the result: hello

4) Enter the debugging analysis stage.

Add a breakpoint before the doGet() method of HelloServlet, click the debug button, enter the debugging phase, and start the source code analysis.

3 Analysis Process

Click the Debug button to start the analysis process.

First, let's take a look at the execution stack information of the doGet() method.

  1. at HelloServlet.doGet(HelloServlet.java:17)
  2. at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
  3. at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
  4. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  5. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  6. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
  7. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  8. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  9. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
  10. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
  11. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:475)
  12. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
  13. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
  14. at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
  15. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
  16. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
  17. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:498)
  18. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
  19. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:796)
  20. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1368)
  21. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  22. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  23. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  24. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  25. at java.lang.Thread.run(Thread.java:748)

From the above, we can see that there are a total of 25 stack information, and the call is very complicated, but these 25 information are not the beginning of the program. We will take you to find the beginning of the program later.

If we want to understand what is happening behind the doGet() method, we actually need to understand these stack information, so there are 25 pieces of information we have seen so far, and we will take you to understand step by step.

Due to the large amount of analysis content, we will introduce it in several blogs. If you are interested in this series of blogs, please pay attention to the WeChat public account "The Beauty of Algorithms and Programming" to learn more information in time.

First, a brief introduction to these stack information,

HelloServlet.doGet(HelloServlet.java:17)

Represents the doGet() method of the HelloServlet class, with 17 lines of code.

3.1 HelloServlet.doGet

 


@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {


    resp.getWriter().write("hello");  //17
}

Line 17 here is where we break, and where our user-written program begins. The function is simply to write the "hello" string to the HTTP response.

3.2 javax.servlet.http.HttpServlet.service

2. at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)

3. at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)

We plan to analyze 2 and 3 together, because they are all in HttpServlet. Before analyzing the source code in detail, let's introduce some basic knowledge about Servlet.

When learning the basics of Servlet, we all know that Servelt is a server-side program, which is specially used to process requests from clients, and returns a response after the processing is completed. In most cases, the request is an Http request, the response is an Http response, and HTML code is included in the Http response.

Servlet is an interface, which is defined as follows:

public interface Servlet {

        public void init(ServletConfig config) throws ServletException;

        public ServletConfig getServletConfig();

        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

        public String getServletInfo();

        public void destroy();

}

The definition of this interface is very simple, and the main methods are described as follows:

The init method represents the code that the Tomcat server executes when the servlet is just loaded.

The service method represents the code that this servlet executes when processing a request.

The destroy method represents the code to execute when this Servelt is no longer used for destruction.

So we see that servlet has a life cycle. When it is first born, the init method is called. During the service request, the Service method is called, and the destroy method is called when it is finally destroyed.

It is especially important to note that the two formal parameter types of the service() method are ServeltRequest and ServletResponse.

Since we configured in web.xml, the request with the access path '/hello' is handed over to HelloServlet for processing, in addition to the following inheritance relationship of HelloServlet:

- HelloServlet inherits HttpServlet

public class HelloServlet extends HttpServlet

- HttpServlet inherits GenericServlet

public abstract class HttpServlet extends GenericServlet

- GenericServlet implements the Servlet interface

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable

We can conclude that HelloServlet is a Servlet that conforms to the JavaEE specification, so it can process Http requests. According to the theory described above, when the Http request '/hello' arrives at the server, the service method of HelloServlet will be called to process it.

There is no service method in HelloServlet, this method is located in its parent class HttpServlet, and its definition is as follows:

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)res;
    } catch (ClassCastException var6) {
        throw new ServletException("non-HTTP request or response");
    }

    this.service(request, response);
}

As can be seen from the above code, the ServletRequest is forcibly converted to HttpServletRequest, the ServletResponse is forcibly converted to HttpServletResponse, and then handed over to another service() method for processing.

Why do this conversion? Why not just handle ServletRequest and ServletResponse directly?

 You are welcome to leave a message and tell us your views.

After this type of conversion is done, it is handed over to another service method for processing.

protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

    String method = req.getMethod();

    if (method.equals(METHOD_GET)) {

// ...
               doGet(req, resp);

    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {



// ...
}

The above code should be very easy to understand for everyone. First get the type of the Http request method, and then call different methods according to different types. For example, if the method type is get, call the doGet() method. Since the doGet() method is implemented in the subclass HelloServlet, the code we wrote above is finally executed.

Through the analysis of §3.1 and §3.2, we know that when a request reaches a servlet, the request is first converted into HttpServletRequest, the response is converted into HttpServletResponse, and then the method type of the Http request is obtained, and finally according to different method types Call different methods to handle.

4 Summary

This article is the first article of "DoGet Method of Tomcat Source Code Analysis". It mainly introduces the goals and main tasks of source code analysis, and gives a very detailed introduction to Servlet knowledge points to help you better understand Servlet, and Why do user-defined servlets need to inherit HttpServlet?

In the next lecture, we will introduce 4, 5, 6, 7, and 8, focusing on the relevant knowledge points of ApplicationFilterChain. You are welcome to continue to pay attention.

Welcome to continue to pay attention to the "Beauty of Algorithms and Programming" WeChat public account to learn more.

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325341735&siteId=291194637