Spring Integration集成其它EIS系统浅析(spring集成大结局)

注:整个pring Integration集成完整内容的链接如下

https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1467395879861698562&__biz=Mzg5OTA1OTExMQ==#wechat_redirect


背景

J2EE提供JCA(Java Connector Architecture)规范来标准化对EIS的访问。这个规范被分为几个不同的部分:

  • SPI(Service provider interfaces)是连接器提供者(connector provider)必须实现的接口。这些接口组成了一个能被部署在J2EE应用服务器上的资源适配器(resource adapter)。在这种情况下,由服务器来管理连接池(connection pooling)、事务和安全(托管模式(managed mode))。应用服务器还负责管理客户端所拥有的配置。一个连接器(connector)同样能在脱离应用服务器的情况下使用。在这种情况下,应用程序必须直接对它进行配置(非托管模式(non-managed mode))。

  • CCI (Common Client Interface)是应用程序用来与连接器交互并与EIS通信的接口。同样还为本地事务划界提供了API。

Spring对CCI的支持,目的是为了提供以Spring典型的方式来访问CCI连接器的类,并有效地使用Spring的通用资源和事务管理机制。

注意

连接器的客户端不必总是使用CCI。某些连接器暴露它们自己的API来提供JCA资源适配器(resource adapter)以便使用J2EE容器提供的某些系统契约(system contracts)(连接池(connection pooling),全局事务(global transactions),安全(security))。Spring并没有为这类连接器特有(connector-specific)的API提供特殊的支持。

https://documentation.help/j2EE-Spring-Framework/ch21.html



Spring 对JCA CCI的支持

spring的jca cci支持在spring-tx模块:

image.png

配置CCI

  • 连接器配置

使用JCA CCI的基础资源是 ConnectionFactory 接口。所用的连接器必须提供这个接口的一个实现。

为了使用连接器,可以把它部署到你的应用服务器上,并从服务器的JNDI环境(托管模式)取回 ConnectionFactory。连接器必须打包为一个RAR文件(resource adapte archive)并包含一个部署描述符文件 ra.xml 。部署时需要指定资源的实际名字。如果想通过Spring访问它,只要简单地使用Spring的 JndiObjectFactoryBean 来通过JNDI名字获取工厂。

使用连接器的另一种方法是把它嵌入到应用程序中(非托管模式(non-managed mode)),而不用在应用服务器中部署并配置它。Spring提供了通过已提供的 FactoryBean(LocalConnectionFactoryBean))来将连接器配置成一个bean的可能。在这种方式中,只需要把连接器类库放到classpath目录下(不需要RAR文件和 ra.xml 描述符)。如果有必要的话,必须从连接器的RAR文件解压得到那个类库。

一旦访问 ConnectionFactory 实例, 就可以将它注入到组件。这些组件既可以用简单的CCI API编码,也可以利用Spring支持CCI访问的类(比如,CciTemplate)。

注意

当在非托管模式(non-managed mode)下使用连接器时,将无法使用全局事务, 因为该资源从不会被加入或删除到当前线程的当前全局事务中。该资源根本不知道任何可能正在运行的全局的J2EE事务。

  • 在Spring中配置ConnectionFactory

为了创建到 EIS 的连接,如果处于托管模式(managed mode),你需要从应用服务器获取一个 ConnectionFactory , 或者当你在非托管模式(non-managed mode)时直接从Spring去获取。

在托管模式(managed mode)下,你可以从JNDI访问 ConnectionFactory, 它的属性将被配置在应用服务器中。

<bean id="eciConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">

<property name="jndiName" value="eis/cicseci"/>

</bean>

在非托管模式(non-managed mode)下,你必须在Spring配置中将你要用的 ConnectionFactory 配置为一个JavaBean。LocalConnectionFactoryBean 类提供这种配置风格,把 ManagedConnectionFactory 传入到你的连接器的实现中, 暴露应用级的CCI ConnectionFactory。

<bean id="eciManagedConnectionFactory" class="com.ibm.connector2.cics.ECIManagedConnectionFactory">

<property name="serverName" value="TXSERIES"/>

<property name="connectionURL" value="tcp://localhost/"/>

<property name="portNumber" value="2006"/>

</bean>

<bean id="eciConnectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">

<property name="managedConnectionFactory"ref="eciManagedConnectionFactory"/>

</bean>

注意

你不能直接实例化一个指定的 ConnectionFactory 接口。你需要为连接器实现相应的 ManagedConnectionFactory 接口,这个接口是JCA SPI规范的一部分。

  • 配置CCI连接

JCA CCI允许开发者使用自己的连接器的 ConnectionSpec 接口实现来配置到 EIS 的连接。为了配置该连接的属性,需要用一个指定的 ConnectionSpecConnectionFactoryAdapter 适配器来封装目标连接工厂。因此,特定的 ConnectionSpec 接口可以用 connectionSpec 属性来配置(作为一个内部bean)。

