在编写 Servlet 时需要用到两个用于所有 Servlet 的基本软件包:javax.servlet 和 javax.servlet.http。
下面主要介绍 javax.servlet 提供的 Servlet 以及 javax.servlet.http 提供的 HttpServlet 应用编程接口。


Servlet源码:

package javax.servlet;
public interface Servlet
{public abstract void init(ServletConfig servletconfig)throws ServletException;public abstract ServletConfig getServletConfig();public abstract void service(ServletRequest servletrequest, ServletResponse servletresponse)throws ServletException, IOException;public abstract String getServletInfo();public abstract void destroy();
}

以上便是Servlet的源码,Servlet本身是一个接口,只是提供了几个抽象方法。
init() 方法
    在Servlet的生命周期中,仅执行一次 init() 方法,即在服务器装入Servlet时执行。通过配置服务器,可以设定在启动服务器或客户机首次访问Servlet 时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行 init()。
service() 方法
    service()方法是Servlet的主体部分。客户对一个HttpServlet对象的每次请求都会调用该对象的service() 方法,并传递给这个方法一个"请求"对象和一个"响应"对象作为参数。"请求"对象提供有关请求的信息,而"响应"对象提供了一个将响应信息返回给浏览器的通信途径。javax.servlet 软件包中的相关类为ServletRequest和ServletResponse,而javax.servlet.http 软件包中的相关类为HttpServletRequest 和 HttpServletResponse。Servlet 通过这些对象与服务器通信并最终与客户机通信。Servlet 能通过调用"请求"对象的方法获知客户机环境、服务器环境的信息和所有由客户机提供的信息;通过调用"响应"对象的方法,Servlet可以向客户机发送响应。
    HttpServlet中的service()方法默认的服务功能是调用与 HTTP 请求的方法相应的 do 功能。例如,如果 HTTP 请求方法为 GET,则默认情况下就调用 doGet()。当一个客户通过HTML表单发出一个HTTP POST请求时,doPost()方法被调用。与POST请求相关的参数作为一个单独的HTTP 请求从浏览器发送到服务器。当需要修改服务器端的数据时,应该使用doPost()方法。
    Servlet的响应可以是下列几种类型:
    一个输出流,浏览器根据它的内容类型(如text/HTML)进行解释。
    一个HTTP错误响应,重定向到另一个URL、Servlet和JSP。
destroy() 方法
    destroy() 方法仅执行一次,即在服务器停止且卸载Servlet 时执行该方法。当服务器卸载 Servlet 时,将在所有 service() 方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个Servlet 在运行service() 方法时可能会产生其他的线程,因此在调用 destroy() 方法时,必须确认这些线程已终止或完成。
GetServletConfig()方法
    GetServletConfig()方法返回一个 ServletConfig 对象,该对象用来返回初始化参数和ServletContext。ServletContext 接口提供有关Servlet 的环境信息。
GetServletInfo()方法
    GetServletInfo()方法是一个可选的方法,它提供有关Servlet 的信息,如作者、版本、版权。


HttpServlet的源码:

package javax.servlet.http;
public abstract class HttpServlet extends GenericServletimplements Serializable{......此处省略N个字符
}

从HttpServlet的源码定义可以看到,HttpServlet与Servelt没有关联关系,而是继承了GenericServlet,其实GenericServlet是一个抽象类,该类已经实现了Servlet, ServletConfig, Serializable这三个接口。
在HttpServlet的源码中可以看到,该类有两个service()方法,下面我们一一说明:

public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {HttpServletRequest  request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) res;} catch (ClassCastException e) {throw new ServletException("non-HTTP request or response");}service(request, response);
}

通过代码发现,这里只是把相应的request和response转换为了基于HTTP协议的相应对象。
Servlet接口中定义了一个service方法,HttpServlet对该方法进行了实现,将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse。

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 logicdoGet(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 lessmaybeSetLastModified(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);}
}

通过该service()方法可以发现,客户端的请求先提交给Service方法时,先获取提交的方法名,根据方法名调用相应的具体方法。如果重写了该方法,那么就不会根据方法名调用其他具体的方法了
下面看一下HttpServlet类内部的几个DoXXX()方法:

