在正式谈Servlet之前,首先看看JavaEE API规范对Servlet的定义:Servlet是一个运行在Web服务器中的Java小程序。Servlet将会接收和响应来自Web客户端的请求,使用HTTP(超文本传输协议)进行通讯。

(一)初始Servlet

Servlet是所有Web应用程序的核心类,它是唯一的既可以直接处理和响应用户请求,也可以将处理工作委托给应用中的其他部分的类。除非某些过滤器提前终止了客户端的请求,否则所有的请求都将被发送到某些Servlet中。运行应用程序的Web容器将会有一个或多个內建的Servlet。这些Servlet将用于处理各种用户请求,诸如JSP页面、逻辑运算、访问资源等;

所有的Servlet都实现了javax.servlet.Servlet接口,但通常不是直接实现的,它只是一个简单的接口,包含了初始化并销毁Servlet和处理请求的方法,简化代码如下:

public interface Servlet {// 初始化Servletpublic void init(ServletConfig config) throws ServletException;public ServletConfig getServletConfig();// 处理和响应用户请求public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;public String getServletInfo();// 销毁Servletpublic void destroy();
}

不论什么类型的请求,甚至是非HTTP请求(理论上,假设使用的Web容器支持这样的请求)都将会调用service方法。将来的某一天JavaEE有可能会添加新的Servlet用户处理文件传输协议(FTP)。出于这个原因,JavaEE中有许多可用于继承Servlet类。需要注意的是目前Java EE7支持的唯一Servlet协议就是HTTP,这也是你发现最底层实现Servlet类只有HTTPServlet的原因;

在大多数情况下,Servlet都继承自GenericServlet。GenericServlet仍然是一个不依赖于具体协议的Servlet,它只包含了一个抽象的service方法,同时还包含了几个辅助方法用于日志操作和从应用和Servlet配置中获取信息(具体参见Generic源码);

由于GenericServlet不依赖于任何协议,所以要处理HTTP协议的请求,就需要使用HttpServlet类,该类继承自GenericServlet,然后提供了响应每种HTTP方法类型的方法的空实现,如下:

由于目前为止Servlet只支持HTTP协议,所以我们将总是继承HttpServlet,下面我们创建如下一个Servlet,

package com.yxd.servlet;import javax.servlet.http.HttpServlet;public class HelloServlet extends HttpServlet {}

通过上述方式,该Servlet可以接受任何HTTP请求,但却返回一个405 Method Not Allowed错误。这是为什么呢?查看HttpServlet源码,就会发现,原来HttpServlet在提供针对不同的请求方法实现的时候,都添加了如下类似的实现,这就要求我们必须重写对应的请求方法,比如用get方式提交请求的,重写doGet(),其余依次类推


那好,接下来我们提供一个简单的doGet()方法实现,如下:

package com.yxd.servlet;import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {resp.getWriter().println("Hello, World!");}
}

现在该Servlet可以对GET请求作出响应,并在响应主体中显示出普通文本“Hello, World!”;有IO流知识的同学会发现这不就是一个通过响应对象获取一个字符打印输出流,然后通过这个流返回响应内容。可以看出通过Servlet后不再担心任何原生HTTP请求或响应的细节。那到底是谁干了这个工作呢?没错,Web容器会处理请求的解释,并从套接字(socket)中读取请求头和参数。在Servlet的方法返回之后,Web容器还将格式化响应头和主体,并协会到套接字中;

注意:学过IO流的会发现,获取了一个PrintWriter对象,最后为什么没有调用对应的close方法呢?一般来说,在Java中只需要关闭自己创建的资源即可。Web容器创建了该资源,所以它也会负责关闭该资源;
在完成并运行第一个Servlet时,可能会注意到init和destroy方法。那这两个方法有什么作用呢?当Web容器启动Servlet时,将会调用Servlet的init方法。在Web容器关闭Servlet时,将会调用Servlet的destory方法;

(二)Servlet的初始化方法和销毁方法

