Servlet源码级别进行详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
    }
}

 

以上是关于Servlet源码级别进行详解的主要内容,如果未能解决你的问题,请参考以下文章

JSP详解

详解Spring mvc工作原理及源码分析

JFinal源码详解

Java 中的 Filter 过滤器详解

过滤器Filter详解

JavaEE基础(02):Servlet核心API用法详解