Servlet的生命周期

目录

一.什么是servlet?

二.servlet的体系结构

三.servlet的主要任务

四.servlet的生命周期

(1)init()方法

(2)service()方法

  (3)destory()方法

五.servlet的线程安全问题

六.总结


一.什么是servlet?

     

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

servlet的应用:
  1.   创建Servlet
  2.  在类上使用@WebServlet注解,配置该Servlet的访问路径
  3.  继承HttpServlet
  4.  重写doPost()doGet()方法
  5.  启动Tomcat,浏览器输入URL访问该Servlet

示例代码:

@WebServlet("/ServletTest")
public class ServletTest implements  Servlet {
	private static final long serialVersionUID = 1L;

	@Override
	public void init(ServletConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
	System.out.println("hello servlet");
		
	}
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return null;
	}
}
URL:

 控制台:

使用servlet实现控制器:

 Tomcat和servlet的关系: 

    Tomcat 是Web应用服务器,是Apache开源软件组织下的一个软件项目。Tomcat作为Web服务器,可以通过Http协议与客户端(浏览器)进行数据交互。同时也可以来发布Web应用。tomcat与Web应用是由不同的开发商开发的,那么这两种不同的软件系统是如何进行交互的呢。答案就是通过Servlet(最主要的接口)。Servlet是由Oracle公司指定的一个接口,用来规范Web服务器与Web应用之间的交互。Oracle制定了一系列交互相关接口以及对交互时的一些细节做了规定。这些接口以及规定统称为Servlet规范。Servlet规范把能够发布和运行Java Web应用的Web服务器称为Servlet容器(如Tomcat)。
 

Servlet 的优点:

  • 方便:Servlet提供了大量的实用工具例程,如处理很难完成的HTML表单数据、读取和设置HTTP头,以及处理Cookie和跟踪会话等。

  • 跨平台:Servlet用Java类编写,可以在不同操作系统平台和不同应用服务器平台下运行。

  • 灵活性和可扩展性:采用Servlet开发的Web应用程序,由于Java类的继承性及构造函数等特点,使得应用灵活,可随意扩展。

  • Servlet具有功能强大、能够在各个程序之间共享数据、安全性强等特点。

二.servlet的体系结构

 

servlet接口:

  • Servlet接口规定了必须由Servlet类实现并且由Servlet引擎识别和管理的方法集。
  • Servlet接口的基本目标是提供与Servlet生命周期相关的方法,如:init()、service()和destroy()等。

ServletConfig接口:

  • 一个 Web 应用中可以存在多个 ServletConfig 对象,一个 Servlet 只能对应一个 ServletConfig 对象,即 Servlet 的初始化参数仅对当前 Servlet 有效。

GenericServlet抽象类:

  • GenericServlet是一个通用的协议无关的Servlet,它实现了Servlet和ServletConfig接口。
  • GenericServlet继承自Servlet,应该重写service()方法。

httpServlet类:

  •  HttpServlet指能够处理HTTP请求的Servlet,它在原有Servlet接口上添加了对HTTP协议的处理,它比Servlet接口的功能更为强大。

三.servlet的主要任务

Servlet 执行以下主要任务:

  • 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
  • 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
  • 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
  • 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
  • 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。

四.servlet的生命周期

        生命周期就是Servlet什么时候创建,调用了何种方法,最后在什么时候被销毁。我们之前学过的对象都是自己手动创建的,最后由JVM来销毁,而Servlet的整个生命周期,都是由tomcat服务器来控制的。

servlet的生命周期具体步骤:

(1)Servlet对象创建:接收到浏览器请求后,才创建对象

(2)Servlet初始化创建对象之后,会调用init()方法作用:是在Servlet对象创建后,执行一些初始化操作

(3)Servlet处理客户端请求:接收到请求之后调用service()方法在每次接到请求后都会执行

(4)Servlet面临对象的销毁当前Web应用卸载之前调用destroy()方法在应用卸载之前,可能需要释放一些资源,关闭某些连接。

具体流程:

(1)init()方法

           init()方法只会被调用一次,是在第一次访问(or 创建) Servlet 的时候被调用,在后续的每次请求时都不会再调用 init() 方法了, init()方法用于 Servlet 的初始化,可以简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

实现init()方法(实现servlet接口就会实现servlet的抽象方法):

         ServletConfig:代表的是配置信息。Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用ServletConfig对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过ServletConfig对象获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的Servlet容器进行通信。

(2)service()方法

        service()方法是Servlet的核心,是在servlet生命周期中的服务期,默认在HttpServlet类中实现,根据HTTP请求方法(GET、POST等),将请求分发到doGet、doPost等方法实现。

