1.servlet是什么
2.servlet生命周期
3. servlet 工作原理
4 .ServletContextListener全局监听器
什么是Servlet?
Servlet是JavaWeb的 三大组件之一 ,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
接收请求数据; 客户端发送请求至服务器
处理请求; 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
完成响应。 服务器将响应返回客户端
例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完成处理!Servlet需要我们自己来编写,每个Servlet必须实现javax.servlet.Servlet接口。
Web 服务器接收 HTTP 请求。
Web 服务器将请求转发到 Servlet 容器。
如果对应的 Servlet 不在容器中,那么将被动态检索并加载到容器的地址空间中。
容器调用 init() 方法进行初始化(仅在第一次加载 Servlet 时调用一次)。
容器调用 Servlet 的 service() 方法来处理 HTTP 请求,即读取请求中的数据并构建响应。
Servlet 将暂时保留在容器的地址空间中,可以继续处理其它 HTTP 请求。
Web 服务器将动态生成的结果返回到浏览器/客户端。
实现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的生命周期一般可以用三个方法来表示:
- init():仅执行一次,负责在装载Servlet时初始化Servlet对象
- service() :核心方法,一般HttpServlet中会有get,post两种处理方式。在调用doGet和doPost方法时会构造servletRequest和servletResponse请求和响应对象作为参数。
- 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“共生死了”
Tomcat启动时,通过loadOnStartUp 的加载顺序(正整数小的先被加载)自动加载servlet
在servlet容器加载的的时候,会加载这个ServletConfig配置类,同时重写init方法中带参数的方法,可以得到ServletContext对象。
Servlet容器是整个servlet的运行环境,初始化整个servlet容器的时候就会初始化加载web.xml文件,同时也会创建整个类的全局变量ServletContext。
servlet初始化的过程中,会创建servlet对象,这个对象就是web.xml中配置的servlet类的相关信息。
ServletContext是JavaWeb四大域对象之一:
PageContext;一个页面
ServletRequest;一次请求
HttpSession; 一次会话
ServletContext;整个WEB应用 服务器开始,其就存在,服务器关闭,其才释放。
servlet tomcat 和spring的关系
用spring搭建的web项目里的service为何为空?
为什么servlet不能交给spring容器管理?
(无法注入)
servlet上下文存储spring容器
tomcat(web服务器(Servlet容器中有
Context:表示一个Web应用程序,对应着一个Servlet上下文(ServletContext),可以包含多个Wrapper;
Wrapper:表示一个独立的Servlet;
Servlet容器和ServletContext的关系:
ServletContext是servlet与servlet容器之间的直接通信的接口。Servlet容器在启动一个Web应用时,会为它创建一个servletContext对象。每个web应用有唯一的servletContext对象。同一个web应用的所有servlet对象共享一个serveltContext,servlet对象可以通过它来访问容器中的各种资源。
ServletContext官方叫servlet上下文,服务器会为每一个工程创建一个对象,这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。
ApplicationContext是什么
ApplicationContext(spring容器)
Spring容器(父 )是管理service和dao的。
SpringMVC容器(子)是管理controller对象的。
XmlWebApplicationContext:从web应用的根目录读取配置文件,需要先在web.xml中配置,可以配置监听器或者servlet来实现
为什么要在web.xml注册监听器?
把spring容器放到全局作用域ServletContext中
使用监听器,当全局作用域被创建时,创建容器,放到ServletContext中
为什么要放全局作用域中?
容器对象需要在多个Servlet中使用,需要把容器对象放入到全局作用域ServletContext
因为监听器中要创建ApplicationContext对象,需要加载配置
监听器被创建后,会读取/WEB-INF/applicationContext.xml
目的是创建容器对象,创建了容器对象,就能把spring.xml配置文件中的所有对象都创建好,用户发起请求就可以直接使用对象
classpath:默认是从resource目录下
ConfigurableWebApplicationContext
继承
WebApplicationContext
继承
ApplicationContext
从servletContext全局作用域中获取容器对象,webApplicationContext 再从容器对象中获取service对象
各个容器的创建过程:
1、TOMCAT启动,
Servlet容器随即启动,然后读取server.xml配置文件,启动里面配置的web应用,为每个应用创建一个“全局上下文环境”(ServletContext);
2、创建Spring容器实例。
调用web.xml中配置的ContextLoaderListener,初始化WebApplicationContext上下文环境(即IOC容器),加载contextparam指定的配置文件信息到IOC容器中。WebApplicationContext在ServletContext中以键值对的形式保存。
3、创建SpringMVC容器实例。调用web.xml中配置的servlet-class,为其初始化自己的上下文信息,并加载其设置的配置信息到该上下文中。将WebApplicationContext设置为它的父容器。
4、此后的所有servlet的初始化都按照3步中方式创建,初始化自己的上下文环境,将WebApplicationContext设置为自己的父上下文环境。当Spring在执行ApplicationContext的getBean时,如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找。
https://www.cnblogs.com/jieerma666/p/10805966.html