Analysis of the working principle of servlet (Tomcat)

After an http request comes, the connector, one of the core components of tomcat, will accept the request, obtain the parameter information from the input stream InputStream, accept the request and response objects on the page, and encapsulate them into httprequest and httpresponse objects, and then generate a The thread to process the request and pass the generated Request and Response objects to the thread that processes the request. The thread to process the request is what Container, another core component of tomcat, needs to do.
After the container receives this request, it will create and call engine--host--context--wrapper in sequence, where the wrapper is the encapsulation form of the servlet in tomcat, so that a Request request reaches the final Wrapper container, we now know How does the request reach the correct Wrapper container, but some steps have to be completed for the request to reach the final Servlet, the Filter chain must be executed, and the listener defined in web.xml must be notified, and according to the request in http, from the mapper ( When tomcat starts, it will read the configuration information of all servlets from the configuration file) to find the corresponding servlet, and then load and instantiate the servlet and initialize it. The code is as follows:
public synchronized Servlet loadServlet() throws ServletException {
    ………
    Servlet servlet;
    try {
        ………
        ClassLoader classLoader = loader.getClassLoader();
        ………
        Class classClass = null;
        ………
        servlet = (Servlet) classClass.newInstance();
        if ((servlet instanceof ContainerServlet) &&
            (isContainerProvidedServlet(actualClass) ||
            ((Context)getParent()).getPrivileged() )) {
                ((ContainerServlet) servlet).setWrapper(this);
        }
        classLoadTime=(int) (System.currentTimeMillis() -t1);
        try {
            instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,servlet);
            if( System.getSecurityManager() != null) {
                Class[] classType = new Class[]{ServletConfig.class};
                Object[] args = new Object[]{((ServletConfig)facade)};
                SecurityUtil.doAsPrivilege("init",servlet,classType,args);
            } else {
                servlet.init(facade);
            }
            if ((loadOnStartup >= 0) && (jspFile != null)) {
                ………
                if( System.getSecurityManager() != null) {
                    Class[] classType = new Class[]{ServletRequest.class,
                        ServletResponse.class};
                    Object[] args = new Object[]{req, res};
                    SecurityUtil.doAsPrivilege("service",servlet,classType,args);
                } else {
                    servlet.service(req, res);
                }
            }
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,servlet);
            ………
        
 return servlet;
}


From the above code, we can see that after instantiating a servlet, the service method of the servlet will be called. Let's take a look at what is done in the service method (assuming that the servlet we wrote ourselves inherits from httpServlet)
protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }
        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
            
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);        
            
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
            
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
            
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

This code clearly tells us that in the service method of the servlet, the corresponding methods such as doGet(.,.), doPost(.,.) will be called according to the method method written on your page, that is, our own servlet Write your own business logic.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327070770&siteId=291194637