J2EE连接器的开发

2003 年 8 月 21 日

本文基于J2EE连接器体系结构,介绍一个典型的资源适配器案例开发的过程和开发技巧,然后开发客户端,并在客户端通过连接器调用资源层。学习完本文,读者将能理解JCA的体系结构和开发的各个细节,并且能自主开发新的J2EE连接器。

阅读本文,您需要以下的知识和工具:

  • 至少一种J2EE应用服务器的使用经验;
  • 能够开发、部署EJB,并且能够在客户端调用;
  • Java Socket编程、线程的基础知识。

 

本文的参考资料见 参考资料

引言

J2EE连接器(JCA)是一种企业级应用整合的技术。目前,在J2EE平台中,常使用的应用整合的技术有:

  • Java消息服务(JMS);
  • Web服务(Web Services);
  • J2EE 连接器体系结构(JCA)。

Java消息服务是一组在Java程序中使用企业级消息的API,它为整合J2EE应用和非J2EE应用程序提供了异步整合的方式,在这种方式里,所有的应用都和消息中间件(MOM)进行通信,这样就提供了与平台无关、语言无关的整合。Web服务是一种新兴发展起来的技术,它使用SOAP消息作为传输的载体,使用HTTP或者其它基于文本的协议作为数据传输的协议,Web服务可以是同步的整合,也可以进行异步的整合。同样,Web服务也是一种和平台无关、和开发语言无关的整合技术。

J2EE连接器技术为连接J2EE应用服务器和已有的企业应用系统(ERP/CRM等)提供了解决方案。通过J2EE连接器,EIS(企业信息系统)厂商不需要再为每个应用服务器提供专门的支持接口,同样,应用服务器厂商在连接到新的EIS系统时也不需要再重新开发新的代码,JCA为整合企业资源提供了标准的解决方案。

在JCA1.0规范中,它定义了应用服务器和资源适配器的系统级合同(连接池、事务管理和安全),为资源适配器的客户端定义了通用的客户端接口(Common Client Interface,CCI),同样也规范了JCA打包和部署等细节。但在JCA1.0规范中,只支持OutBound的调用,也就是说只能在J2EE应用中通过资源适配器向外调用企业资源层,而企业资源层不能通过适配器调用J2EE里的资源。在即将发布的JCA1.5规范中,这个问题得到了解决,也就是说,在J2EE的外部可以通过资源适配器直接调用部署在J2EE中的应用,如EJB。

下面简单看一下JCA的体系结构,如图1所示。

图1 JCA的体系结构 图1 JCA的体系结构

下面解释一下上图中的一些概念。

资源适配器(Resource Adapter):为了获得在应用服务器和EIS之间的系统标准可插入性,JCA定义了应用服务器和EIS之间的一系列合约(Contract),资源适配器实现了EIS端的系统级合约。

系统级合同(System Contract):系统级合同定义了一组系统合同,可以让应用服务器和资源适配器连接起来以管理连接、事务和安全性。这样,应用组件的开发者就可以把精力集中与和业务逻辑相关的开发,而没有必要关心系统级的问题。

客户通用接口(CCI):定义了J2EE组件连接到EIS系统的一组通用的API,这些API在具体的开发中进行实现。

在连接器的开发中,主要任务就是开发资源适配器。如果需要,再开发出一套客户通用接口实现(CCI),这样,客户端就可以通过这些通用的接口来连接、使用EIS层的资源了。

在使用连接池的情况下,应用程序组件和JCA以及EIS交互关系如图2所示。

图2 应用程序组件和JCA以及EIS交互之间的交互关系 图2 应用程序组件和JCA以及EIS交互之间的交互关系

