??xml version="1.0" encoding="utf-8" standalone="yes"?>
1.命o行下q行war 文g打包?br />
在Dos H口中进入到WEB 应用根目录下(WebRoot?Q执行如下命令,如:
jar cvf EJBClient.war *Q?/span>再把打包?font face="Verdana">EJBClient.war拯到C:\jboss-5.0.0.GA\server\default\deploy发布?/font>
2.在Ant d中进行war文g打包?/font>
build.xml文g如下Q?br />
<?xml version="1.0" encoding="UTF-8"?>
<project name="EJBClient" default="war" basedir=".">
<property environment="env" />
<property name="jboss.home" value="${env.JBOSS_HOME}" />
<property name="jboss.server.config" value="default" />
<target name="war" description="创徏WEB 发布?>
<war warfile="${basedir}/${ant.project.name}.war" webxml="${basedir}/WebRoot/WEB-INF/web.xml">
<classes dir="${basedir}/WebRoot/WEB-INF/classes">
<include name="**/*.class" />
</classes>
<lib dir="${basedir}/WebRoot/WEB-INF/lib">
<include name="*.jar" />
</lib>
<webinf dir="${basedir}/WebRoot">
<include name="*.*" />
</webinf>
</war>
</target>
<target name="deploy" depends="war" description="发布WAR">
<copy file="${basedir}\${ant.project.name}.war" todir="${jboss.home}\server\${jboss.server.config}\deploy"/>
</target>
<target name="undeploy" description="卸蝲WAR">
<delete file="${jboss.home}\server\${jboss.server.config}\deploy\${ant.project.name}.war"/>
</target>
</project>
q个主要原因在stateless bean的实现类?/font>
仔细查看后发玎ͼ原来我在实现cȝ每个Ҏ前加入了 @WebMethod(指定暴露l外界的Ҏ)Q因此去掉就可以了?/font>
13:41:39,168 WARN [StatelessBeanContext] EJBTHREE-1337: do not get WebServiceContext property from stateless bean context, it should already have been injected
13:41:39,215 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
13:41:39,215 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
13:41:39,230 WARN [InterceptorRegistry] applicable interceptors is non-existent for public cn.ztf.bean.Order cn.ztf.service.impl.OrderServiceBean.getOrder(java.lang.String)
13:41:39,246 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.lang.String cn.ztf.service.impl.OrderServiceBean.getUserName(java.lang.String)
13:41:39,246 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.util.List cn.ztf.service.impl.OrderServiceBean.getOrders()
13:41:39,246 WARN [InterceptorRegistry] applicable interceptors is non-existent for public cn.ztf.bean.Order cn.ztf.service.impl.OrderServiceBean.getOrder(java.lang.String)
13:41:39,261 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.lang.String cn.ztf.service.impl.OrderServiceBean.getUserName(java.lang.String)
13:41:39,261 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.util.List cn.ztf.service.impl.OrderServiceBean.getOrders()
13:41:39,293 WARN [StatelessBeanContext] EJBTHREE-1337: do not get WebServiceContext property from stateless bean context, it should already have been injected
13:46:27,043 WARN [StatelessBeanContext] EJBTHREE-1337: do not get WebServiceContext property from stateless bean context, it should already have been injected
13:46:27,043 WARN [StatelessBeanContext] EJBTHREE-1337: do not get WebServiceContext property from stateless bean context, it should already have been injected
posted @ 2009-03-30 14:33 断点 阅读(647) | 评论 (0)
二者偏重点不同Q?br />
Web服务偏重的是q个pȝ对外提供什么功能;
EJB偏重的是如何使用一个个lgl装q些功能?/font>
例如Q一个硬盘,它对外提供的是存储服务,q是web服务的关注点Q对于怎样l装q个盘Qweb服务q不兛_Q而这些是EJB所x的?/font>
JavaEE为web service提供了两U不同的~程模型Q?span style="color: #0000ff">EJB容器模型、Web容器模型?br /> 下面以最新的JAX-WS2.x规范(Java API for XML-based Web Services)介绍Webservice的开发?br /> 注:JAX-WS的下载\径ؓhttps://jax-ws.dev.java.net/servlets/ProjectDocumentList?folderID=7796&expandFolder=7796&folderID=11088
EJB容器模型的WEB服务的客L开发:
注:首先我们需要徏立一个无状态SessionBeanQ然后把此无状态SessionBean发布为web service?/font>
1.在应用的c\径下攑օJAX-WS的全部jar文gQƈ且把引进的jar文gd到类路径上,卛_击项目名-->Properties-->Java Build Path-->Add JARS?br /> 如果你用的是JDK6Q这一步可以省略,因ؓJDK6已经l定了JAX-WS。目前JDK6l定的JAX-WS版本?.0?/font>
2.把JAX-WS产品lib目录中找到jaxws-api.jar和jaxb-api.jarQ把q两个文件copy到JDK_HOME/jre/lib/endorsed目录下?/font>
3.利用Web Service客户端生成工?wsimport工具的Antdc?生成辅助cR?br />
build.xml文g内容如下Q?br />
<?xml version="1.0" encoding="UTF-8"?>
<project name="WSClient" default="wsclientgen" basedir=".">
<property name="src.dir" value="${basedir}/src" />
<path id="build.classpath" description="讄c\?>
<fileset dir="${basedir}/lib">
<include name="*.jar"></include>
</fileset>
</path>
<target name="wsclientgen" description="生成webservice客户端辅助代码,执行后请h目">
<taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport"
classpathref="build.classpath"/>
<wsimport wsdl="http://localhost:8090/WebService/OrderServiceBean?wsdl"
sourcedestdir="${src.dir}" package="cn.ztf.ws.client" keep="true"
verbose="true" destdir="${basedir}/bin"/>
</target>
</project>
4.借助辅助c调用Web Service?br />
1.java消息驱动bean属于Java消息服务(Java Message ServiceQ简UJMS)?/font>
2.JMS是用于访问企业消息系l的开发商中心的API。企业消息系l可以协助应用Y仉过|络q行消息交互?/font>
3.JMS的编E过E简单概括ؓQ应用程序A-->(消息)-->Jboss JMS-->(消息)-->应用E序B。应用程序A和应用程序B没有直接的代码关联,两者实C解耦。消息传递系l的中心是消息?/font>
消息驱动Bean(MDB)是设计用来专门处理基于消息请求的lgQ它和无状态Session Bean一样也使用了实例池技术,容器可以使用一定数量的bean实例q发处理成百上千个JMS消息。正因ؓMDBh?/font>理大量ƈ发消息的能力Q所以非帔R合应用在一些消息网关品。如果一个业务执行的旉很长Q?/font>而执行结果无需实时向用户反馈时Q也很适合使用MDB。如订单成功后给用户发送一电子邮件或?/font>送一条短信等?/font>
消息有下面几U类型,他们都是z自Message接口?br />
StreamMessageQ一U主体中包含Java基本值流的消息。其填充和读取均按顺序进行?br />
MapMessageQ一U主体中包含一l名-值对的消息?没有定义条目序)
TextMessageQ一U主体中包含Java字符串的消息(例如QXML消息)
ObjectMessageQ一U主体中包含序列化Java对象的消息?br />
BytesMessageQ一U主体中包含q箋字节的消息?/font>
消息的传递模型:
JMS支持两种消息传递模型:点对?point-to-pointQ简UPTP)和发?订阅(publish/subscribeQ?/font>Upub/sub)?br />
二者有以下区别Q?br />
1.PTP 消息传递模型规定了一条消息只能传递给一个接收方。采用javax.jms.Queue表示?br />
2.Pub/sub 消息传递模型允怸条消息传递给多个接收斏V采用javax.jms.Topic表示?/span>
注意Q每U模型都通过扩展公用基类来实现。例如,javax.jms.Queue 和javax.jms.Topic都扩展自javax.jms.Destination cR?/font>
开发步骤如下:
一、配|destinations-service.xml文g?br />
JBOSS使用一个XML文g配置队列地址Q文件的取名格式应遵?-service.xmlQ我取名?/font>destinations-service.xml?br />
jboss默认的全局JNDI名称l成?span style="color: red">Q?queue"+"/"+"目标地址"?/span>
开始JMS~程前,我们需要先配置消息到达的目标地址(Destination)Q因为只有目标地址存在了,我们才能发送消息到q个地址。由于每个应用服务器关于目标地址的配|方式都有所不同Q下面以jbossZQ配|一个queuecd的目标地址?br />
<?xml version="1.0" encoding="UTF-8"?>
<server>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=ztfQueue">
<attribute name="JNDIName">queue/ztfQueue</attribute>
<depends optional-attribute-
name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=ztfTopic">
<attribute name="JNDIName">topic/ztfTopic</attribute>
<depends optional-attribute-
name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
注意QQ何队列或主题被部|之前,应用服务器必d部vDestination Manager MbeanQ所有我?/font>通过<depends>节点声明q一依赖?/font>
二、在javacM发送消?用到jndi.properties)?br />
一般发送消息有以下步骤Q?br />
1.得到一个JNDI初始化上下文(Context)
InitialContext ctx = new InitialContext();
2.Ҏ上下文查找一个连接工厂ConnectionFactoryQ改q接工厂是由JMS提供的,不需我们自己?/font>建,每个厂商都ؓ它绑定了一个全局JNDIQ我们通过它的全局JNDI便获取它Q?br /> QueueConnectionFactory factory = (QueueConnectionFactory)ctx.lookup("ConnectionFactory");
3.从连接工厂得C个连接QueueConnection?br /> QueueConnection conn = factory.createQueueConnection();
4.通过q接来徏立一个会?Session);
QueueSession session = conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);
q句代码意思是Q徏立不需要事务的q且能自动确立消息已接收的会话?/font>
5.查找目标地址Q?br /> Destination destination=(Destination)ctx.lookup("queue/ztfQueue");
6.Ҏ会话以及目标地址来徏立消息生产者MessageProducer(QueueSender和TopicPublisher都扩?/font>自MessageProducer接口)Q?br />
MessageProducer producer = session.createProducer(destination);
TextMessage msg = session.createTextMessage("您好Q荆州,q是我的W一个消息驱动Bean");
producer.send(msg);
三、采用MessageDrivenBean接收消息?/font>
当容器检到bean守候的目标地址有消息到达时Q容器调用onMessage()ҎQ将消息作ؓ参数传入MDB。MDB在onMessage()中决定如何处理改消息。你可以使用注解指定MDB监听哪一个目标地址(Destination)。当MDB部vӞ容器读取其中的配置信息?/font>
一个MDB通常要实现MessageListener接口Q在接口定义了onMessage()Ҏ。Bean通过它来处理收到的JMS消息?/font>
@MessageDriven(activationConfig=
{
@ActivationConfigProperty
(propertyName="destinationType",propertyValue="javax.jms.Queue"),
@ActivationConfigProperty
(propertyName="destination",propertyValue="queue/ztfQueue"),
@ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Auto-
acknowledge")
})
public class MessageDrivenBean implements MessageListener{
public void onMessage(Message message) {
TextMessage msg = (TextMessage)message;
try {
System.out.println(msg.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
四、把工程src下的文g打成jar?用到build.xml)Q在C:\jboss-5.0.0.GA\server\default\deployq行部v?/font>
五、运行发送消息的javac,此时在console中就可看见结果了?/font>
六、至此,一个MessageDrivenBean开发就成功了?/font>
2.通过注解使实体bean与数据库表相映射?/font>
3.当客Lq程调用EJBӞ数据在传送工E中是需要序列化?nbsp;Q业务方法是要返回Entitybean对象到客LQ显然Entitybean对象是要q行序列化的q程Q所以要实现序列化接口,卛_象在交互旉要实现序列化?/font>
4.Entitybean主键值的生成方式?br />
@GeneratedValue(strategy = GenerationType.IDENTITY)针对MysqlQ?br />
@GeneratedValue(strategy = GenerationType.SEQUENCE)针对Oracle,
@GeneratedValue(strategy = GenerationType.AUTO)自动匚w数据库?/font>
5.需要保留一个无参的构造函敎ͼ是JPA规范要求的,如果没有Q在q行时是要报错的?/font>
6.对象之间的比较,通常采用对象标志属性来q行比较Q也是IDq行比较Q因此现在重载hashCode、equals两个Ҏ?/font>
JPA的出C要是Z化现有的持久化开发工作和整合ORM技术,目前实现的JPA规范的主品有Hibernate、Toplink和OpenJPAQ在jboss?/font>采用了Hibernate作ؓ其持久化实现产品?
ҎJPA规范的要求:在实体bean应用中,我们需要在应用的类路径下的META-INF目录加入持久化配|文件persistence.xml?br />
persistence.xml文g用于指定Entitybean使用的数据源及EntityManager对象的默认行为?
persistence.xml的配|说明如下:
<?xml version="1.0" encoding="UTF-8"?>
<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/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<!-- 一个持久化单元是一个Entitybean的集合,JTA代表全局事物?->
<persistence-unit name="ztf" transaction-type="JTA">
<jta-data-source>java:/ztfDS</jta-data-source>
<properties>
<!-- Ҏ元数据生成数据库的表l构?-->
<property name="hibernate.hbm2ddl.auto" value="update"/>
<!-- 昄执行的SQL?-->
<property name="hibernate.show_sql" value="true"/>
<!-- 格式化显C的SQL ?-->
<property name="hibernate.format_sql" value="true"/>
<!-- SQL方言?-->
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9Dialect"/>
</properties>
</persistence-unit>
</persistence>
注意Q因为jboss 采用HibernateQHibernate 有一属性hibernate.hbm2ddl.autoQ该属性指定实体Bean发布时是否同步数据库l构?/font>
1.如果hibernate.hbm2ddl.auto的D为create-dropQ在实体Bean发布及卸载时自动创建及删除相应数据库表(注意QJboss 服务器启动或关闭时也会引发实体Bean 的发布及卸蝲)?/font>
2.如果hibernate.hbm2ddl.auto的D为update,以后Z实体bean的改动能反应到数据表Q徏议用updateQ这样实体Bean d一个属性时能同时在数据表增加相应字Dc?/font>
本地接口调用ejb的过E:
通过本地接口调用ejbQ直接在内存交互Q这样就可以避免因网l通信所造成的各U性能开销?br />
注意Q?br />
1.只有客户端与EJB应用都在同一个JVM内运行的时候,我们才能调用本地接口Q否则只能调用远E接口?br />
2.只要客户端与ejb发布在同一个jboss内,我们p为它们在同一个JVM?br />
3.客户端可以调用本地接口;也可调用q程接口Q当本地接口与远E接口都有同一个方法时Q优先调用本地接口中的方法?/span>
开发一个自qq程接口的无状态会话beanQ?/span> 开发一个自q本地接口的无状态会话beanQ?br />
1.需要自己开发的EJB的组?jar包?br />
注意Q在实现cM加入注解Q绑定接口?br />
@Stateless、@Local(HelloWorldLocal.class)//接口?br />
2.需要自己开发出的EJB的客LQƈ把客L工程打成.war文g?br />
注意Q客L所要知道的JNDI名称Q下面的HelloWorldLocal 为本地接口?br />
InitialContext ctx = new InitialContext(); Bean实例的两U管理技术: Jboss生成的JNDI名称Q默认命名规则如下: jndi.properties的配|:
1.需要自己开发的EJB的组?jar包?br />
注意Q在实现cM加入注解Q绑定接口?br />
@Stateless、@Remote(HelloWorld.class) //为接口?br />
2.需要自己开发出的EJB的客LQƈ把客L工程打成.war文g?br />
注意Q客L所要知道的JNDI名称Q下面的HelloWorld E接口?br />
InitialContext ctx = new InitialContext();
HelloWorld helloWorld = (HelloWorld)ctx.lookup("HelloWorldBean/remote");
out.println(helloWorld.sayHello("荆州"));
3.?jar?war文g拯到jboss的deploy区?br />
4.打开览器,输入自己开发出的EJB客户端的.jsp面Q即可?/p>
HelloWorldLocal helloWorld = (HelloWorldLocal)ctx.lookup("HelloWorldLocalBean/local");
out.println(helloWorld.sayHello("荆州"));
3.?jar?war文g拯到jboss的deploy区?br />
4.打开览器,输入自己开发出的EJB客户端的.jsp面Q即可?/p>
1.无状态bean使用实例池技术管理beanQ?br />
2.有状态bean使用Ȁz?activation)理bean?/p>
如果把EJB应用打包成后题ؓ.jar的模块文Ӟ默认的全局JNDI名称?br />
本地接口QEJB-CLASS-NAME/local
q程接口QEJB-CLASS-NAME/remote
例如Q把EJB-HelloWorld(里面包含接口HelloWorld和实现类HelloWorldBean)应用打包成EJB-HelloWorld.jar文gQ它的远E接口的JNDI名称是:HelloWorldBean/remote?/p>
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
posted @ 2009-03-26 09:56 断点 阅读(255) | 评论 (0)
]]>
下面介绍Elispse 打包向导和Ant 打包d?br />
1. Elispse 打包向导
在Elispse 开发环境下Q可以通过向导q行打包。右击项目名Uͼ在蟩出的菜单中选择Export-->Java-->JAR fileQ在"选择要导出的资源"Ӟ选择源目录和用到的资源然Q后选择一个存攄录及文g名,?完成"q束了打包?/p>
2. Ant 打包d
主要是在Eclipse下,通过配置build.xmlq行ANT 打包Q来提高开发效?也是推荐的打包方式?br />
下面我们看一个简单的打包d?br />
<?xml version="1.0" encoding="UTF-8"?>
<project name="EJB-HelloWorld" basedir=".">
<property name="src.dir" value="${basedir}\src" />
<property environment="env" />
<property name="jboss.home" value="${env.JBOSS_HOME}" />
<property name="jboss.server.config" value="default" />
<property name="build.dir" value="${basedir}\build" />
<path id="build.classpath">
<fileset dir="${jboss.home}\client">
<include name="*.jar"></include>
</fileset>
<pathelement location="${build.dir}"/>
</path>
<target name="prepare">
<delete dir="${build.dir}"/>
<mkdir dir="${build.dir}"/>
</target>
<target name="compile" depends="prepare" description="~译 ">
<javac srcdir="${src.dir}" destdir="${build.dir}">
<classpath refid="build.classpath" />
</javac>
</target>
<target name="ejbjar" depends="compile" description="创徏EJB发布?>
<jar jarfile="${basedir}\${ant.project.name}.jar" >
<fileset dir="${build.dir}" >
<include name="**/*.class"></include>
</fileset>
</jar>
</target>
<target name="deploy" depends="ejbjar" description="发布EJB">
<copy file="${basedir}\${ant.project.name}.jar" todir="${jboss.home}\server\${jboss.server.config}\deploy"/>
</target>
<target name="undeploy" description="卸蝲EJB">
<delete file="${jboss.home}\server\${jboss.server.config}\deploy\${ant.project.name}.jar"/>
</target>
</project>
再右健点L配置文gbuild.xmlQ选择Run As-->Ant Build卛_Q?/p>
posted @ 2009-03-26 09:51 断点 阅读(158) | 评论 (0)
采用EJB开发基于MVCQ包含显C层、控制层和业务层Q结构的应用Q那么EJB是用于开发应用的业务层?/span>
开发EJB遵@如下步骤q行Q?br />
1.开发构成EJBlg的Java源文Ӟ比如Q组件接口、Home接口、企业BeancR所需的辅助类{?br />
2.手工完成部v描述W,或者借助与IDE?br />
3.~译步骤1开发的java源文?
4.借助于JDK自带的jar使用工具Q来创徏含有部v描述W和.class文g的EJB-jar文g?br />
5.通过具体EJb容器提供的部|徏议,来完成Ejb-jar文g的部|Ӏ?br />
6.配置EJB服务器,使得Ejb-jar含有的Ejblg能够正常q作?br />
7.启动EJB服务器。此Ӟ开发者可以验证EJBlg是否部v成功,q运行?br />
EJB3.0规范定义了如?UEJBlgcdQ?br />
1、会话Bean(SessionBean)Q无状态会话Bean(Stateless SessionBean)、有状态会话Bean(Stateful SessionBean)?br />
会话Bean通常有以下属性:
Q?Q代表单个客h执行?br />
Q?Q可以是事务的?br />
Q?Q可以更新共享数据库中的数据?br />
Q?Q生存期相对较短?br />
Q?Q其生存期通常是客户机的生存期?br />
Q?QQ何持久性数据都有Bean理?br />
Q?Q可以依容器的判断予以删除?br />
Q?Q会在EJB服务器失败时被删除?br />
EJB容器理无状态会话Bean的生存周期,其方式是通过创徏_多数量的此种Bean适应客户机工作负?q在不需要它们的时候将其删除或者将闲置的Bean写到盘上?br />
如果会话Bean在方法调用之前需要保留状态信息,则必M用有状态的会话Bean(Stateful SessionBean)?br />
会话Bean在J2EE应用E序中被用来完成一些服务器端的业务操作Q例如访问数据库、调用其他EJBlg?br />
MQ会话Bean代表一U操作:它检索或者存储数据以满用户的请求?/span>
2、实体Bean(EntityBean)Q通常有以下属?
Q?Q代表数据库的数据?br />
Q?Q是事务性的?br />
Q?Q允许多个用户共同访问?br />
Q?Q可以长期存在?br />
Q?Q持久性数据可以由容器理?br />
Q?Q在EJB服务器失败后能l生存?br />
实体Bean被用来代表应用数据库中用到的数据。例如在一个电子商务系l中Q实体Bean可以被用来代表品、雇员、信用卡、订单数据等数据对象?br />
持久性是实体Bean的一个基本属性。EJB规范允许两种形式的实体持久?Bean理的持久?BMP)和容器管理的持久?CMP)?br />
实体Bean支持多个用户q发的访问数据。EJB规范说明Q维护数据的完整性是容器的责仅R容器完成这个Q务通常的做法是Q锁定数据库中的数据Qƈ使访问串行化Q或者通过创徏多个实体Bean的实例,q允许在基础数据存储中用ƈ发控Ӟ来管理访问?br />
MQ实体Bean代表一U数据集Q可以访问这些数据集以满用Lh?/span>
3、消息驱动bean(Message DrivenBean)
消息驱动Bean要与JMSl合使用Q以提供消息驱动的异步处理功能。例如电子商务系l的交易认可以用消息驱动Bean来实现?br />
消息驱动Bean作ؓJMS队列和主题的监听器部|Ԍ当有JMS消息到达Q系l就会调用消息驱动Beand成业务逻辑Ҏ?br />
MQ客h不能直接调用消息驱动BeanQ客户通过发送JMS消息调用消息驱动Bean?/font>