05月13, 2019

Java Web--Servlet--初识Servlet,Servlet的继承关系与生命周期

初识Servlet-Servlet继承关系与生命周期

一、Servlet产生背景

网页有静态和动态之分。静态的只能看看,而动态可以实现客户端和服务器的交互,比如登录的功能,我们输入用户名和密码后提交到服务器,服务器会处理这些信息,如果正确的话则进入主页。若不正确,则给出提示信息。这是我们很常实现的例子,可是我们有没有想过:客户端到服务器之间这个交互的过程是怎么实现的?Java当然就是通过Servlet来实现

二、Servlet是什么

Servlet(Server Applet),全称Java Servlet,是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。

2.1、广义上来讲

从本质上来讲,Servlet就是一个特殊的Java类,说它特殊是因为这个Java类必须直接或间接地实现Servlet接口(javax.servlet.Servlet),我们自定义的Servlet更多是采用继承HttpServlet的方式,以达到间接实现Servlet接口的目的。

Servlet还有一个比较特殊的地方:必须运行在Web容器(服务器)中,不能像普通类使用main方法访问,它的方法由服务器在相应情况下调用执行。一般来说自定义Servlet要覆盖其doGet和doPost方法,根据请求是GET/POST方式会自动调用相应的doGet/doPost方法。

又要实现接口,又只能在Web容器中运行,那么Servlet的任务就来了:

  • 获取请求数据
  • 处理请求
  • 完成响应

2.2、狭义上来讲

首先要明白的是,JavaEE实际上是sun公司定义的一系列技术标准所组成的平台,用来B/S结构的应用程序。所以它实质是一套体系或者说是一套标准(其中如我们所熟知的JSP、JSTL和Servlet都隶属其中),所以有了以下Servlet的狭义说法。

所以,狭义的Servlet是指Java语言实现的一个接口,再白话一点,你可以理解为,Servlet就是一套规范,不过是以接口的形式展现。下面摘自J2EE的API:

A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.

可以看到,在J2EE这套大标准中,Servlet是作为服务器端用以交互请求和响应的一套标准

而符合J2EE这套标准(包括Servlet标准)的产品叫“实现”,不同服务器对待这套标准的方式不同,我们也可以说,“实现”是不同的,所以像JBossTomcatWebLogic都是J2EE标准的“实现”。

三、Servlet的开发流程

狭义上讲,servlet是java语言实现的一个类,所以我们就要根据这个类进行相应的扩展开发. 开发流程如下:

  • 编写一个java类,继承HttpServlet类
  • 重写HttpServlet类的doGet方法和doPost方法
  • 配置web.xml文件,或者使用注解对servlet进行配置

3.1、通过IDEA创建Java Web工程

(1)、创建web工程

-w798

(2)、定义工程名与模块名

-w798

(3)、项目的基本结构

-w308

注意:WEB-INF下的资源在外部是不能通过URL访问的

(4)、创建Servlet

-w570

(5)、定义Servlet名与配置方式

-w488

(6)、自定义Servlet的基本结构

-w756

(7.1)、HelloServlet对应的web.xml配置

-w693

web.xml配置说明:

<webapp>
<!-- 配置一个servlet -->
  <!-- servlet的配置 -->
  <servlet>
      <!-- servlet的内部名称,自定义。尽量有意义 -->
      <servlet-name>HelloServlet</servlet-name>
      <!-- servlet的类全名: 包名+简单类名 -->
      <servlet-class>com.yingside.controller.HelloServlet</servlet-class>
  </servlet>


  <!-- servlet的映射配置 -->
  <servlet-mapping>
      <!-- servlet的内部名称,一定要和上面的内部名称保持一致!! -->
      <servlet-name>HelloServlet</servlet-name>
      <!-- servlet的映射路径(访问servlet的名称) -->
      <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</webapp>

如果使用web.xml配置,还可以直接使用注解配置

(7.2)、注解配置HelloServlet

-w760