我们简要看一下请求传递的顺序:

  1. 应用程序组件发出获得连接的请求;
  2. 连接工厂调用连接管理器的allocateConnection;
  3. 连接管理器向连接池管理器发出获得连接的请求;
  4. 连接池管理器试图从ManagedConnectionFactory进行连接匹配,如果没有匹配到连接,那么返回null;
  5. 由于没有匹配到连接,连接池管理器调用ManagedConnectionFactory的createManagedConnection方法来创建连接;
  6. ManagedConnectionFactory接收到连接池管理器的请求后,创建一个ManagedConnection实例,同时ManagedConnection打开和EIS之间的物理连接,然后把这个ManagedConnection实例返回给连接池管理器;
  7. 连接池管理器调用ManagedConnection实例的getConnection方法以获得一个Connection实例;
  8. ManagedConnection实例收到连接池管理器的getConnection请求后,创建一个Connection实例,然后把这个实例返回给连接池管理器;
  9. 这个Connection实例通过连接池管理顺次返回给应用程序组件;
  10. 应用程序组件通过返回的Connection来创建Interaction或者调用业务方法;
  11. 应用程序组件通过Connection调用业务方法时,实际上Connection使用了ManagedConnection的物理连接和EIS进行交互。

下面我们介绍一个简单的案例的开发。

回页首

案例介绍

这个案例使用了典型的J2EE多层体系结构,如图3所示。EIS层是一个简单的能处理多线程的Socket服务程序,当它接收到客户端发送来的字符串时,就在这个字符串前增加"Hello:"字符串,然后返回。资源适配器用于连接到EIS,使得J2EE应用(如EJB)能够通过它调用EIS层。这个案例的客户端有两种,一种是基于浏览器的客户端,它通过HTTP来访问Web服务器上的JSP组件,JSP组件通过RMI调用EJB来访问EIS;另一种客户端是普通的Java程序,它通过RMI来调用部署在EJB服务器中的EJB组件以访问EIS。

图3 案例体系结构 图3 案例体系结构

下面我们看简单资源层的代码。

回页首

开发简单资源层

资源层是一个Socket服务程序,当它接收到客户端发送来的字符串时,就在这个字符串前增加"Hello:"字符串,然后返回这个新的字符串。代码如例程1所示。

例程1 EIS资源层

package com.hellking.jca.eis;
import java.net.*;
import java.io.*;
public class EISServer
{
	public static void main(String[] args)
	{		
	  try
      {
	    System.out.println ("启动服务....");	
	    ServerSocket s = new ServerSocket (2008);
	    // 处理客户端请求
	    while (true)
	    {
	      System.out.println ("监听客户端连接..."); 
	      new ServerThread(s.accept()).start();	
           System.out.println ("接收到一个连接");            
	    }	  
    }
    catch(Exception e)
    {
       e.printStackTrace(System.err);
    }
  }
}
  
  class ServerThread extends Thread
  {
  	private Socket socket=null;
  	public ServerThread(Socket socket)
  	{
  		super("a new thread");
  		this.socket=socket;
  	}
  	public void run()
  	{
  		 try
  		 {
  		 	BufferedReader in = new BufferedReader 
	        (new InputStreamReader (socket.getInputStream()));
		      PrintStream out = new PrintStream(socket.getOutputStream()); 
		      String line;
		      do
		        {
		             line = in.readLine();
			        System.out.println ("接收到以下输入: " + line);
			        if (line != null)
			          {
			          out.println ("Hello: "+line);
			          }
			    } while (line != null);
		      System.out.println ("关闭连接");
		      socket.close();
		  }
		  catch(Exception e)
		  {
		  	e.printStackTrace();
		  }
     }
  }
回页首

资源适配器的开发

开发资源适配器,我们从最基本的连接(Connection)类开始。

DemoConnection DemoConnection扩展了CCI的Connection接口,它由客户端程序使用,代表了到EIS的"虚拟"连接,通过这个"虚拟"的连接客户端可以调用EIS。需要注意的是,虚拟连接关闭时,物理连接不一定关闭。DemoConnection定义了资源适配器所实现的业务方法。如例程2所示。

例程2 DemoConnection的代码

package com.hellking.jca;
import javax.resource.cci.Connection;
import javax.resource.ResourceException;
public interface DemoConnection extends Connection
{
	//业务方法
	public String sayHello(String name)throws ResourceException;
}

