Servlet入门、生命周期和初始化参数 Love The Way You Lie 2022-04-04 05:18 143阅读 0赞 JavaWeb:是用Java技术来解决相关web(Web就是在Http协议基础之上, 利用浏览器进行访问的网站)互联网领域的技术总和. ### 一、Servlet与Servlet容器 ### **1、什么是Servlet** Servlet是一个JavaEE的**组件**,Servlet是一个程序(类),只不过必须要遵循Servlet的规范,必须实现Servlet接口 Servlet也是JavaEE中的一个**规范**,服务器其实是对Servlet的实现。 **Java Servlet**(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容。即 运行在服务器端以多线程的方式处理客户端请求的小程序。 **2、Servlet容器** Servlet容器也叫做Servlet引擎,是Web服务器或应用程序服务器的一部分,Servlet没有main方法,不能独立运行,它必须被部署到Servlet容器中,由容器来实例化和调用 Servlet的方法,Servlet容器在Servlet的生命周期内包容和管理Servlet。管理和运行Servlet/JSP的容器也称为**Web容器**。 Web容器的产品:Tomcat,JBoss,WebSphere,WebLogic 等等 **3、Servlet可以完成以下功能** 1)创建并返回客户请求的动态HTML页面 2)创建可以嵌入到 HTML页面的HTML片段 3)与其他服务器(如数据库或基于Java的应用程序)进行通信 ### 二、搭建一个Servlet程序 ### **1、新建一个 dynamic web project动态的 JavaWeb项目** **2、新建一个 DemoServlet类** ** Servlet的含义:运行在服务器端的以多线程的方式处理客户端请求的小程序** ** **可以让 DemoServlet类去 implements Servlet接口或 extends GenericServlet类或 extends HttpServlet类 import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloServlet implements Servlet{ @Override public void init(ServletConfig config) throws ServletException { System.out.println("init"); } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("service"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { System.out.println("destroy"); } } **3、在web.xml中注册Servlet的实现类** <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>DemoServlet</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 1.注册servlet servlet-name的值是可以自定义的 servlet-class 包名加上类名 --> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>cn.jq.demo.HelloServlet</servlet-class> </servlet> <!-- 2.给已注册的servlet,映射一个url地址 servlet-name的值和servlet标签中的servlet-name值一致 url-pattern:servlet的访问方式 是可以自定义的,但是必须以 / 打头 --> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app> **4、项目部署到服务器** 浏览器访问:http://127.0.0.1:8080/DemoServlet/hello,然后 stop服务器 ![20190925094732147.png][] ![20190925094634297.png][] ## ## ### 三、Servlet的生命周期 ### Servlet的生命周期:Servlet对象的创建,初始化,运行,销毁操作的整个过程。即阐述Servlet从产生到毁灭的整个过程。 服务器(Tomcat)管理了Servlet对象的生命周期,Servlet的创建,初始化,运行,销毁行为的整个过程都是由Tomcat来负责调用的, **1、新建一个 LifeServlet类,注册同上** public class LifeServlet implements Servlet{ public LifeServlet() { System.out.println("构造方法"); } // 初始化阶段 @Override public void init(ServletConfig config) throws ServletException { System.out.println("init"); } // 获取Servlet的配置信息对象 @Override public ServletConfig getServletConfig() { return null; } // 响应客户请求阶段 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("service"); } // 获取Servlet的信息(作者,版权等) @Override public String getServletInfo() { return null; } // 终止阶段 @Override public void destroy() { System.out.println("destroy"); } } ![20190925105027239.png][] **2、Servlet生命周期相关方法** **1)Servlet对象的构造方法** 最先被执行,构造方法被执行意味着创建实例,且只会被执行一次,意味着Servlet是单例的,在整个Servlet容器中每个具体的Servlet实现类都只有一个实例! **2)init方法** 在一个Servlet的生命周期中,构造方法执行之后,马上被执行,且只会执行一次,之后无论用户执行多少次请求,都不会在调用该方法。 关于init方法的执行时机,有两种方式可选: servlet默认是在用户第一次访问的时候创建而且只创建一个对象 是单例模式的(保证一个类只有一个对象产生), 也可以设置Servlet容器启动时自动装载某些Servlet,这时创建的servlet对象也是单例模式的。 实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码: <servlet> <servlet-name>LifeServlet</servlet-name> <servlet-class>cn.jq.demo.LifeServlet</servlet-class> <!--若为大于0的正整数(默认值为0)时表示web应用启动时,自动装载对应的Servlet,整数越小,越优先执行,只执行一次随web应用启动时。 若为负数,则会在第一次请求时被执行对象的Servler(和默认值一样)。 --> <load-on-startup>1</load-on-startup> </servlet> **3)service方法** 当一个客户请求该Servlet时,实际的处理工作全部有service方法来完成,service方法用来处理客户端的请求,并生成格式化数据返回给客户端。 每一次请求服务器都会开启一个新的线程并执行一次service方法,service是由web容器来调用的。 **4)destroy方法** 该方法在整个生命周期中,也是只会被调用一次,在Servlet对象被销毁是调用,在servlet中,我们可以做一些资源的释放等操作,执行destory方法之后的servlet对象,会等待jvm虚拟机的垃圾回收机制择时回收。 **总结:**Servlet的生命周期:构造器 -> init方法 -> service方法(循环)-> destroy方法 注意: 1)Servlet类的构造器必须使用 public修饰 2)Servlet类必须是无参数构造器(不写默认是)。原因:底层创建Servlet对象是 Class.newInstance()方式,必须有公共的无参数构造器 ### 四、Servlet的请求流程 ### 对上面的访问大致分析 Servlet的请求流程: 1、浏览器访问发送请求:http://127.0.0.1:8080/DemoServlet/life 2、Tomcat 解析请求:/DemoServlet/life 上下文路径:/DemoServlet 资源名称: /life 3、解析Tomcat根 /cong/server.xml文件,获取其中所有的<Context>元素,并找到 path属性值为 /DemoServlet的元素,在读取该<Context>元素并获取docBase属性值,该属性值就是当前访问的Web项目的根路径。 <Context docBase="DemoServlet" path="/DemoServlet" /> 4、从该Web项目的根路径下找到 /WEB-INF/web.xml 文件 5、读取 web.xml文件,获取所有的<url-pattern>元素,并判断查到值为 /life。 找到:进入第6步 找不到:报 404错误 6、通过资源名称 /life,找到当前Servlet的全限定名:cn.jq.demo.LifeServlet 7、从Servlet的实例缓存池(Map集合)中获取 cn.jq.demo.LifeServlet对应的对象 Map<String, Servlet> cache = ...; 若为第一次请求:进入第8步,否则:进入第11步。 8、使用反射创建Servlet对象 Servlet obj = Class.forName("cn.jq.demo.LifeServlet").newInstance(); 9、把创建的Servlet对象存储到Servlet实例缓存池中,供下次请求使用。 cache.put("cn.jq.demo.LifeServlet", obj ); 10、Web容器创建 ServletConfig对象,并调用 init方法,来完成初始化操作 11、Web容器容器创建 ServletRequest和 ServletResponse对象,并调用service方法处理请求 12、在service方法中,通过ServletResponse对象对当前请求的客户端作为响应。 ### 五、Servlet初始化参数 ### **1、ServletConfig 接口**:表示当前的 Servlet的配置信息对象 在web.xml中,每个Servlet可以单独配置/获取其初始化的配置信息。可以用一个或多个<init-param>标签(在Servlet标签里面)为 Servlet配置一些初始化参数。 ** 1)Servletconfig接口的方法:** <table> <tbody> <tr> <td style="width:154px;"><code><a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html?is-external=true" rel="nofollow">String</a></code></td> <td style="width:693px;"><code><a href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletConfig.html#getInitParameter-java.lang.String-" rel="nofollow">getInitParameter</a>(<a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html?is-external=true" rel="nofollow">String</a> name)</code> <p>Gets the value of the initialization parameter with the given name.</p> </td> </tr> <tr> <td style="width:154px;"><code><a href="http://docs.oracle.com/javase/7/docs/api/java/util/Enumeration.html?is-external=true" rel="nofollow">Enumeration</a><<a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html?is-external=true" rel="nofollow">String</a>></code></td> <td style="width:693px;"><code><a href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletConfig.html#getInitParameterNames--" rel="nofollow">getInitParameterNames</a>()</code> <p>Returns the names of the servlet's initialization parameters as an <code>Enumeration</code> of <code>String</code> objects, or an empty <code>Enumeration</code> if the servlet has no initialization parameters.</p> </td> </tr> <tr> <td style="width:154px;"><code><a href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html" rel="nofollow">ServletContext</a></code></td> <td style="width:693px;"><code><a href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletConfig.html#getServletContext--" rel="nofollow">getServletContext</a>()</code> <p>Returns a reference to the <a href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html" rel="nofollow"><code>ServletContext</code></a> in which the caller is executing.</p> </td> </tr> <tr> <td style="width:154px;"><code><a href="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html?is-external=true" rel="nofollow">String</a></code></td> <td style="width:693px;"><code><a href="https://docs.oracle.com/javaee/7/api/javax/servlet/ServletConfig.html#getServletName--" rel="nofollow">getServletName</a>()</code> <p>Returns the name of this servlet instance.</p> </td> </tr> </tbody> </table> **2、ServletCotext接口**:很重要,先简单认识一下 如果多个Servlet有公共的初始化参数时,此时得使用全局的初始化参数 在web.xml中,可以用一个或多个<context-param>标签(与Servlet标签并列)为整个Web应用配置初始化信息,所有的Servlet都能访问配置的初始化信息。 ** 1)ServletContext域对象可以在整个web应用范围内共享数据** 作用范围:整个web应用范围内共享数据 生命周期:当服务器启动web应用加载后创建出ServletContext域对象。当web应用被移除出容器或服务器关闭时随着web应用的销毁域销毁。 ** 2)ServletContext接口的方法:** 方法很多,具体查看API:[https://docs.oracle.com/javaee/7/api/][https_docs.oracle.com_javaee_7_api] **3、获取初始化参数** <context-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>123456</param-value> </context-param> <servlet> <servlet-name>LifeServlet</servlet-name> <servlet-class>cn.jq.demo.LifeServlet</servlet-class> <!-- 配置该servelt的初始化参数(键值对) --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>username</param-name> <param-value>admin</param-value> </init-param> </servlet> public class LifeServlet implements Servlet { private ServletContext servletContext; // 初始化阶段 @Override public void init(ServletConfig config) throws ServletException { System.out.println("init"); //获取当前Servlet在web.xml中配置的名字 System.out.println(config.getServletName()); //获取当前Servlet指定名称的初始化参数的值 String usernameValue = config.getInitParameter("encoding"); System.out.println(usernameValue); //获取当前Servlet所有初始化参数的名字 Enumeration enumeration = config.getInitParameterNames(); while (enumeration.hasMoreElements()) { String name = (String) enumeration.nextElement(); String value = config.getInitParameter(name); System.out.println(name + ":" + value); } //获取代表当前web应用的ServletContext对象 this.servletContext = config.getServletContext(); System.out.println(servletContext); } // 响应客户请求阶段 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("service"); // 获取单个的Context里面的初始化参数 String value1 = servletContext.getInitParameter("encoding"); String value2 = servletContext.getInitParameter("password"); System.out.println(value1 + ";" + value2); // 一次性获取Context里所有的初始化参数 Enumeration enumeration = servletContext.getInitParameterNames(); while (enumeration.hasMoreElements()) { String name = (String) enumeration.nextElement(); String value = servletContext.getInitParameter(name); System.out.println(name + ";" + value); } //获取当前WEB应用的名称 System.out.println(servletContext.getContextPath()); } ... } ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNDAyODU0_size_16_color_FFFFFF_t_70][] 重新整理了下 ends ~ [20190925094732147.png]: https://img-blog.csdnimg.cn/20190925094732147.png [20190925094634297.png]: /images/20220404/40e82a2f77d949878296d7994718de7f.png [20190925105027239.png]: /images/20220404/1cb4834c4de44a00b1b7dbb286611717.png [https_docs.oracle.com_javaee_7_api]: https://docs.oracle.com/javaee/7/api/ [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNDAyODU0_size_16_color_FFFFFF_t_70]: /images/20220404/647398c5cecc418a87986a38f61eeceb.png
还没有评论,来说两句吧...