EJB3.0介绍

  • Post author:
  • Post category:其他



Enterprice


JavaBeans


是一个用于分布式业务应用的标准服务端组件模型。采用


Enterprice


JavaBeans



架构

编写的应用是可伸缩的、事务性的、多用户安全的。


采用


ejb


编写的这些应用,可以部署在任何支持


Enterprice


JavaBeans


规范的服务器平台,如


jboss





weblogic


等。



EJB


实际上是用于编写业务层代码。


我们知道一个基于


MVC


结构的应用应包含显示层、控制层和业务层


,


假设我们采用


ejb


开发基于


MVC


结构的应用


,


那么


ejb


就是用于开发应用的业务层


.


EJB最大的特点是分布式,EJBs都是业务层的东西,对于多个显示层可以做到业务层完全不用改变。我们写的EJBs发布到EJB容器比如JBOSS中,客户端(普通

Java

应用或者JavaWeb应用)通过JNDI找到你的EJB,这中间通过socket通信,为了降低这种消耗,可以定义本地的EJB,但是这个EJB必须和你的客户端在同一个JVM中,即一个JBoss中,比如你的JavaWeb发布到这个JBoss中。




EJB


为我们提供了很多在企业开发中需要使用到的服务


,


如事务管理


/


安全


/


持久化


/


分布式等


,


因为这些服务由容器提供


,


无需我们自行开发


,


这样大大减少了我们的开发工作量


.


另外


EJB


提供了强制式分层解耦设计方法





EJB3.0运行环境


EJB3.0


应用需要运行在


JDK1.5


以上版本。


进入


http://java.sun.com/javase/downloads/index_jdk5.jsp


下载


JDK


。在页面中找到


JDK5.0 Update 16


(版本在不断更新中,有可能大于


16


),点击右边的


Download




按照安装向导提示安装,安装路径选择


C:\Java\jdk1.5.0_16





Jdk


安装完后,接着问你是否安装


jre


,也一起安装上。


右键点击“我的电脑”


->


“属性”


->


“高级”


->


“环境变量”,在“系统变量”里添加


JAVA_HOME


变量,值为


JDK


的安装路径,如:


C:\Java\jdk1.5.0_16




在“系统变量”里再添加


CLASSPATH


变量,值为:


.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;


在系统变量栏找到变量名为


Path


的选项,点“编辑”在变量值的末尾添加


;%JAVA_HOME%\bin;




EJB3.0


应用需要运行在


EJB


容器里,下面是一些


JavaEE


应用服务器,


JavaEE


应用服务器包含


Web


容器和


EJB


容器。


l


Jboss





4.2.x


以上版本)




是一个成熟的开源的准


JavaEE


应用服务器,在开源


JavaEE


应用服务器中所占市场份额第一。如果你打算选用开源的


JavaEE


应用服务器,那么


jboss


是最值得选择的。


l


Glassfish



是一个开源的

JavaEE


应用服务器,对


JavaEE


规范的支持非常好,其运行性能比较高。因为发展时间相对较短,市场占有率比较低。另外,它能否提供稳定的运行性能,还有待时间的考验。


l


Weblogic





10


以上版本)



是商业市场占有率第一的商业

JavaEE


应用服务器,它具有出色的稳定性,并提供了人性化的管理界面,还有企业需要使用到的众多功能。


l


Sun ApplicationServer





9.0


以上版本)



商业

JavaEE


应用服务器,如果你打算选用商业应用服务器运行


ejb3


,这个是不错的选择。


l


Oracle ApplicationServer





10g


以上版本)



商业

JavaEE


应用服务器,如果你的

数据库





Oracle



,要想兼容性更好,这个是不错的选择。


l


apusic


应用服务器




这是国内的商业


JavaEE


应用服务器,主要在政府中占有一定的市场份额。但是其向开发人员提供的文档实在太少了。



注意:


Tomcat


目前只是


Web


容器,它不能运行


EJB


应用。




进入http://labs.jboss.com/jbossas/downloads/下载页面,选择jboss4.2.3.GA下载(大小为95MB),如果你安装的jdk是1.5版本,请选择jboss-4.2.3.GA.zip文件下载。如果你安装的jdk是1.6版本,请选择jboss-4.2.3.GA-jdk6.zip文件下载。下载后直接解压缩文件即可完成安装,为了避免应用出现莫名的错误,解压缩的路径最好不要带有空格和中文,如“Program Files”。