DemoConnectionImpl DemoConnectionImpl是DemoConnection的实现类,它通过ManagedConnection来完成具体的业务方法。ManagedConnection是代表到EIS的物理连接,将在后面介绍。

例程3 DemoConnectionImpl大代码

package com.hellking.jca;
import javax.resource.*;
import javax.resource.spi.*;
import javax.resource.cci.*;
import javax.security.auth.*;
import java.util.*;
import java.io.*;
//连接实现类,它通过DemoManagedConnection来完成具体的任务
public class DemoConnectionImpl implements DemoConnection
{
	protected PrintWriter out;//logOut
	protected DemoManagedConnection demoManagedConnection;
	
   //关闭连接,释放资源
   public void close()
   {
	  if (demoManagedConnection == null) return;  
	  demoManagedConnection.removeConnection(this);
	  demoManagedConnection.connectionClosedEvent();
	  demoManagedConnection = null;
   }
  //返回和这个连接关联的被管理连接
  public DemoManagedConnection getManager() 
  { 
	  return demoManagedConnection; 
  }
  //设置和这个连接关联的被管理连接
  public void setManager (DemoManagedConnection manager)
  {
	  this.demoManagedConnection =manager;
  }
  
  //业务方法,它通过调用被管理的连接来实现。
  public String sayHello(String name)throws ResourceException
  {
        return demoManagedConnection.sayHello (name);
   }
  
  //使连接无效
  public void invalidate()
  {
	  demoManagedConnection = null;
  }  
	public void setLogWriter(PrintWriter out)
	{
	   this.out = out;
	 }
	
	public PrintWriter getLogWriter()
    {
	  return out;
	}
		
   public ConnectionMetaData getMetaData()  
   {
    	return null;
   }
   public ResultSetInfo getResultSetInfo()  
   {
   	 return null;
   }
   public javax.resource.cci.LocalTransaction getLocalTransaction()  
   {
   	   return null;
   }
   public  Interaction createInteraction() 
   {
     	return null;
   } 
 
}

DemoConnectionFactoryImpl DemoConnectionFactoryImpl也是和CCI相关的类,它实现了ConnectionFactory接口,它主要用于创建客户端要使用的虚拟连接(DemoConnection)。由于DemoConnectionFactoryImpl类需要在JNDI名字空间中注册,故它需实现Serializable和Referenceable接口。客户端查找DemoConnectionFactoryImpl类,然后使用这个类来获得到EIS的连接。DemoConnectionFactoryImpl代码如例程4所示。

例程4 DemoConnectionFactoryImpl的代码

package com.hellking.jca;
import javax.resource.*;
import javax.resource.spi.*;
import javax.resource.cci.*;
import javax.naming.*;
import java.io.*;
public class DemoConnectionFactoryImpl implements ConnectionFactory
{
	protected Reference reference;
	protected ManagedConnectionFactory manager;
	protected ConnectionManager connectionManager;
	protected PrintWriter out;//logOut
	
	//构造方法
	public DemoConnectionFactoryImpl (ManagedConnectionFactory manager, 
           ConnectionManager connectionManager)
	{
	    this.manager = manager;
	    //如果连接管理器为空,那么创建一个新的连接管理器
	    if (connectionManager == null) 
	    {
		    connectionManager = new DemoConnectionManager();
		    ((DemoConnectionManager)connectionManager).setLogWriter (out);
	    } 
	    else 
	    {
	       this.connectionManager = connectionManager;
	    }
	}
	   //获得一个连接	  
	  public Connection getConnection() throws ResourceException 
	  {
		  return (DemoConnection)
		    connectionManager.allocateConnection (manager, null);
	  }
	  //不支持此方法
	  public Connection getConnection(ConnectionSpec p) throws ResourceException 
	  {
	       return null;
	  }
	  public void setReference(Reference ref) 
	  {
		  reference = ref;
	  }
	public Reference getReference()  
	{
		  return reference;
	 }
	
	public void setLogWriter(PrintWriter _out) 
	{
	  out = _out;
	}
	
