Ejb3开发
来源:互联网 发布:桥接模式java类图 编辑:程序博客网 时间:2024/05/19 01:14
1.开发无状态会话Bean的步骤。
a.开发接口类,并提供业务方法。
b.开发实现类,并实现业务方法。
c.使用@Stateless注解,声明实现类是一个无状态会话Bean。
4.使用@Remote(接口类.class),声明接口为一个远程借口。(默认为本地接口)。//此步骤可省略。
接口HelloWorld.java:
package com.qcd.ejb3;
public interface HelloWorld {
public String sayHello(String name);
}
实现类HelloWorldBean.java:
package com.qcd.ejb3.impl;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import com.qcd.ejb3.HelloWorld;
@Stateless//声明HelloWorldBean为一个无状态会话Bean。
@Remote(HelloWorld.class)// 声明HelloWorld为一个远程借口,默认是本地借口
public class HelloWorldBean implements HelloWorld {
@Override
public String sayHello(String name) {
return name + " says:hello world!";
}
}
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
Properties props = new Properties();
props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
props.put("java.naming.provider.url", "localhost:1099");
try {
InitialContext ic = new InitialContext(props);
HelloWorld helloworld = (HelloWorld)ic.lookup("HelloWorldBean/remote");
System.out.println(helloworld.sayHello("张三"));
} catch (NamingException e) {
// TODO Auto-generated catch block
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应用作为模块打包成EAR HelloWorld.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 {
InitialContext ic = new InitialContext();
HelloWorld helloworld = (HelloWorld)ic.lookup("HelloWorldBean/remote");
System.out.println(helloworld.sayHello("lisi"));
System.out.println(helloworld.getClass().getName());
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
4.使用Ant提高工作效率
<?xml version="1.0" encoding="utf-8"?>
<project basedir="." name="HelloWorldEjb3">
<property name="src.dir" value="${basedir}/src">
</property>
<property environment="env">
</property>
<property name="jboss.home" value="${env.JBOSS_HOME}">
</property>
<property name="jboss.server.config" value="default">
</property>
<property name="build.dir" value="${basedir}/build">
</property>
<path id="build.classpath">
<fileset dir="${jboss.home}/client">
<include name="*.jar" />
</fileset>
<!--将build作为classpath的一部分。-->
<pathelement location="${build.dir}" />
</path>
<target name="prepare">
<delete dir="${build.dir}">
</delete>
<mkdir dir="${build.dir}" />
</target>
<!--在编译Java文件之前,先创建文件夹build-->
<target name="compile" depends="prepare">
<!--将编译后的class文件放到build目录-->
<javac srcdir="${src.dir}" destdir="${build.dir}" includeantruntime="on">
<classpath refid="build.classpath">
</classpath>
</javac>
</target>
<target name="ejbjar" depends="compile" description="创建EJB发布包">
<jar destfile="${basedir}/${ant.project.name}.jar">
<fileset dir="${build.dir}">
<include name="**/*.class" />
</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">
</copy>
</target>
<target name="undeploy" description="卸载EJB">
<delete file="${jboss.home}/server/${jboss.server.config}/deploy/${ant.project.name}.jar">
</delete>
</target>
</project>
在执行Ant任务时遇到2个问题:
1.warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
解决办法:将
<javac srcdir="${src.dir}" destdir="${build.dir}">
改为:
<javac srcdir="${src.dir}" destdir="${build.dir}" includeantruntime="on">
2.Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to "C:\Program Files\Java\jre6"。
解决办法:将C:\Program Files\Java\jdk1.6.0_22\lib\tools.jar复制到C:\Program Files\Java\jre6\lib。
5.远程接口调用Ejb的过程
a.客户端与Ejb建立Socket通信
b.客户端与Ejb在通信管道上发送IIOP协议消息。
那么在此过程中,必然产生网络通信开销、协议解析开销、对象序列化开销等。
但是如果客户端与Ejb在同一机器的同一JVM内,那么它们完全可以通过内存交互,这样就避免了上面因网络通信产生的各种开销。
此时,就可以使用本地接口。
6.本地接口的开发
跟远程接口差不多,只需要将@remote改为@local即可。
调用的时候也不需要指明上下文环境信息。
HelloWorldBean.java:
package com.qcd.ejb3.impl;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import com.qcd.ejb3.HelloWorld;
@Stateless//声明HelloWorldBean为一个无状态会话Bean。
//@Remote(HelloWorld.class)//声明HelloWorld为一个远程借口,默认是本地借口
@Local(HelloWorld.class) // 指明为本地接口。
public class HelloWorldBean implements HelloWorld {
@Override
public String sayHello(String name) {
return name + " says:hello world!";
}
}
新建Web工程,进行测试
Test.jsp:
<import="com.qcd.ejb3.HelloWorld"%>
<import="javax.naming.NamingException"%>
<import="javax.naming.InitialContext"%>
<import="java.util.Properties"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Ejb Local Interface</title>
</head>
<body>
<%
try {
InitialContext ic = new InitialContext();
HelloWorld helloworld = (HelloWorld)ic.lookup("HelloWorldBean/local");
out.println(helloworld.sayHello("lisi"));
System.out.println(helloworld.getClass().getName());
} catch (NamingException e) {
// TODO Auto-generated catch block
out.println(e.getLocalizedMessage());
}
%>
</body>
</html>
测试:
不需要将接口类放入Web的classpath,将ejb应用引入到web工程即可。
在实际开发中,会充分考虑到本地调用和远程调用的情况。
因此,一般会有一个远程接口,一个本地接口,本地接口继续远程接口。
实现类同时实现本地接口和远程接口的所有业务方法。
将本地接口类指明为本地接口,远程接口类指明为远程接口。
远程接口HelloWorld.java:
package com.qcd.ejb3;
public interface HelloWorld {
public String sayHello(String name);
}
本地接口HelloWorldLocal.java:
package com.qcd.ejb3;
public interface HelloWorldLocal extends HelloWorld{
}
实现类HelloWorldBean.java:
package com.qcd.ejb3.impl;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import com.qcd.ejb3.HelloWorld;
import com.qcd.ejb3.HelloWorldLocal;
@Stateless//声明HelloWorldBean为一个无状态会话Bean。
@Remote(HelloWorld.class) // 指明HelloWorld为远程接口
@Local(HelloWorldLocal.class) // 指明HelloWorldLocal为本地接口。
public class HelloWorldBean implements HelloWorld,HelloWorldLocal {
@Override
public String sayHello(String name) {
return name + " says:hello world!";
}
}
这样的话,不管是本地调用还是远程调用都是OK的。
将JBoss Server集成到Eclipse中,启动JBoss报如下错误:
原因是AttachmentStore初始化错误。
打开jboss-5.1.0.GA/server/default/conf/bootstrap下的profile.xml文件。
关于AttachmentStore的配置
<!-- The attachment store -->
<bean name="AttachmentStore" class="org.jboss.system.server.profileservice.repository.AbstractAttachmentStore">
<constructor><parameter><inject bean="BootstrapProfileFactory" property="attachmentStoreRoot" /></parameter></constructor>
改成
<!-- The attachment store -->
<bean name="AttachmentStore" class="org.jboss.system.server.profileservice.repository.AbstractAttachmentStore">
<constructor><parameter class="java.io.File"><inject bean="BootstrapProfileFactory" property="attachmentStoreRoot" /></parameter></constructor>
启动JBoss时报如下错误:
[Naming] Could not start on port 1099
解决办法:
修改\server\default\conf\bindingservice.beans\META-INF\bindings-jboss-beans.xml
<!-- Naming Service -->
<bean class="org.jboss.services.binding.ServiceBindingMetadata">
<property name="serviceName">jboss:service=Naming</property>
<property name="bindingName">Port</property>
<property name="port">1099</property>
<property name="description">The listening socket for the Naming service</property>
</bean>
j将端口1099修改为其他即可。
7.Ejb调用其他Ejb
我们再创建一个具有本地接口的无状态会话Bean。
在HelloWorldBean中调用这个Bean。
本地接口DateUtil.java:
package com.qcd.ejb3;
public interface DateUtil {
public String getSystemTime() ;
}
本地接口实现类DateUtilBean.java:
package com.qcd.ejb3.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ejb.Stateless;
import com.qcd.ejb3.DateUtil;
@Stateless
public class DateUtilBean implements DateUtil {
/**
* 获取当前系统时间。
*/
public String getSystemTime() {
// TODO Auto-generated method stub
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:MM:ss");
Date date = new Date();
return sdf.format(date);
}
}
HelloWorldBean.java:
package com.qcd.ejb3.impl;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.qcd.ejb3.DateUtil;
import com.qcd.ejb3.HelloWorld;
import com.qcd.ejb3.HelloWorldLocal;
// 在HelloWorldBean中调用DateUtilBean
// 第一种方式,是使用jndi查找DateUtilBean.
// 第二种房事,是使用依赖注入。
//@Stateless//声明HelloWorldBean为一个无状态会话Bean。
@Stateful
//@Remote(HelloWorld.class)//声明HelloWorld为一个远程借口,默认是本地借口
@Remote(HelloWorld.class) // 指明HelloWorld为远程接口
@Local(HelloWorldLocal.class) // 指明HelloWorldLocal为本地接口。
public class HelloWorldBean implements HelloWorld,HelloWorldLocal {
@Override
public String sayHello(String name) {
try {
InitialContext ic = new InitialContext();
DateUtil du = (DateUtil) ic.lookup("/DateUtilBean/local");
String time = du.getSystemTime();
return name + "说:现在时间是:" + time;
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
用的是JNDI查找的方式。
第二种方式是使用依赖注入。
// 使用依赖注入获取Bean
@EJB
private DateUtil dateUtil;
@Override
public String sayHello(String name) {
String time = dateUtil.getSystemTime();
return name + "说:现在时间是:" + time;
}
使用@EJB,如果EJB发现有多个实现类时,EJB会报一个异常。
因此,在使用@EJB注解时,通过beanName指定EJB的名称。
如:
@EJB(beanName="DateUtilBean")
private DateUtil du;
对于定时服务,数据源等,要使用@Resource注解。
- Ejb3开发
- EJB3.0开发指南
- EJB3.0开发工具
- Ejb3.0开发指南
- weblogic10+eclipse 开发ejb3
- ejb3实例开发
- Myeclipse + Jboss开发EJB3
- EJB3.0开发环境
- Eclipse开发EJB3
- Eclipse开发EJB3
- JBOSS+EJB3+MYSQL开发
- 使用NetWeaver开发EJB3.0
- MyEclipse+JBoss开发EJB3.0
- 开始EJB3应用程序的开发
- Eclipse开发EJB3 - EclipseLink属性
- Myeclipse+JBoss开发EJB3.0
- MyEclipse+JBoss开发EJB3.0
- Weblogic EJB3开发及常见问题
- 服务器端编程之如何开发IDispatch接口的实现类
- 十年MFC经历认识的Microsoft技术
- 表格中的上移和下移
- Sudoku Solver
- Linux串口(serial、uart)驱动程序设计
- Ejb3开发
- Ubuntu Nvidia 显卡 双屏显示设置
- file、inode在应用层和驱动层之间的联系
- ubuntu下c/c++开发环境配置
- 由于为列"***"指定了多个代码页(936和1252),无法处理此列 .
- A+B
- 代码间相互作用和正则表达式
- 2013年急需的十大热门 IT 技能
- 数组和哈希的数值排序问题(sort)