1、首先说说初始化方法,JavaEE API在Servlet接口中声明了如下方法:

同时在GenericServlet中提供了对Servlet接口中init方法的实现,但是又额外提供了一个不带参数的init方法的空实现,如图:,所以尽管可以重写原始方法,但是更推荐重写上述空实现的方法,因为如果之后忘记了调用父类中的方法,那么该Servlet可能无法正确实例化;

init方法可以完成许多操作。更为重要的是,init方法在Servlet构造完成之后自动得到调用,但在响应第一个请求之前。与构造器不同,在调用init方法时,Servlet中的所有属性都已经设置完毕,并提供了对ServletConfig和javax.servlet.ServletContext对象的访问。所以使用该方法可以读取属性文件,或者JDBC连接数据库。该方法的调用时机如下:

(1)如果无特殊配置,则将在第一次请求访问它接收的Servlet时调用;

(2)如果将Servlet配置为在Web应用程序部署和启动时自动启动,那么将随Web容器一同调用;

2、再来说说destroy(),先来看看它在Servlet的声明:

同样,在GenericServlet中提供了空实现,如下:

destory在Servlet不再接收请求之后立即调用。一般来说发生在Web的应用程序被停止或卸载,或者Web容器关闭时。它的调用时机是在卸载或关闭应用时立即调用,所以不需要等待垃圾回收在清理资源之前触发终止化器。因此应该使用destrory方法清理Servlet持有的资源(在所有请求的处理过程中);

(三)配置可部署的Servlet

在上述一、二中,我们了解且可以创建一个可以响应HTTP请求并发出问候的类,但是我们尚未编写指令告诉容器如何部署应用程序中的Servlet。由于一个Web项目的大部分配置项目都需要在部署描述符(web.xml)中部署,下面开始部署Servlet,分两部分进行:
1、向部署描述符中添加Servlet
2、将Servlet映射到URL
示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 下列web-app的XML Schema URI都是为了兼容JavaEE7而必须使用的URI -->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><!-- 设置应用程序在应用服务器中显示的名字 --><display-name>Hello World Application</display-name><!-- 向部署描述符中添加Servlet --><servlet><!-- 指定Servlet名字,一般是Servlet类首字母小写后的字符串 --><servlet-name>helloServlet</servlet-name><!-- Servlet类的完全限定名 --><servlet-class>com.yxd.HelloServlet</servlet-class><!-- 下面这个配置的作用表示Web容器在应用程序启动后立即启动Servlet,即调用init方法多用在比如某个Servlet的init方法需要完成许多工作,花费很长时间的情况 --><!-- 比如有多个Servlet都配置了该标签,按照值大小启动,即数越小启动越快;数一样时,按照在部署符中的顺序启动 --><load-on-startup>1</load-on-startup></servlet><!-- 将Servlet映射到URL --><servlet-mapping><!-- 需要与Servlet标签中的servlet-name属性值一致 --><servlet-name>helloServlet</servlet-name><!-- 所有访问应用程序相对URL/greeting的请求都将由helloServlet处理 --><url-pattern>/greeting</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list>
</web-app>

需要说明的有两点:

1、<servlet>和<servlet-mapping>标签中的子标签<servlet-name>属性值应该一致。Web容器通过这种方式关联这两个配置。如果应用程序在部署后的URL为:http://localhost:8080/helloweb,那么Servlet相应的URL地址为http://localhost:8080/helloweb/greeting
2、多个url-pattern可以映射到同一个Servlet,具体根据实际逻辑而定!