这个属性不是必需的,因为CCI ConnectionFactory 接口定义了两个不同的方法来获取 CCI 连接。ConnectionSpec 的一些属性常常可以被配置在应用服务器中(托管模式(managed mode)) 或相关的本地 ManagedConnectionFactory 实现。

public interface ConnectionFactory implements Serializable, Referenceable {

...

Connection getConnection() throws ResourceException;

Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException;

...

}

Spring提供了 ConnectionSpecConnectionFactoryAdapter 适配器, 允许你指定一个 ConnectionSpec 接口的实例, 供给定工厂的所有操作使用。如果指定了适配器的 connectionSpec 属性,适配器就使用没有参数的 getConnection 变量, 而不是有 ConnectionSpec 参数的变量。

<bean id="managedConnectionFactory"

class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">

<property name="connectionURL" value="jdbc:hsqldb:hsql://localhost:9001"/>

<property name="driverName" value="org.hsqldb.jdbcDriver"/>

</bean>

<bean id="targetConnectionFactory"

class="org.springframework.jca.support.LocalConnectionFactoryBean">

<property name="managedConnectionFactory" ref="managedConnectionFactory"/>

</bean>

<bean id="connectionFactory"

class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">

<property name="targetConnectionFactory" ref="targetConnectionFactory"/>

<property name="connectionSpec">

<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">

<property name="user" value="sa"/>

<property name="password" value=""/>

</bean>

</property>

</bean>

  • 使用一个 CCI 单连接

如果想使用一个 CCI 单连接,Spring提供一个额外的 ConnectionFactory 适配器来管理它。SingleConnectionFactory 适配器类将延迟打开一个单独的连接并在应用程序销毁这个bean的时候关闭它。这个类将暴露出特殊 Connection 的相应代理,并共享同一个底层的物理连接。

<bean id="eciManagedConnectionFactory"

class="com.ibm.connector2.cics.ECIManagedConnectionFactory">

<property name="serverName" value="TEST"/>

<property name="connectionURL" value="tcp://localhost/"/>

<property name="portNumber" value="2006"/>

</bean>

<bean id="targetEciConnectionFactory"

class="org.springframework.jca.support.LocalConnectionFactoryBean">

<property name="managedConnectionFactory" ref="eciManagedConnectionFactory"/>

</bean>

<bean id="eciConnectionFactory"

class="org.springframework.jca.cci.connection.SingleConnectionFactory">

<property name="targetConnectionFactory" ref="targetEciConnectionFactory"/>

</bean>

注意

这个 ConnectionFactory 适配器不能直接用 ConnectionSpec 配置。如果需要特定 ConnectionSpec 的单一连接,那么可以用 SingleConnectionFactory 与之通信的中间 ConnectionSpecConnectionFactoryAdapter 适配器。


CciTemplate类

CciTemplate 类是 CCI 核心支持包(org.springframework.jca.cci.core)中主要的类。它简化了CCI的使用,因为它会处理资源的创建和释放。这有助于避免常见的错误,比如总是忘记关闭连接。它关注连接和交互对象的生命周期,从而使应用程序的代码可以专注于处理从应用程序数据中生成输入记录和从输出记录中提取应用程序数据。

JCA CCI规范定义了两个不同的方法来在EIS上调用操作。CCI Interaction 接口提供两个 execute 方法的签名:

public interface javax.resource.cci.Interaction {

...

boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException;

Record execute(InteractionSpec spec, Record input) throws ResourceException;

...

}

依赖于模板方法的调用,CciTemplate 类可以知道 interaction上的哪个 execute 方法被调用。在任何情况下,都必须有一个正确初始化过的 InteractionSpec 实例。

CciTemplate.execute(..)可以以下列两种方式使用:

  • 在提供直接的 Record 参数的情况下,只需要传递输入记录给 CCI , 而返回的对象就是对应的 CCI 输出记录。

  • 在提供使用记录映射的应用对象的情况下,你需要提供相应的 RecordCreator 和 RecordExtractor 实例。

第一种方法将使用下面的模板方法。这些模板方法将直接对应到 Interaction 接口。

public class CciTemplate implements CciOperations {

public Record execute(InteractionSpec spec, Record inputRecord)

throws DataAccessException { ... }

public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord)

throws DataAccessException { ... }

}

第二种方法需要我们以参数的方式指定创建记录和记录提取的策略。使用前面记录转化一节中描述的接口。对应的 CciTemplate 方法如下:

public class CciTemplate implements CciOperations {

public Record execute(InteractionSpec spec, RecordCreator inputCreator)

throws DataAccessException { ... }

public Object execute(InteractionSpec spec, Record inputRecord, RecordExtractor outputExtractor)

throws DataAccessException { ... }

public Object execute(InteractionSpec spec, RecordCreator creator, RecordExtractor extractor)

throws DataAccessException { ... }

}

