Servlet的生命周期以及线程安全问题
一:Servlet生命周期图,以及注意事项
二:代码演示
LifeCycleServlet.java
1 package cn.woo.servlet; 2 3 import java.io.IOException; 4 5 import javax.annotation.PostConstruct; 6 import javax.annotation.PreDestroy; 7 import javax.servlet.ServletException; 8 import javax.servlet.ServletRequest; 9 import javax.servlet.ServletResponse; 10 import javax.servlet.http.HttpServlet; 11 import javax.servlet.http.HttpServletRequest; 12 import javax.servlet.http.HttpServletResponse; 13 14 /** 15 * 类说明:演示Servlet的生命周期 16 * @author wyh 17 * @version 创建时间:2018年8月13日 上午9:06:20 18 */ 19 public class LifeCycleServlet extends HttpServlet{ 20 21 /** 22 * Servlet是单例多线程的,Servlet加载的时候只会创建一次,只存在一个实例,当服务关闭的时候才销毁该servlet 23 * 当多个客户端并发访问Servlet的时候,Servlet会开启多个线程分别去执行Servlet的service方法 24 * 25 */ 26 27 28 private static final long serialVersionUID = 1L; 29 30 /** 31 * 使用@PostConstruct的非静态void方法,属于新增的Servlet生命周期的一部分,在Servlet的init方法之前执行 32 */ 33 @PostConstruct 34 public void beforeServletInit() { 35 System.out.println("在Servlet的init方法之前执行"); 36 } 37 38 /** 39 * 初始化Servlet的时候执行,并且只执行一次 40 * 该方法会在加载该Servlet的时候最先执行,如果在web.xml文件中配置<load-on-startup>1</load-on-startup>的时候,当项目启动的时候就会加载该Servlet 41 * ①:通常在该方法中进行一些初始化参数,或者上下文参数的获取。避免写在doGet/doPost方法中重复读取。 42 */ 43 @Override 44 public void init() throws ServletException { 45 // String initParameter = getServletConfig().getInitParameter("paramName"); 46 System.out.println("初始化LifeCycleServlet"); 47 } 48 49 /** 50 * 服务,每一次客户端访问Servlet的时候都会执行该方法 51 */ 52 @Override 53 public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { 54 //执行服务 55 System.out.println("执行service方法跳转到指定的get、post方法中"); 56 super.service(request, response); 57 } 58 59 /** 60 * 销毁Servlet的时候执行该方法(通常关闭服务的时候就会执行该方法),仅执行一次: 61 * ①:通常在该方法中进行一些对象、数据销毁的操作 62 */ 63 @Override 64 public void destroy() { 65 System.out.println("销毁LifeCycleServlet"); 66 } 67 68 /** 69 * 使用@PreDestroy的非静态void方法,属于新增的Servlet生命周期的一部分,在Servlet的destroy方法之后执行 70 */ 71 @PreDestroy 72 public void afterServletDestroy() { 73 System.out.println("在Servlet的destroy方法执行后执行"); 74 } 75 76 @Override 77 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 78 System.out.println("执行doPost方法"); 79 } 80 81 @Override 82 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 83 System.out.println("执行doget方法"); 84 } 85 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> 3 <display-name>ServletDemo1</display-name> 4 <welcome-file-list> 5 <welcome-file>index.html</welcome-file> 6 <welcome-file>index.htm</welcome-file> 7 <welcome-file>index.jsp</welcome-file> 8 <welcome-file>default.html</welcome-file> 9 <welcome-file>default.htm</welcome-file> 10 <welcome-file>default.jsp</welcome-file> 11 </welcome-file-list> 12 13 <!-- Servlet --> 14 <servlet> 15 <servlet-name>LifeCycleServlet</servlet-name> 16 <servlet-class>cn.woo.servlet.LifeCycleServlet</servlet-class> 17 <!-- 配置项目一启动的时候就加载该Servlet --> 18 <load-on-startup>1</load-on-startup> 19 </servlet> 20 21 <servlet-mapping> 22 <servlet-name>LifeCycleServlet</servlet-name> 23 <url-pattern>/servlet/LifeCycleServlet</url-pattern> 24 </servlet-mapping> 25 </web-app>
三:关于Servlet的线程安全
因为Servlet是单例的,当多个客户端并发访问Servlet中的某个成员属性的时候,就会造成数据不同步的问题。如:线程A要读取成员属性name属性的值,由于某种原因(如:A线程睡眠了几秒钟),在睡眠的过程中,线程B已经将name的值给改了,此时线程A再次输出的值已经不再是原先的值了。