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 }
Servlet类
 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>
web.xml

 

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 }
线程安全问题解决办法

 

posted @ 2017-05-26 21:58  寻渝记  阅读(141)  评论(0)    收藏  举报