Servlet特性
Servlet特性:生命周期,servletContext,线程安全问题
一. Servlet生命周期

二.ServletConfig和ServletContext
1.它们的作用和区别
1)作用
- 可以从web.xml中读取数据,给Servlet使用
- config:读取常量
-
1 ServletConfig cfg = getServletConfig(); 2 String maxonline = 3 cfg.getInitParameter("maxonline"); - context:读取常量:
-
1 ServletContext ctx = getServletContext(); 2 String size = ctx.getInitParameter("size");读取变量(特殊用法)
-
1 Integer count = (Integer) 2 ctx.getAttribute("count"); 3 ctx.setAttribute("count", ++count);
它们都能够给Servlet预置参数
2)区别
- config和Servlet是1对1的关系(config读取私有的数据)
- context和Servlet是1对多的关系(context读取公有的数据)
Tomcat会保障它们和Servlet的关系

2.ServletConfig
1)场景介绍
- 假设开发一个网页游戏
- 如果在线人数达到最大值时,新登录的人需要排队
- 需要开发登录功能LoginServlet
- 在此Servlet内要获取在线人数最大值并加以判断
- 最大值maxonline要求可以配置
2)实现方式
- 将参数配置到web.xml内
- 该参数只给登录功能LoginServlet使用,使用config读取
1 package web;
2
3 import java.io.IOException;
4
5 import javax.servlet.ServletConfig;
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 LoginServlet extends HttpServlet {
12
13 /**
14 * 1.config对象由tomcat创建及传入
15 *
16 * LoginServlet servlet = new LoginServlet();
17 * //Tomcat每创建一个Servlet后,就会立刻给它
18 * //创建一个config对象.
19 * //config内有静态块,调用时加载参数(首次访问)
20 * ServletConfig cfg = new ServletConfig();
21 * //通过init方法传入此config对象
22 * servlet.init(cfg);
23 * //父类的init(cfg)方法内部调用了init()
24 *
25 * 2.使用config不是必须要重写init(),
26 * 若在service()中调用config,通过父类
27 * 提供的getServletCofig()就可以获取它.
28 * 该方法返回的config就是init()所传入
29 * 的那个config.
30 *
31 * */
32
33 @Override
34 public void init(ServletConfig config) throws ServletException {
35 System.out.println("调用有参的init()");
36 super.init(config);
37 }
38
39 @Override
40 public void init() throws ServletException {
41 System.out.println("调用无参的init()");
42 super.init();
43 }
44
45 @Override
46 protected void service(
47 HttpServletRequest req,
48 HttpServletResponse res) throws ServletException, IOException {
49 //获取在线人数最大值
50 ServletConfig cfg = getServletConfig();
51 String maxonline =
52 cfg.getInitParameter("maxonline");
53 System.out.println(maxonline);
54 }
55
56 }
配置参数:红的
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>servlet4</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>demo</servlet-name>
15 <servlet-class>web.DemoServlet</servlet-class>
16 <!-- 启动时第2个加载此Servlet -->
17 <load-on-startup>2</load-on-startup>
18 </servlet>
19 <servlet-mapping>
20 <servlet-name>demo</servlet-name>
21 <url-pattern>/demo</url-pattern>
22 </servlet-mapping>
23
24 <servlet>
25 <servlet-name>login</servlet-name>
26 <servlet-class>web.LoginServlet</servlet-class>
27 <init-param>
28 <param-name>maxonline</param-name>
29 <param-value>3000</param-value>
30 </init-param>
31 </servlet>
32 <servlet-mapping>
33 <servlet-name>login</servlet-name>
34 <url-pattern>/login</url-pattern>
35 </servlet-mapping>
36
37 <servlet>
38 <servlet-name>findDept</servlet-name>
39 <servlet-class>web.FindDeptServlet</servlet-class>
40 </servlet>
41 <servlet-mapping>
42 <servlet-name>findDept</servlet-name>
43 <url-pattern>/findDept</url-pattern>
44 </servlet-mapping>
45
46 <servlet>
47 <servlet-name>findEmp</servlet-name>
48 <servlet-class>web.FindEmpServlet</servlet-class>
49 </servlet>
50 <servlet-mapping>
51 <servlet-name>findEmp</servlet-name>
52 <url-pattern>/findEmp</url-pattern>
53 </servlet-mapping>
54
55 <!--
56 给所有的Servlet预置参数,该参数由context
57 对象自动读取.
58 Tomcat启动时首先就会创建context对象,它会
59 给每个项目创建唯一的一个context.
60 context内部有静态块,首次调用时就执行,
61 此块内加载了web.xml中的参数.
62 -->
63 <!--
64 在标签外配置参数是给所有servlet公用的参数,他们
65 可以通过context读取参数
66 -->
67 <context-param>
68 <param-name>size</param-name>
69 <param-value>10</param-value>
70 </context-param>
71
72 <servlet>
73 <servlet-name>init</servlet-name>
74 <servlet-class>web.InitServlet</servlet-class>
75 <load-on-startup>1</load-on-startup>
76 </servlet>
77
78 <servlet>
79 <servlet-name>up</servlet-name>
80 <servlet-class>web.UpServlet</servlet-class>
81 </servlet>
82 <servlet-mapping>
83 <servlet-name>up</servlet-name>
84 <url-pattern>/up</url-pattern>
85 </servlet-mapping>
86
87 </web-app>
3.ServletContext
1)场景介绍
- 项目通常都有很多查询功能,几乎每个查询都支持分页
- 分页的已知条件: 页码page, 每页显示行数size
- size要求可以配置,便于系统上线时实施人员去修改
2)实现方式
- 配置到web.xml中
- 因为多个功能都要使用该参数,所以使用context来读取它
1 package web;
2
3 import java.io.IOException;
4
5 import javax.servlet.ServletContext;
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 FindDeptServlet extends HttpServlet {
12
13 @Override
14 protected void service(
15 HttpServletRequest req,
16 HttpServletResponse res) throws ServletException, IOException {
17 /*Tomcat启动时就会创建唯一的context,
18 并且会调用它的方法加载web.xml中的公用参数
19 context时全局的,任何servlet都可以使用
20 */
21 //获取每页显示的行数
22 ServletContext ctx = getServletContext();
23 String size = ctx.getInitParameter("size");
24 System.out.println(size);
25 //统计流量
26 Integer count = (Integer)
27 ctx.getAttribute("count");
28 ctx.setAttribute("count", ++count);
29 System.out.println("流量:"+count);
30 }
31
32 }
配置参数:绿的
4.ServletContext的特殊用途
1)特殊用途
- config和context典型的用途是读取web.xml中的常量(看2,3)
- 特殊用途:context还可以读写变量setAttribte()/getAttribute()
2)场景介绍
- 要统计软件的流量(访问量/访问人次)
- 任何人访问软件的任何功能,则流量+1
3)实现方式

1 package web;
2
3 import javax.servlet.ServletContext;
4 import javax.servlet.ServletException;
5 import javax.servlet.http.HttpServlet;
6
7 /**
8 * 该Servlet不用来处理任何请求,只是用来
9 * 在Tomcat启动时初始化一些数据而已.
10 * 在你工作时会发现很多项目中都有1个/多个
11 * 这样的Servlet.
12 */
13 public class InitServlet extends HttpServlet {
14
15 @Override
16 public void init() throws ServletException {
17 super.init();
18 //将流量初始化为0
19 ServletContext ctx = getServletContext();
20 ctx.setAttribute("count", 0);
21 }
22
23 }
配置参数:蓝的
二.Servlet线程安全问题
1.什么时候会出现线程安全问题?
1)局部变量
- 存于栈中
- 每个线程都有自己的栈帧
每个线程访问自己的数据,没有冲突
2)成员变量
- 存于堆中
- 堆中的数据被多个线程共用的
多个线程同时修改这样的数据,有冲突
2.如何解决线程安全问题?
- 加锁
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 UpServlet extends HttpServlet {
12
13 private Double salary = 3000.0;
14
15 @Override
16 protected void service(
17 HttpServletRequest req,
18 HttpServletResponse res) throws ServletException, IOException {
19 synchronized(this) {
20 //模拟涨工资
21 salary += 100;
22 //模拟网络延迟
23 try {
24 Thread.sleep(8000);
25 } catch (InterruptedException e) {
26 e.printStackTrace();
27 }
28 res.setContentType(
29 "text/html;charset=utf-8");
30 PrintWriter out = res.getWriter();
31 out.println(salary);
32 out.close();
33 }
34 }
35
36
37
38 }
温壶月光当茶饮

浙公网安备 33010602011771号