servlet04 在谈servlet对象的生命周期、【config】、【context】、模拟并发、线程安全问题
1 servlet的生命周期

创建servlet对象(自动完成) -> 初始化(自动完成) -> 执行service方法 -> 销毁servlet对象
2 config
利用config可以读取web.xml文件中的参数
config和Servlet是1对1的关系

2.1 补充知识
在创建完servlet对象过后,就会对刚刚创建的这个servlet对象进行初始化;其中初始化函数有两个,一个没有参数,一个有参数(参数类型是ServletConfig);在初始化servlet对象时默认使用的初始化函数是么有参数的那个init()方法;但是,如果我们在web.xml文件中设置了参数,那么就会自动调用有参数的那个init()方法。

2.2 tomcat 创建并初始化Servlet的过程
LoginServlet s = new LoginServlet(); (自动完成)
ServletConfig c = new ServletConfig(); (自动完成)
c.静态块{} // 加载 web.xml 的参数(自动加载的)
s.init(c)/s.init() // 自动调用父类的方法实现(自动实现)
2.3 在配置文件中设置参数

2.4 在servlet类中读取参数值
2.4.1 获取config对象
获取到的config对象就是初始化servlet对象用到的init()方法的参数
ServletConfig config = getServletConfig();
2.4.2 通过config对象去读取参数值
注意:获取到的参数值都是字符串类型
String max = config.getInitParameter("maxOnline");

2.5 config的应用场景
限制某个网站的登录人数;例如:当某个用户A在访问一个网站的时候,向服务器发送请求后,服务器会监测当前正在访问的用户数量,如果当前用户数量已经达到上限值,那么服务器机会给用户A返回一个类似于系统繁忙的页面【学校的选课系统就是一个很典型的应用config的案例】
1 package web; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.ServletConfig; 7 import javax.servlet.ServletException; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 public class IndexServlet extends HttpServlet { 13 14 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 15 System.out.println("service()"); // 追踪 16 resp.setContentType("text/html;charset=utf-8"); // 指定发送给浏览器的文件格式以及文件编码 17 req.setCharacterEncoding("utf-8"); // 设定读取浏览器请求参数时使用的编码方式【post方式有效】 18 19 PrintWriter out = resp.getWriter(); 20 21 String path = req.getServletPath(); // 获取请求资源的路径 22 System.out.println("path" + path); // 打印输出路径 23 24 if("/index.do".equals(path)) { // 请求分发 25 index(req, resp, out); 26 } 27 28 } 29 30 private void index(HttpServletRequest req, HttpServletResponse resp, PrintWriter out) { 31 System.out.println("index()"); 32 33 String name = req.getParameter("username"); // 读取请求参数 34 System.out.println(name); 35 36 // 获取config对象,这里获取到的config对象就是初始化方法init()穿进去的参数 37 ServletConfig config = getServletConfig(); 38 // 通过config对象去获取参数值 39 String max = config.getInitParameter("maxOnline"); 40 41 System.out.println("max:" + max); 42 System.out.println("根据参数max判断是否达到最大人数"); 43 44 out.println("重庆:" + name); 45 } 46 47 }
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_2_5.xsd" version="2.5"> 3 <display-name>testServlet</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-name>index</servlet-name> 15 <servlet-class>web.IndexServlet</servlet-class> 16 <init-param> 17 <param-name>maxOnline</param-name> 18 <param-value>2000</param-value> 19 </init-param> 20 </servlet> 21 <servlet-mapping> 22 <servlet-name>index</servlet-name> 23 <url-pattern>*.do</url-pattern> 24 </servlet-mapping> 25 26 </web-app>
3 context
context和Servlet是1对多的关系【即:一个web项目只有一个context对象】
3.1 补充知识
tomcat在启动时会首先创建context,则context类中的静态块被执行了,这个静态块的作用就是加载web.xml中预置的公共参数
tomcat给Servlet提供了方法可以获取此context对象
直接通过从父类的父类继承过来的方法获取
ServletContext context = getServletContext();
通过 request对象 的方法获取
ServletContext context = req.getServletContext(); // 利用 request对象 的方法获取
web项目内右且只有一个context【即:一个项目一个context】
3.2 配置静态公共参数【web.xml文件中配置】

3.3 配置动态公共参数
3.3.1 添加一个servlet类来配置动态的公共参数【必须在Tomcat启动的时候就创建这个servlet对象】
在servlet的初始化方法init()中配置动态公共参数的初始值

在 web.xml文件 中配置该servlet类

1 package web; 2 3 import javax.servlet.ServletConfig; 4 import javax.servlet.ServletContext; 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 8 public class InitServlet extends HttpServlet { 9 10 @Override 11 public void init(ServletConfig config) throws ServletException { 12 super.init(config); 13 // 获取 context对象 14 ServletContext context = getServletContext(); 15 // 配置动态参数的初始值 16 context.setAttribute("count", 0); 17 // System.out.println("hello Ajax"); 18 } 19 20 }
3.4 读取公共参数
3.4.1 获取 context对象

3.4.2 通过 context对象 读取公共参数

3.5 注意
读取到的公共参数都是字符串类型
context对象的名字就是项目名
String name123 = context.getServletContextName(); // 读取 context对象的名字【就是项目名】
3.6 应用场景
动态的公共参数可以统计流量;例如:一个web项目的起始流量数为0,每一个客户端访问一次这个项目流量就多一次


4 模拟并发
利用线程阻塞来模拟并发

5 线程安全问题
5.1 局部变量
局部变量存储于栈内
每个线程有自己的栈帧
同时修改局部变量没问题
5.2 成员变量
成员变量存储在堆内
多个线程共享堆中数据
同时修改成员变量有问题
5.3 解决办法
利用加锁来实现同步请求
1 package web; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class UpSalaryServlet extends HttpServlet { 12 double salary = 3000.0; 13 14 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 15 16 17 synchronized (this) {// 加锁 18 // 模拟涨工资 19 salary += 100; 20 21 // 利用阻塞模拟并发 22 try { 23 Thread.sleep(8000); 24 } catch (Exception e) { 25 e.printStackTrace(); 26 } 27 28 // 输出响应信息 29 resp.setContentType("text/html"); 30 PrintWriter out = resp.getWriter(); 31 out.println(salary); 32 out.close(); 33 } 34 35 } 36 }
浙公网安备 33010602011771号