进入


jboss





bin


目录,找到


启动脚本


run.bat


。双击


run.bat


即可启动


jboss


,此时启动的配置项为


default






如果启动出错,请检查下列情况


:



1.

端口是否被占用,如:


8080





1099



2

是否为


JDK


设置的


JAVA_HOME





ClassPath


系统变量,如果没有,请按照前面视频介绍的方法设置。



3.

检查


jboss


所用的


jdk


是否


1.5


以上版本,这些信息可以在


jboss


的控制台观察到。



4.

如果启动时出现这样的错误:“


findstr


不是内部或外部命令,也不是可运行的程序或批处理文件”。那么应该在系统变量


Path


中追加“


%SystemRoot%\system32;%SystemRoot%;










最后的办法是重装机器上的


JDK


,祝你好运。



l


因为在后面的学习中,我们需要使用到系统变量


JBOSS_HOME


,它指向


jboss


的安装路径。所以


安装完后


我们需要添加该变量,方法是:


右键点击“我的电脑”


->





属性”


->





高级”


->





环境变量”,

在“系统变量”里添加




JBOSS_HOME


变量,值为


Jboss


的安装路径,如:


D:\JavaEEServer\jboss





l


为了方便输入


jboss


的命令,我们把


jboss





bin


目录添加到系统路径里。


在系统变量一栏找到变量名为


Path


的选项,点“编辑”在变量值的末尾添加:


;%JBOSS_HOME%\bin;









开发


EJB


依赖的


jar


文件





可以在


jboss


安装路径的


client


目录下找到


,


通常会把


client


目录下的所有


jar


文件添加到项目的类路径下


.




EJB


中的三种


bean







1.


会话


bean(session bean)




负责与客户端交互


,


是编写业务逻辑的地方


,


在会话


bean


中可以通过


jdbc


直接操作数据库


,


但大多数情况下都是通过实体


bean


来完成对数据库的操作


.



2.


实体


bean(entity bean)




它实际上属于


java


持久化规范


(


简称


JPA)


里的技术


,JPA


的出现主要是为了简化现有的持久化开发工作和整合


ORM


技术,结束现在



hibernate






TopLink





ORM


框架各自为营的局面。



3.


消息驱动


bean(message-driven bean)




它是专门用于异步处理


java


消息的组件


.


具有处理大量并发消息的能力


.



两种会话bean






无状态会话


bean




平常


,


我们使用最多的是无状态


bean,


因为它的


bean


实例可供多个用户使用


,


所以它的性能比有状态


bean





.


正因为一个


bean


实例被多个用户使用


.


那么


,


前一个用户设置的值有可能被后一个用户所修改


,


所以它无法正确保存某个用户设置的值


,


因此是无状态的


.无状态


bean


使用


实例池


技术管理


bean





有状态会话


bean


有状态


bean


平常使用的并不多


,


因为它的一个


bean


实例只供一个用户使用


,


所以性能开销比较大


,


正因为它的实例只被一个用户使用


,


用户为它设置的值是不会被其他用户修改


,


所以可以正确保存用户设置的值


,


因此是有状态的


.





状态


bean


使用


激活


(activation)


管理


bean



每个用户都有自己的


Bean


实例,相当于有多少个用户就有多少个


Bean


实例为之服务。如果不采取任何机制,这样必然会导致服务器资源严重消耗,最后落个


down


机罢工。为了解决这个问题,


EJB


引入了激活机制。该机制实现的原理是这样的,在


EJB


服务器需要节省资源时,就从内存中收回


bean


实例,将其所保持的会话状态序列化到硬盘中,并且释放其所占有的内存。若此时客户端对


EJB


再次发起请求,


EJB


容器会重新实例化一个


Bean


实例,并从硬盘中将之前的状态恢复。



客户端编程


public static void main(String[]


args


) {



Properties props =

new Properties();





props.setProperty


(”


java.naming.factory.initial


“,”


org.jnp.interfaces.NamingContextFactory


“);





props.setProperty


(”


java.naming.provider.url





,”


localhost:1099


“);


try {




InitialContext


ctx


=


new


InitialContext


(props);




HelloWorld


helloworld


= (


HelloWorld


)


ctx.lookup


(”


HelloWorldBean


/remote


“);




System.


out.println


(


helloworld.sayHello


(”


佛山


“));


}


catch (


NamingException


e) {




System.


out.println


(


e.getMessage


());


}


}









