1.开发无状态会话Bean的步骤。
a.开发接口类,并提供业务方法。
b.开发实现类,并实现业务方法。
c.使用@Stateless注解,声明实现类是一个无状态会话Bean。
4.使用@Remote(接口类.class),声明接口为一个远程借口。(默认为本地接口)。//此步骤可省略。
接口HelloWorld.java:
packagecom.qcd.ejb3;
publicinterfaceHelloWorld{
publicStringsayHello(Stringname);
}
实现类HelloWorldBean.java:
packagecom.qcd.ejb3.impl;
importjavax.ejb.Remote;
importjavax.ejb.Stateless;
importcom.qcd.ejb3.HelloWorld;
@Stateless//声明HelloWorldBean为一个无状态会话Bean。
@Remote(HelloWorld.class)//声明HelloWorld为一个远程借口,默认是本地借口
publicclassHelloWorldBeanimplementsHelloWorld{
@Override
publicStringsayHello(Stringname){
returnname+"says:helloworld!";
}
}
2.发布EJB
a.讲EJB打成Jar(可以使用Eclipse的export命令,导出Jar包。也可以用Ant生成Jar包。)
b.复制JAR到发布目录(JBoss默认启动模式是default,那么复制Jar到%JBoss_home%/server/default/deploy)
c.启动JBoss,JBoss会自动发现并部署EJB。(如果已经启动了JBoss,则JBoss可以热部署)。
3.调用EJB
Propertiesprops=newProperties();
props.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
props.put("java.naming.provider.url","localhost:1099");
try{
InitialContextic=newInitialContext(props);
HelloWorldhelloworld=(HelloWorld)ic.lookup("HelloWorldBean/remote");
System.out.println(helloworld.sayHello("张三"));
}catch(NamingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
java.naming.factory.initial:即Context.INITIAL_CONTEXT_FACTORY,制定JNDI连接工厂。
java.naming.provider.url:即Context.PROVIDER_URL,制定JNDI连接字符串。
调用服务器不同,连接工厂和连接字符串也不同。
Jboss的:
java.naming.factory.initial:org.jnp.interfaces.NamingContextFactory
java.naming.provider.url:localhost:1099
WebLogic的:
java.naming.factory.initial:org.weblogic.jndi.WLInitialContextFactory
java.naming.provider.url:t3://localhost:7001
客户端程序可以部署到另外的计算机上,只需要更改连接的服务器IP地址和启动JBoss绑定相应IP地址即可。
这正是EJB的远程调用特性。
上面代码中返回的HelloWorld对象并不是我们在服务器端编写的HelloWorldBean,而是一个实现了HelloWorld借口的代理对象。
这个代理对象最终调用我们的实现类HelloWorldBean.
helloworld.getClass().getName()可以得到此代理类的类名。
HelloWorldBean/remote:Jndi名称。
讲EJB应用打成Jar包后,默认的全局JNDI名称是:
本地接口:ejb-class-name/local;
远程接口:ejb-class-name/remote;
例如:讲HelloWorld应用打包成Jar,那么它的远程接口的JNDI名称是:HelloWorldBean/remote.
如果讲EJB打包成EAR,默认的全局JNDI名称为:
本地接口:ear-file-base-name/ejb-class-name/local;
远程接口:ear-file-base-name/ejb-class-name/remote;
如讲HelloWorld应用作为模块打包成EARHelloWorld.ear,它的远程接口为:HelloWorld/HelloWorldBean/remote。
除了硬编码制定Context环境外,还可以在类路径新建jndi.properties,讲配置信息写入jndi.properties。
在构造Context时,会自动在类路径查找jndi.properties,并将配置信息加载。
/src/jndi.properties:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
try{
InitialContextic=newInitialContext();
HelloWorldhelloworld=(HelloWorld)ic.lookup("HelloWorldBean/remote");
System.out.println(helloworld.sayHello("lisi"));
System.out.println(helloworld.getClass().getName());
}catch(NamingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
4.使用Ant提高工作效率
<?xmlversion="1.0"encoding="utf-8"?>
<projectbasedir="."name="HelloWorldEjb3">
<propertyname="src.dir"value="${basedir}/src">
</property>
<propertyenvironment="env">
</property>
<propertyname="jboss.home"value="${env.JBOSS_HOME}">
</property>
<propertyname="jboss.server.config"value="default">
</property>
<propertyname="build.dir"value="${basedir}/build">
</property>
<pathid="build.classpath">
<filesetdir="${jboss.home}/client">
<includename="*.jar"/>
</fileset>
<!--将build作为classpath的一部分。-->
<pathelementlocation="${build.dir}"/>
</path>
<targetname="prepare">
<deletedir="${build.dir}">
</delete>
<mkdirdir="${build.dir}"/>
</target>
<!--在编译Java文件之前,先创建文件夹build-->
<targetname="compile"depends="prepare">
<!--将编译后的class文件放到build目录-->
<javacsrcdir="${src.dir}"destdir="${build.dir}"includeantruntime="on">
<classpathrefid="build.classpath">
</classpath>
</javac>
</target>
<targetname="ejbjar"depends="compile"description="创建EJB发布包">
<jardestfile="${basedir}/${ant.project.name}.jar">
<filesetdir="${build.dir}">
<includename="**/*.class"/>
</fileset>
</jar>
</target>
<targetname="deploy"depends="ejbjar"description="发布EJB">
<copyfile="${basedir}/${ant.project.name}.jar"todir="${jboss.home}/server/${jboss.server.config}/deploy">
</copy>
</target>
<targetname="undeploy"description="卸载EJB">
<deletefile="${jboss.home}/server/${jboss.server.config}/deploy/${ant.project.name}.jar">
</delete>
</target>
</project>
在执行Ant任务时遇到2个问题:
1.warning:'includeantruntime'wasnotset,defaultingtobuild.sysclasspath=last;settofalseforrepeatablebuilds
解决办法:将
<javacsrcdir="${src.dir}"destdir="${build.dir}">
改为:
<javacsrcdir="${src.dir}"destdir="${build.dir}"includeantruntime="on">
2.Unabletofindajavaccompiler;
com.sun.tools.javac.Mainisnotontheclasspath.
PerhapsJAVA_HOMEdoesnotpointtotheJDK.
Itiscurrentlysetto"C:\ProgramFiles\Java\jre6"。
解决办法:将C:\ProgramFiles\Java\jdk1.6.0_22\lib\tools.jar复制到C:\ProgramFiles\Java\jre6\lib。
5.远程接口调用Ejb的过程
a.客户端与Ejb建立Socket通信
b.客户端与Ejb在通信管道上发送IIOP协议消息。
那么在此过程中,必然产生网络通信开销、协议解析开销、对象序列化开销等。
但是如果客户端与Ejb在同一机器的同一JVM内,那么它们完全可以通过内存交互,这样就避免了上面因网络通信产生的各种开销。
此时,就可以使用本地接口。
6.本地接口的开发
跟远程接口差不多,只需要将@remote改为@local即可。
调用的时候也不需要指明上下文环境信息。
HelloWorldBean.java:
packagecom.qcd.ejb3.impl;
importjavax.ejb.Local;
importjavax.ejb.Remote;
importjavax.ejb.Stateless;
importcom.qcd.ejb3.HelloWorld;
@Stateless//声明HelloWorldBean为一个无状态会话Bean。
//@Remote(HelloWorld.class)//声明HelloWorld为一个远程借口,默认是本地借口
@Local(HelloWorld.class)//指明为本地接口。
publicclassHelloWorldBeanimplementsHelloWorld{
@Override
publicStringsayHello(Stringname){
returnname+"says:helloworld!";
}
}
新建Web工程,进行测试
Test.jsp:
<import="com.qcd.ejb3.HelloWorld"%>
<import="javax.naming.NamingException"%>
<import="javax.naming.InitialContext"%>
<import="java.util.Properties"%>
<%@pagelanguage="java"contentType="text/html;charset=UTF-8"
pageEncoding="ISO-8859-1"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
<title>TestEjbLocalInterface</title>
</head>
<body>
<%
try{
InitialContextic=newInitialContext();
HelloWorldhelloworld=(HelloWorld)ic.lookup("HelloWorldBean/local");
out.println(helloworld.sayHello("lisi"));
System.out.println(helloworld.getClass().getName());
}catch(NamingExceptione){
//TODOAuto-generatedcatchblock
out.println(e.getLocalizedMessage());
}
%>
</body>
</html>
测试:
不需要将接口类放入Web的classpath,将ejb应用引入到web工程即可。
在实际开发中,会充分考虑到本地调用和远程调用的情况。
因此,一般会有一个远程接口,一个本地接口,本地接口继续远程接口。
实现类同时实现本地接口和远程接口的所有业务方法。
将本地接口类指明为本地接口,远程接口类指明为远程接口。
远程接口HelloWorld.java:
packagecom.qcd.ejb3;
publicinterfaceHelloWorld{
publicStringsayHello(Stringname);
}
本地接口HelloWorldLocal.java:
packagecom.qcd.ejb3;
publicinterfaceHelloWorldLocalextendsHelloWorld{
}
实现类HelloWorldBean.java:
packagecom.qcd.ejb3.impl;
importjavax.ejb.Local;
importjavax.ejb.Remote;
importjavax.ejb.Stateless;
importcom.qcd.ejb3.HelloWorld;
importcom.qcd.ejb3.HelloWorldLocal;
@Stateless//声明HelloWorldBean为一个无状态会话Bean。
@Remote(HelloWorld.class)//指明HelloWorld为远程接口
@Local(HelloWorldLocal.class)//指明HelloWorldLocal为本地接口。
publicclassHelloWorldBeanimplementsHelloWorld,HelloWorldLocal{
@Override
publicStringsayHello(Stringname){
returnname+"says:helloworld!";
}
}
这样的话,不管是本地调用还是远程调用都是OK的。
将JBossServer集成到Eclipse中,启动JBoss报如下错误:
原因是AttachmentStore初始化错误。
打开jboss-5.1.0.GA/server/default/conf/bootstrap下的profile.xml文件。
关于AttachmentStore的配置
<!--Theattachmentstore-->
<beanname="AttachmentStore"class="org.jboss.system.server.profileservice.repository.AbstractAttachmentStore">
<constructor><parameter><injectbean="BootstrapProfileFactory"property="attachmentStoreRoot"/></parameter></constructor>
改成
<!--Theattachmentstore-->
<beanname="AttachmentStore"class="org.jboss.system.server.profileservice.repository.AbstractAttachmentStore">
<constructor><parameterclass="java.io.File"><injectbean="BootstrapProfileFactory"property="attachmentStoreRoot"/></parameter></constructor>
启动JBoss时报如下错误:
[Naming]Couldnotstartonport1099
解决办法:
修改\server\default\conf\bindingservice.beans\META-INF\bindings-jboss-beans.xml
<!--NamingService-->
<beanclass="org.jboss.services.binding.ServiceBindingMetadata">
<propertyname="serviceName">jboss:service=Naming</property>
<propertyname="bindingName">Port</property>
<propertyname="port">1099</property>
<propertyname="description">ThelisteningsocketfortheNamingservice</property>
</bean>
j将端口1099修改为其他即可。
7.Ejb调用其他Ejb
我们再创建一个具有本地接口的无状态会话Bean。
在HelloWorldBean中调用这个Bean。
本地接口DateUtil.java:
packagecom.qcd.ejb3;
publicinterfaceDateUtil{
publicStringgetSystemTime();
}
本地接口实现类DateUtilBean.java:
packagecom.qcd.ejb3.impl;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjavax.ejb.Stateless;
importcom.qcd.ejb3.DateUtil;
@Stateless
publicclassDateUtilBeanimplementsDateUtil{
/**
*获取当前系统时间。
*/
publicStringgetSystemTime(){
//TODOAuto-generatedmethodstub
SimpleDateFormatsdf=newSimpleDateFormat("yyyy-mm-ddHH:MM:ss");
Datedate=newDate();
returnsdf.format(date);
}
}
HelloWorldBean.java:
packagecom.qcd.ejb3.impl;
importjavax.ejb.Local;
importjavax.ejb.Remote;
importjavax.ejb.Stateful;
importjavax.ejb.Stateless;
importjavax.naming.InitialContext;
importjavax.naming.NamingException;
importcom.qcd.ejb3.DateUtil;
importcom.qcd.ejb3.HelloWorld;
importcom.qcd.ejb3.HelloWorldLocal;
//在HelloWorldBean中调用DateUtilBean
//第一种方式,是使用jndi查找DateUtilBean.
//第二种房事,是使用依赖注入。
//@Stateless//声明HelloWorldBean为一个无状态会话Bean。
@Stateful
//@Remote(HelloWorld.class)//声明HelloWorld为一个远程借口,默认是本地借口
@Remote(HelloWorld.class)//指明HelloWorld为远程接口
@Local(HelloWorldLocal.class)//指明HelloWorldLocal为本地接口。
publicclassHelloWorldBeanimplementsHelloWorld,HelloWorldLocal{
@Override
publicStringsayHello(Stringname){
try{
InitialContextic=newInitialContext();
DateUtildu=(DateUtil)ic.lookup("/DateUtilBean/local");
Stringtime=du.getSystemTime();
returnname+"说:现在时间是:"+time;
}catch(NamingExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnnull;
}
}
用的是JNDI查找的方式。
第二种方式是使用依赖注入。
//使用依赖注入获取Bean
@EJB
privateDateUtildateUtil;
@Override
publicStringsayHello(Stringname){
Stringtime=dateUtil.getSystemTime();
returnname+"说:现在时间是:"+time;
}
使用@EJB,如果EJB发现有多个实现类时,EJB会报一个异常。
因此,在使用@EJB注解时,通过beanName指定EJB的名称。
如:
@EJB(beanName="DateUtilBean")
privateDateUtildu;
对于定时服务,数据源等,要使用@Resource注解。
相关推荐
### EJB3开发部署全过程详解 #### 一、EJB3简介及背景 EJB (Enterprise JavaBeans) 是Java平台为企业级应用提供的组件模型之一,主要用于构建可移植、健壮、可重用、多服务的应用程序。随着技术的发展,EJB3引入了...
【DORADO整合EJB3开发】 DORADO是一款由上海锐道公司研发的高性能、易用的展现层中间件,其特色在于采用AJAX技术,为开发者提供了一种高效且用户友好的前端开发框架。EJB3(Enterprise JavaBeans 3.0)则是Java EE...
**描述**提到这是“2008年最新EJB开发架构权威指南”,意味着它包含了最新的技术和最佳实践。 #### 二、EJB 3 的发展历程与特点 EJB 3 是Java企业级应用的重要组成部分之一,它是对EJB 2.x的重大改进。EJB 3 采用...
### Eclipse + JBoss 5 + EJB3 开发指南 #### (1):编写第一个无状态的SessionBean ##### 一、配置开发环境 在开始编写无状态的SessionBean之前,首先需要确保开发环境已经正确配置。以下是所需的主要组件: 1...
EJB3是Java EE(企业版)平台的一个重要组成部分,它极大地简化了企业级组件的开发和部署流程,减少了对XML配置的需求,并引入了更丰富的注解支持。 首先,我们来了解Eclipse,这是一个广泛使用的开源IDE,尤其适合...
### EJB3开发指南知识点概览 #### 一、EJB3体系结构简介 - **定义与背景**:EJB(Enterprise JavaBeans)是Java平台的一部分,用于开发和部署可重用的服务组件。EJB3引入了重大改进,简化了企业级应用的开发流程。 ...
EJB3是EJB规范的一个重要版本,它在EJB2的基础上进行了许多简化和改进,使得开发更加高效且易于理解。本文将深入探讨EJB3中的Entity Bean,它是EJB3中的持久化组件,用于代表数据库中的实体。 1. **实体Bean的概念*...
**EJB3 开发第一个无状态会话 Bean 知识详解** 无状态会话 Bean(Stateless Session Bean)是企业级 Java(EJB)3.0 中的核心组件,主要用于实现业务逻辑,它不保存任何特定客户端的状态信息。本篇文章将深入讲解...
"Mastering EJB3"和"Beginning EJB3 Application Development"都是深入讲解EJB3技术的专业书籍,涵盖了从基础概念到高级特性的全面内容,包含实例代码和实战指导,是学习和进阶EJB3开发的重要参考。 通过阅读这些...
### EJB3+JPA开发总结 #### 一、EJB3概述 EJB3 (Enterprise JavaBeans 3) 是Java EE平台上的一个重要组件,它主要用于构建企业级应用程序中的业务逻辑层。相比于早期版本,EJB3进行了大量改进,简化了许多开发流程...
**EJB 3 开发框架详解** EJB(Enterprise JavaBeans)是Java平台上的企业级组件模型,用于构建可扩展、安全且可靠的分布式应用程序。EJB3是EJB规范的一个重要版本,它在EJB2的基础上进行了重大改进,极大地简化了...
EJB3引入了许多重大的改进,使其变得更加轻量级,降低了开发复杂性,使得开发者能够更专注于业务逻辑而不是基础设施的实现。 **EJB3的主要特点包括:** 1. **注解驱动(Annotation-based)**:在EJB3中,开发者...
以示例的形式详细介绍了JSF、EJB的开发过程,是快速上手的最好教程!都是个人的总结(⊙o⊙)哦
3. **Eclipse 或 MyEclipse**:Eclipse是流行的Java集成开发环境,MyEclipse是其针对企业级开发的扩展,包含了更多的功能和插件,特别适合EJB3的开发。 【无状态Bean的开发步骤】 1. **创建EJB工程**:在Eclipse中...
EJB 3是其第三个主要版本,发布于2006年,它引入了许多重大改进,极大地简化了EJB的开发模式,降低了学习曲线,提高了开发效率。本实例源代码集就是针对EJB 3技术的实践应用展示。 EJB 3中的关键概念包括: 1. **...
EJB3(Enterprise JavaBeans 3)是EJB规范的一个版本,它大大简化了之前的版本,并引入了许多新特性,使开发人员能够更轻松地创建可扩展、健壮的企业应用。 - **轻量级:**EJB3采用了POJO(Plain Old Java Object)...
根据提供的文件信息,这里将详细解析与JSF(JavaServer Faces)+ EJB3(Enterprise JavaBeans 3)开发环境相关的知识点。 ### JSF + EJB3 开发环境搭建 #### 1. 软件准备 在搭建 JSF + EJB3 的开发环境中,需要...