	public PrintWriter getLogWriter() 
	{
	  return out;
	}	
   public RecordFactory getRecordFactory()  throws  ResourceException
   {
   	   return null;
   }
   public ResourceAdapterMetaData getMetaData()  
   {
   	return null;
   }
}

DemoConnectionManager DemoConnectionManager是连接的管理器,它为资源适配器把连接请求传递给应用服务器提供了一个切入点。应用服务器实现DemoConnectionManager接口,这个实现不针对具体的资源适配器和连接工厂接口。DemoConnectionManager的任务就是分配连接。对于一些高级的应用,DemoConnectionManager通过和连接池交互来分配连接,在我们开发的这个案例中,DemoConnectionManager直接使用ManagedConnectionFactory来分配连接。ManagedConnectionFactory的代码如例程5所示。

例程5 ManagedConnectionFactory的代码

package com.hellking.jca;
import java.io.Serializable;
import java.io.PrintWriter;
import javax.resource.ResourceException;
import javax.resource.spi.*;
public class DemoConnectionManager 
  implements ConnectionManager, Serializable
{
	protected PrintWriter out;	
	//分配一个连接
	public Object allocateConnection (ManagedConnectionFactory managedConnectionFactory,
ConnectionRequestInfo connectionRequestInfo)
	throws ResourceException 
	  {
	     ManagedConnection managedConnection =
	     managedConnectionFactory.createManagedConnection(null, connectionRequestInfo);
	     return managedConnection.getConnection(null, connectionRequestInfo);
	  } 
	public void setLogWriter(java.io.PrintWriter out) 
	{
	  	this.out =out;
	}  
}

DemoManagedConnectionMetaData DemoManagedConnectionMetaData提供了和ManagedConnection关联的后台EIS实例的信息。应用服务器通过这个接口来获得与它连接的EIS实例的运行环境信息。DemoManagedConnectionMetaData的代码如例程6所示。

例程6 DemoManagedConnectionMetaData的代码

package com.hellking.jca; 
import javax.resource.spi.*;
public class DemoManagedConnectionMetaData 
  implements ManagedConnectionMetaData
{
	protected DemoManagedConnection demoManagedConnection;
	
	public DemoManagedConnectionMetaData (DemoManagedConnection demoManagedConnection) 
	{
	    this.demoManagedConnection = demoManagedConnection;
	}	
    //获得EIS的提供商
	public String getEISProductName() 
	{
	  return "Hellking's Simple EIS server";
	}	
//获得EIS产品的版本
	public String getEISProductVersion()
	{
	  return "Version 1.2";
	}
	//eis支持的最大连接数
	public int getMaxConnections()
	{ 
	  return 10000;   
	}
	public String getUserName()  
	{
	    return "Hellking";
	}
}

DemoManagedConnection DemoManagedConnection是资源适配器的关键所在,它代表了和EIS的物理连接,前面介绍的DemoConnection是由客户端使用的虚拟连接,虚拟连接要通过物理连接才能使用EIS。一个物理连接可以被多个虚拟连接使用,可以通过associateConnection方法来把虚拟连接和物理连接进行关联。DemoManagedConnection也提供了产生虚拟连接实例的方法。DemoManagedConnection的代码如例程7所示。

例程7 DemoManagedConnection的代码

package com.hellking.jca; 
import javax.resource.*;
import javax.resource.spi.*;
import javax.security.auth.*;
import java.util.*;
import java.io.*;
import java.net.*;
import javax.transaction.xa.*;
//DemoManagedConnection代表了到EIS的物理的连接
public class DemoManagedConnection implements ManagedConnection
{
	protected Socket socket;//和server连接的Socket
	protected PrintStream serverStream;//
	protected BufferedReader serverBufferedReader;
	protected boolean destroyed;//是否销毁
	protected PrintWriter out;
	protected Set connections = new HashSet();//被管理的连接
	protected Set connectionListeners = new HashSet();//连接监听器	
	          DemoManagedConnectionFactory factory;//连接工厂
	