Servlet接口中定义了一个service()方法,而我们一般是使用HttpServlet,HttpServlet中对它进行了实现,将ServletRequest和ServletResponse转变成为HttpServletRequest和HttpServletResponse在service中实现。

一般来说service方法是不需要重写的,因为在HttpServlet中已经有了很好的实现,它会根据请求的方法名(GET,POST),调用doGet,doPos以及其他的doXXX方法,也就是说service是用来转向的,所以我们一般写一个servlet,只需要重写doGet或者doPost就可以了。

  • Servlet中的service方法用于应答浏览器请求,每次请求都会调用该方法
  • ServletRequest:封装了请求信息,可以从中获取到任何的请求信息。
  • ServletResponse:封装了响应信息,用于响应用户请求。
  • 这两个接口都是服务器给予实现的,并在服务器调用service方法时传入。

(3)destory()方法

        Java Servlet中destroy()的含义是,在容器决定销毁该Servlet之前,将立即执行内容。但是,如果您自己调用destroy()方法,则只执行内容,然后继续相应的过程。对于这个问题,destroy()被执行,然后servlet初始化完成。

首先调用destroy()方法,然后从容器中删除Servlet,然后最终进行垃圾回收。 destroy()方法通常包含用于释放将不会被垃圾收集的任何资源(如JDBC连接)的代码。

  • 在servlet容器调用destroy方法之前,它必须允许servlet的service方法中当前正在运行的所有线程完成执行,或超过服务器定义的时间限制。
  • 在Servlet实例上调用destroy方法后,容器可能不会将其他请求路由到该Servlet实例。
  • 如果容器需要再次启用Servlet,则必须使用Servlet类的新实例来启用。

五.servlet的线程安全问题

Servlet是线程不安全的:这是单列模式导致的。

单例模式就是:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

        当不同的请求都调用这一个servlet,单例模式只new ()一次,只在堆里申请了一个对象空间,即只实例化了一次。所以,不管来了多少请求,都是这一个实例在处理。如果多个请求在同一时刻出现,就会并发执行。

        Servlet体系是建立在java多线程的基础之上的,它的生命周期是由Tomcat来维护的。当客户端第一次请求Servlet的时候,tomcat会根据web.xml配置文件实例化servlet,当又有一个客户端访问该servlet的时候,不会再实例化该servlet,也就是多个线程在使用这个实例。

        多线程和单线程Servlet具体区别:多线程下每个线程对局部变量都会有自己的一份copy,这样对局部变量的修改只会影响到自己的copy而不会对别的线程产生影响,线程安全的。但是对于实例变量来说,由于servlet在Tomcat中是以单例模式存在的,所有的线程共享实例变量。多个线程对共享资源的访问就造成了线程不安全问题。

编写servlet线程安全的建议:

(1)用方法的局部变量保存请求中的专有数据。对方法中定义的局部变量,进入方法的每个线程都有自己的一份方法变量拷贝。任何线程都不会修改其他线程的局部变量。如果要在不同的请求之间共享数据,应该使用会话来共享这类数据。

(2)只用 Servlet的成员变量来存放那些不会改变的数据。有些数据在 Servlet 生命周期中不发生任何变化,通常是在初始时确定的,这些数据可以使用成员变量保存,如数据库连接名称、其他资源的路径等。

(3)对可能被请求修改的成员变量同步。有时数据成员变量或者环境属性可能被请求修改。当访问这些数据时应该对它们同步,以避免多个线程同时修改这些数据。

(4)如果 Servlet 访问外部资源,那么需要同步访问这些资源。例如,假设 Servlet 要从文件中读写数据。当一个线程读写一个文件时,其他线程也可能正在读写这个文件。文件访问本身不是线程安全的,所以必须编写同步访问这些资源的代码。在编写线程安全的 Servlet 时,下面两种方法是不应该使用的:

 (5)在 Servlet API 中提供了一个 SingleThreadModel 接口,实现这个接口的 Servlet 在被多个客户请求时一个时刻只有一个线程运行。这个接口已被标记不推荐使用。

 (6)对 doGet() 或doPost() 方法同步。如果必须在 Servlet 中使用同步代码,应尽量在最小的代码块范围上进行同步。同步代码越小,Servlet 执行得才越好。 

六.总结

  1.  service()是Servlet的核心,负责响应客户的请求。每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。
  2. Servlet是线程不安全的,在Servlet类中可能会定义共享的类变量,这样在并发的多线程访问的情况下,不同的线程对成员变量的修改会引发错误。
  3.  service()是用来转向的,所以我们一般写一个servlet,只需要重写doGet或者doPost就可以了。如果重写了service方法,那么servlet容器就会把请求交给这个方法来处理,倘若你重写的service方法没有调用doXXX,即使你在Servlet中又重写了其他doGet doPost等也是不回被调用的因为Servlet的service被自动调用。
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值