Servlet的生命周期

news2024/11/25 6:34:39

servlet

1.servlet是什么

2.servlet生命周期

3. servlet 工作原理

4 .ServletContextListener

什么是Servlet?

Servlet是JavaWeb的 三大组件之一 ,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:

  • 接收请求数据;  客户端发送请求至服务器

  • 处理请求; 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器

  • 完成响应。 服务器将响应返回客户端

  例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完成处理!Servlet需要我们自己来编写,每个Servlet必须实现javax.servlet.Servlet接口。

实现Servlet有三种方式:

  • 实现javax.servlet.Servlet接口;

  • 继承javax.servlet.GenericServlet类;

  • 继承javax.servlet.http.HttpServlet类; 

GenericServlet是Servlet接口的实现类。

HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持。

Servlet中的方法由Tomcat来调用。并且Servlet的对象也不由我们来创建,由Tomcat来创建!

在web.xml中配置Servlet的目的是把访问路径与一个Servlet绑定到一起

再使用springmvc创建项目时servlet-class 为 

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

或者使用注解 ` @RequestMapping`

<servlet>		
    <servlet-name>hello</servlet-name>		
    <servlet-class>org.csmf.servlet.HelloServlet</servlet-class>	
</servlet>	
<!-- <servlet>`和`<servlet-mapping>`通过`<servlet-name>`这个元素关联在一起了!-->
<servlet-mapping>		
    <servlet-name>hello</servlet-name>		
    <url-pattern>/helloworld</url-pattern>	
</servlet-mapping> 

Servlet的生命周期

Servlet的生命周期可以分为初始化阶段,运行阶段和销毁阶段三个阶段

public interface Servlet { 
    //初始化
    public void  init(ServletConfig config)  throws  ServletException; 
    public ServletConfig getServletConfig();  //返回由Servlet容器传给init( )方法的ServletConfig对象。
    // 运行
    public void  service(ServletRequest req, ServletResponse res) throws      ServletException, IOException;      
    public  String getServletInfo();  //返回Servlet的一段描述,可以返回一段字符串。  
    //销毁   
    public  void   destroy();
}

Servlet的生命周期一般可以用三个方法来表示:

  1. init():仅执行一次,负责在装载Servlet时初始化Servlet对象
  2. service() :核心方法,一般HttpServlet中会有get,post两种处理方式。在调用doGet和doPost方法时会构造servletRequest和servletResponse请求和响应对象作为参数。
  3. destory():在停止并且卸载Servlet时执行,负责释放资源

Servlet的出生

服务器会在Servlet 第一次被访问时创建

一个Servlet类型,服务器只创建一个实例对象

首次访问servlet时,先查看是否已经创建过,如果没有,服务器才会通过反射来创建实例。再次访问时,就直接使用上次创建的实例。

在Servlet被创建后,服务器会马上调用Servlet的void init(ServletConfig)方法。

  • ServletConfig 配置对象

        它对应Servlet的配置信息,对应web.xml文件中的<servlet>元素。

        String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值;

        Enumeration getInitParameterNames(String name):用来获取在web.xml中配置的所有初始化参数名称

ServletConfig对象 servlet配置对象

ServletContext对象  servlet的上下文对象

   ServletContext getServletContext(); 获得ServletContext对象

  • ServletContext  

         ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。

ServletContext翻译成中文叫做“Servlet上下文”或者“Servlet全局”,但是这个翻译我认为翻译的实在是有点牵强,也导致了许多的开发者不明白这个变量到底具体代表了什么。其实ServletContext就是一个“域对象”,它存在于整个应用中,并在在整个应用中有且仅有1份,它表示了当前整个应用的“状态”,你也可以理解为某个时刻的ServletContext代表了这个应用在某个时刻的“一张快照”,这张“快照”里面包含了有关应用的许多信息,应用的所有组件都可以从ServletContext获取当前应用的状态信息。ServletContext随着程序的启动而创建,随着程序的停止而销毁。通俗点说,我们可以往这个ServletContext域对象中“存东西”,然后也可以在别的地方中“取出来”。
 

      

因为有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中保存在ServletContext中的对象被称作属性。

ServletContext中的下列方法负责处理属性:

Object getAttribute(String var1);   是获取对象容器中的数据值;
Enumeration<String> getAttributeNames();
void setAttribute(String var1, Object var2);
void removeAttribute(String var1);

Servlet服务

 当服务器每次接收到请求时,都会去调用Servlet的service(ServletRequest req, ServletResponse res)方法来处理请求。

   Servlet容器对于接受到的每一个Http请求,都会创建一个ServletRequest对象和一个ServletResponse对象,并把这两个对象传递给Servlet的Sevice( )方法

  • ServletRequest 请求对象

         它封装了所有与请求相关的数据

        

        String getParameter(String var1);//返回请求参数的值

  • ServletResponse 响应对象

        在service()方法中完成对客户端的响应需要使用这个对象

ServletRequest和ServletResponse的实例由服务器创建,然后传递给service()方法。

Servlet的销毁

在服务器被关闭时,先去调用Servlet的destroy()方法 ,再去销毁Servlet

以下过程属于初始化阶段是 A C D

A.加载Servlet类及.class对应的数据
B.创建servletRequest和servletResponse对象  运行阶段
C.创建ServletConfig对象 
D.创建Servlet对象

初始化阶段:Servlet启动,会读取配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,将ServletConfig作为参数来调用init()方法。所以选ACD。B是在调用service方法时才构造的

如何获取ServletContext设置的参数值? B

A.context.getParameter() 是获取POST/GET传递的参数值;
B.context.getInitParameter() 获取Tomcat的server.xml中设置Context的初始化参数
C.context.getAttribute()  是获取对象容器中的数据值;
D.context.getRequestDispatcher() 请求转发。
通过ServletConfig接口的getInitParameter(java.lang.String name)方法可以获得Servlet的初始化参数

session存放在哪里?

cookie存放在哪里?

HttpServlet

springmvc中web.xml的监听器给干嘛用?

web.xml

  <!--配置一个监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

ContextLoaderListener 继承ContextLoader 实现 ServletContextListener 

这个类也实现了 监听ServletContext初始化和销毁 的两个方法 

ServletContextListener(Servlet全局监听器)

监听ServletContext初始化和销毁  ServletContextListener两个方法

 spring给我们提供的这个监听器类是如何实现的?

当ServletContext初始化后,Spring IOC容器也能跟着初始化的呢?

ApplicationContext是spring的核心 应用的容器 Spring上下文 spring容器负责管理Bean与Bean之间的依赖关系。

webApplicationContext继承自ApplicationContext 该接口提供了 获取 ServletContext 对象的方法

//WebApplicationContext接口
@Nullable
ServletContext getServletContext();

为 web 应用 提供 配置(获取 ServletContext)的接口

ServletContext 同一个web应用的所有Servlet对象共享一个 ServletContext,Servlet对象可以通过它来访问容器中的各种资源 存取共享数据方法: WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。

spring的启动过程:

首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;

其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;

 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
     // 先判断当前servlet 中是否存ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE根容器标识
        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
            //抛异常  因为已经存在根应用程序上下文
            throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!");
        } else {
            servletContext.log("Initializing Spring root WebApplicationContext");
            Log logger = LogFactory.getLog(ContextLoader.class);
            if (logger.isInfoEnabled()) {
                logger.info("Root WebApplicationContext: initialization started");
            }
            用来计算初始化这个过程会耗费多少时间
            long startTime = System.currentTimeMillis();
​
        try {
                // 1.默认会实例化一个根容器
            if (this.context == null) {
                // spring 会生成一个父级ioc容器 XmlWebApplicationContext
                this.context = this.createWebApplicationContext(servletContext);
            }
XmlWebApplicationContext是ConfigurableWebApplicationContext的实现类,指定的contextClass应该是ConfigurableWebApplicationContext的实现类
​
            if (this.context instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
                if (!cwac.isActive()) {
                    if (cwac.getParent() == null) {
                        //2.为创建的root 容器设置父上下文 一般父上下文为空
                        ApplicationContext parent = this.loadParentContext(servletContext);
                        cwac.setParent(parent);
                    }
                    //3.配置容器并刷新
                    this.configureAndRefreshWebApplicationContext(cwac, servletContext);
                }
            }
​
​
            //  注册标识 全局共享 将其存储到ServletContext中,避免再被初始化
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
            
            //保存到当前线程
            ClassLoader ccl = Thread.currentThread().getContextClassLoader();
            if (ccl == ContextLoader.class.getClassLoader()) {
                currentContext = this.context;
            } else if (ccl != null) {
                currentContextPerThread.put(ccl, this.context);
            }
​
            if (logger.isInfoEnabled()) {
                long elapsedTime = System.currentTimeMillis() - startTime;
                logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");
            }
​
            return this.context;
        } catch (Error | RuntimeException var8) {
            logger.error("Context initialization failed", var8);
             //即使初始化失败仍不允许有再次的初始化        
           
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
            throw var8;
        }
    }
}

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
   //获取context的类
    //在determineContextClass()方法中 经过两个判断来返回context 类的类信息
    Class<?> contextClass = this.determineContextClass(sc);
    //判断是否是ConfigurableWebApplicationContext 的子类
    if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
        throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
    } else {
        // 生成WebApplicationContext 的对象
        return (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
    }
}

ConfigurableApplicationContext 接口:ApplicationContext 的子类,提供 配置 一个 应用上下文的 属性,如设置 environment,BeanFactoryPostProcessor,ApplicationListener,ProtocolResolver 等;

分析到这一步,我们发现Spring容器在这个方法中被实例化了。接下来,就让我们整理一下整体的思路:

当Servlet容器启动时,ServletContext对象被初始化,然后Servlet容器调用web.xml中注册的监听器的

public void contextInitialized(ServletContextEvent event)

方法,而在监听器中,调用了this.initWebApplicationContext(event.getServletContext())方法,在这个方法中实例化了Spring IOC容器。即ApplicationContext对象。

因此,当ServletContext创建时我们可以创建applicationContext对象,当ServletContext销毁时,我们可以销毁applicationContext对象。这样applicationContext就和ServletContext“共生死了”

ServletContext是JavaWeb四大域对象之一:

  • PageContext;一个页面

  • ServletRequest;一次请求

  • HttpSession; 一次会话

  • ServletContext;整个WEB应用 服务器开始,其就存在,服务器关闭,其才释放。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/84300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于RSS和TOA两种方法的无线传感器网络定位测量算法matlab仿真

up目录 一、理论基础 二、核心程序 三、测试结果 一、理论基础 无线传感器网络(Wireless Sensor Networks, WSN)是一种分布式传感网络&#xff0c;它的末梢是可以感知和检查外部世界的传感器。WSN中的传感器通过无线方式通信&#xff0c;因此网络设置灵活&#xff0c;设备位…

去哪儿旅行微服务架构实践,全文带图加详细解析,带你多方面了解

文章目录一、背景介绍二、微服务架构模式的最佳实践三、微服务开发效率提升实践四、服务治理实践五、ServiceMesh 尝试六、总结今天我带来的主题是去哪儿旅行 微服务架构实践。我将从以下几个方面进行介绍&#xff1a;背景介绍微服务架构模式的最佳实践微服务开发效率的提升实践…

前台用户注册_发送邮件配置

在用户注册成功后&#xff0c;要向用户的邮箱发送一封激活邮件&#xff0c;发送邮件需要在系统中配置发件人&#xff0c;同学们使用自己的邮箱作为发件人即可。 配置邮箱第三方登录。 我们在系统中使用邮箱发送邮件属于第三方登录&#xff0c;而市面上的邮箱默认是不能第三方…

自监督学习系列(四):基于蒸馏的图片掩码学习

前文 好久不见&#xff01;自监督系列文章继续更新啦&#xff01;在前几期的文章我们介绍了基于辅助任务&#xff0c;对比学习&#xff0c;和图片掩码学习的自监督学习范式 (对比学习&#xff0c;图片掩码学习其实也可以归属于基于辅助任务的自监督学习&#xff0c;由于这两类…

百度安全怎么查询,怎么彻底解决百度安全弹出的风险提示

当我们在百度搜索自己的网站时&#xff0c;搜索结果中出现各种风险提示&#xff0c;比如安全联盟提醒您&#xff1a;该网站可能存在安全风险&#xff0c;请谨慎访问&#xff01; 别慌&#xff01;今天我们就来解决百度安全弹出的风险提示的问题。 第一步&#xff1a;查询网站…

Python 自动化测试框架unittest与pytest的区别

这篇文章主要讲unittest与pytest的区别&#xff0c;pytest相对unittest而言&#xff0c;代码简洁&#xff0c;使用便捷灵活&#xff0c;并且插件很丰富。 Unittest vs Pytest 主要从用例编写规则、用例的前置和后置、参数化、断言、用例执行、失败重运行和报告这几个方面比较…

传奇GOM引擎微端架设教程

传奇GOM引擎微端架设教程 GOM引擎架设微端需要准备好微端程序&#xff0c;用网站下载在服务器的版本 &#xff08;注&#xff1a;本文章图有打码处因平台GZ原因需打码望读者理解&#xff09; Mirserver文件一般都是自带微端程序的&#xff0c;偶尔也有版本没有微端程序那我们…

基于多目标遗传算法(NSGA-II)和多目标粒子群算法(MOPSO)的分布式仿真系统双目标负载平衡模型【Matlab代码实现】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清…

Oracle单机部署:GI安装

Oracle单机部署&#xff1a;GI安装存储配置ASM磁盘空间评估GI单机安装配置GI图形化安装流程安装后测试&#x1f42c; 使用grid用户来安装GI。 存储配置 Oracle存储支持Oracle ASM、Oracle ACFS、本地文件系统、网络文件系统&#xff08;NFS/NAS&#xff09;、Oracle Memory S…

RK3588平台开发系列讲解(RTC篇)RTC的使用

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、RTC简介二、HYM8563驱动配置2.1、设备树配置2.1、驱动代码三、RTC的使用3.1、SYSFS接口3.2、PROCFS接口3.3、IOCTL接口沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍RK3588平台RTC驱动及使用方…

玩以太坊链上项目的必备技能(基本类型转换以及推断-Solidity之旅六)

基本类型之间的转换 熟悉过其他编程语言的您&#xff0c;对基本类型之间的转换并不陌生吧&#xff01;当然&#xff0c;这基本类型进行转换可分为隐式转换和显示转换。 隐式转换 Solidity 支持隐式转换&#xff0c;通过编译器自动进行转换&#xff0c;而不要开发人员的干涉&…

信道估计算法误码率仿真,对比不同导频长度,对比不同信道估计算法包括CS-OMP,LS,MMSE

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 所谓信道估计&#xff0c;就是从接收数据中将假定的某个信道模型的模型参数出来的过程。如果信道是线性的话&#xff0c;那么信道估计就是对系统冲激响应进行估计。 CS-OMP 正则正交匹配追踪(Re…

分布式操作系统 - 5.分布式命名管理

文章目录1.基本概念2.非结构化命名管理2.1 简单的实体定位方法&#xff1a;广播和多播方法&#xff08;1&#xff09;广播方法&#xff08;broadcast&#xff09;&#xff08;2&#xff09;多播方法&#xff08;multicast&#xff09;&#xff08;3&#xff09;问题&#xff1a…

图形API学习工程(30):尝试使用panorama来代替Cubemap作为全景图

工程GIT地址&#xff1a;https://gitee.com/yaksue/yaksue-graphics 前言 为了能得到全方位的光照数据&#xff0c;我之前学习了使用CubeMap作为全景图。CubeMap包含六张贴图对应了上下左右前后六个方向的数据。但是最近在下载全景图的资源时&#xff0c;看到很多并非是CubeM…

Python基于Django的毕业设计论文提交过程管理系统

项目介绍 在各学校的教学过程中&#xff0c;django过程管理系统是一项非常重要的事情。随着计算机多媒体技术的发展和网络的普及。采用当前流行的B/S模式以及3层架构的设计思想通过Python技术来开发此系统的目的是建立一个配合网络环境的django过程管理系统的平台&#xff0c;这…

c#入门-访问基类成员

调用基类构造器 在构建派生类前&#xff0c;会首先构建出完整的基类。 即便是派生类无权访问的成员&#xff0c;也会存在。 因此才能保证派生类能完全地当作基类来使用。 因此&#xff0c;在执行派生类的构造器前&#xff0c;首先需要先调用基类的构造器。 而如果基类没有&am…

017 | 精准扶贫视野下非遗传承的研究与启示——以三峡皮影为例 | 大学生创新训练项目申请书 | 极致技术工厂

&#xff08;一&#xff09;研究目的 百年党建视域下&#xff0c;全面建成小康社会的历史目标已成功达成&#xff0c;但东西部经济发展的不平衡、不平均依旧是新时代发展中亟需解决的问题。坚持党的领导&#xff0c;响应西部大开发的战略号召&#xff0c;本团队深入探访于2018…

S2SH药膳馆会员管理系统计算机专业毕业论文java毕业设计开题报告

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之S2SH药膳馆会员管理系统-IT实战营_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzygog…

基于jsp+mysql+ssm足球新闻发布网站-计算机毕业设计

项目介绍 同完成整个足球新闻发布系统的设计开发。系统实现的功能主要包括&#xff1a;前台浏览足球新闻的功能&#xff1b;后台用户在成功登录该系统的后台时&#xff0c;可以对用户、足球新闻类别、足球新闻、留言进行添加、修改和删除等功能&#xff1b;以及对用户名密码等…

Arthas(Java 应用诊断利器)

文章目录Arthas使用背景Arthas&#xff08;阿尔萨斯&#xff09;能做什么&#xff1f;Arthas Spring Boot StarterArthas Arthas 是由Alibaba开源的Java监控诊断工具&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情…