	public DemoManagedConnection(DemoManagedConnectionFactory factory)
	{
		  this.factory = factory;
	}
	//为连接增加事件监听器
	public void addConnectionEventListener(ConnectionEventListener l)
	{
		  connectionListeners.add(l);
	}
	//清除连接监听器
	public void removeConnectionEventListener(ConnectionEventListener l)
	{
	  connectionListeners.remove(l);
	}
	
	//返回连接工厂
	public DemoManagedConnectionFactory getFactory ()
	{ 
		return factory;
	}
	
	//增加一个连接,并且返回它
	public Object getConnection (Subject subject,
	    ConnectionRequestInfo cxRequestInfo)
	  {
		  DemoConnectionImpl connection = new DemoConnectionImpl();
		  connection.setManager(this);
		  connection.setLogWriter (out);
		  addConnection(connection);
		  return connection;
	  }
	  
    //清除占用的资源
	public void cleanup() throws ResourceException
	{
		  destroyedError();
		  Iterator it = connections.iterator();
		  while (it.hasNext()) 
		    {
		    DemoConnectionImpl demoConnectionImpl = (DemoConnectionImpl) it.next();
		    demoConnectionImpl.invalidate();
		    }
		  connections.clear();
	 }
	  
    //销毁所有的物理连接
	public void destroy() 
	{
		  if (destroyed) return; 		 
		  Iterator it = connections.iterator();
		  while (it.hasNext()) 
		    {
			    DemoConnectionImpl DemoConnectionImpl = (DemoConnectionImpl) it.next();
			    DemoConnectionImpl.invalidate();
		    }
		  connections.clear();
		  if (socket != null) 
		    try {socket.close();}
		     catch (Exception e){}
		  destroyed = true;
	  }    
	
	//把一个Connection和这个被管理的连接关联
	public void associateConnection(Object _connection) 
	    throws ResourceException
	  {
		  destroyedError();
		  if (_connection instanceof DemoConnection) 
		    {
		    DemoConnectionImpl connection = 
		      (DemoConnectionImpl)_connection;
		    
		    DemoManagedConnection demoManagedConnection = connection.getManager();
		    if (demoManagedConnection == this) return; 
		    try
		    {
		    	demoManagedConnection.removeConnection(connection);
		    }
		    catch(Exception e)
		    {
		    }
		    addConnection(connection);
		    connection.setManager (this);
		    } 
		  else 
		    {
		    throw new javax.resource.spi.IllegalStateException 
		      ("Invalid connection object: " + _connection);
		    }	  
	  }		
	//不支持此方法
	public XAResource getXAResource() throws ResourceException
	{
		  throw new NotSupportedException("不支持分布式事务");
	}
	
	//不支持此方法
	public LocalTransaction getLocalTransaction()
	    throws ResourceException
	  {
		  throw new NotSupportedException ("Local transaction not supported");
	  }
	
	//返回元数据
	public ManagedConnectionMetaData getMetaData() 
    {
		  return new DemoManagedConnectionMetaData(this); 
	}
	
	protected void destroyedError()
	    throws javax.resource.spi.IllegalStateException
	  {
	  if (destroyed) 
	    throw new javax.resource.spi.IllegalStateException 
	      ("DemoManagedConnection 已经销毁");
	  }
	
    //增加一个和此被管理连接(ManagedConnection)关联连接(Connection) 
	protected void addConnection(DemoConnection connection)
    {
		  connections.add(connection);
	}
	//删除一个和此被管理连接(ManagedConnection)关联连接(Connection) 
	protected void removeConnection(DemoConnection connection)
	  {
		  connections.remove(connection);
	  }
   //设置LogWriter	  
   public void setLogWriter(PrintWriter _out)
   {
	   out = _out;
	}
	