设置JNDI访问环境信息


在进行


JNDI


查找前,我们必须设置应用服务器的上下文信息,主要是设置


JNDI


驱动的类名(


java.naming.factory.initial


)和命名服务提供者的


URL





java.naming.provider.url


) 。


l


java.naming.factory.initial





Context.INITIAL_CONTEXT_FACTORY


:环境属性名,用于指定


InitialContext


工厂(作者称它为


JNDI


驱动更容易理解),它类似于


JDBC


指定数据库驱动类。


因为本例子连接的是


JbossNS


(命名服务的实现者),所以使用


Jboss


提供的驱动类:


org.jnp.interfaces.NamingContextFactory


l


java.naming.provider.url





Context.PROVIDER_URL


:环境属性名,包含提供命名服务的主机地址和端口号。它类似于


JDBC


指定数据库的连接


URL


。连接到


JbossNS





URL


格式为:


jnp://host:port


,该


URL


的“


jnp:


”部分是指使用的协议,


JBoss


使用的是基于


Socket/RMI


的协议。


host


为主机的地址,


port





JNDI


服务的端口。除了


host


之外,其他部分都是可以不写的。

l


下面是数据库访问例子


:


Class.forName(“org.gjt.mm.

MySQL

.Driver”).newInstance();


Properties props = new Properties();


props.put(“user”,”root”);


props.put(“password”,”123456″);


Connection conn =

DriverManager.getConnection(“jdbc:mysql://

localhost:3306


/itcast”,


props


);



如同数据库一样,根据访问命名服务器的不同,为上下文设置的驱动类和


URL


也是不同的,如下面是访问


Sun


应用服务器的上下文信息:


Properties props =


new


Properties();


props.setProperty


(”


java.naming.factory.initial


“, ”


com.sun.enterprise.naming.SerialInitContextFactory


“);


props.setProperty


(”


java.naming.provider.url


“, ”


localhost:3700


“);


InitialContext


=


new


InitialContext


(props);


HelloWorld


helloworld


= (


HelloWorld


)


ctx.lookup


(“com.foshanshop.ejb3.HelloWorld”);


如果客户端运行在应用服务器内,我们不需要为


InitialContext


设置应用服务器的上下文信息,也不建议设置。因为应用服务器启动时会把


JNDI


驱动类等上下文信息添加进系统属性,创建


InitialContext


对象时如果没有指定


Properties


参数,


InitialContext


内部会调用


System.getProperty


()


方法从系统属性里获取必要的上下文信息。对本例子而言,你可以省略传入


props


参数,之所以给


InitialContext


设置参数,目的是引出相关知识点,便于教学。在实际应用中,如果给


InitialContext


设置了参数,反而会带来不可移植的问题。


注:创建


InitialContext


对象时如果没有指定


Properties


参数,


InitialContext


还会在


classpath


下寻找


jndi.properties


文件,并从该文件中加载应用服务器的上下文信息。这样避免了硬编码为


InitialContext


设置


Properties


参数。


jndi.properties


的配置如下:


java.naming.factory.initial


=


org.jnp.interfaces.NamingContextFactory


java.naming.provider.url


=localhost:1099


java.naming.factory.url.pkgs


=


org.jboss.naming:org.jnp.interfaces





EJB


发布到


Jboss


时,如果我们没有为它指定全局


JNDI


名称或修改过其默认


EJB


名称,


Jboss


就会按照默认的命名规则为


EJB


生成全局


JNDI


名称,默认的命名规则如下:


如果把


EJB


作为模块打包进后缀为


*


.ear






Java EE



企业应用文件,默认的全局


JNDI


名称是


l


本地接口:


EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local

l


远程接口:


EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote



EAR-FILE-BASE-NAME




ear


文件的名称,


EJB-CLASS-NAME





EJB


的非限定类名。


例:把


HelloWorld


应用作为


EJB


模块打包进名为


HelloWorld.ear


的企业应用文件,它的远程接口的


JNDI


名称是:


HelloWorld


/


HelloWorldBean


/remote


如果把


EJB


应用打包成后缀为


*


.jar


的模块文件,默认的全局


