火星文 技术研习社

Noname Cat, Keep Thinking
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Servlet 线程安全与 Servlet 映射有关

Posted on 2006-12-02 23:12  剑廿三  阅读(679)  评论(0编辑  收藏  举报

在 web.xml 中,一个 Servlet 可以被映射为两个 url ,例如:

  <servlet>
    
<description>TestServlet444</description>
    
<display-name>TestServlet123</display-name>
    
<servlet-name>TestServlet1</servlet-name>
    
<servlet-class>org.stephencat.test.TestServlet</servlet-class>
    
<init-param>
        
<param-name>username</param-name>
        
<param-value></param-value>
    
</init-param>
  
</servlet>
  
  
<servlet>
    
<description>TestServlet444</description>
    
<display-name>TestServlet123</display-name>
    
<servlet-name>TestServlet2</servlet-name>
    
<servlet-class>org.stephencat.test.TestServlet</servlet-class>
    
<init-param>
        
<param-name>username</param-name>
        
<param-value>abc</param-value>
    
</init-param>
  
</servlet>

  
<servlet-mapping>
    
<servlet-name>TestServlet1</servlet-name>
    
<url-pattern>/test</url-pattern>
  
</servlet-mapping>
  
<servlet-mapping>
    
<servlet-name>TestServlet2</servlet-name>
    
<url-pattern>/test2</url-pattern>
  
</servlet-mapping>

以上配置把 TestServlet 通过使用不同的两个名称 TestServlet1 和 TestServlet2 配置为两个不同的 url :/test 和 /test2

在 TestServlet 中定义了如下的类属性:

public String servletID = String.valueOf(Calendar.getInstance().getTimeInMillis());

这是在属性定义时就已经赋值的。

另外还定义了如下类属性:

private String username = null;

该类属性在声明时没有赋值,而是通过 init() 初始化方法从 web.xml 中读取初始化参数 username 给它赋值:

    /**
     * Initialization of the servlet. <br>
     *
     * 
@throws ServletException if an error occure
     
*/
    
public void init(ServletConfig config) throws ServletException {
        
// Put your code here
        this.username = config.getInitParameter("username");
    }

在 servlet 的 doGet() 方法中,包含如下输出语句:

        if(this.username==null){
            out.println(
"null");
        }
else if(this.username.equals("")){
            out.println(
"blank");
        }
else{
            out.println(username);
        }
        out.println(request.getSession().getId());
        out.println(servletID);

分别打开两个 IE 窗口,访问:
http://localhost:8080/.../test

http://localhost:8080/.../test2

分别得到如下结果:

/test 的结果:
blank CD0C16C3CFFBE533BD8497522546EF75 1165071414984

/test2 的结果:
abc EE35E9B6588607D54E282DA865CEB8AD 1165071408234

再打开两个 IE 窗口分别访问以上网址,两个窗口的 username 和 servletID 值没有改变,只有 sessionID 值改变了。

小结:

1. 在一个 Servlet 映射内部,Servlet 的类属性是线程不安全的,因为一个映射产生唯一一个实例,多个线程访问这个唯一的实例

2. 在两个 Servlet 映射之间,类属性的值(包括在获取初始化参数时赋值和声明时直接赋值)互不干扰、相对独立