	public PrintWriter getLogWriter()
	{
	  return out;
    }
    	//判断是否已经销毁
    public boolean isDestroyed()
	{
	  return destroyed;
	}	
	//关闭连接的事件,释放资源,由连接监听器来处理
	void connectionClosedEvent() 
   {
		  Iterator it = connectionListeners.iterator();
		  while (it.hasNext())
		    {
		    ConnectionEventListener listener = 
		      (ConnectionEventListener) it.next();
		    listener.connectionClosed
		      (new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED));
		    }
	 }
	
	//打开物理连接,物理连接是和EIS的正在的连接。通过Socket来进行通信
	public void openPhysicalConnection (String serverName, int portNumber)
	    throws UnknownHostException, IOException
	  {
		  socket = new Socket (serverName, portNumber);
		  serverStream = new PrintStream (socket.getOutputStream());
		  serverBufferedReader = new BufferedReader 
		    (new InputStreamReader (socket.getInputStream()));
	  }
	//业务方法,它是同步的,同时只能一个和Server进行通信
	public synchronized String sayHello(String name)
	    throws ResourceException
	  {
		  serverStream.println (name);
		  try
		    {
		    String in = serverBufferedReader.readLine();
		    return in;
		    }
		  catch (Exception e)
		    {
		      throw new ResourceException 
		      ("调用sayHello()发生错误: " + e.toString());
		    } 
	  }		
}

DemoManagedConnectionFactory DemoManagedConnectionFactory是DemoManagedConnection的工厂,它的主要任务是创建和匹配DemoManagedConnection实例,在创建DemoManagedConnection实例时,DemoManagedConnection实例同时打开到EIS的物理连接。DemoManagedConnectionFactory的代码如例程8所示。

例程8 DemoManagedConnectionFactory的代码

package com.hellking.jca;
import javax.resource.*;
import javax.resource.spi.*;
import javax.security.auth.*;
import java.util.Set;
import java.util.Iterator;
import java.io.*;
public class DemoManagedConnectionFactory 
    implements ManagedConnectionFactory, Serializable
{
	protected PrintWriter out = new PrintWriter(System.out);
	private int port;//连接EIS的端口
	private String server;//eis服务器的url
	
	
	//创建连接工厂,指定连接工厂的连接管理者为connectionManager
	public Object createConnectionFactory
	     (ConnectionManager connectionManager) 
	{
		  DemoConnectionFactoryImpl demoConnectionFactoryImpl = 
		    new DemoConnectionFactoryImpl (this, connectionManager);
		  demoConnectionFactoryImpl.setLogWriter(out);
		  return demoConnectionFactoryImpl;
	}
	  
	//创建连接工厂,没有指定连接管理者
	public Object createConnectionFactory() 
	{
		  DemoConnectionFactoryImpl demoConnectionFactoryImpl = 
		    new DemoConnectionFactoryImpl (this, null);
		  demoConnectionFactoryImpl.setLogWriter(out);
		  return demoConnectionFactoryImpl;
	  }
	
	//创建被管理的连接,被管理的连接是和EIS的真实连接,它是物理连接。
	public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cri) 
	throws ResourceException
   {
		  DemoManagedConnection demoManagedConnection = 
new DemoManagedConnection(this);
		  demoManagedConnection.setLogWriter(out);
		  try
		    {
			    //打开物理连接
			    System.out.println("打开物理连接.....");
			    demoManagedConnection.openPhysicalConnection (server, port);
			    return demoManagedConnection;
		    }
		  catch (IOException e)
		  {
		    throw new ResourceException (e.toString());
		  }
	  }
	
	//匹配被管理的连接,如果匹配到连接,则返回,否则返回null
	public ManagedConnection matchManagedConnections
	    (Set connections, Subject subject, ConnectionRequestInfo cri) 
	  {
		  Iterator it = connections.iterator();
		  while (it.hasNext()) 
		    {
			    Object obj = it.next();
			    if (obj instanceof DemoManagedConnection) 
			      {
			      DemoManagedConnection demoManagedConnection =
 (DemoManagedConnection) obj;
			      DemoManagedConnectionFactory demoManagedConnectionf =
 demoManagedConnection.getFactory();
			      if (demoManagedConnectionf.equals(this))
			      {
			        return demoManagedConnection;
			     }
		      }
	   		 }
		  return null; 
	  }	
		
	public int hashCode()
	{
		  if (server == null) return 0;
		  return server.hashCode();
	}
	//判断两个被管理的连接工厂是否相等
	public boolean equals(Object o)
	  {
		  if (o == null) return false;
		  if (!(o instanceof DemoManagedConnectionFactory)) 
		    return false; 
		  DemoManagedConnectionFactory other = 
		    (DemoManagedConnectionFactory)o;
		  if (server.equalsIgnoreCase(other.server) &&
		    port == other.port) return true;
		  return false; 
	  }	
	  public void setLogWriter(java.io.PrintWriter out) 
	 {
	 	 this.out = out;
      }
	
	public PrintWriter getLogWriter() 
	{
	 	 return out;
	 }
	
	public void setServer (String server) 
	{ 
		  this.server = server;
    }
	
	public String getServer () 
	  {
		  return server;
	  }
	
	public void setPort (Integer port) 
    {
		  this.port = port.intValue();
	}
	
	public Integer getPort () 
	{
		  return new Integer(port);
	}
}