JNDI


名称是


l


本地接口:


EJB-CLASS-NAME/local

l


远程接口:


EJB-CLASS-NAME/remote


例:把


HelloWorld


应用打包成


HelloWorld.jar


文件,它的远程接口的


JNDI


名称是:


HelloWorldBean


/remote



使用注释改变会话bean的JNDI名



如果我们没有指定


EJB





JNDI


名称,当


EJB


发布到应用服务器时,应用服务器会按默认规则为


EJB


生成全局


JNDI


名称。当我们需要自定义


JNDI


名称时,可以这样做


如果


EJB





Jboss


中使用,可以使用


Jboss


提供的


@


LocalBinding





@


RemoteBinding


注释,


@


LocalBinding


注释指定


Session Bean





Local


接口的


JNDI


名称,


@


RemoteBinding


注释指定


Session Bean





Remote


接口的


JNDI


名称,如下:


@Stateless


@Remote ({



Operation.class


})


@


RemoteBinding


(


jndiBinding


=”


foshanshop


/


RemoteOperation


“)


@Local ({



LocalOperation.class


})


@


LocalBinding


(


jndiBinding


=”


foshanshop


/


LocalOperation


“)


public class


OperationBean


implements Operation,


LocalOperation


{


}






使用


xml


部署描述文件


改变


SessionBean





JNDI


名称



由于


JNDI


名称与厂商有关,如果使用注释定义


JNDI


名称会带来移植问题,因此建议使用


ejb-jar.xml


部署描述文件进行定义,该文件必须放置在


jar





META-INF


目录下


<?xml version=”1.0″encoding=”UTF-8″?>


<


ejb


-jar


xmlns


=



http://java.sun.com/xml/ns/javaee





xmlns:xsi


=”http://www.w3.org/2001/XMLSchema-instance”




xsi:schemaLocation


=”http://java.sun.com/xml/ns/javaee



http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd”  version=”3.0″>


<enterprise-beans>



<session>



<

ejb


-name>


HelloWorldBean


</


ejb


-name>



<mapped-name>

HelloWorldBean


</mapped-name>



</session>


</enterprise-beans>


</


ejb


-jar>


ejb


-name





EJB


名称,


mapped-name





bean





JNDI


名称。目前


jboss


不支持在


ejb-jar.xml


通过


mapped-name


指定


JNDI


名称,但我们可以使用他专属的部署描述文件


jboss.xml


进行定义,如下:


<?xml version=”1.0″encoding=”UTF-8″ ?>


<!DOCTYPE


jboss


PUBLIC “-//


JBoss


//DTDJBOSS 4.2//EN“ “http://www.jboss.org/j2ee/dtd/jboss_4_2.dtd”>


<


jboss


><enterprise-beans> <session>



<

ejb


-name>


HelloWorldBean


</


ejb


-name>



<

jndi


-name>hello/remote</


jndi


-name>


</session></enterprise-beans></


jboss


>


本地接口的bean




@Local ({



HelloWorldLocal.class


})




EJB的调用机制



由于


EJB


的调用过程对开发者来说是透明的,以至于我们错误地认为:


lookup()


方法返回的对象就是


bean


实例。实际上,客户端与


Session bean


交互,它并不直接与


Bean


实例打交道,而是经由


bean


的远程或本地接口。当你调用远程或本地接口的方法时,接口使用的是存根(


stub


)对象。该存根实现了


session bean


的远程或本地接口。它负责将方法调用经过网络发送到远程


EJB


容器,或将请求路由到位于本地


JVM


内的


EJB


容器。存根是在部署期间使用


JDK


所带的


java.lang.reflect.Proxy


动态生成。利用RMI、远程代理实现远程调用。





第一步


:客户端调用远程接口的


SayHello


()


方法(实际上调用的是存根对象的


SayHello


()


方法,该存根实现了


HelloWorld


的远程接口)。


第二步


:方法调用经过


IIOPRuntime


被转换成


CORBA IIOP


消息发往应用服务器。


第三步


:应用服务器接收到请求消息后,交由骨架(


skeleton


)处理。骨架通过


IIOP Runtime


解析协议消息,并根据协议要求调用


bean


实例的


SayHello


()


方法。


第四步


:骨架(


skeleton


)将


SayHello


()


方法的返回值经过


IIOPRuntime