漫谈Servlet(一)相关推荐

  1. 互联网架构设计漫谈 (5)-搞清SpringCloud

    互联网架构设计漫谈 (5)-搞清SpringCloud 微服务发展至今有许多公司都提供了架构来协助搭建微服务平台,比较著名的有 Dubbo,DubboX,Spring Cloud.今天带大家来了解一下 ...

  2. Ajax接收Java异常_java – 处理来自Servlet的Jquery AJAX响应中的异常

    我的servlet代码是 try{ //something response.setStatus(201); out.print("Data successfully saved" ...

  3. JavaEE学习笔记之Servlet

    同一用户的不同页面的共享数据 1.1 cookie技术 1.2 sendRedirect()转向 1.3 隐藏表单 1.4 session技术 ###session技术: 当用户打开浏览器,访问某个网 ...

  4. 【JavaWeb】servlet与http请求协议

    Servlet: 概念: server applet (服务端小程序)运行在服务器端的小程序 Servlet就是一个接口,定义了Java类被浏览器访问到(Tomcat识别)的规则. 将我我们自定义一个 ...

  5. 使用最新版(2020)IntelliJ IDEA 创建Servlet项目

    一:选择左上端的File,创建Project,选择创建Web Application 项目: 注:不勾选Create web.xml 二:设置项目名称:helloworld,并创建一个Servlet( ...

  6. 2020了,还要学JSP嘛?入个门呗!毕竟Servlet亲兄弟~

    目录 1.什么是JSP 2.JSP原理 3.JSP基础语法 jsp表达式 jsp脚本片段 jsp声明 jsp注释 4.JSP指令 5.JSP行为 6.9大内置对象 7.EL表达式 格式 变量 [ ]与 ...

  7. 来谈谈Servlet~~

    目录 1.Servlet简介 2.第一个Servlet程序 3.Servlet原理 4.servlet-mapping的配置 5.关于ServletContext 1.共享数据 2.获取初始化参数 3 ...

  8. 使用Servlet完成单表的CRUD

    实现步骤 第一步:准备一张数据库表.(sql脚本) 第二步:准备一套HTML页面(项目原型)[前端开发工具使用HBuilder] 第三步:分析我们这个系统包括哪些功能 第四步:在IDEA当中搭建开发环 ...

  9. 适配器(GenericServlet)改造Servlet

    JavaWeb系列教程 JavaWeb-Servlet 模拟Servlet本质 使用IDEA开发Servlet程序 Servlet对象的生命周期 适配器(GenericServlet)改造Servle ...

最新文章

  1. 使用 FRP 反向代理实现 Windows 远程连接
  2. python numpy安装-Numpy安装
  3. python判断操作系统类型
  4. Qt QProces的使用
  5. ARC107——D - Number of Multisets
  6. eNSP模拟器RIP2动态路由,DHCP服务,ACL流控,组合使用的拓扑网络
  7. CSS3 弹性布局盒模型 Flex布局
  8. TinyURL生成器
  9. windows操作系统的使用 —— 资源监视器
  10. DICOM医学图像处理:基于DCMTK工具包学习和分析worklist
  11. 打印机驱动安装及换色带
  12. go语言基础(一)之文件读写
  13. 大主宰PHP文章,大主宰:沈苍生让李玄通放弃洛璃?牧尘受到眷顾!北溟再出手相助...
  14. MPC5607B串口接收中断程序
  15. c++实现maxpooling+利用OpenMP、SIMD优化代码
  16. Redis中setex与setnx的区别?
  17. ARM64+树莓派4b+JLINK仿真器实验环境搭建指南
  18. 你了解这些常用器件封装及其名字来历么?
  19. SCU - 4572 醉后不知天在水,满船清梦压星河【思维】
  20. Praat脚本-018 | Praat批量调整音量

热门文章

  1. C#树状图 初始默认选中节点
  2. linux 建议锁和强制锁
  3. 原创:Spring整合junit测试框架(简易教程 基于myeclipse,不需要麻烦的导包)
  4. 分支-13. 计算天数
  5. Oracle 获取每月最后一天的函数
  6. jQuery初识 - jQuery案例练习
  7. [jQuery基础] jQuery动效案例(一) -- 弹窗广告、对联广告
  8. Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks -译文
  9. 7-69 超市促销 (6 分)
  10. 6-4 链表逆置 (10 分)