HttpServlet source code analysis

JavaWeb series of tutorials
JavaWeb—Servlet
simulation Servlet essence
Using IDEA to develop servlet program
Servlet object life cycle
adapter (GenericServlet) to transform Servlet
ServletConfig
Servlet-ServletContext
HTTP protocol, the difference between get and post
Web site welcome page
One learn HttpServletRequest
If you find it helpful If so, you might as well move your little hands, like and collect a wave, which is also convenient for later review.
insert image description here

mind Mapping
insert image description here

HttpServet source code analysis

public class HelloServlet extends HttpServlet {
    
    
	// 用户第一次请求,创建HelloServlet对象的时候,会执行这个无参数构造方法。
	public HelloServlet() {
    
    
    }
    
    //override 重写 doGet方法
    //override 重写 doPost方法
}

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable {
    
    
           
	// 用户第一次请求的时候,HelloServlet对象第一次被创建之后,这个init方法会执行。
    public void init(ServletConfig config) throws ServletException {
    
    
        this.config = config;
        this.init();
    }
	// 用户第一次请求的时候,带有参数的init(ServletConfig config)执行之后,会执行这个没有参数的init()
	public void init() throws ServletException {
    
    
        // NOOP by default
    }
}

// HttpServlet模板类。
public abstract class HttpServlet extends GenericServlet {
    
    
    用户发送第一次请求的时候这个service会执行
     用户发送第N次请求的时候,这个service方法还是会执行。
     用户只要发送一次请求,这个service方法就会执行一次。
    @Override
    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException {
    
    

        HttpServletRequest  request;
        HttpServletResponse response;

        try {
    
    
            // 将ServletRequest和ServletResponse向下转型为带有Http的HttpServletRequest和HttpServletResponse
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
    
    
            throw new ServletException(lStrings.getString("http.non_http"));
        }
        // 调用重载的service方法。
        service(request, response);
    }
    
     这个service方法的两个参数都是带有Http的。
      这个service是一个模板方法。
     在该方法中定义核心算法骨架,具体的实现步骤延迟到子类中去完成。
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    
    
        // 获取请求方式
        // 这个请求方式最终可能是:""
        // 注意:request.getMethod()方法获取的是请求方式,可能是七种之一:
        // GET POST PUT DELETE HEAD OPTIONS TRACE
        String method = req.getMethod();

        // 如果请求方式是GET请求,则执行doGet方法。
        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;
                try {
    
    
                    ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                } catch (IllegalArgumentException iae) {
    
    
                    // Invalid date header - proceed as if none was set
                    ifModifiedSince = -1;
                }
                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)) {
    
    
            // 如果请求方式是POST请求,则执行doPost方法。
            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);
        }
    }
    
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException{
    
    
        // 报405错误
        String msg = lStrings.getString("http.method_get_not_supported");
        sendMethodNotAllowed(req, resp, msg);
    }
    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
    
    
        // 报405错误
        String msg = lStrings.getString("http.method_post_not_supported");
        sendMethodNotAllowed(req, resp, msg);
    }
    
}

 

Through the above source code analysis:
Suppose the request sent by the front-end is a get request, and the method rewritten by the back-end programmer is doPost.
Suppose the request sent by the front-end is a post request, and the method rewritten by the back-end programmer is doGet
. What happens?
An error like 405 occurs.
405 indicates an error in the front end, and the request sent is incorrect. inconsistent with the server. Not the way the server needs to request.

From the above source code, we can know that as long as the doGet method or doPost method in the HttpServlet class is executed, it must be 405.

How to avoid 405 errors?
The back-end rewrites the doGet method, and the front-end must send a get request.
The back-end rewrites the doPost method, and the front-end must send a post request.
This avoids 405 errors.

What kind of request needs to be sent by the front-end, in fact, the back-end should have the final say. The way the back end lets you send it, the way the front end has to send it.

Some people, you will see that in order to avoid 405 errors, the doGet and doPost methods have been rewritten in the Servlet class.
In this way, the occurrence of 405 can indeed be avoided, but it is not recommended, and the 405 error is still useful. When it's time to report an error, let him report an error.
If you rewrite doGet and doPost at the same time, it is better to rewrite the service method directly. This way you can
write less code.

Hope to get your supportinsert image description here

Guess you like

Origin blog.csdn.net/qq_52797170/article/details/123459749