转换成


CORBA IIOP


应答消息发回客户端。


第五步:存根对象通过


IIOP Runtime





CORBAIIOP


应答消息解析成返回值。







EJB中的依赖注入



注入


ejb


:


@Stateless


@Remote (


Injection.


class


)


public


class


InjectionBean


implements


Injection {





@EJB(

beanName


=”


HelloBean


“)


LocalHello


helloworld


;




public


String


SayHello


() {




return


helloworld.SayHello


(”


注入者


“);



}


}


注入数据源


:


@Resource(


mappedName


= “java:/


DefaultMySqlDS


“)


DataSource


myDb


;



Connection

conn


= null;



try {




conn


=


myDb.getConnection


();



Statementstmt =

conn.createStatement


();




ResultSet


rs


=


stmt.executeQuery


(“SELECT


studentName


FROM student”);



if (

rs.next


())


str


=


rs.getString


(1);


rs.close


();




stmt.close


();



} catch (

SQLException


e) {




e.printStackTrace


();



}finally{



try {



if(null!=

conn


&& !


conn.isClosed


())


conn.close


();



} catch (

SQLException


e) {




e.printStackTrace


();



}




}





配置数据源





<?xml version=”1.0″encoding=”UTF-8″?>


<


datasources


>



<local-

tx





datasource


>



<

jndi


-name>


DefaultMySqlDS


</


jndi


-name>



<connection-

url


>


jdbc:mysql


://localhost:3306/


itcast?useUnicode


=


true&amp;characterEncoding


=UTF-8</connection-


url


>



<driver-class>

org.gjt.mm.mysql.Driver


</driver-class>



<user-name>root</user-name>



<password>123456</password>



<min-pool-size>3</min-pool-size>



<max-pool-size>100</max-pool-size>



<!–



TRANSACTION_READ_UNCOMMITTED



TRANSACTION_READ_COMMITTED



TRANSACTION_REPEATABLE_READ



TRANSACTION_SERIALIZABLE




<transaction-isolation>TRANSACTION_SERIALIZABLE</transaction-isolation>–>



<exception-sorter-class-name>

org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter


</exception-sorter-class-name>



<metadata>



<type-mapping>

mySQL


</type-mapping>



</metadata>



</local-

tx





datasource


>


</


datasources


>



实体Bean







它属于


java


持久化规范


(


简称


JPA)


里的技术,实体


bean


通过元数据在


javabean


和数据库表之间建立起映射关系,然后


Java


程序员就可以随心所欲的使用面向对象的编程思想来操纵数据库。


JPA


的出现主要是为了简化现有的持久化开发工作和整合


ORM


技术,目前实现的


JPA


规范的主流产品有


Hibernate





TopLink





OpenJPA








jboss


中采用了


Hibernate


作为其


持久化实现产品





添加


JPA


的配置文件


persistence.xml






根据


JPA


规范的要求:在实体


bean


应用中,我们需要在应用的类路径下的


META-INF


目录加入持久化配置文件


persistence.xml


<?xml version=”1.0″?>


<persistence


xmlns


=”http://java.sun.com/xml/ns/persistence”


xmlns:xsi


=”http://www.w3.org/2001/XMLSchema-instance”


xsi:schemaLocation


=”http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd”version=”1.0″>



</persistence>



<propertyname=”hibernate.hbm2ddl.auto” value=”create-drop”/>


<!–


显示最终执行的


SQL –>


<property name=”


hibernate.show_sql


” value=”true”/>


<!–


格式化显示的


SQL –>


<property name=”


hibernate.format_sql


” value=”true”/>



JMS(Java消息服务)



Java


消息服务(



Java

Message Service


,简称


JMS


)是用于访问企业消息系统的开发商中立的


API


。企业消息系统可以协助应用软件通过网络进行消息交互。


JMS


的编程过程很简单,概括为:应用程序


A


发送一条消息到消息服务器的某个目得地


(Destination)


,然后消息服务器把消息转发给应用程序


B


。因为应用程序


A


和应用程序


B


没有直接的代码关连,所以两者实现了解偶。如下图:






消息传递系统的中心就是消息。一条


Message


由三个部分组成:


