JNDI介绍
JNDI(Java Naming and Directory Interface)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI SPI的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。集群JNDI实现了高可靠性JNDI[8],通过服务器的集群,保证了JNDI的负载平衡和错误恢复。在全局共享的方式下,集群中的一个应用服务器保证本地JNDI树的独立性,并拥有全局的JNDI树。每个应用服务器在把部署的服务对象绑定到自己本地的JNDI树的同时,还绑定到一个共享的全局JNDI树,实现全局JNDI和自身JNDI的联系。JNDI目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。在
DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。
在javax.naming的包包中提供Context接口,提供了两个很好用的方法:
1、void bind( String name , Object object )
将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。
2 、Object lookup( String name )
检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表示与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。
JNDI运行机制:
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() 方法并没有关闭事实上的数据库连接,仅仅是释放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。现在,数据库的连接没有用到连接池几乎很少很少,每个项目组都可能有自己的数据库连接池组件,各容器提供商也提供了各自的数据库连接池,下面介绍一下WebLogic的数据库连接管理。
WebLogic下配置JNDI
Weblogic中配置数据源可以利用weblogic管理控制台图形界面按照相关提示进行配置,配置完成后会在域目录下生成配置文件,我的配置文件目录为:
C:\Oracle\Middleware\user_projects\domains\base_domain\config\jdbc\mysqldatasource-jdbc.xml
其内容为:
<?xml version='1.0' encoding='UTF-8'?>
<jdbc-data-source xmlns="http://xmlns.oracle.com/weblogic/jdbc-data-source" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/jdbc-data-source http://xmlns.oracle.com/weblogic/jdbc-data-source/1.0/jdbc-data-source.xsd">
<!-- WebLogic 域中标识该数据源的唯一名称-->
<name>mysqldatasource</name>
<!--有关Mysql数据库连接的参数 -->
<jdbc-driver-params>
<!-- Mysql数据库地址 -->
<url>jdbc:mysql://127.0.0.1:3306/jdbctest</url>
<!-- Mysql数据库驱动名称 -->
<driver-name>com.mysql.jdbc.Driver</driver-name>
<properties>
<property>
<!-- Mysql用户名 -->
<name>user</name>
<value>root</value>
</property>
</properties>
<!-- 通过加密算法加密之后的密码 -->
<password-encrypted>{AES}CirkUeG+1VmFjN1jzbKwezLpOtBDEX+r6bd/zmJTYHA=</password-encrypted>
</jdbc-driver-params>
<!-- 数据库连接池相关参数 -->
<jdbc-connection-pool-params>
<!-- 在weblogic建立数据源测试时的表名 -->
<test-table-name>SQL SELECT 1</test-table-name>
</jdbc-connection-pool-params>
<jdbc-data-source-params>
<!-- 此数据源绑定到的 JNDI 路径,默认情况下, JNDI 名称就是数据源的名称,供其他外部应用调用!-->
<jndi-name>mysqljndi</jndi-name>
<global-transactions-protocol>OnePhaseCommit</global-transactions-protocol>
</jdbc-data-source-params>
</jdbc-data-source>
外部调用代码:
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL,"t3://localhost:7001");
// 初始化查找命名空间
Context ctx = new InitialContext(env);
DataSource ds = (DataSource) ctx.lookup("mysqljndi");
// 获取数据库连接
Connection conn = ds.getConnection();
JTA介绍
Java Transaction API(Application Programming Interface),JTA Transaction是指由J2EE Transaction manager去管理的事务。其最大的特点是调用UserTransaction接口的begin,commit和rollback方法来完成事务范围的界定,事务的提交和回滚。JTATransaction可以实现同一事务对应不同的数据库,但是它仍然无法实现事务的嵌套。JTA是只是一组java接口用于描述,J2ee框架中事务管理器与应用程序,资源管理器,以及应用服务器之间的事务通讯。它主要包括高层接口即面向应用程序的接口;XAResource接口即面向资源的接口;以及事务管理器的接口。值得注意的是JTA只提供了接口,没有具体的实现。JTS是服务OTS的JTA的实现。简单的说JTS实现了JTA接口,并且符合OTS的规范。资源管理器只要其提供给事务管理器的接口符合XA接口规范,就可以被事务管理器处理。所以,JTA可以处理任何提供符合XA接口的资源。包括:数据库,JMS,商业对象等等 ,“
Java 事务 API”(JTA)启用两阶段提交功能。当配置WebLogic Server 以访问数据库时,可选择具有JTA 能力的驱动程序。如果需要两阶段提交功能,则必须使用启用 JTA 的驱动程序。
只要在事务中调用了多个数据库连接,就需要JTA。只要在事务中调用了多个数据库服务器,就需要两阶段提交。这些连接可以是相同的物理数据库服务器或多个数据库服务器,
当事务涉及到多个进程时,JTA 也是必需的。
weblogic中使用JTA
1 通过JNDI得到TransactionManager,然后可以用TransactionManager的begin,commit等方法来控制事务。
traMgr = (TransactionManager) context.lookup("javax.transaction.UserTransaction");
2 获取在weblogic上定义的datasource,datasource必须支持XA。
DataSource ds1 = (DataSource)context.lookup("jndi名称");
3 用TransactionManager声明事务开始,通过DataSource操作数据库,然后commit或者rollback事务。
traMgr.begin();//通过DataSource得到connection,然后操作数据库。
traMgr.commit();或者traMgr.rollback();
有时候
,数据源可能不是在weblogic上配置的,或者是从不同的APP server上获取的,需要利用TransactionManager.enlistResource(XAResource)主动的把这种资源加入到当前的事务管理中来。而对于从weblogic上配置的DataSource,TransactionManager声明事务后,DataSource可以自动的发现并加入当前的事务,TransactionManager在begin()的时候会将当前的事务信息绑定到当前的线程上。