首页 > 学院 > 开发设计 > 正文

开发 Web 应用程序的快捷途径介绍

2019-11-18 12:53:01
字体:
来源:转载
供稿:网友

  共享物理连接
  共享一个连接只能在共享作用域中发生。最常见的共享作用域是多个活动的连接句柄可以共享同一物理连接的事务作用域。在 application Server V5 中有两个事务作用域:全局事务和本地事务容器(Local Transaction Containment,LTC)边界。
  
  全局事务可以是由 J2EE 应用程序启动的用户事务,或者是由 Application Server EnterPRise java Bean(EJB)容器所启动的容器全局事务。当使用 Required 或 RequiresNew 事务属性配置了 EJB 方法时,EJB 容器就启动一个全局事务。当使用 Required、Supports 或 Mandatory 事务属性配置了 EJB 方法时,EJB 容器也可以使用客户端的全局事务。注重 EJB 的客户端可以是 J2EE 应用程序、Servlet、jsp 或另一个 EJB。
  LTC 边界与资源治理器本地事务(Resource Manager Local Transaction,RMLT)是有区别的,后者是本地事务的资源视图。LTC 是一个作用域,在它里面可以访问多个 RMLT。在没有全局事务的时候,通常由容器来建立 LTC。LTC 的一个示例是含事务属性 NotSupported 的 Bean 方法的执行。 RMLT 的一个示例是将 autocommit 设置为 false,稍后再提交连接。
  在 Application Server 中,连接共享作用域是全局事务。虽然在 LTC 中调用多次 getConnection 可以返回具有同一物理连接的多个连接句柄,该物理连接被连续重用,但是并没有被共享。此行为是"连接串行重用(connection serial reuse)。"后面将讨论 LTC 中的连接串行重用。
  
  正如上面所提到的,假如一个应用程序的部署描述符元素 res-sharing-scope 被设置为 shareable,并且符合某些条件,那么在此应用程序中多次调用 getConnection 符合共享同一连接的条件。要让一个共享作用域中调用多次 getConnection 返回同一物理连接,下列连接特性必须一致:
  
  Java 命名和目录接口(Java Naming and Directory Interface,JNDI)名称。 虽然 JNDI 名称实际上不是一个连接特性,但是此必要条件表示您只能共享来自位于相同服务器进程的相同数据源的连接。您必须在应用程序服务器中的相同数据源上调用两次 getConnection 调用以共享一个物理连接。
  资源认证设置。使用资源引用的资源认证设置来指定应用程序组件供给者如何将一个主体(用户 ID 和密码)联系到一个资源治理器。对于非 CMP 应用程序,资源认证由 res-auth 部署描述符来标识。它的值是 Application 或 Container。Application Server 也为 CMP 连接工厂的资源认证提供一个 IBM 扩展。该设置由 IBM 部署描述符扩展文件 ibm-ejb-jar-ext.xmi 中的 resAuth 元素来标识。您可以将 resAuth 的值设置为 Per_Connection_Factory 或 Container。Per_Connection_Factory 与 res-auth 部署描述符的 Application 值一致。当两个数据源或连接工厂引用与 Application Server 中的一个数据源相关联,那么在(并且仅在)这两个引用拥有相同的资源认证值的情况下连接是可共享的。要查阅有关资源认证的描述,请参考 WebSphere Application Server V5 中的数据库验证。
  主体。相同的主题表示相同的用户和密码对于相关的数据库是必需的。假如应用程序使用一个不同的用户 ID 和密码来获取连接,那么从 getConnection 调用返回的物理连接将是不同的。当应用程序的资源认证设置被设置为 Application 时,您可以通过 getConnection() 或 getConnection(String userid, String passWord) 来获取连接。请注重,即使与数据源相关联的受组件治理的认证别名在所使用的 getConnection(String userid, String password) 中有相同的用户 ID 和密码,从这两个调用获取的连接也不是共享的。
  连接事务隔离级别特性。在 Application Server 中,您可以通过几种方法来指定获取的连接所使用的隔离级别:
  您可以使用访问意图来指定事务隔离级别。
  您可以使用 IBM 扩展(在 IBM 扩展文件中指定为 isolationLevel)来指定特定应用程序的数据源引用的隔离级别。
  您可以将事务隔离级别设置为 IBM 扩展 API(JDBCConnectionSpec),然后使用 WSDataSource.getConnection(JDBCConnectionSpec)来获取连接。要共享同一物理连接,在一个给定事务中的多个 getConnection 调用的事务隔离级别必须是相同的。请注重,IBM 扩展 API-JDBCConnectionSpec 是一个私有 API。假如您使用这个 API,您的应用程序将不能转换到其他应用程序服务器。
  连接 readOnly、catalog 和 typeMap 特性。正如同连接事务隔离级别,这三个连接特性对多个 getConnection 调用必须是相同的,以共享同一物理连接。应用程序可以使用 JDBCConnectionSpec 来指定这三个特性的值。
  假如上述必要条件中的一个没有满足,那么两个 getConnection 调用将返回不同的物理连接。
  
  清单 1 显示了在一个用户事务中共享同一物理连接的两个连接句柄。资源引用的资源共享作用域被设为 Shareable。连接 conn1 和 conn2 是从同一数据源 ds 获取的两个连接句柄。由于这两个连接是在一个共享作用域(在本例中,是一个用户事务)中获取的,并且所有的共享必要条件都已满足,所以 conn1 和 conn2 共享同一物理连接。
  
  假如将一个应用程序的部署描述符中的 res-sharing-scope 部署描述符元素设置为 Unshareable,那么这些连接不共享同一物理连接。在一个全局事务或 LTC 中的多个 getConnection 调用将返回包含不同物理连接的连接句柄。
  
  清单 1. 在一个用户事务中共享连接
  
  // Start a user transaction
  userTransaction.begin();
  
  // Get the first connection
  java.sql.Connection conn1 = ds.getConnection();
  java.sql.Statement stmt1 = conn1.createStatement();
  ...
  
  // Get the second connection
  java.sql.conenction conn2 = ds.getConnection();
  java.sql.Statement stmt2 = conn2.createStatement();
  ...
  
  // Commit the user transaction
  userTransaction.commit();
  
  LTC 中的连接串行重用
  在一个本地事务容器(Local Transaction Containment,LTC)边界中,您不能拥有多个使用同一物理连接的活动连接句柄。然而,假如前面的包装相同物理连接的连接句柄已关闭,那么您可以重用该物理连接。在您使用如下模式时将发生连接重用:
  
  获得连接 1 -> 使用连接 1 -> 提交/回滚连接1(可选) -> 关闭连接 1 -> 获得连接 2 -> 使用连接 2 -> 提交/回滚连接 2(可选) -> 关闭连接 2 -> ...
  假设使用了相同的特性并且没有将 res-sharing-scope 设置为 unshareable,那么从第二个 getConnection 返回的连接与从第一个 getConnection 返回的连接相同。因为连接的使用是串行的,在同一时间仅有一个到基础物理连接的连接句柄,所以没有发生真正的连接共享。因此,物理连接被"串行重用(serially reused)。" 请注重,在本模式中提交和回滚连接是可选的。也就是说,即使第一个连接没有被提交或回滚,一旦前一连接已关闭,第二个 getConnection 仍然返回相同的物理连接。您必须注重下列语句隐藏的事务语义:"连接句柄 2 的回滚或提交将回滚或提交对连接句柄 2 所做的工作。它也将回滚或提交对连接句柄 1 所做的工作。"
  
  清单 2 显示了在一个 LTC 中两个连接句柄重用相同的物理连接。该代码在一个 Web 应用程序(Servlet)中,或者位于在全局事务边界内未执行的 EJB 方法中。在没有全局事务边界的情况下,将建立 LTC 边界。在本应用程序中,连接 conn1 从数据源 ds 获得,然后连接 conn1 的 autocommit 值被设为 false。再将记录 1 插入到数据库中。在此之后,没有经过提交或回滚连接,连接 conn1 就被关闭了。然后从相同的数据库 ds 获得连接 conn2。由于用来获得连接 conn2 的连接特性与用来获得连接 conn1 的连接特性相同,并且连接 conn1 已关闭,所以连接 conn2 重用相同的物理连接。在此之后,conn2 的 autocommit 被设置为 false(重用连接,所以不需要将 autocommit 设置为 false,因为它已经是 false),然后记录 2 被插入到数据库中。当回滚连接 conn2 时,不仅回滚了记录 2 插入,同时也回滚了记录 1 插入。
  
  清单 2. 在 LTC 边界中重用连接
  
  // Get the first connection
  java.sql.Connection conn1 = ds.getConnection();
  conn1.setAutoCommit(false)
  java.sql.Statement stmt1 = conn1.createStatement();
  
  //use statement1 to insert record 1
  ... ...
  
  conn1.close();
  
  java.sql.conenction conn2 = ds.getConnection();
  conn2.setAutoCommit(false);
  java.sql.Statement stmt2 = conn2.createStatement();
  
  //use statement 2 to insert record 2
  ... ...
  conn2.rollback();
  conn2.close();
  
  编程模型
  共享连接使应用程序更具有可伸缩性。它减少了资源分配,还减少了出现死锁情况的机会。然而,在共享连接时是有限制的。例如,不答应在可共享的连接上设置特性,这是因为一个连接句柄的用户可能无法预见由其他连接句柄做出的更改。该限制是 J2EE 1.3 标准的一部分。
  
  在某些情况下,您不希望应用程序共享物理连接。一个原因在于该应用程序可能需要更改连接属性,而那些更改对于可共享连接是不被答应的。然而,除了增加资源分配消耗之外,还有其他有关使用不可共享连接的约束。
  
  让我们在此查看清单 1 中的代码。假设数据源的资源引用被标记为 Unshareable。连接句柄 conn1 和 conn2 将有不同的物理连接。该应用程序在下

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表