分析servlet最深层的源码读懂servlet如何实现

目录

1 Servlet 继承结构

1.1Servlet 接口

1.2 ServletConfig 接口

1.3 GenericServlet 是个抽象类

1.4 HttpServlet类


1 Servlet 继承结构

1.1Servlet 接口

反编译工具打开看其源码解析:

代码:

package javax.servlet;

import java.io.IOException;

public abstract interface Servlet
{
  public abstract void init(ServletConfig paramServletConfig)
    throws ServletException;

  public abstract ServletConfig getServletConfig();

  public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
    throws ServletException, IOException;

  public abstract String getServletInfo();

  public abstract void destroy();
}

1.init(),创建 Servlet 对象后立即调用该方法完成其他初始化工作。

2.service(),处理客户端请求,执行业务操作,利用响应对象响应客户端请求。

3.destroy(),在销毁 Servlet 对象之前调用该方法,释放资源。

4.getServletConfig()ServletConfig 是容器向 servlet 传递参数的载体。

5.getServletInfo(),获取 servlet 相关信息。

1.2 ServletConfig 接口

代码:
package javax.servlet;

import java.util.Enumeration;

public abstract interface ServletConfig
{
  public abstract String getServletName();

  public abstract ServletContext getServletContext();

  public abstract String getInitParameter(String paramString);

  public abstract Enumeration<String> getInitParameterNames();
}

  Servlet 运行期间,需要一些辅助信息,这些信息可以在 web.xml 文件中,使用一个或多 个元素,进行配置。当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息,封装到一个 ServletConfig 对象中,通过调用 init(ServletConfig config)方法,将 ServletConfig 对称传递给 Servlet

1.3 GenericServlet 是个抽象类

代码:

package javax.servlet;

import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration;

public abstract class GenericServlet
  implements Servlet, ServletConfig, Serializable
{
  private static final long serialVersionUID = 1L;
  private transient ServletConfig config;

  public void destroy()
  {
  }

  public String getInitParameter(String name)
  {
    return getServletConfig().getInitParameter(name);
  }

  public Enumeration<String> getInitParameterNames()
  {
    return getServletConfig().getInitParameterNames();
  }

  public ServletConfig getServletConfig()
  {
    return this.config;
  }

  public ServletContext getServletContext()
  {
    return getServletConfig().getServletContext();
  }

  public String getServletInfo()
  {
    return "";
  }

  public void init(ServletConfig config)
    throws ServletException
  {
    this.config = config;
    init();
  }

  public void init()
    throws ServletException
  {
  }

  public void log(String msg)
  {
    getServletContext().log(getServletName() + ": " + msg);
  }

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

  public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse)
    throws ServletException, IOException;

  public String getServletName()
  {
    return this.config.getServletName();
  }
}

  GenericServlet 是实现了 Servlet 接口的抽象类。在 GenericServlet 中进一步的定义了Servlet 接口的具体实现,其设计的目的是为了和应用层协议解耦,在 GenericServlet 中包含一个 Service 抽象方法。我们也可以通过继承 GenericServlet 并实现 Service 方法实现请求的处 理 , 但是需要将 ServletReuqest ServletResponse 转为 HttpServletRequest 和HttpServletResponse。

有的人会问有什么用呢?

我HttpServlet直接实现上面三个接口不香吗?现在Http协议较为优秀但是我以后再来一个XXX协议,再来跟多XXX协议,你的代码就会非常的冗余而且很多无用代码,而采用中间接口以后不管什么协议直接继承就可以了。

1.4 HttpServlet

可以看到一个service父类和子类的方法同名:

也就是我们在写的时候会自动的转为子接口类型HttpServletRequest和Response因为他重写了GenericServlet,这个调用不是递归调用你看参数是不同的。

  继承自 GenericServlet. 针对于处理 HTTP 协议的请求所定制。在 HttpServlet service() 方法中已经把 ServletReuqest 和 ServletResponse 转 为 HttpServletRequest 和 HttpServletResponse。 直接使用 HttpServletRequest HttpServletResponse, 不再需要强转。实际开发中, 直接继承 HttpServlet, 并根据请求方式复写 doXxx() 方法即可。

posted @ 2020-06-25 10:35  赵广陆  阅读(30)  评论(0编辑  收藏  举报