3.2、Servlet映射路径的配置问题

  • 精确匹配 精确匹配就是我们上面用的那种方式,使用固定的url来访问这个servlet,这种没什么需要说明的
  • 模糊匹配 模糊匹配就是比较有意思的了,通过模糊匹配,我们可以让好多路径映射到同一个servlet,模糊匹配一般有如下格式
/*                任意路径都映射到这个servlet
/home/*        /home下的任意路径映射到该servlet
*.(*.do  *.action *.html)    /任意路径.do/action/html

这里面有两点是需要注意的,一是url要么以/开头,要么以*开头,其他的都是非法的

四、Servlet的生命周期

一般来讲,servlet只会初始化一次,也就是整个过程中只存在一个servlet对象,即便是有多次访问,依然只有一个对象,这个对象是可以复用的.我想你一定会好奇这个servlet究竟是在什么时候创建的,所以就来讲一下servlet的生命周期,所谓的生命周期我们在java基础知识中一定也了解过,就是servlet类究竟在什么时候创建,调用了何种方法,最后在什么时候被销毁.我们之前学过的对象都是自己手动创建,最后由JVM来销毁的,而servlet的整个生命周期,都是由tomacat,也就是服务器控制的 我们以一张图来了解一下:

可以看到,servlet共有三个关键的方法,分别是init(),service(),destroy().

init方法只会调用一次,只是在创建servlet实例的时候才会创建

service方法,是进行数据处理的,只要接受了一次请求,就会被调用一次

destroy方法,销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象,同样也是调用一次

关键是init(),service(),destroy()这些是什么?

五、Servlet的继承关系

假如现有我们自定义的一个Servlet,继承HttpServlet,那么实际上它的继承链如下图:

可以看到,核心的部分在于: 两个顶级接口 Servlet ServletConfig 接口的实现类 GenericServlet 基于HTTP协议的实现类 HttpServlet

我们剥离一下,把不需要看的去掉,再把方法显示一下,可清晰知道Servlet的整体继承关系如下:

其中重点摘录部分进行说明:

  • ServletConfig Servlet的配置信息,常用来在Servlet初始化时进行信息传递

    • getServletContext() 获取Servlet运行的上下文环境对象,可以获取对应信息(如Servlet路径),存取容量级的变量
    • getInitParameter(String name) 获取初始化参数(web.xml中配置的init-param)
  • GenericServlet 一般的Servlet,实现了Servlet和ServletConfig接口

    • init(ServletConfig config) 初始化方法,方法中调用了init()
    • init() 初始化方法,方法体为空,主要用于自定义Servlet的覆盖
    • service(ServletRequest request, ServletResponse response) 抽象方法service,要求继承类实现
    • destory() Servlet销毁前要执行的方法
  • HttpServlet 基于HTTP协议的实现类

    • service(ServletRequest request, ServletResponse response) 实现了GenericServlet的抽象方法,调用了service(HttpServletRequest, HttpServletResponse)
    • service(HttpServletRequest request, HttpServletResponse response) 根据请求的不同调用了doGet或doPost方法
    • doGet() 处理GET方式的请求
    • doPost() 处理POST方式的请求

根据Servlet的继承关系,详细的Servlet生命周期应该是下面这个样子:

  • 初始化
    • 构造方法
    • init(ServletConfig config)
    • init()
  • 提供服务
    • service(ServletRequest request, ServletResponse response)
    • doGet() / doPost()
  • 销毁
    • destory()

最后简单总结下要点:

  • Servlet只初始化一次,它是单例的,只有一个实例,通过多线程访问。即Servlet是多线程单实例的
  • 实例化过程中,先调用构造方法,再调用init方法,所以初始化操作可以覆盖写到init方法中
  • 请求方式不同会调用doGet()或doPost()方法
  • 根据实际情况在Servlet销毁前调用其destroy()方法

本文链接:http://www.yanhongzhi.com/post/servlet_1.html

-- EOF --

Comments