EJB3.0学习笔记
来源:互联网 发布:手机惠普打印机软件 编辑:程序博客网 时间:2024/04/28 22:06
3.2 EJB实例分析
该实例是运行在JBOSS5.1与SQLServer2005下。
(1) 会话BEAN
对于会话Bean的开发,相对简单如图:
图3.4 会话Bean接口声明
声明接口即与使用此EJB的用户签定了契约。用户可以使用接口提供的功能。当然要为接口实现此功能如图:
图3.5 会话Bean服务实现类
对于接口服务的实现,EJB3中使用了更为方便的标签方式,声明这个Bean并为其指定接口。完成之后,即可以向外提供服务,需要组织成构件,如图:
图3.6 jar文件
当这个jar文件部署到服务器中时,服务器解析此为一个EJB的实体Bean,并向外提供服务。
图3.7 调用EJB服务代码
图3.8 调用结果显示
(2) 实体BEAN
由于实体BEAN的开发就要涉及与数据库的关联,所以要配置数据源
对于JBOSS数据源的配置做简单的介绍。
对于JBOSS5.1数据源的配置,在目录docs/example/jca中已经包含了相关的数据源配置的xml例子文件,如图:
图3.9 数据源配置xml文档
首先复制一份文件,并修改
<?xml version="1.0"encoding="UTF-8"?><datasources> <local-tx-datasource> <jndi-name>MSSQLDS</jndi-name>//这是设置jndi名称以供在程序能够找到这个数据源 <connection-url>jdbc:sqlserver://localhost:1433;DatabaseName=MBOOK</connection-url> <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class> <user-name>sa</user-name> <password>123456</password> <metadata> <type-mapping>MS SQLSERVER2005</type-mapping> </metadata> </local-tx-datasource></datasources>
修改好这个文件,同时需要把SQLServer2005所用的jdbc驱动包拷贝到jboss-5.1.0.GA\server\default\lib目录下,如图:
图3.10 数据驱动jar包
然后将文件移动到目录jboss-5.1.0.GA\server\default\deploy发布。如果此时你的jboss已经是启动状态,则会看到控制台打印:
图3.11 数据源加载成功
表示数据源加载成功。
接下来可以写你的EJB应用:
需要注意的是在实体Bean中,(注意实体bean中,get方法才有ejb的标签。另要确保实体bean有一个默认的的构造函数)需要包含一个persistence.xml文件,此文件在导出jar包的时候也要包含。此文件可以为此EJB对象指定数据源。即上面已经配置好的并加载进JBOSS中的。
<persistencexmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <!--持久化单元 transaction-type事物的类型。一个是全局事物JTA,一个是本地事物 --> <persistence-unitname="sql"transaction-type="JTA"> <jta-data-source>java:MSSQLDS</jta-data-source> <!--当数据源发布到jboss的时候,他的jndi名称默认是在java:的命名空间里 , 需要加上,jndi默认是在全局上找的 --> <properties>//注意如如果下面方言不配置,有时是会报错的。 <propertyname="hibernate.dialect"value="org.hibernate.dialect.SQLServerDialect"/> <propertyname="hibernate.show_sql"value="true"/> <propertyname="hibernate.format_sql"value="true"/> <propertyname="hibernate.jdbc.fetch_size"value="50"/> </properties> </persistence-unit></persistence>
而jndi.properties文件在测试时和应用EJB时是必不可少的。
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
发布到jboss-5.1.0.GA-jdk6\jboss-5.1.0.GA\server\default\deploy目录下:
图3.12 发布EJB
如上图,已经成功发布了EntityBeanTest的EJB,该EJB是以jar文件形式存在的。并且还指出了beanName为PersonServiceBean,以及接口名IPersonService.
测试如下:
publicclass PersonServiceTest { privatestatic IPersonServicepersonService; @BeforeClass publicstaticvoid setUpBeforeClass()throws Exception { try { InitialContextic =new InitialContext( ); personService = (IPersonService)ic.lookup("PersonServiceBean/remote"); } catch (Exception e){ e.printStackTrace(); } } @Test publicvoid testSave() { personService.save(newPerson("sunquan")); }}
执行成功,由于在persistence.xml中showSql为true,控制台显示了相应的sql语句。
图3.13 SQL语句
查看数据库:
图3.14 数据添加成功
收到对应结果。
1. 有几点需要注意,在数据库的设计过程中,id必须设为主键,且自增长。
2. 导入jboss/client的所有jar包。由于持久化操作,所以需要hibernate.jar包。
这样对于一个实体的bean,对应数据库中的一张表,并且包括对于数据的相应操作,就都包含在这个EJB对象当中。
(3) 消息驱动BEAN
消息驱动BEAN的特性有如异步调用,无状态特性,以及无本地远程接口等。
对于一个消息驱动BEAN,即当客户端发送一条消息时,该BEAN能够自动响应这条消息。能过客户端的消息来驱动该BEAN的调用、执行。
那么首先要存在这样一个所谓消息BEAN,并且他能够监听特定的消息。
packagecn.sunquan.MessageBean;importjavax.ejb.ActivationConfigProperty;importjavax.ejb.EJBException;importjavax.ejb.MessageDriven;importjavax.ejb.MessageDrivenBean;importjavax.ejb.MessageDrivenContext;importjavax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;importjavax.jms.TextMessage;@MessageDriven(mappedName="MyMessageDrivenBean",activationConfig = { @ActivationConfigProperty(propertyName ="destinationType", propertyValue ="javax.jms.Queue"), @ActivationConfigProperty(propertyName ="destination", propertyValue ="queue/itmQueue")})//关于上述标签的解释:destination指明要去监听容器通道的名字,destinationType指//明要去监听容器通道的类型。mappedName非必须的。publicclassMyMessageDrivenBeanimplements MessageDrivenBean, MessageListener { privatestaticfinallongserialVersionUID = 1L; publicMyMessageDrivenBean() { //TODO Auto-generated constructor stub } @Override publicvoid onMessage(Messagemessage) { TextMessagemsg = (TextMessage) message; try { System.out.println(msg.getText()); } catch (JMSException e) { e.printStackTrace(); } } @Override publicvoid ejbRemove()throws EJBException { } @Override publicvoidsetMessageDrivenContext(MessageDrivenContext arg0) throws EJBException { }}
下面这个xml文件就是声明上述那个通道,打在jar包和单独发布到deploy目录下效果一样。
<?xmlversion="1.0"encoding="UTF-8"?> <server> <mbeancode="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:server=Queue,name=itmQueue"> <attributename="JNDIName">queue/itmQueue</attribute> <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends> </mbean> <!-- <mbeancode="org.jboss.mq.server.jmx.Topic" name="jboss.mq.destination:service=Topic,name=itmTopic"> <attributename="JNDIName">topic/itmTopic</attribute> <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends> </mbean> --> </server>
测试发现在bean打成jar包后,如果不包含上述这个xml的文件(xxx-service.xml)时,这个消息驱动bean是bound不成功的。为什么呢?
图3.15 绑定不成功
既然JBOSS已经发现了一个叫做itemQueue类型的消息,服务器此时只能从bean中的标签中发现itemQueue,至此服务器已经知道有一个bean,
他是处理itemQueue类型的。当一个itemQueue消息发送过来的时候,服务器应该是可以把这条消息交给指定bean处理的,或者是这个bean一直在等待,类似监听这类消息,一旦有就处理。(仅是猜测)
那么EJB消息驱动Bean是哪种处理方法的呢?
很明显,由于异步的需要,是采用的第二种,BEAN一直在监听。那么JBOSS就要为这个BEAN开辟一条通道,让BEAN在这条通道上监听,发送对应类型的消息时,也发送到这个通道上。那么我们就需要为JBOSS指定这个通道,然后把BEAN绑定到这条通道上。
(同时联想到bean中的一个属性名是destination,目的地,bean是消息处理的终点,怎么还有目的地,哈哈,此处的意思是去容器的一个目的通道上监听。)
而上面我们只声明了BEAN,JBOSS中确不存在这条通道,而你的bean又要去这里监听,那么JBOSS服务器会显示指定的通道没有绑定。
所以有理由相信,所以要通过上面xml文件使用容器创建一个通道(该文件可以打包在jar文件中,也可以只直接以xml文件的方式发布在deploy目录下,其效果是一样的):
图3.16 绑定成功
接下来就是处理发送消息:
package cn.sunquan.send;import java.util.Properties;import javax.jms.Queue;importjavax.jms.QueueConnection;import javax.jms.QueueConnectionFactory;import javax.jms.QueueSession;import javax.jms.TextMessage;import javax.naming.InitialContext;publicclass QueueSender { publicstaticvoid main(String[]args){ try { Properties props = new Properties(); props.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory"); props.setProperty("java.naming.provider.url","localhost:1099"); props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming"); InitialContext ctx = new InitialContext(props); //查找 QUeue类型的连接工厂。 QueueConnectionFactory factory = (QueueConnectionFactory)ctx .lookup("ConnectionFactory"); QueueConnection conn=factory.createQueueConnection(); //创建一个到该地址的会话,第二个参数:消息的确认模式,这里用自动的确认模式。 QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE); Queue queue = (Queue) ctx .lookup("queue/itmQueue"); TextMessage msg =session.createTextMessage("您好,这是我的第一个消息驱动Bean"); javax.jms.QueueSender sender=session.createSender(queue); sender.send(msg); session.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
可以看到lookup时是找的queue/itmQueue
图3.17 绑定成功
即在bean中指定的destination.
图3.18 显示结果
(注:上面的xxx-service.xml既然可以放在jar包中,那么实体bean中的dataSource.xml声明是否也可以放在实体bean的jar包中……)
下载:
HelloWorldEJB
EntityBeanTest
MessageBeanTest
- ejb3.0学习笔记
- EJB3.0学习笔记
- EJB3.0学习笔记之一
- EJB3.0 draft学习笔记(1)
- EJB3.0学习笔记之三 Interceptor
- EJB3.0学习笔记之EntityBean
- EJB3.0 draft学习笔记(1)
- EJB3.0 draft学习笔记(1)
- EJB3.0技术体系---学习笔记
- EJB3.0学习笔记1—入门
- EJB3学习笔记_JPA
- EJB3 学习笔记一
- EJB3 学习笔记二
- EJB3 学习笔记三
- EJB3 学习笔记四
- EJB3 学习笔记五
- EJB3 学习笔记六
- EJB3 学习笔记七
- 黑马程序员——WinForm
- coderforce 1c--Ancient Berland Circusp
- easyui message按钮文字自定义
- 黑马程序员_JavaScript学习后整理资料
- 从扑克牌种任取4张,通过加减乘除四则运算得到数字24
- EJB3.0学习笔记
- 貌似桶排序的快速排序—线性时间
- 线性表代码示例——C#
- 剑指offer面试题14 调整数组元素顺序使得奇数在前半部分偶数在后半部分
- UVa 437 - The Tower of Babylon LIS
- Tornado AsyncHTTPTestCase gotchas
- 生成树计数 spoj 104 highways
- 策略模式+简单工厂+反射
- java.util.concurrent.CyclicBarrier