1. 编写接口
参考官网案例,定义一个接口 RemoteCalculator 远程计算器,可以实现加法与减法。
public interface RemoteCalculator {
int add(int a, int b);
int subtract(int a, int b);
}
定义 RemoteCalculator 的实现类,并进行了 @Stateless 无状态注解,@Remote 远程接口注解。
@Stateless
@Remote(RemoteCalculator.class)
public class CalculatorBean implements RemoteCalculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
}
以上都做完之后,打包成 JAR 文件部署到 JBoss 中
2. 编写客户端程序
public class RemoteEJBClient {
public static void main(String[] args) throws Exception {
invokeStatelessBean();
}
private static void invokeStatelessBean() throws NamingException {
final RemoteCalculator calculator = lookupRemoteStatelessCalculator();
System.out.println("3 + 6 = " + calculator.add(3, 6));
}
private static RemoteCalculator lookupRemoteStatelessCalculator() throws NamingException {
final Hashtable<String, Object> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
final String appName = "";
final String moduleName = "ejb-0113"; // 此处 jar 包为 ejb-0113.jar
final String distinctName = "";
final String beanName = CalculatorBean.class.getSimpleName();
final String viewClassName = RemoteCalculator.class.getName();
return (RemoteCalculator) context.lookup(
"ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
}
}
从 lookupRemoteStatelessCalculator方法可以看出,如果想找到一个 Bean,需要一定格式的 JNDI 命名,这个格式针对无状态 Bean 和有状态 Bean 有所不同,但区别不大。
对于无状态 Bean,格式为:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
对于有状态 Bean ,只是在无状态 Bean 格式后面加上了 ?stateful,即 JNDI 在接口的全限定类名后面跟上 ?stateful:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>?stateful
app-name 应用名称
一般地,是部署 EJB 的 .ear 文件名。
但是,Java EE 6 允许通过 application.xml 设置新的应用名称。
如果 EJB 部署在 war 或者 jar 中,非 .ear 文件,查找时,应用程序名称必须为空字符串。
moduleName EJB 的模块名。
典型的就是,JAR 文件名。
但是,通过部署 ejb-jar.xml 或 web.xml 可以设置,Java EE 6 允许覆盖模块名称。
模块名称不能为空字符串。
distinctName,AS7 允许每个部署有一个唯一确定的名字(可选的)。
bean-name bean 名称
通常是 Bean 实现类的非限定类名。
但是,可以通过 ejb-jar.xml 或者注解覆盖。
bean-name 不能空字符串。
fully-qualified-classname-of-the-remote-interface,远程接口的全限定类名
这是查找的接口的全限定类名。
不能是空字符串。
客户端代码
final Hashtable<String, Object> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
在这里,我们通过向 InitialContext 传递一些属性(Properties)来实例化它。Context.URL_PKG_PREFIXES 设置为 org.jboss.ejb.client.naming,这是必须的。
除了通过构造函数传递属性,也可以在客户端应用程序的类路径(classpath)添加 jndi.properties,该文件至少包含以下属性:
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming