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 }

 

 

posted @ 2017-04-26 14:58  等你,在雨中  阅读(518)  评论(0)    收藏  举报