首页 > 代码库 > Head First Servlets and JSP】笔记9:属性的作用域、线程安全

Head First Servlets and JSP】笔记9:属性的作用域、线程安全

什么是属性?

属性和参数

属性的3个作用域

属性API

属性不好的一面

 

1、到底什么是属性(Attribute)?

属性就是一个对象,可以被设置(bound,也可以叫绑定)到另外三个servlet API对象ServletContext、HttpSession、HttpServletRequest中。可以把它简单地认为是一个名/值对,名是String、值是object。在实际中,我们并不知道也不关心它具体如何实现,我们关心的只是属性所在的作用域。

 

2、属性不是参数(Parameter)!

笔记1中的参数——请求参数:

技术分享

笔记7中的参数——servlet初始化参数:

技术分享

技术分享

以及,上下文初始化参数参数:

技术分享

技术分享

 

3、属性的3个作用域:

  • ServletContext属性(上下文属性)——Web应用中的每一部分都能访问
  • HttpSession属性(会话属性)——能访问特定的HttpSession的部分才可访问
  • HttpServletRequest属性(请求属性)——能访问特定的ServletRequest的部分才可访问

 

4、设置、访问属性的API——每个接口(ServletContext、HttpS......)的属性API完全相同

技术分享

关于Enumeration,参见Java-Enumeration总结 by IAMTJW

 

5、属性不好的一面.··.```..``..`.`.`...`..

  1. 上下文属性不是线程安全的!一个上下文属性可能同时被多个servlet所更改、访问。糟糕的解决方案是给doGet(或者是其它方法)加上synchronized,这样并不能解决问题,原因在于关于synchronized只能防止同一个servlet中的其他线程访问上下文属性,但是不能阻止另外一个servlet访问。关于ynchronized参见java synchronized详解 by Gang.Wang。技术分享

    正确的方法是:对上下文加锁,而不是对servlet加锁。怎么实现呢?看下面的代码:技术分享

     

  2. 会话属性是线程安全的吗?不是,因为用户可能打开好几个浏览器窗口...解决方案类似:技术分享
  3. 只有请求属性和局部变量是线程安全的!技术分享

    要注意的是servlet的实例域不是线程安全的,除非实现了SingleThreadModel,或者是同步服务方法,但这是十分糟糕的做法,会让Web应用的效率变得非常差,所以,一个servlet根本不该有实例变量,有也应该是final的,如果真的需要在多个线程中共享一些东西,那就把它加到合适的作用域上去。

 

Head First Servlets and JSP】笔记9:属性的作用域、线程安全