头(


header





,


属性(


property


)和主体(


body


)。


消息有下面几种类型,他们都是派生自


Message


接口。


StreamMessage


:一种主体中包含


Java


基元值流的消息。其填充和读取均按顺序进行。


MapMessage


:一种主体中包含一组名





值对的消息。没有定义条目顺序。


TextMessage


:一种主体中包含


Java


字符串的消息(例如,


XML


消息)。


ObjectMessage


:一种主体中包含序列化


Java


对象的消息。


BytesMessage


:一种主体中包含连续字节流的消息。



JMS




支持两种消息传递模型

:点对点(


point-to-point


,简称


PTP


)和发布


/


订阅(


publish/subscribe


,简称


pub/sub


)。这两种消息传递模型非常相似,但有以下区别:


PTP


消息传递模型规定了一条消息只能传递给一个接收方。采用


javax.jms.Queue


表示。


Pub/sub


消息传递模型允许一条消息传递给多个接收方。采用


javax.jms.Topic


表示


这两种模型都通过扩展公用基类来实现。例如:


javax.jms.Queue





javax.jms.Topic


都扩展自


javax.jms.Destination


类。


P2P



P/S



配置目标位置



开始


JMS


编程前,我们需要先配置消息到达的目标地址


(Destination)


,因为只有目标地址存在了,我们才能发送消息到这个地址。由于每个应用服务器关于目标地址的配置方式都有所不同,下面以


jboss


为例,配置一个


queue


类型的目标地址。


<?xml version=”1.0″encoding=”UTF-8″?>


<server>



<

mbean


code=”


org.jboss.mq.server.jmx.Queue





name=”

jboss.mq.destination:service


=


Queue,name


=


foshanshop


“>




<attributename=”


JNDIName


“>


queue/


foshanshop


</attribute>



<dependsoptional-attribute-name=”

DestinationManager


“>


jboss.mq:service


=


DestinationManager


</depends>



</

mbean


>


</server>


Jboss


使用一个


XML


文件配置队列地址,文件的取名格式应遵守*


-service.xml


<attribute name=”


JNDIName


“>


属性指定了该目标地址的全局


JNDI


名称。如果你不指定


JNDIName


属性,


jboss


会为你生成一个默认的全局


JNDI


,其名称由“


queue”+“/”+


目标地址名称组成。另外在任何队列或主题被部署之前,应用服务器必须先部署


Destination Manager


Mbean


,所以我们通过


<depends>


节点声明这一依赖。


发送消息



一般发送消息有以下步骤:


(1)


得到一个


JNDI


初始化上下文


(Context)




InitialContext


ctx


= new


InitialContext


();


(2)


根据上下文查找一个连接工厂


QueueConnectionFactory


。该连接工厂是由


JMS


提供的,不需我们自己创建,每个厂商都为它绑定了一个全局


JNDI


,我们通过它的全局


JNDI


便可获取它;




QueueConnectionFactory


factory = (


QueueConnectionFactory


)


ctx.lookup


(”


QueueConnectionFactory


“);


(3)


从连接工厂得到一个连接


QueueConnection




conn


=


factory.createQueueConnection


();


(4)


通过连接来建立一个会话


(Session);



session =

conn.createQueueSession


(false,


QueueSession.AUTO_ACKNOWLEDGE


);




这句代码意思是:建立不需要事务的并且能自动确认消息已接收的会话。


(5)


查找目标地址:




例子对应代码:


Destination


destination


= (Destination )


ctx.lookup


(“queue/


foshanshop


“);


(6)


根据会话以及目标地址来建立消息生产者


MessageProducer





QueueSender





TopicPublisher


都扩展自


MessageProducer


接口)


例子对应代码:


MessageProducer


producer =


session.createProducer


(destination);


TextMessage


msg


=


session.createTextMessage


(”


您好,这是我的第一个消息驱动


Bean”);


producer.send


(


msg


);


采用消息驱动Bean接收消息





消息驱动


Bean(MDB)


是设计用来专门处理基于消息请求的组件。它和无状态


Session Bean


一样也使用了实例池技术,容器可以使用一定数量的


bean


实例


并发处理成百上千个


JMS


消息


。正因为


MDB


具有处理大量并发消息的能力,所以非常适合应用在一些消息网关产品。如果一个业务执行的时间很长,而执行结果无需实时向用户反馈时,也很适合使用


MDB


。如订单成功后给用户发送一封电子邮件或发送一条短信等。


一个


MDB


