陷阱:在 WebApp 中谨防 Singleton 错误
1、编写 Singleton 类
先来看一个单例: TestStaticInWeb.java
Code:
[Ctrl+A Select All]
这个单例很简单,通过 getInstance() 获得唯一实例,通过 getCreateTime() 来获得该唯一实例的创建时间。
普通情况下,这是没问题的,然而,在 Web 应用程序中,它的表现又如何呢?
2、构建 Web 应用程序
(1)编写一个 JSP,在这个 JSP 中显示出上述单例的相关信息:index.jsp
Code:
[Ctrl+A Select All]
(2)创建一个目录,名称为 testA,在 testA 下建 WEB-INF
(3)在 WEB-INF 下建 lib 目录
(4)在 WEB-INF 目录下建立 web.xml
Code:
[Ctrl+A Select All]
(5)把 index.jsp 放到 testA 目录下
(6)把 TestStaticInWeb.java 编译并打包成 test.jar,并拷贝到 testA\WEB-INF\lib 目录下
(7)把 testA 目录整个复制一份,然后重命名为 testB
(8)把 testA 和 testB 一起拷贝到 tomcat\webapps 目录下去
(9)启动 Tomcat
3、查看运行结果
(1)打开 IE,输入 [url]http://localhost:8080/testA[/url],得下如下结果:
testA-1
(2)输入 [url]http://localhost:8080/testB[/url],得到如下结果:
testB-1
显然,上述两个结果是不一样的!在 Tomcat,显然存在两个 TestStaticInWeb 类的实例,也就是说,通过单例模式,得到的唯一实例并不“唯一”!
4、原因何在
在一个 ClassLoader 的作用范围内,一个类只会被 load 一次,对于用 static 修改的类或变量,也只会存在一份。
通常情况下,一个 JVM 对应着一个 ClassLoader,但在 Tomcat 等 J2EE 容器内,ClassLoader 则是相对复杂的,一个 JVM 可能对应着多个 ClassLoader,而且 ClassLoader 之间,是层次的结构。根据 Web 应用程序的相关规范(参见 Java Servlet SpecificationVersion 2.4 第 9 章:Web Applications),部署在 Tomcat 中的每个 webapp 都有一个与之对应的特殊的 ClassLoader,这个 ClassLoader 是在系统的 System ClassLoader 的基础上,优先 load 位于 WEB-INF/classes 和 WEB-INF/lib/*.jar 中的 class 文件。
由于 testA 和 testB 分属于两个不同的 webapp,所以,它们所得到的 TestStaticInWeb 类的 ClassLoader 也不一样。此时,单例模式只能保证在同一个 webapp 内部唯一,不能保证一个 JVM(即 Tomcat 容器)范围内唯一。
5、解决办法
如果确实要在 Tomcat 范围内唯一,则可以把 test.jar 拷贝到 Tomcat\common\lib 目录下去,并从 WEB-INF\lib 目录下删除之(重要!否则会出错!)。
以下是拷贝到 Tomcat\common\lib 目录下去之后的结果:
可以看出,这种方案下,TestStaticInWeb 类都是由系统的 ClassLoader 读取和初始化的,能保证全局唯一。
testA-2
testB-2
6、下载
单击这里可以下载 WEB 应用程序,源码位于 WEB-INF/src 目录下。
本文中的例子,在 Tomcat 5.5.15 + JDK 1.4 环境下通过。
附件:http://down.51cto.com/data/2347369
陷阱:在 WebApp 中谨防 Singleton 错误相关推荐
- singleton 类_在Java中对Singleton类进行双重检查锁定
singleton 类 Singleton类在Java开发人员中非常常见,但是它给初级开发人员带来了许多挑战. 他们面临的主要挑战之一是如何使Singleton保持为Singleton? 也就是说,无 ...
- 在Java中对Singleton类进行双重检查锁定
Singleton类在Java开发人员中非常常见,但是它给初级开发人员带来了许多挑战. 他们面临的主要挑战之一是如何使Singleton保持为Singleton? 也就是说,无论出于何种原因,如何防止 ...
- HOW-TO:带有Spring MVC的Tomcat中的自定义错误页面
默认的Tomcat错误页面看起来很可怕. 此外,它们可能会公开有价值的信息,包括服务器版本和异常堆栈跟踪. Servlet规范提供了一种通过web.xml配置异常行为的方法. 可以配置对特定Java异 ...
- C++ 中的Singleton 类的实现
摘要:ANSI C++ 中的 Singleton 实现说难不难,说容易也不容易,很多人写 ANSI C++ 的 Singleton class 都有错误.这篇文章讨论怎样在 ANSI c++ 中写 S ...
- 在Wicket中配置404错误页面
始终建议为" 404页面未找到"错误自定义一个不错的错误页面. 本指南向您展示如何在Wicket中配置404错误页面. 1.错误页面 为Wicket创建错误页面和类. packag ...
- JAVA Web项目中所出现错误及解决方式合集(不断更新中)
JAVA Web项目中所出现错误及解决方式合集 前言 一.几个或许会用到的软件下载官网 二.Eclipse的[preferences]下没有[sever]选项 三.Tomcat的安装路径找不到 四.T ...
- Sql Server 因为触发器问题导致数据库更新报错“在触发器执行过程中引发了错误,批处理已中止”的问题处理...
在维护一个非常旧的项目时,由于该项目版本已经非常老了,而且在客户现场运行的非常稳定,更要命的是本人目前没有找到该项目的代码,为了处理一个新的需求而且还不能修改程序代码,于是决定从数据库入手,毕竟该项目 ...
- react 错误边界_React with GraphQL和错误边界中的自定义错误页面
react 错误边界 by Abi Noda 通过Abi Noda React with GraphQL和错误边界中的自定义错误页面 (Custom error pages in React with ...
- 诊断IIS中的ASP0115错误
诊断IIS中的ASP0115错误 作者:未知 重要说明:本文包含有关修改注册表的信息.修改注册表之前,一定要备份注册表,并且一定要知道在发生问题时如何还原注册表.有关如何备份.还原和编辑注册表的信息, ...
最新文章
- KVM — 与 QEMU 和 Libvirt 的关系
- 导入训练好的决策树文件_决策树在sklearn中的实现
- 阿里研究员谷朴:警惕软件复杂度困局
- 升讯威微信营销系统开发教程:(1)订阅号和服务号深入分析
- php删除菜单栏,如何删除WordPress站点健康状态面板和菜单项
- 计算机职称业务工作业绩总结,档案职称工作业绩
- http://java.sun.com/jsp/jstl/core cannot be resolved(含有jstl1.2jar包网盘)
- VC++ Tab Control控件的使用
- 强悍的 Ubuntu —— 强悍的任意进制转换命令行工具 bc
- python难学吗-Python为什么那么受欢迎?学习Python难不难?
- JavaWeb 基础系列篇
- windows控制台cmd乱码的解决办法
- ROC曲线的绘制过程/AUC/TPR、FPR、敏感度和特异度
- 看完你就明白的锁系列之自旋锁
- Casbin-authz-plugin:基于Casbin的Docker权限管理、访问控制插件
- 关闭eclipse控制台console中的非Java Server(ESLint、Angular Language Server等)
- 一亩三分地每日答题答案
- vue 防抖节流,开箱即用
- 红米3s运行linux,小米红米3S 3X(Redmi 3S)刷机教程,看教程刷机
- 建一个java项目并部署到weblogic服务器
热门文章
- mongodb mysql配置_mongoDB数据库原生配置
- form表单提交按钮点击事件先触发还是提交数据先触发_如何实现图片上传并保存到数据库?...
- 我,27岁,程序员,今年无情被辞:该转行还是降薪和年轻人抢饭碗?
- centos 文件夹网络连接_CentOS的网络配置的命令详解
- expec不管异常 try_java – 如何使用ExpectedException规则在一个测试中测试多个异常?...
- 模型ks_风控建模 模型指标篇
- 死磕java_死磕 java同步系列之AQS起篇
- Farthest Point Sampling on 2d image
- Boost Graph Library 快速入门
- 20复变函数的积分(六)