在DemoManagedConnectionFactory类中,设置了两个属性,Port和Server,Port表示连接EIS使用的端口,Server表示连接EIS时使用的URL。这两个属性需要在资源适配器的部署描述符里指定具体的值。

回页首

编写部署描述符

下面的任务就是在部署描述符里指定资源适配器的相关接口和实现类。具体需要指定以下的接口和类:

  • ManagedConnectionFactory,这里是DemoManagedConnectionFactory;
  • Connectionfactory的接口,这里是javax..resource.cci.ConnectionFactory;
  • Connectionfactory的实现类,这里是DemoConnectionFactoryImpl;
  • 连接的接口,这里是DemoConnection;
  • 连接的实现类,这里是DemoConnectionImpl。

另外,还需要指定以下的属性:

  • 是否支持事务,这里是NoTransaction;
  • 安全认证的支持,这里是false;
  • DemoManagedConnectionFactory中使用的属性,其中Server的值为localhost,Port的值为2008。

例程9是资源适配器的具体内容,它要保存为ra.xml放在资源适配器打包文件RAR的META-INF目录下。

例程9 资源适配器的具体内容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE connector PUBLIC '-//Sun Microsystems, Inc.//DTD Connector 1.0//EN' 
'http://java.sun.com/dtd/connector_1_0.dtd'>
<connector>
  <display-name>DemoRA</display-name>
  <vendor-name>HELLKING</vendor-name>
  <spec-version>1.0</spec-version>
  <eis-type>NO TRANS</eis-type>
  <version>1.2</version>
  <resourceadapter>
    <managedconnectionfactory-class>com.hellking.jca.DemoManagedConnectionFactory
</managedconnectionfactory-class>    
<connectionfactory-interface>javax.resource.cci.ConnectionFactory</connectionfactory-interface> 
   <connectionfactory-impl-class>com.hellking.jca.DemoConnectionFactoryImpl
</connectionfactory-impl-class>
    <connection-interface>com.hellking.jca.DemoConnection</connection-interface>
    <connection-impl-class>com.hellking.jca.DemoConnectionImpl</connection-impl-class>
    <transaction-support>NoTransaction</transaction-support>
    <config-property>
      <config-property-name>Server</config-property-name>
      <config-property-type>java.lang.String</config-property-type>
      <config-property-value>localhost</config-property-value>
    </config-property>
    <config-property>
      <config-property-name>Port</config-property-name>
      <config-property-type>java.lang.Integer</config-property-type>
      <config-property-value>2008</config-property-value>
    </config-property>
    <reauthentication-support>false</reauthentication-support>
  </resourceadapter>
</connector>
回页首

下一步

通过上面的介绍,相信读者都JCA的体系结构和开发已经有了全面的了解。