除非在模板上设置 outputRecordCreator 属性(参见下一部分), 不然每个方法都将调用CCI Interaction 中相应的含有两个参数:InteractionSpec 和输入 Record的 execute 方法, 并接收一个输出 Record 作为返回值。

通过 createIndexRecord(..) 和 createMappedRecord(..) 方法, CciTemplate 在 RecordCreator 实现类外部也提供了创建 IndexRecord 和 MappedRecord。还可以用来在DAO实现内创建记录实例并传入到相应的 CciTemplate.execute(..) 方法。

public class CciTemplate implements CciOperations {

public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... }

public MappedRecord createMappedRecord(String name) throws DataAccessException { ... }

}

  • DAO支持

Spring的 CCI 支持为 DAO 提供了一个抽象类,支持 ConnectionFactory 或 CciTemplate 实例的注入。这个类的名字是 CciDaoSupport:它提供了简单的 setConnectionFactory 和 setCciTemplate 方法。在内部,该类将为传入的 ConnectionFactory 创建一个 CciTemplate 实例, 并把它暴露给子类中具体的数据访问实现使用。

public abstract class CciDaoSupport {

public void setConnectionFactory(ConnectionFactory connectionFactory) { ... }

public ConnectionFactory getConnectionFactory() { ... }

public void setCciTemplate(CciTemplate cciTemplate) { ... }

public CciTemplate getCciTemplate() { ... }

}

  • 自动输出记录生成

如果所用的连接器只支持以输入输出记录作为参数的 Interaction.execute(..) 方法 (就是说,它要求传入期望的输出记录而不是返回适当的输出记录), 你可以设定 CciTemplate 类的 outputRecordCreator 属性来自动生成一个输出记录, 当接收到响应时JCA连接器(JCA connector)将填充该记录并返回给模板的调用者。

因为这个目的,这个属性只持有 RecordCreator 接口的一个实现。RecordCreator 接口已经在 第 21.3.1 节 “记录转换” 进行了讨论。outputRecordCreator 属性必须直接在 CciTemplate 中指定,可以在应用代码中做到这一点。

cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator());

或者如果 CciTemplate 被配置为一个专门的bean实例,那么outputRecordCreator还可以在Spring文件中配置(推荐的做法):

<bean id="eciOutputRecordCreator" class="eci.EciOutputRecordCreator"/>

<bean id="cciTemplate" class="org.springframework.jca.cci.core.CciTemplate">

<property name="connectionFactory" ref="eciConnectionFactory"/>

<property name="outputRecordCreator" ref="eciOutputRecordCreator"/>

</bean>

注意

因为 CciTemplate 类是线程安全的,所以它通常被配置为一个共享实例。


拓展tomcat Connector

Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后再交给Connector返回给客户端。

image.png

Tomcat源码中与connector相关的类位于org.apache.coyote包中,Connector分为以下几类:

  • Http Connector, 基于HTTP协议,负责建立HTTP连接。它又分为BIO Http Connector与NIO Http Connector两种,后者提供非阻塞IO与长连接Comet支持。默认情况下,Tomcat使用的就是这个Connector。

  • AJP Connector, 基于AJP协议,AJP是专门设计用来为tomcat与http服务器之间通信专门定制的协议,能提供较高的通信速度和效率。如与Apache服务器集成时,采用这个协议。

  • APR HTTP Connector, 用C实现,通过JNI调用的。主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能。现在这个库已独立出来可用在任何项目中。Tomcat在配置APR之后性能非常强劲。

tomcat中实现了以下几种Connector:

#以下三种Connector实现都是直接处理来自客户端Http请求

  • org.apache.coyote.http11.Http11Protocol : 支持HTTP/1.1 协议的连接器。

  • org.apache.coyote.http11.Http11NioProtocol : 支持HTTP/1.1 协议+New IO的连接器。

  • org.apache.coyote.http11.Http11AprProtocol : 使用APR(Apache portable runtime)技术的连接器,利用Nativ


#以下三种实现方法则是与web server打交道

  • org.apache.coyote.ajp.AjpProtocol:使用AJP协议的连接器,实现与web server(如Apache httpd)之间的通信

  • org.apache.coyote.ajp.AjpNioProtocol:SJP协议+ New IO

  • org.apache.coyote.ajp.AjpAprProtocol:AJP + APR

总结

Spring 提供了对jca cci的支持,通过模板类CciTemplate,配置ConnectionFactory后即可使用。另外,Connector模式应用比较广泛,如tomcat。

jca的协议是JSR 322,有想要更深入学习的,可以认证学习此spec。



猜你喜欢

转载自blog.51cto.com/15015181/2556224