protected void doXXX(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{String protocol = req.getProtocol();String msg = lStrings.getString("http.method_xxx_not_supported");if (protocol.endsWith("1.1")) {resp.sendError(405, msg);} else {resp.sendError(400, msg);}
}

发现doXXX()方法只是判断协议类型,然后抛出相应的异常,其他什么都没做。所以,在实现自己的Servlet时,需要重写这些方法,以符合自己的需求。一般不需要重写service方法。

转载于:https://blog.51cto.com/zlfwmm/1614397

源码解析Servlet和HttpServlet相关推荐

  1. Tomcat7源码解析

    Tomcat7 源码阅读学习     背景     Tomcat源码目录结构     Tomcat体系结构     Tomcat源码解析           Tomcat的启动流程           ...

  2. SpringMVC源码解析

     一:springmvc运行过程: 1. dispatcherServlet 通过 HandlerMapping 找到controller 2. controller经过后台逻辑处理得到结果集mode ...

  3. SpringBoot入门-源码解析(雷神)

    一.Spring Boot入门 视频学习资料(雷神): https://www.bilibili.com/video/BV19K4y1L7MT?p=1 github: https://github.c ...

  4. Zuul源码解析(一)

    说在前面 我们公司有一个线上服务报错通知群,经常报网关服务的一个 EOFException 异常.这个异常报出来好久了,如下图所示,艾特相关的人也不去处理,大概是不重要异常吧,反正看样子是不影响线上核 ...

  5. spring aop 注入源码解析

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  6. 源码解析 使用tomcat作为web容器时,用到的外观模式

    源码解析 使用tomcat作为web容器时,接收浏览器发送过来的请求, tomcat会将请求信息封装成ServletRequest对象, 如下图①处对象. 但是大家想想ServletRequest是一 ...

  7. spring aop 注入源码解析 1

    spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...

  8. springboot源码解析autoconfigure之WebMvcAutoConfiguration

    2019独角兽企业重金招聘Python工程师标准>>> 说在前面 本次开始spring-boot-autoconfigure源码解析之WebMvcAutoConfiguration ...

  9. tns03505 无法解析名称_SpringBootWeb源码解析SpringMVC自动配置

    SpringMVC自动配置 在 Spring Boot 中引入了 spring-boot-starter-web 依赖,并完成了 DispatcherServlet 的自动配置之后,便会通过 WebM ...

最新文章

  1. 智源青年科学家张新雨:从模型平均到集成学习、迁移学习
  2. 惠普打印机怎么无线连接电脑_惠普打印机打印中突然停止怎么办?
  3. Java论坛系统 JForum
  4. 从直觉主义到量化分析 让大数据做主
  5. SQL Server2008R2查询数据库的物理路径
  6. axis2接收json_AXIS2 如何返回JSON数据
  7. 语句拼接_Linux 进阶语句
  8. 向java全台推送数据等
  9. python设计教务管理系统_python实现教务管理系统
  10. 使用ffmpeg打开ts格式视频文件
  11. Json文件格式化方法
  12. gif动图怎么制作?gif动图制作软件推荐
  13. 硬派健身——健身先健脑
  14. 微信公众平台万能代码详解-php语言(二)
  15. html flappybird小游戏代码,原生js实现Flappy Bird小游戏
  16. 2018年度计划清单
  17. Element级联菜单省市json数据
  18. Java程序设计实验(二):类的创建和封装实验
  19. git解决代码冲突、合并代码
  20. mysql-8.0.21-winx64数据库安装过程记录

热门文章

  1. 短视频抢了直播饭碗,花椒、映客们逆袭抖音、快手无门
  2. OpenExpressApp架构-信息系统开发平台
  3. 在MyEclipse(2015)中上传项目到github的步骤(很详细)
  4. 使用 CSS3 实现 3D 图片滑块效果
  5. Top 5 Agile Project Management Books
  6. 三部委明确能源互联网建设10重点
  7. 史上最简单安装摄像头的方法
  8. 百度Apollo发布智能驾驶商业化解决方案
  9. Android从无知到有知——NO.6
  10. Python和它高大上的插件们