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的生命周期一般可以用三个方法来表示:
- 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“共生死了”
ServletContext是JavaWeb四大域对象之一:
-
PageContext;一个页面
-
ServletRequest;一次请求
-
HttpSession; 一次会话
-
ServletContext;整个WEB应用 服务器开始,其就存在,服务器关闭,其才释放。