• Servlet源码级别进行详解


    1.首先我们先看看Servlet的类结构图,然后再分别介绍其中的接口方法

    由上图可以看到,Servlet和ServletConfig都是顶层接口类,而GenericServlet实现了这两个顶层类,然后HttpServlet实现了GenericServlet类.所以要实现一个Servlet直接就可以继承HttpServlet.

    2.Servlet接口代码

    public interface Servlet {
        //容器在启动的被调用,仅调用一次
        void init(ServletConfig var1) throws ServletException;
        //获取Servlet配置
        ServletConfig getServletConfig();
        //处理具体请求
        void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
        //获取Servlet的相关信息
        String getServletInfo();
        //Servlet销毁后释放资源
        void destroy();
    }

    其中,init方法接收一个ServletConfig参数,由容器传入.ServletConfig就是Servlet的配置,在web.xml中定义Servlet时通过init-param标签配置的参数由ServletConfig保存.

    3.ServletConfig接口定义

    public interface ServletConfig {
        //用于获取Servlet名,web.xml中定义的servlet-name
        String getServletName();
        //获取应用本身(非常重要)
        ServletContext getServletContext();
        //获取init-param中的配置参数
        String getInitParameter(String var1);
        //获取配置的所有init-param名字集合
        Enumeration<String> getInitParameterNames();
    }

    ServletConfig是Servlet级别,而ServletContext是Context(也就是Application)级别.ServletContext通常利用setAttribute方法保存Application的属性.

    4.Servlet第一个实现类GenericServlet

    GenericServlet是Servlet的默认实现,是与具体协议无关的,主要做了三件事.

    1) 实现了ServletConfig接口,可以调用ServletConfig里面的方法.

    public abstract class GenericServlet implements Servlet, ServletConfig, Serializable

    2) 提供了无参的init方法

    public void init() throws ServletException {}

    3)提供了2个log方法,一个记录日志,一个记录异常.

    public void log(String msg) {
        this.getServletContext().log(this.getServletName() + ": " + msg);
    }
    
    public void log(String message, Throwable t) {
        this.getServletContext().log(this.getServletName() + ": " + message, t);
    }

    5.基于协议的HttpServlet

    HttpSerVlet是基于Http协议实现的Servlet基类,我们在写Servlet的时候直接继承它就行了.SpringMVC中的DispatchServlet就是继承了HttpServlet.HttpServlet重新了service方法,而service方法首先将ServletRequest和ServletResponse转成HttpServletRequest和HttpServletResponse,然后根据Http不同类型的请求,再路由到不同的处理方法进行处理.

    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");
        }
        //调用Http的请求方法处理
        this.service(request, response);
    }
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();//获取请求类型
        long lastModified;
    //根据请求类型进行路由
        if(method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if(lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }
    
                if(ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if(method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if(method.equals("POST")) {
            this.doPost(req, resp);
        } else if(method.equals("PUT")) {
            this.doPut(req, resp);
        } else if(method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if(method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if(method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }
    }
  • 相关阅读:
    Python环境搭建-anaconda
    UITableView的基本使用方法
    模拟网易新闻上方滚动条
    iOS之导航栏基本设置
    UITextField 方法和代理的使用
    UITextField详解
    init方法的重写与自定义
    OC中协议的理解protocal
    IOS中检测键盘出现和消失的消息
    怎么重装系统(一)
  • 原文地址:https://www.cnblogs.com/fxust/p/7944242.html
Copyright © 2020-2023  润新知