- EJB到底是什么是这个
- 看完才知道Enterprise Java Bean,其实就是进一步封装了RMI的一个技术,让编程人员可以更专注于功能的实现而不是其连接。
- 引用原文中的一段话如下
通过RMI 技术,J2EE 将EJB 组件创建为远程对象,EJB 虽然用了RMI 技术,但是却只需要定义远程接口而无需生成他们的实现类,这样就将RMI 技术中的一些细节问题屏蔽了。但不管怎么说,EJB 的基础仍然是RMI,所以,如果你想了解EJB 的原理,只要把RMI的原理搞清楚就行了。你也就弄清楚了什么时候用EJB 什么时候不需要用EJB 了。
环境配置
- jdk
- eclipse
- wildfly(以前叫Jboss)
- 可以直接在eclipse的插件市场中下载
- Help -> Eclipse Markerplace , 搜素“JBoss”并install
- 不过这个还只是在eclipse开启wildfly服务的一个插件,真正的wildfly还要再下载
- Window -> Show View -> Other里面找到Server文件夹下的Servers,打开Servers窗口
- Servers窗口里右键New->Server,建立一个新的服务器,比如选择WildFly 8.X
- 然后Next -> Next,然后就既不能Next也不能Finish了,因为你还没有装wildfly,此时页面里的Home Directory是空的,其右上角有个链接Download and install runtime,通过这个链接可以直接下载安装wildfly。
- 装好wildfly后就可以顺利的新建server了。
关于wildfly
- 我们写的EJB项目是要发布在一个ejb container里作为服务端程序运行
- wildfly是一个ejb container
- wildfly同时也是一个web container,可以发布web服务,也就是网页
- EJB基于RMI,可以用来做分布式计算,因为调用的是服务端的方法,网络上只传输参数和结果
wildfly上发布ejb项目
- eclipse中建立EJB项目
- 在eclipse的插件市场里装好JBoss后,就可以直接建立EJB项目了
- File -> New -> Other -> EJB -> EJB Project
- 手动发布EJB项目
- 假设正在编辑的EJB项目名为EJB
- 首先右键项目,Export -> EJB EJB JAR files,生成一个名为EJB.jar的文件
- 指定Destination,则可以在桌面看到生成的EJB.jar
- 将这个EJB.jar文件放到“wildfly根目录/standalone/deployments”文件夹下
- 运行“wildfly根目录/standalone/add-user.bat”来添加用户,根据提示操作即可
- 运行“wildfly根目录/standalone/standalone.bat”即可以启动wildfly,其自动检测“wildfly根目录/standalone/deployments”目录下的jar文件并发布。
- ejb程序这就开始运行了,其运行的输出结果也会显示在这个命令行界面上
- 直接在eclipse里运行EJB Project
- 右键项目Run as -> Run on server
- 选择刚刚安装好的wildfly服务器
- OK这就运行了,输出会显示在eclipse里的Console里,没有这个窗口就Window->Show View里去打开
Hello EJB
- 惯例写一个Hello程序来体验学习
- 整个结构如下
Server端HelloEJB项目
- 项目建立参照前文eclipse中建立EJB项目
- server包
- IHello接口
- HelloBean类实现了IHello接口
//IHello.java
package server;
public interface IHello {
String say();
}
//Hello.java
package server;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote(IHello.class)
public class HelloBean implements IHello{
@Override
public String say() {
return "Hello EJB";
}
}
- server端就这么点东西
client端HelloEJBClient项目
- 这是建立的一个普通的java project
- src目录下client包,一个client.java,代码具体后面内容再说
//client.java
package client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import server.IHello;
public class client {
public static void main(String[] args) {
try {
java.util.Properties p = new java.util.Properties();
p.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context context = new InitialContext(p);//NamingException
IHello obj = (IHello) context.lookup("ejb:/HelloEJB/HelloBean!" + IHello.class.getName());
String str = obj.say();
System.out.println(str);
} catch (NamingException e) {
e.printStackTrace();
}
}
}
- 因为需要用到HelloEJB项目里的server包下的IHello接口,所以
把HelloEJB项目添加到HelloEJBClient的build path里
- 右键HelloEJBClient项目 -> Build Path -> Configure Build Path
- 找到Projects标签卡,Add里选中HelloEJB项目
- 配置client端的属性
- src目录下右键New->Other->General->File
- 文件名为“jboss-ejb-client.properties”,eclipse会识别.properties
这个后缀,即配置文件 - 保证该文件位于src目录下
- 添加如下内容
- 添加client端依赖的jboss包,方法简而言之就是根据console的错误提示,缺失哪个包就到wildfly里面去找
- 那么前提就是要运行client端来输出错误信息
- 右键HelloEJB项目,Run As -> Run on Server启动服务端
- 右键client.java,Run As -> Java Application
- 最终确定下HelloEJBClient项目所需要的数目最少的包为下面这几个
- 均位于“wildfly-8.2.1.Final\modules\system\layers\base\org\jboss”目录下
client端代码
java.util.Properties p = new java.util.Properties();
p.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context context = new InitialContext(p);
- 获取一个上下文Context
- 那么什么是上下文呢,我也不知道
IHello obj = (IHello) context.lookup("ejb:/HelloEJB/HelloBean!" + IHello.class.getName());
- 通过JDNI来获取远程对象
- 关于lookup的参数格式,以stateful为例
// The JNDI lookup name for a stateful session bean has the syntax of:
// ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful
//
// <appName> The application name is the name of the EAR that the EJB is deployed in
// (without the .ear). If the EJB JAR is not deployed in an EAR then this is
// blank. The app name can also be specified in the EAR's application.xml
//
// <moduleName> By the default the module name is the name of the EJB JAR file (without the
// .jar suffix). The module name might be overridden in the ejb-jar.xml
//
// <distinctName> : WildFly allows each deployment to have an (optional) distinct name.
// This example does not use this so leave it blank.
//
// <beanName> : The name of the session been to be invoked.
//
// <viewClassName>: The fully qualified classname of the remote interface. Must include
// the whole package name.
- 至于stateless,就不加最后的“?stateful”即可
关于stateful和stateless的javabean的区别,不赘述了
其实通过server端启动的输出信息也可以看到发布的ejb的jndi
String str = obj.say();
System.out.println(str);
- 通过IHello接口调用远程对象方法,获得返回信息str并输出到console
- 注意在say()这个方法的实现里,即Hello.java里的这个方法的实现里的System.out.println()是会输出到server端的标准输出的,也就是server端启动时输出了一堆启动信息的那个控制台上
运行client端
- 前提:server已上线
EJB探索未解之谜
- 为什么eclipse在手动export引用了第三方类库(比如jdbc)的EJB Project的时候,并不会把我引用的类库也发布到生成的jar里面呢
- 为什么我设置了EJB Project项目的Deploment Assembly(右键项目Properities),将我引用的第三方类库添加到了export里,还是看不到第三方类库的发布呢,相反仅仅在配置文件MANIFEST.MF的Class-Path里看到了类库的名字。坑爹呢!
- 而我按照这个教程去修改了发布的EJB.jar包,结果毫无作用。。。。。。好气啊
- 而我如果想让wildfly在启动的时候直接添加某个第三方类库又应该
如何配置wildfly呢?tomcat可以直接放在lib目录下,可毕竟是tomcat是个web container,不同于我所需求的EJB项目
一个超笨的方法
- 目前我有个需求,需要让server端的bean来访问数据库,通过jdbc来访问sql server。无第三方类库的EJB测试通过,唯独调用jdbc来连接sql server的时候报错
- client报错
server报错
仔细看了看报的错
- client端报空指针
- 也就是说我没能拿到与数据库连接的connection,于是写个输出测试一下(DB跑由Bean调用在server端,输出也在server)
- server端并没有输出这两句的任何一句,相反让我找到了这个
- 好气啊,为什么找不到呢,我明明在eclipse里的build path添加了啊
- 后来经过前文的尝试毫无作用,于是直接把我所需要的第三方类sqljdbc42.jar解压,com和microsoft两个文件夹直接添加到了EJB Project里,反正里面就是我需要的.class文件呗
- 再发布果然运行成功