通常要实现


MessageListener


接口,该接口定义了


onMessage


()


方法。


Bean


通过它来处理收到的


JMS


消息。


package javax.jms;


public interface


MessageListener


{



public void

onMessage


(Message


message


);


}


当容器检测到


bean


守候的目标地址有消息到达时,容器调用


onMessage


()


方法,将消息作为参数传入


MDB





MDB





onMessage


()


中决定如何处理该消息。你可以使用注释指定


MDB


监听哪一个目标地址


(Destination)


。当


MDB


部署时,容器将读取其中的配置信息。


@


MessageDriven


(


activationConfig


=


{



@

ActivationConfigProperty


(


propertyName


=”


destinationType


“,




propertyValue


=”


javax.jms.Queue


“),



@

ActivationConfigProperty


(


propertyName


=”destination”,




propertyValue


=”queue/


foshanshop


“),



@

ActivationConfigProperty


(


propertyName


=”


acknowledgeMode


“,




propertyValue


=”Auto-acknowledge”)


})


public class


PrintBean


implements


MessageListener


{



public void

onMessage


(Message


msg


) {



WebService服务



Web


服务也是一种分布式技术,它与


EJB


最大的不同是,


Web


服务属于行业规范,可以跨平台及语言。而


EJB


属于


java


平台的规范,尽管理论上可以跨平台,但实现起来比较复杂,所以其应用范围局限在了


java


平台。看上去两者好像是互相竞争的关系,其实不是。它们两者的偏重点不一样,


Web


服务偏重的是这个系统对外提供什么功能,而


EJB


偏重的是如何


使


用一个个组件组装这些功能。就好比一个硬盘,它对外提供的是存储服务,这是


web


服务的关注点,对于怎样组装这个硬盘,怎样构造这些小零件,


web


服务并不关心,但这些却是


EJB


所关注的。


JavaEE





web service


提供了两种不同的编程模型:


EJB


容器模型及


Web


容器模型


,这里


将以最新的


JAX-WS2.x


规范(


Java API for XML-based Web Services


)介绍


webservice


的开发。


@


WebService


(


targetNamespace


=”http://ws.foshanshop.com”,



name = ”

HelloWorld


“,




serviceName


= ”


HelloWorldService


“)


客户端




开发步骤如下:


1.


在应用的类路径下放入


JAX-WS





jar


文件


(


下载路径





https://jax-ws.dev.java

.NET

)


。如果你使用的是


JDK6


,这一步可以省略,因为


JDK6


已经绑定了


JAX-WS


。目前


JDK6


绑定的


JAX-WS


版本是


2.0


。这意味着,当某些应用使用的


JAX-WS


版本高于


2.0


时,就有可能发生版本问题,这时,你需要升级


JDK6


中的


JAX-WS


版本,方法如下:


下载最高版本的


JAX-WS


,在产品


lib


目录中找到


jaxws-api.jar





jaxb-api.jar


,把这两个文件


copy





JDK6_HOME/


jre


/lib/endorsed


目录下。





如果有同学使用开发工具是


myeclipse





这时应该把


myeclipse


所使用的


jdk


更改为你系统安装的


jdk




2.


利用


Web Service


客户端生成工具生成辅助类。


3.


第三步:借助辅助类调用


web service





这里我们使用


wsimport


工具的


Ant


任务类生成辅助类


<?xml version=”1.0″encoding=”UTF-8″?>


<project name=”


WSClient


” default=”


wsclientgen





basedir


=”.”>



<propertyname=”src.dir” value=”${


basedir


}/


src


” />



<path id=”

build.classpath


“description=”


设置类路径


“>



<

fileset


dir=”${



basedir


}/lib”>



<includename=”*.jar”/>



</

fileset


>



</path>



<targetname=”

wsclientgen


“description=”


生成


webservice


客户端辅助代码,执行后请刷新项目


“>



<

taskdef


name=”


wsimport





classname


=”


com.sun.tools.ws.ant.WsImport





classpathref


=”


build.classpath


“/>



<

wsimport


wsdl


=”http://localhost:8080/WsHelloWorld/HelloWorldBean?wsdl”




sourcedestdir


=”${src.dir}” package=”


com.foshanshop.ws.client


“keep=”true”



verbose=”true”

destdir


=”${



basedir


}/bin”/>



</target>


</project>