- 浏览: 1012517 次
- 性别:
- 来自: 福州
最新评论
-
guanxin2012:
大神,您好。非常感谢您贡献了IKExpression。我们现在 ...
分享开源表达式解析器IK-Expression2.0 -
qqgigas:
LZ,public boolean createUser(LD ...
Sun Directory Server/LDAP学习笔记(二)——API说明及代码样例 -
gao_shengxian:
Hibernate: update T_GX_TEST set ...
优雅Java编程 之 使用Hibernate存储Oracle Spatial对象 -
a78113534:
感谢大神,在安卓里面调用成功了。
发布IK Expression开源表达式解析器 V2.1.0 -
majiedota:
加油
来自开源支持者的第一笔捐赠
前言:
看过JbossCache的开发手册,发现在JbossCache与AppServer的集成章节对JNDI方式的集成没有明确说明,在Jboss App Server 下,你可以使用MBean方式管理JbossCache,更多情况下,你可能需要写一个Factory类,通过API方法来启用JbossCache了。
在企业的应用中,尤其是SOA结构的系统中,在一个应用服务器上,同时运行多个应用的场景是经常遇到的,JbossCache作为群集缓存的实现,我们希望是对一个应用服务器上的多应用,分享一个JBossCache的实例,而不是为每个应用起一个单独的。
1.Tomcat JNDI 实现
Tomcat JNDI估计大家都接触过,最常用的莫过于数据库的DataSource了。在Tomcat服务器启动后,它的JNDI会呈现Read Only模式,无法通过API方式往上发布资源。因此我们需要实现一个可以通过配置声明的JNDI JbossCache服务。
声明一个Cache逻辑相关的接口 - ClusterCache
ClusterCache接口是对JbossCache的Cache接口的简化封装。代码如下:
将ClusterCache接口实现成可发布的JNDI 引用 -
任何资源要发布成JNDI,就必须实现javax.naming.Referenceable接口,该接口只有一个方法public Reference getReference() ;它返回一个javax.naming.Reference类型的对象。JNDI的SPI端需要这个Reference 对象提供足够的信息来初始化JNDI资源实例并提供给使用者。
对于ClusterCache业务接口的Referenceable实现如下:
要说明的是,ClusterCache的实现中,对Jbosscache采用了单一实例。根据Jbosscache的API文档说明,其Cache的实现是ThreadSafe的。
2.在Tomcat的服务器全局域发布JbossCache的JNDI服务类
发布Tomcat的全局JNDI相信大家都做过,这里为了读者的思路连续,我再罗嗦一次吧。
发布jar包
进行全局JNDI的发布,需要将jar包拷贝到Tomcat的\lib目录下,因此我们要把上述的两个类打包成一个jar,比如:ClusterCache.jar,同时带上JbossCache的JAR包拷贝到lib目录下,JbossCache相关包清单如下:
此外,在JNDIClusterCache中,我们声明了jbosscache的配置文件为jbosscache.cfg.xml,因此我们也要把该配置文件拷到lib目录中。
配置Tomcat全局的资源
在Tomcat的\conf目录下,找到context.xml文件,在其中加上以下配置
配置Web App应用的客户端JNDI引用
在要使用JNDI Cache应用的web.xml中加上对cache资源的引用配置
在应用取得JNDI上的JbossCache
到此为止,我们已经实现了将JbossCache发布到Tomcat的JNDI上。这样做的好处是,一个应用服务器只有一个JbossCache服务实例,群集服务器Cache间的同步将更有效率,内存及CPU资源消耗更少。
但这样做也有个问题,就是JNDI上的Jbosscache将无法使用分布在各个应用中CacheListener监听器。原因是Tomcat的全局lib的classLoader比web应用的classloader在类加载层次上更底层一些,简单的说,就是web-inf\lib中的类可以引用全局lib的类,但全局lib的类没法反向应用web-inf\lib中的jar类,除非你把CacheListener一起发布到全局的lib下。
【全文完】
感谢提醒,我目前改行互联网了,JbossCache已经过气了,现在主要使用Memcached了,JbossCache建议用在群集系统同步控制领域,比如:服务路由表,用来避免单点故障。这些数据相对固定,增删改频度低,不容易造成OOM
前提在Tomcat环境下使用JbossCache的楼主,看来楼上的回复,表示西瓜很大
看过JbossCache的开发手册,发现在JbossCache与AppServer的集成章节对JNDI方式的集成没有明确说明,在Jboss App Server 下,你可以使用MBean方式管理JbossCache,更多情况下,你可能需要写一个Factory类,通过API方法来启用JbossCache了。
在企业的应用中,尤其是SOA结构的系统中,在一个应用服务器上,同时运行多个应用的场景是经常遇到的,JbossCache作为群集缓存的实现,我们希望是对一个应用服务器上的多应用,分享一个JBossCache的实例,而不是为每个应用起一个单独的。
1.Tomcat JNDI 实现
Tomcat JNDI估计大家都接触过,最常用的莫过于数据库的DataSource了。在Tomcat服务器启动后,它的JNDI会呈现Read Only模式,无法通过API方式往上发布资源。因此我们需要实现一个可以通过配置声明的JNDI JbossCache服务。
声明一个Cache逻辑相关的接口 - ClusterCache
ClusterCache接口是对JbossCache的Cache接口的简化封装。代码如下:
package org.wltea.cache; import java.util.Map; import java.util.Set; import org.jboss.cache.Node; public interface ClusterCache { /** * 打开cache的批处理事务 */ public void beginBatchTx(); /** * 提交cache的批处理事务 */ public void commitBatchTx(); /** * 回滚cache的批处理事务 */ public void rollbackBatchTx(); /** * 在指定的结点上缓存一个key-value型数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param key 缓存对象的键 * @param value 缓存对象 */ public void cacheData(String nodePath , String key , Object value); /** * 在指定的结点上缓存整个Map数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param dataMap 缓存对象的Map */ public void cacheDataMap(String nodePath , Map<String , Object> dataMap); /** * 获取指定结点上缓存的数据对象 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param key 缓存对象的键 * @return Object 返回缓存对象 */ public Object getCacheData(String nodePath , String key); /** * 获取指定结点上缓存的数据集 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @return Map 返回缓存的Map数据集 */ public Map<String , Object> getCacheDataMap(String nodePath); /** * 清除指定结点上的缓存数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , */ public void clearData(String nodePath); /** * 取得指定结点上的缓存数据的记录数 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , */ public int getDataSize(String nodePath); /** * 获取指定结点上的子结点集合 * @param nodePath * @return Set<Node<String,Object>> , 返回指定结点上的子结点集合 */ public Set<Node<String,Object>> getChildren(String nodePath); /** * 移出指定结点上的单个数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param key 缓存对象的键 * @return Object 返回缓存对象 */ public Object removeData(String nodePath , String key); /** * 移出整个的指定结点 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @return boolean true:成功移除结点 ; false:没有找到指定结点 */ public boolean removeNode(String nodePath); }
将ClusterCache接口实现成可发布的JNDI 引用 -
任何资源要发布成JNDI,就必须实现javax.naming.Referenceable接口,该接口只有一个方法public Reference getReference() ;它返回一个javax.naming.Reference类型的对象。JNDI的SPI端需要这个Reference 对象提供足够的信息来初始化JNDI资源实例并提供给使用者。
对于ClusterCache业务接口的Referenceable实现如下:
/** * */ package org.wltea.cache; import java.util.Map; import java.util.Set; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.Referenceable; import org.jboss.cache.Cache; import org.jboss.cache.CacheFactory; import org.jboss.cache.DefaultCacheFactory; import org.jboss.cache.Fqn; import org.jboss.cache.Node; /** * 群集缓存JNDI实现 * @author 林良益 * */ public class JNDIClusterCache implements Referenceable , ClusterCache{ //配置文件路径 private static String CONFIG_FILE_LOCATION = "jbosscache.cfg.xml"; //Jboss Cache 工厂 private static final CacheFactory<String , Object> factory = new DefaultCacheFactory<String , Object>(); //Jboss cache private static Cache<String , Object> cache = null; //默认JNDI工厂名 private String factoryClassName = "org.apache.naming.factory.BeanFactory"; public String getFactoryClassName() { return factoryClassName; } public void setFactoryClassName(String factoryClassName) { this.factoryClassName = factoryClassName; } public JNDIClusterCache(){ if(cache == null){ synchronized(JNDIClusterCache.class){ if(cache == null){ cache = factory.createCache(CONFIG_FILE_LOCATION); } } } } /** * 获取JNDI引用对象 */ public Reference getReference() throws NamingException { Reference ref=new Reference(getClass().getName(),getFactoryClassName(),null); //添加Reference属性 //ref.add(new StringRefAddr("location",location)); //ref.add(new StringRefAddr("state",state)); return ref; } /** * 打开cache的批处理事务 */ public void beginBatchTx(){ cache.startBatch(); } /** * 提交cache的批处理事务 */ public void commitBatchTx(){ cache.endBatch(true); } /** * 回滚cache的批处理事务 */ public void rollbackBatchTx(){ cache.endBatch(false); } /** * 在指定的结点上缓存一个key-value型数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param key 缓存对象的键 * @param value 缓存对象 */ public void cacheData(String nodePath , String key , Object value){ Fqn<String> fqn = Fqn.fromString(nodePath); cache.put(fqn, key, value); } /** * 在指定的结点上缓存整个Map数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param dataMap 缓存对象的Map */ public void cacheDataMap(String nodePath , Map<String , Object> dataMap){ Fqn<String> fqn = Fqn.fromString(nodePath); cache.put(fqn, dataMap); } /** * 获取指定结点上缓存的数据对象 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param key 缓存对象的键 * @return Object 返回缓存对象 */ public Object getCacheData(String nodePath , String key){ Fqn<String> fqn = Fqn.fromString(nodePath); return cache.get(fqn, key); } /** * 获取指定结点上缓存的数据集 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @return Map 返回缓存的Map数据集 */ public Map<String , Object> getCacheDataMap(String nodePath){ Fqn<String> fqn = Fqn.fromString(nodePath); return cache.getData(fqn); } /** * 清除指定结点上的缓存数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , */ public void clearData(String nodePath){ Fqn<String> fqn = Fqn.fromString(nodePath); Node<String,Object> node = cache.getNode(fqn); node.clearData(); } /** * 取得指定结点上的缓存数据的记录数 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , */ public int getDataSize(String nodePath){ Fqn<String> fqn = Fqn.fromString(nodePath); Node<String,Object> node = cache.getNode(fqn); return node.dataSize(); } /** * 获取指定结点上的子结点集合 * @param nodePath * @return Set<Node<String,Object>> , 返回指定结点上的子结点集合 */ public Set<Node<String,Object>> getChildren(String nodePath){ Fqn<String> fqn = Fqn.fromString(nodePath); Node<String,Object> node = cache.getNode(fqn); return node.getChildren(); } /** * 移出指定结点上的单个数据 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @param key 缓存对象的键 * @return Object 返回缓存对象 */ public Object removeData(String nodePath , String key){ Fqn<String> fqn = Fqn.fromString(nodePath); return cache.remove(fqn, key); } /** * 移出整个的指定结点 * @param nodePath 缓存结点的路径 如:/aaa/bbb/ccc , * @return boolean true:成功移除结点 ; false:没有找到指定结点 */ public boolean removeNode(String nodePath){ Fqn<String> fqn = Fqn.fromString(nodePath); return cache.removeNode(fqn); } }
要说明的是,ClusterCache的实现中,对Jbosscache采用了单一实例。根据Jbosscache的API文档说明,其Cache的实现是ThreadSafe的。
2.在Tomcat的服务器全局域发布JbossCache的JNDI服务类
发布Tomcat的全局JNDI相信大家都做过,这里为了读者的思路连续,我再罗嗦一次吧。
发布jar包
进行全局JNDI的发布,需要将jar包拷贝到Tomcat的\lib目录下,因此我们要把上述的两个类打包成一个jar,比如:ClusterCache.jar,同时带上JbossCache的JAR包拷贝到lib目录下,JbossCache相关包清单如下:
- jbosscache-core-3.2.1
- commons-logging-1.1.1.jar
- jboss-common-core.jar
- jboss-logging-spi.jar
- jboss-transaction-api.jar ( 即jta.jar )
- jcip-annotations.jar
- jgroups.jar
此外,在JNDIClusterCache中,我们声明了jbosscache的配置文件为jbosscache.cfg.xml,因此我们也要把该配置文件拷到lib目录中。
配置Tomcat全局的资源
在Tomcat的\conf目录下,找到context.xml文件,在其中加上以下配置
<Resource name="ik/clustercache" auth="Container" type="com.wltea.cache.JNDIClusterCache" factory="org.apache.naming.factory.BeanFactory"/>
配置Web App应用的客户端JNDI引用
在要使用JNDI Cache应用的web.xml中加上对cache资源的引用配置
<resource-ref> <description>JNDI Cluster Cache</description> <res-ref-name>ik/clustercache</res-ref-name> <res-type>com.wltea.cache.ClusterCache</res-type> <res-auth>Container</res-auth> </resource-ref>
在应用取得JNDI上的JbossCache
// Put your code here Context initContext; try { initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); ClusterCache cache = (ClusterCache)envContext.lookup("ik/clustercache"); } catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); }
到此为止,我们已经实现了将JbossCache发布到Tomcat的JNDI上。这样做的好处是,一个应用服务器只有一个JbossCache服务实例,群集服务器Cache间的同步将更有效率,内存及CPU资源消耗更少。
但这样做也有个问题,就是JNDI上的Jbosscache将无法使用分布在各个应用中CacheListener监听器。原因是Tomcat的全局lib的classLoader比web应用的classloader在类加载层次上更底层一些,简单的说,就是web-inf\lib中的类可以引用全局lib的类,但全局lib的类没法反向应用web-inf\lib中的jar类,除非你把CacheListener一起发布到全局的lib下。
【全文完】
评论
7 楼
ldb19890624
2010-08-28
LZ把你的代码拷进去了 代码报错了 提示下 你的jbosscache 版本是多少。。。。
6 楼
linliangyi2007
2010-07-25
IcyFenix 写道
今年以来我们起码处理了5次因为jbosscache nakack栈导致的OOM……准确的说是jgroup,jbosscache在大规模应用时我觉得已经不是同步速度慢的问题了
感谢提醒,我目前改行互联网了,JbossCache已经过气了,现在主要使用Memcached了,JbossCache建议用在群集系统同步控制领域,比如:服务路由表,用来避免单点故障。这些数据相对固定,增删改频度低,不容易造成OOM
5 楼
IcyFenix
2010-07-24
今年以来我们起码处理了5次因为jbosscache nakack栈导致的OOM……准确的说是jgroup,jbosscache在大规模应用时我觉得已经不是同步速度慢的问题了
4 楼
linliangyi2007
2010-07-24
IcyFenix 写道
3年的jbosscache用户表示使用jbosscache鸭梨很大。
前提在Tomcat环境下使用JbossCache的楼主,看来楼上的回复,表示西瓜很大
3 楼
IcyFenix
2010-07-24
3年的jbosscache用户表示使用jbosscache鸭梨很大。
2 楼
linliangyi2007
2010-07-24
呵呵,这篇文章发了好久了,终于有个回帖的了,看来在Tomcat下使用JbossCache的用户不多啊
1 楼
wangshare
2010-07-24
兄弟,想不到你先干了我想干的事情,谢谢,太能理解你的思路,
发表评论
-
来自开源支持者的第一笔捐赠
2013-01-09 21:15 57772013年1月9号,一个平凡而又不平常的日子! IK中文分词 ... -
发布 IK Analyzer 2012 FF 版本
2012-10-23 17:50 25068首先感谢大家对IK分词器的关注。 最近一段时间正式公司事务最 ... -
发布 IK Analyzer 2012 版本
2012-03-08 11:23 36160新版本改进: 支持分词歧义处理 支持数量词合并 词典支持中英 ... -
CSDN发生严重用户账号泄密事件
2011-12-21 19:21 2563之前有在CSDN注册过的兄弟们,注意了。。。 如果你的邮箱, ... -
一个隐形的java int溢出
2011-08-30 09:44 7554故事的背景: 笔者最近在做一个类SNS的项目,其中 ... -
雷军 :互联网创业的葵花宝典
2011-05-04 10:35 3592博主评: 这片博客很短 ... -
Luci-mint站内搜索实测
2011-04-02 16:18 4134关于Luci-mint 服务器硬 ... -
发布 IK Analyzer 3.2.8 for Lucene3.X
2011-03-04 17:49 14249IK Analyzer 3.2.8版本修订 ... -
TIPS - XML CDATA中的非法字符处理
2011-02-17 15:03 3300XML解析过程中,常遇见CDATA中存在非法字符,尤其在火星文 ... -
对Cassandra的初体验
2010-10-13 17:58 9130作为“云计算”时代的架构设计人员而言,不懂K-V库会被 ... -
Spring + iBatis 的多库横向切分简易解决思路
2010-10-11 13:43 93541.引言 笔者最近在做一个互联网的“类SNS”应用,应用 ... -
发布 IK Analyzer 3.2.5 稳定版 for Lucene3.0
2010-09-08 14:43 5821新版本IKAnnlyzer3.2.8已发布! 地址: http ... -
关于Lucene3.0.1 QueryParser的一个错误
2010-05-21 21:33 2125表达式1: 引用 id:"1231231" ... -
发布 IK Analyzer 3.2.3 稳定版 for Lucene3.0
2010-05-15 14:13 6713IK Analyzer 3.2.3版本修订 在3.2.0版 ... -
windows平台上的nginx使用
2010-01-28 17:13 3401转载自:http://nginx.org/en/docs/wi ... -
发布IKAnnlyzer3.2.0稳定版 for Lucene3.0
2009-12-07 09:27 9572最新3.2.5版本已经推出,http://linliangyi ... -
Spring AOP小例子
2009-11-16 10:35 3402PS: 要注明一下,这个是转载滴,之前漏了说鸟,汗死 这里给 ... -
ActiveMQ 5.X 与 Tomcat 集成一(JNDI部署)
2009-11-10 15:15 5647原文地址:http://activemq.apache.org ... -
发布IKAnalyzer中文分词器V3.1.6GA
2009-11-08 23:10 11853IKAnalyzer3.2.0稳定版已经发布,支持Lucene ... -
设计模式感悟
2009-11-07 17:57 3694最近又把以前学习的模式过了一遍,感觉模式不是学出来的,是悟出来 ...
相关推荐
3. **缺少依赖库**:如果驱动程序JAR(如MySQL JDBC驱动)不在`$CATALINA_HOME/lib`目录下,Tomcat将无法加载数据源所需的类,从而导致配置错误。 4. **Web应用上下文配置**:如果你的应用是在特定的Web应用上下文...
在Tomcat服务器中,JNDI的应用主要体现在其内置的JNDI实现——Tomcat JNDI,它允许开发者在应用中通过名称查找和使用资源,如数据源、环境变量等。本文将深入解析Tomcat 5.0中JNDI的工作原理,特别是`ContextBinding...
在Tomcat6.0中配置JNDI,主要是为了实现应用中的数据源管理,使得多个应用可以共享一个数据库连接池,提高资源利用率和系统性能。 **一、JNDI的基本概念** JNDI提供了一个统一的接口,让开发者可以查找和绑定各种...
在这个场景中,“intellij idea使用tomcat开发时自动部署jndi数据源”是一个重要的知识点,它涉及到如何在IDE中配置和管理数据库连接,以便于在应用运行时动态地查找和使用数据源。 JNDI(Java Naming and ...
TOMCAT8 JNDI对用户名和密码加密
在 Tomcat 的 Catalina\localhost 目录下,可以新建一个 XML 文件,文件名以应用程序名为名,内容与 server.xml 文件中的 Context 节点一样,可以直接配置私有数据源,也可以引用全局数据源。 例如,在 Catalina\...
本篇将详细介绍如何在Tomcat下配置JNDI,以便于多个组件共享数据库连接池,例如在Hibernate框架中使用。 首先,我们需要理解Tomcat中的JNDI配置。JNDI允许我们将资源(如数据源)注册到一个全局命名空间中,这样...
在Tomcat配置JNDI数据源的三种方式
在Java应用服务器中,Tomcat是一个广泛使用的轻量级服务器,而JNDI(Java Naming and Directory Interface)则是Java平台中的一个核心API,用于提供命名和目录服务。本篇文章将深入探讨Tomcat与JNDI的结合使用,帮助...
我们需要在WEB-INF目录下创建一个web.xml文件,以指定JNDI数据源。然后,我们可以在JSP页面中使用JNDI来连接数据库。 在本文中,我们将详细介绍如何使用Tomcat通过JNDI方式连接SqlServer数据库的步骤。 一、配置...
JNDI提供了一种更加灵活的方式来管理数据库连接和其他资源,尤其是在大型应用服务器环境下,这种方式可以极大地提高程序的可维护性和扩展性。 #### 二、JNDI与JDBC对比 JNDI作为JDBC的一种补充,主要优势在于: 1. ...
本示例主要讲解如何在Tomcat6中结合JNDI(Java Naming and Directory Interface)和C3P0库来配置数据库连接池,这对于初学者理解Web应用服务器与数据库的交互方式具有很大帮助。 首先,C3P0是一个开源的JDBC连接池...
在本教程中,我们将深入探讨如何在Tomcat 6.0.18这个特定版本下手动配置JNDI,以便为应用程序提供数据库连接或其他服务。 首先,我们需要理解JNDI的工作原理。JNDI提供了一个全局的命名空间,使得应用程序可以使用...
本文将详细介绍在Tomcat 6下配置JNDI连接池的步骤。 首先,我们需要创建一个Web项目。在这个例子中,我们将项目命名为`JNDITest`,并将其与Tomcat 6关联。为了实现JNDI连接池,我们需要引入两个外部库:`commons-...
1. **创建发布XML文件**:在`jakarta-tomcat-5.5.9\conf\Catalina\localhost`目录下创建一个名为`myprj.xml`的文件,用于指定Web应用程序的上下文参数。 2. **编辑`myprj.xml`**:编辑该文件,添加以下内容: ```...
tomcat中配置jndi 数据源!!!
【描述】:“在Tomcat服务器上配置JNDI数据源,特别是通过DBCP连接池的方式” 【标签】:“tomcat,配置,JNDI数据源” 【内容】:配置JNDI数据源在Java Web应用程序中是一个重要的任务,它允许应用与数据库之间的...
本篇文章将深入探讨如何在这样的环境下配置JNDI(Java Naming and Directory Interface),以便于应用程序能方便地查找和使用数据库资源。JNDI是Java平台中的一种标准服务,它提供了一个统一的接口来查找和管理各种...
标题中的“Tomcat6.0配置JNDI数据源完整例子”是指在Apache Tomcat 6.0服务器中设置Java Naming and Directory Interface (JNDI)数据源的过程。JNDI是一个API,它允许应用程序查找和使用命名服务,如数据库连接池。...