JNDI,JTA和JMS简介
什么是JNDI
原理:在DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。
JNDI( Java Naming and DirectoryInterface ),是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个 API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。
在javax.naming的包中提供Context接口,提供了两个很好用的方法:
<1> void bind( String name , Object object )
将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。
<2>Object lookup( String name )
检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表示与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。
运行机制:
1、首先程序代码获取初始化的 JNDI 环境并且调用 Context.lookup() 方法从 JNDI 服务提供者那里获一个 DataSource 对象
2、中间层 JNDI 服务提供者返回一个 DataSource 对象给当前的 Java 应用程序这个 DataSource 对象代表了中间层服务上现存的缓冲数据源
3、应用程序调用 DataSource 对象的 getConnection() 方法
4、当 DataSource 对象的 getConnection() 方法被调用时,中间层服务器将查询数据库连接缓冲池中有没有PooledConnection 接口的实例对象。这个 PooledConnection 对象将被用于与数据库建立物理上的数据库连接
5、如果在缓冲池中命中了一个PooledCoonection 对象那么连接缓冲池将简单地更新内部的缓冲连接队列并将该PooledConnection 对象返回。如果在缓冲池内没有找到现成的PooledConnection 对象,那么 ConnectionPoolDataSource 接口将会被用来产生一个新的PooledConnection 对象并将它返回以便应用程序使用
6。中间层服务器调用PooledConnection 对象的 getConnection() 方法以便返还一个 java.sql.Connection 对象给当前的 Java 应用程序
7、当中间层服务器调用PooledConnection 对象的 getConnection() 方法时, JDBC 数据库驱动程序将会创建一个 Connection 对象并且把它返回中间层服务器
8、中间层服务器将 Connection 对象返回给应用程序 Java 应用程序,可以认为这个 Connection 对象是一个普通的 JDBC Connection 对象使用它可以和数据库建立。事实上的连接与数据库引擎产生交互操作。
9、当应用程序不需要使用 Connection 对象时,可以调用 Connection 接口的 close() 方法。请注意这种情况下 close() 方法并没有关闭事实上的数据库连接,仅仅是释放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。
现在,数据库的连接没有用到连接池几乎很少很少,每个项目组都可能有自己的数据库连接池组件,各容器提供商也提供了各自的数据库连接池,下面介绍一下tomcat的数据库连接管理。
tomcat6 数据源配置(server.xml方式和context.xml方式)
在server.xml下配置你必需重启服务器才能生效,而context.xml配置保存后tomcat会自动加载无需重启
在JNDI配配置数据源中需注意:项目下需要引入数据库驱动包,并且TOMCAT下也需要引入,不然会报错的
1.context.xml方式
Tomcat-6.0.26\conf\context.xml文件当添加以下的配置信息:
<Resource name="jdbc/mysql" auth="Container"type="javax.sql.DataSource" maxActive="100"maxIdle="30" maxWait="60" wait_timeout="18800"timeBetweenEvictionRunsMillis="300000"minEvictableIdleTimeMillis="600000" username="root"password="jdzxdb" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/sxtele?comautoReconnect=true&failOverReadOnly=false" removeAbandoned="true"removeAbandonedTimeout="60" logAbandoned="true"/> <Resource name="jdbc/db2" auth="Container"type="javax.sql.DataSource" maxActive="100"maxIdle="30" maxWait="60" wait_timeout="18800"timeBetweenEvictionRunsMillis="300000"minEvictableIdleTimeMillis="600000" username="lcgluser" password="lcgluser"driverClassName="com.ibm.db2.jcc.DB2Driver" url="jdbc:db2://133.64.46.65:50000/STEDWDB" removeAbandoned="true"removeAbandonedTimeout="60" logAbandoned="true"/>
其中:
name 表示指定的jndi名称
auth 表示认证方式,一般为Container
type 表示数据源床型,使用标准的javax.sql.DataSource
maxActive 表示连接池当中最大的数据库连接
maxIdle 表示最大的空闲连接数
maxWait 当池的数据库连接已经被占用的时候,最大等待时间
logAbandoned 表示被丢弃的数据库连接是否做记录,以便跟踪
username 表示数据库用户名
password 表示数据库用户的密码
driverClassName 表示JDBC DRIVER
url 表示数据库URL地址
注意,这里你配置的name值要和程序中使用的是一样的,比如按照这个例子,程序就应该是这样的,Java代码:
String gENV = "java:comp/env/"; Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup(gENV+"jdbc/mysql"); Connection conn =ds.getConnection(); String gENV = "java:comp/env/"; Context ctx = new InitialContext(); DataSource ds =(DataSource)ctx.lookup(gENV+"jdbc/db2"); Connection conn =ds.getConnection();
关于获取数据源的语法,大体有(javax.sql.DataSource) ctx.lookup("java:comp/env/XXX")和(javax.sql.DataSource)ctx.lookup("XXX")两种写法,好多人以为这两种写法是相同的,以为都是通过JNDI来获取数据源。其实java:comp/env和 JNDI是不同的,java:comp/env 是环境命名上下文(environmentnaming context(ENC)),是在EJB规范1.1以后引入的,引入这个是为了解决原来JNDI查找所引起的冲突问题,也是为了提高EJB或者J2EE应用的移植性。ENC是一个引用,引用是用于定位企业应用程序的外部资源的逻辑名。引用是在应用程序部署描述符文件中定义的。在部署时,引用被绑定到目标可操作环境中资源的物理位置(JNDI名)。使用ENC是把对其它资源的JNDI查找的硬编码解脱出来,通过配置这个引用可以在不修改代码的情况下,将引用指向不同的EJB(JNDI)。
什么是JTA
Java Transaction API(Java事务API)(JTA)Java Transaction API(Application Programming Interface)
什么是JTA Transaction?它有怎样的特点呢?JTA Transaction是指由J2EE Transaction manager去管理的事务。其最大的特点是调用UserTransaction接口的begin,commit和rollback方法来完成事务范围的 界定,事务的提交和回滚。JTATransaction可以实现同一事务对应不同的数据库,但是它仍然无法实现事务的嵌套。
分布式事务的规范由OMG的OTS所描述。
JTA是只是一组java接口用于描述,J2ee框架中事务管理器与应用程序,资源管理器,以及应用服务器之间的事务通讯。
它主要包括高层接口即面向应用程序的接口;XAResource接口即面向资源的接口;以及事务管理器的接口。值得注意的是JTA只提供了接口,没有具体的实现。
JTS是服务OTS的JTA的实现。简单的说JTS实现了JTA接口,并且符合OTS的规范。
资源管理器只要其提供给事务管理器的接口符合XA接口规范,就可以被事务管理器处理。 所以,JTA可以处理任何提供符合XA接口的资源。包括:数据库,JMS,商业对象等等
“Java 事务 API”(JTA)启用两阶段提交功能。当配置WebSphere Application Server 以访问数据库时,可选择具有 JTA 能力的驱动程序。如果需要两阶段提交功能,则必须使用启用 JTA 的驱动程序。
只要您在事务中调用了多个数据库连接,就需要 JTA。只要您在事务中调用了多个数据库服务器,就需要两阶段提交。这些连接可以是相同的物理数据库服务器或多个数据库服务器。例如:
[list=1][*]实体企业 BeanEntity1 在应用程序服务器 AppServer1 中部署。[*]实体企业 Bean Entity2 在应用程序服务器AppServer1 中部署。[*]会话企业 Bean Session1 在应用程序服务器 AppServer1 中部署。[/list]如果Session1 对同一事务内的 Entity1 和 Entity2 调用了方法而这两个企业 Bean 正在使用不同的物理数据库连接,则必须对 Entity1 和 Entity2 使用的数据源启用 JTA。当从相同的数据源对象获取那些连接时,这也是成立的。这需要具有 JTA 能力的驱动程序以提交事务。
当事务涉及到多个进程时,JTA 也是必需的。例如,一个事务可能会涉及在多个应用程序服务器中部署的企业 Bean。
[list=1][*]实体企业 BeanEntity1 在应用程序服务器 AppServer1 中部署。[*]实体企业 Bean Entity2 在应用程序服务器AppServer2 中部署。[*]会话企业 Bean Session1 在应用程序服务器 AppServer1 中部署。[/list]如果Session1 对同一事务(此事务构成一个分布式事务)内的 Entity1 和 Entity2 调用了方法,则必须对 Entity1 和 Entity2 使用的数据源启用 JTA。
性能实现JTA 启用的连接与非 JTA 启用的连接执行情况不同。基于此原因,如果您的应用程序不需要 JTA,则最好使用非 JTA 启用的驱动程序。
其它信息有关 WebSphere Application Server 如何支持 JTA 的信息,参见 WebSphere Application Server 和 DB2UDB iSeries 版的事务处理及其子主题。
什么是JMS
jms即Java消息服务(JavaMessage Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。jms同时也可以指Journal of Marketing Science,《营销科学学报》的简称。此外,佳木斯的拼音缩写也是jms。
传递方式
JMS有两种传递消息的方式。标记为NON_PERSISTENT的消息最多投递一次,而标记为PERSISTENT的消息将使用暂存后再转送的机理投递。如果一个JMS服务离线,那么持久性消息不会丢失但是得等到这个服务恢复联机时才会被传递。所以默认的消息传递方式是非持久性的。即使使用非持久性消息可能降低内务和需要的存储器,并且这种传递方式只有当你不需要接收所有的消息时才使用。
虽然JMS规范并不需要JMS供应商实现消息的优先级路线,但是它需要递送加快的消息优先于普通级别的消息。JMS定义了从0到9的优先级路线级别,0是最低的优先级而9则是最高的。更特殊的是0到4是正常优先级的变化幅度,而5到9是加快的优先级的变化幅度。举例来说: topicPublisher.publish (message, DeliveryMode.PERSISTENT, 8, 10000); //Pub-Sub 或 queueSender.send(message,DeliveryMode.PERSISTENT, 8, 10000);//P2P 这个代码片断,有两种消息模型,映射递送方式是持久的,优先级为加快型,生存周期是10000 (以毫秒度量)。如果生存周期设置为零,这则消息将永远不会过期。当消息需要时间限制否则将使其无效时,设置生存周期是有用的。
总结
本文关于JNDI,JTA和JMS简介就到这里,希望对大家有所帮助。