下一节介绍资源适配器客户端的开发,并且在不同的应用服务器平台下部署这个J2EE应用和资源适配器。

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于J2EE的快速开发平台Jeecg-Boot,可以帮助开发人员快速地构建和部署企业级应用程序。Jeecg-Boot使用了J2EE开发框架,如Spring Boot、MyBatis等,提供了一套全面的工具和模块,帮助开发人员简化开发过程,提高开发效率。 首先,在使用Jeecg-Boot开发时,我们可以利用其提供的代码生成工具,快速生成大量基础代码。通过定义数据表结构,代码生成工具会自动生成与数据库交互的基础增删改查模块,减少了手动编写这些重复代码的工作量,提高了开发效率。 其次,Jeecg-Boot提供了丰富的业务模块和组件,包括权限管理、菜单管理、数据字典、文件上传下载等等。这些模块和组件可以直接集成到应用程序中,减少了开发人员自行开发这些基础功能的时间和精力,同时保证了应用程序的功能完整性。 此外,Jeecg-Boot还提供了一系列的插件和扩展,可以满足不同开发需求。例如,Jeecg-Boot支持在线开发模式,在不停服的情况下,实时修改代码并生效,极大地提高了调试和修改的效率。同时,Jeecg-Boot也支持分布式部署和集群部署,可以应对高并发和大规模访问的需求。 总之,基于J2EE快速开发平台Jeecg-Boot开发的优势在于提供了一套完整的开发工具和模块,帮助开发人员快速构建和部署企业级应用程序,大大提高了开发效率和质量。 ### 回答2: jeecg-boot是一个基于j2ee的快速开发平台,提供了一整套开发工具和框架,使开发者能够快速构建基于j2ee的应用程序。 jeecg-boot具有丰富的功能和特性,包括代码生成器、权限管理、后台管理、前后端分离、多数据源支持等。借助于代码生成器,开发者可以根据数据库表结构自动生成实体类、Dao、Service等代码,节省了手动编写重复代码的时间和工作量。权限管理模块可以帮助开发者实现灵活的用户权限控制,保护系统安全。后台管理模块提供了丰富的功能页面和交互界面,使开发者能够方便地管理系统。前后端分离的特性使得前端开发和后端开发可以独立进行,提高了开发效率。多数据源支持可以满足多数据库连接的需求,适用于复杂的业务场景。 在使用jeecg-boot进行开发时,开发者可以按照自己的需求进行定制和扩展。jeecg-boot提供了丰富的插件和可扩展的接口,使开发者可以灵活地集成自己的业务逻辑和功能。此外,jeecg-boot还提供了详细的文档和示例代码,方便开发者学习和使用。 总之,jeecg-boot是一个强大的基于j2ee的快速开发平台,提供了丰富的功能和特性,可以帮助开发者快速构建高质量的j2ee应用程序。无论是开发一个简单的小型应用还是一个复杂的企业级应用,jeecg-boot都是一个优秀的选择。 ### 回答3: jeecg-boot是基于J2EE的快速开发平台,它提供了一套简单、高效的开发框架,可以帮助开发人员快速构建企业级应用程序。 首先,jeecg-boot采用了主流的J2EE技术栈,包括Spring Boot、Spring Cloud、Mybatis等,这些技术在企业应用开发中被广泛应用,具有成熟、稳定的特点。通过使用这些技术,开发人员可以快速搭建整体项目架构,减少重复性的工作,提高开发效率。 其次,jeecg-boot提供了丰富的代码生成器和模板,可以根据数据库表结构自动生成代码。这样一来,开发人员只需要定义好数据库表结构,就能够生成对应的实体类、控制器、服务类等代码,省去了大量的手动编写代码的时间和精力。 此外,jeecg-boot还内置了权限管理、数据字典、代码生成、报表打印等常用功能模块,开发人员可以快速集成这些功能,并根据实际需求进行定制。同时,它还支持多数据源配置,能够满足复杂业务场景下的需求。 最后,jeecg-boot具有良好的可扩展性和可维护性。通过遵循一些设计原则和开发规范,开发人员可以编写易于扩展和维护的代码。此外,jeecg-boot还提供了一些常见的工具类和插件,帮助开发人员更好地进行开发工作。 总之,基于jeecg-boot开发可以大大提高开发效率和代码质量,快速构建功能完善、稳定可靠的企业级应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值