全球第一款网络点验钞机诞生在浙江温州 ,点钞机/网络点钞机,通过客户端维融金网卫士连接网络,云存储数据和网络验钞
1.重点关注
EJB3的基础开发,其中最为重要的几点是:
1.接口与Bean类的开发;
2.注释的使用;
3.JNDI的定义;
4.访问EJB;
2.无状态会话Bean
2.1 实现远程接口。
创建接口。
文件地址:[EJB3/JavaSource/com/mh/ejb3/test/EJB3Test.java]
包:[com.mh.ejb3.test]
名称:[EJB3Test]
内容如下: -----------------------------------------------------------------------
package com.mh.ejb3.test;
public interface EJB3Test {
public String sayTest();
}
-----------------------------------------------------------------------
是不是觉得这也太简单了,是的,这就是EJB3!
创建Bean类。
文件地址:[EJB3/JavaSource/com/mh/ejb3/test/EJB3TestBean.java]
包:[com.mh.ejb3.test]
名称:[EJB3TestBean]
Bean类型:[无状态会话Bean]
实现接口:[远程接口]
内容如下: -----------------------------------------------------------------------
package com.mh.ejb3.test;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless(mappedName = "EJB3TestBean")
@Remote(EJB3Test.class)
public class EJB3TestBean implements EJB3Test {
public String sayTest() {
String strResult = "EJB3,无状态会话Bean,实现远程接口!";
// 返回函数值
return strResult;
}
}
-----------------------------------------------------------------------
其实我觉得,做程序开发是需要激情的,如果你不爱好它,你会觉得它是一项繁重的工作。简洁的开发,会让程序员乐趣无穷,这就是EJB3的特点!
[@Stateless(mappedName = "EJB3TestBean")]:Bean类映射的名称,它决定了你访问它的JNDI是:[EJB3TestBean#com.mh.ejb3.test.EJB3Test],#后面是接口的全称。如果你想查看你的JNDI,可以在[控制中心]中查看服务器的JNDI树,在《Hello world》中有讲到。
[@Remote(EJB3Test.class)]:表示实现了远程接口,接口是:[EJB3Test.class]。有了这段,你下面的部分可以写成[public class EJB3TestBean implements EJB3Test],也是可以的。但最好不要这样写,这样写不好。
到这里,这个名叫[EJB3Test]的EJB,我们就做完了,接下来,我们要调用这个EJB了。
修改文件[WebContext/JavaSource/com/mh/servlet/test/CommonSV.java]
-----------------------------------------------------------------------
package com.mh.servlet.test;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mh.ejb3.test.EJB3Test;
import com.mh.ejb3.test.HelloWorldLocal;
public class CommonSV extends HttpServlet {
@Override
public void init() throws ServletException {
// TODO 自动生成方法存根
super.init();
}
@Override
public void destroy() {
// TODO 自动生成方法存根
super.destroy();
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doWork(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doWork(request, response);
}
/**
* @描述:公共处理方法
*
* @param strJNDI
* @return
* @throws Excep
*/
private void doWork(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取输出对象
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8"); // 设置输出编码
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 结果值
String message = "Test:<br><hr size='1'>";
try {
// 获取参数
String strPara = (String) request.getParameter("dowith");
// 处理运行
if (strPara != null && strPara.equals("HelloworldLocal")) {
// 通过JNDI获取对象
HelloWorldLocal helloLocal = (HelloWorldLocal) getEJBObject("java:comp/env/HelloWorldLocalBean");
message += helloLocal.sayHello();
/*---------------------- 这里是新加的 ----------------------------*/
} else if (strPara != null && strPara.equals("EJB3Test")) {
// 通过JNDI获取EJB对象
EJB3Test test = (EJB3Test) getEJBObject("EJB3TestBean#com.mh.ejb3.test.EJB3Test");
message += test.sayTest();
/*---------------------- 这里是新加的 ----------------------------*/
}
} catch (Exception e) {
e.printStackTrace();
message += e.toString();
} finally {
}
// 输出
out.print(message);
out.flush();
out.close();
}
/**
* @功能 获取EJB对象
*
* @param strJNDI
* @return
* @throws Exception
*/
private Object getEJBObject(String strJNDI) throws Exception {
// 创建属性对象
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.setProperty(Context.PROVIDER_URL, "t3://localhost:7001");
// 创建上下文环境对象
InitialContext ctx;
ctx = new InitialContext(props);
// 本地接口
Object oEJB = ctx.lookup(strJNDI);
// 返回函数值
return oEJB;
}
}
-----------------------------------------------------------------------
上面新加部分的JNDI[EJB3TestBean#com.mh.ejb3.test.EJB3Test]的解释,之前已经讲过原理了,这里就不多说了。
修改欢迎页面[WebContext/index.jsp]。
-----------------------------------------------------------------------
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>EJB3测试</title>
</head>
<body>
<p>
<center><a href="http://localhost:7001/console/" target="_blank">weblogic控制</a></center>
</p>
<hr size="1">
<p>
<center><a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=HelloworldLocal" target="_blank">EJB3测试:本地会话Bean</a></center>
</p>
<!-- -------------------------- 这里是新加的 --------------------------------- -->
<p>
<center><a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=EJB3Test" target="_blank">EJB3测试:无状态会话Bean远程接口</a></center>
</p>
<!-- -------------------------- 这里是新加的 --------------------------------- -->
</body>
</html>
-----------------------------------------------------------------------
做完这些,你就可以使用[build.xml]来编译发布程序了!等一会后你可以打开[http://localhost:7001/ejb3test/],看到你预想到的结果!一切就是这么容易!
2.2 实现本地接口
创建接口。
文件地址:[EJB3/JavaSource/com/mh/ejb3/test/EJB3TestLocal.java]
包:[com.mh.ejb3.test]
名称:[EJB3TestLocal]
内容如下: -----------------------------------------------------------------------
/**
*
*/
package com.mh.ejb3.test;
/**
* @author moshco zhu
*
*/
public interface EJB3TestLocal {
public String sayTest();
}
-----------------------------------------------------------------------
创建Bean类。
文件地址:[EJB3/JavaSource/com/mh/ejb3/test/EJB3TestLocalBean.java]
包:[com.mh.ejb3.test]
名称:[EJB3TestLocalBean]
EJB类型:[无状态会话Bean]
实现接口:[本地接口]
内容如下:
-----------------------------------------------------------------------
/**
*
*/
package com.mh.ejb3.test;
import javax.ejb.Local;
import javax.ejb.Stateless;
/**
* @author moshco zhu
*
*/
@Stateless
@Local(EJB3TestLocal.class)
public class EJB3TestLocalBean implements EJB3TestLocal {
/*
* (非 Javadoc)
*
* @see com.mh.ejb3.test.EJB3TestLocal#sayTest()
*/
public String sayTest() {
String strResult = "EJB3,无状态会话Bean,实现本地接口!";
// 返回函数值
return strResult;
}
}
-----------------------------------------------------------------------
其实,EJB最初设计时,是没有本地接口的,后来,发现这是一个缺陷,因此加上了,但实际上从中间件分布式应用的角度讲,本地接口的意义是不存在的。EJB的应用本就不应该只是做些小型的开发,它的目标应该是让客户使用最少的硬件成本,弄出一个无限膨胀的业务系统!满足客户一个简单的需求:“我需要什么,它就能帮我做到什么!”
那些还在使用价格100万人民币的服务器,装一个web服务的时代早就应该结束了!呵呵!
到这里为止,我们已经开发出了一个实现本地接口的EJB,在《Hello,world》中已经讲了如何使用servlet访问本地无状态会话Bean,这里就不想重复了,现在我们使用一种叫做[依赖注入]的方式来调用这个本地会话Bean,讲到这里,有两点需要强调:
1.依赖注入,是java一种创建Java对象的概念,说简单点就是要创建一个对象,使用了这种方式;其实我很讨厌使用一些披着华丽的名词而又晦涩难懂的东西!
2.想要访问只实现本地接口的EJB,条件是:必须在同一个运行的应用服务器中,才有可能,而且不同的应用服务器,采用的方式还不一样!weblogic ejb3只有两种方式:第一是同一容器的其它EJB访问(依赖注入的方式;或在配置文件中定义引用,再使用JNDI访问。);第二种是同一服务器的servlet中,先在配置文件中定义引用,再在servlet中使用JNDI访问。除此以外再没有其它可能。
下面我们实现上面说的[依赖注入]的访问方式。
创建一个接口。
文件地址:[EJB3/JavaSource/com/mh/ejb3/test/UseLocalEJB.java]
包:[com.mh.ejb3.test]
名称:[UseLocalEJB]
内容如下: -----------------------------------------------------------------------
/**
*
*/
package com.mh.ejb3.test;
/**
* @author moshco zhu
*
*/
public interface UseLocalEJB {
public String sayTest();
}
-----------------------------------------------------------------------
创建Bean类。
文件地址:[EJB3/JavaSource/com/mh/ejb3/test/UseLocalEJBBean.java]
包:[com.mh.ejb3.test]
名称:[UseLocalEJB]
EJB类型:[无状态会话Bean]
实现接口:[远程接口]
内容如下:
-----------------------------------------------------------------------
/**
*
*/
package com.mh.ejb3.test;
import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;
/**
* @author moshco zhu
*
*/
@Stateless(mappedName = "UseLocalEJBBean")
@Remote(UseLocalEJB.class)
public class UseLocalEJBBean implements UseLocalEJB {
/**
* 这里使用了依赖注入的方式访问本地会话Bean[EJB3TestLocal],需要注意的是,
* [EJB3TestLocal]这个EJB必须和当前会话Bean在同一个容器中才能这样使用。
*/
@EJB
private EJB3TestLocal ejb3Test;
/*
* (非 Javadoc)
*
* @see com.mh.ejb3.test.UserLocalEJB#sayTest()
*/
public String sayTest() {
String strResult = "EJB3,使用依赖注入的方式,远程接口的EJB使用了实现本地接口的EJB[EJB3TestLocal]!/n<br>";
if (ejb3Test != null) {
strResult += ejb3Test.sayTest();
}
// 返回函数值
return strResult;
}
}
-----------------------------------------------------------------------
[@EJB private EJB3TestLocal ejb3Test;],EJB容器会在第一次访问这个变量时,容器会根据变量的类型[EJB3TestLocal]创建一个EJB对象给它。容器是不是太厉害了,了不起!
到这里,我们创建了两个EJB,一个是实现本地接口的EJB[EJB3TestLocal],它是被调用者;一个是实现远程接口的EJB[UseLocalEJB],调用了实现本地接口的EJB;接下来,我们使用servlet来用JNDI的方式调用这个实现远程接口的EJB。
修改文件[WebContext/JavaSource/com/mh/servlet/test/CommonSV.java]。
-----------------------------------------------------------------------
package com.mh.servlet.test;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mh.ejb3.test.EJB3Test;
import com.mh.ejb3.test.HelloWorldLocal;
import com.mh.ejb3.test.UseLocalEJB;
public class CommonSV extends HttpServlet {
@Override
public void init() throws ServletException {
// TODO 自动生成方法存根
super.init();
}
@Override
public void destroy() {
// TODO 自动生成方法存根
super.destroy();
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doWork(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doWork(request, response);
}
/**
* @描述:公共处理方法
*
* @param strJNDI
* @return
* @throws Excep
*/
private void doWork(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取输出对象
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8"); // 设置输出编码
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 结果值
String message = "Test:<br><hr size='1'>";
try {
// 获取参数
String strPara = (String) request.getParameter("dowith");
// 处理运行
if (strPara != null && strPara.equals("HelloworldLocal")) {
// 通过JNDI获取对象
HelloWorldLocal helloLocal = (HelloWorldLocal) getEJBObject("java:comp/env/HelloWorldLocalBean");
message += helloLocal.sayHello();
} else if (strPara != null && strPara.equals("EJB3Test")) {
// 通过JNDI获取EJB对象
EJB3Test test = (EJB3Test) getEJBObject("EJB3TestBean#com.mh.ejb3.test.EJB3Test");
message += test.sayTest();
/* --------------------- 这里是新加的部分 ------------------------- */
} else if (strPara != null && strPara.equals("UseLocalEJB")) {
// 通过JNDI获取EJB对象
UseLocalEJB test = (UseLocalEJB) getEJBObject("UseLocalEJBBean#com.mh.ejb3.test.UseLocalEJB");
message += test.sayTest();
/* --------------------- 这里是新加的部分 ------------------------- */
}
} catch (Exception e) {
e.printStackTrace();
message += e.toString();
} finally {
}
// 输出
out.print(message);
out.flush();
out.close();
}
/**
* @功能 获取EJB对象
*
* @param strJNDI
* @return
* @throws Exception
*/
private Object getEJBObject(String strJNDI) throws Exception {
// 创建属性对象
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.setProperty(Context.PROVIDER_URL, "t3://localhost:7001");
// 创建上下文环境对象
InitialContext ctx;
ctx = new InitialContext(props);
// 本地接口
Object oEJB = ctx.lookup(strJNDI);
// 返回函数值
return oEJB;
}
}
-----------------------------------------------------------------------
还记得访问实现远程接口EJB的方式吗?
[UseLocalEJBBean#com.mh.ejb3.test.UseLocalEJB],[UseLocalEJBBean]是你在EJB中使用注释定义的映射名称,就是这一部分[@Stateless(mappedName = "UseLocalEJBBean")],如果你不写[(mappedName = "UseLocalEJBBean")],那么它的默认名称应该是Bean类的名称,就是[UseLocalEJBBean]。
[com.mh.ejb3.test.UseLocalEJB]是EJB的接口[com.mh.ejb3.test.UseLocalEJB]。
接下来在[WebContext/index.jsp]中添加一个访问servlet的连接。
-----------------------------------------------------------------------
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>EJB3测试</title>
</head>
<body>
<p>
<center><a href="http://localhost:7001/console/" target="_blank">weblogic控制</a></center>
</p>
<hr size="1">
<p>
<center><a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=HelloworldLocal" target="_blank">EJB3测试:本地会话Bean</a></center>
</p>
<p>
<center><a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=EJB3Test" target="_blank">EJB3测试:无状态会话Bean远程接口</a></center>
</p>
<!-- --------------------------- 这里是新加的部分 ------------------------------- -->
<p>
<center><a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=UseLocalEJB" target="_blank">EJB3测试:使用无状态会话Bean本地接口</a></center>
</p>
<!-- --------------------------- 这里是新加的部分 ------------------------------- -->
</body>
</html>
-----------------------------------------------------------------------
使用[Build/build.xml],编译发布,然后看结果吧!
是不是越来越有感觉了!这说明你已经进入了状态!
2.3 实现本地和远程接口
有一种业务需求是可能存在的,就是可能希望某一个EJB所有的业务功能都能被本地访问,但只有其中一部分业务功能被远程计算机访问,如果有这种需求,我们就需要让这个EJB既实现本地接口,也实现远程接口。并组织好它们之间的关系!
对于这个业务需求的基本设计应该是这样的:本地接口应该继承了远程接口,EJB Bean类应该既实现本地接口也实现远程接口。
好!首先创建一个远程接口。内容如下:
----------------------------------------------------------------------
/**
*
*/
package com.mh.ejb3.test;
/**
* @author moshco zhu
*
*/
public interface EJB3TestRL {
public String sayTest();
}
----------------------------------------------------------------------
本地接口,本地接口继承于远程接口。
----------------------------------------------------------------------
/**
*
*/
package com.mh.ejb3.test;
/**
* @author moshco zhu
*
*/
public interface EJB3TestRLLocal extends EJB3TestRL {
public String sayTestLocal();
}
----------------------------------------------------------------------
EJB Bean类:
----------------------------------------------------------------------
package com.mh.ejb3.test;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless(mappedName = "EJB3TestRLBean")
@Local(EJB3TestRLLocal.class)
@Remote(EJB3TestRL.class)
public class EJB3TestRLBean implements EJB3TestRLLocal {
/**
* @描述:这是远程接口中要实现的方法,访问无限制。
*/
public String sayTest() {
String strResult = "EJB3,实现远程和本地接口,这是远程接口的业务方法!";
// 函数返回值
return strResult;
}
/**
* @描述:这是本地接口要实现的方法,只能在同一应用服务器中访问
*/
public String sayTestLocal() {
String strResult = "EJB3,实现远程和本地接口,这是本地接口的业务方法!";
// 函数返回值
return strResult;
}
}
----------------------------------------------------------------------
要注意[public class EJB3TestRLBean implements EJB3TestRLLocal ]容易让人难于理解,其实这一部分可用简写成[public class EJB3TestRLBean],但是这样写不好,因为在IDE中编写代码的时候,你会忘记了自己的Bean类要实现那些方法。还有就是,这里真正决定EJB实现那些接口的应该是[@Local(EJB3TestRLLocal.class)]和[@Remote(EJB3TestRL.class)]。
到这里EJB就算是写好了,接下来编写访问的代码。
为了能够在servlet中有效的访问到本地接口,我们需要在web.xml中加入引用,需要再次强调的是,本地接口的只能在同一个server中访问,另外一台电脑的应用服务器的web服务是没有办法访问到当前电脑的本地接口的。
修改web.xml的内容如下:
----------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!-- version="2.4"这一部分不可以顺便改动,改动容易造成发布错误 -->
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- web项目发布名称 -->
<display-name>ejb3test</display-name>
<!-- 默认文件列表 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<!-- 定义一个Servlet -->
<servlet>
<servlet-name>CommonSV</servlet-name>
<servlet-class>com.mh.servlet.test.CommonSV</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CommonSV</servlet-name>
<url-pattern>/sv/CommonSV.do</url-pattern>
</servlet-mapping>
<!-- 定义引用一个ejb3的本定接口 -->
<ejb-local-ref>
<ejb-ref-name>HelloWorldLocalBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<!-- 因为是EJB3所有不能有这一部分 -->
<!-- <local-home></local-home> -->
<local>com.mh.ejb3.test.HelloWorldLocal</local>
<ejb-link>ejb3test_ejb.jar#HelloWorldLocalBean</ejb-link>
</ejb-local-ref>
<!-- --------------------- 这里是新加的 ----------------------- -->
<!-- 定义引用一个ejb3的本定接口 -->
<ejb-local-ref>
<ejb-ref-name>EJB3TestRLBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<!-- 因为是EJB3所有不能有这一部分 -->
<!-- <local-home></local-home> -->
<local>com.mh.ejb3.test.EJB3TestRLLocal</local>
<ejb-link>ejb3test_ejb.jar#EJB3TestRLBean</ejb-link>
</ejb-local-ref>
<!-- --------------------- 这里是新加的 ----------------------- -->
</web-app>
----------------------------------------------------------------------
修改文件[WebContext/JavaSource/com/mh/servlet/test/CommonSV.java],在方法[doWork]中加入下面一部分:
----------------------------------------------------------------------
} else if (strPara != null && strPara.equals("EJB3TestRL")) {
// 通过JNDI获取EJB对象
EJB3TestRL test = (EJB3TestRL) getEJBObject("EJB3TestRLBean#com.mh.ejb3.test.EJB3TestRL");
message += test.sayTest();
} else if (strPara != null && strPara.equals("EJB3TestRLLocal")) {
// 通过JNDI获取EJB对象
EJB3TestRLLocal test = (EJB3TestRLLocal) getEJBObject("java:comp/env/EJB3TestRLBean");
message += test.sayTestLocal() + "/n<br>";
message += test.sayTest();
----------------------------------------------------------------------
看看,这是两种不同的JNDI的访问。
在欢迎页面程序[WebContext/index.jsp],中加入下面一部分:
----------------------------------------------------------------------
<p>
<center>
EJB3测试:实现了本地接口和远程接口的EJB:<br>
<a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=EJB3TestRL" target="_blank">远程接口访问</a>
<br>
<a href="<%=request.getContextPath() %>/sv/CommonSV.do?dowith=EJB3TestRLLocal" target="_blank">使用web.xml中定义的JNDI访问本地接口</a>
<br>
</center>
</p>
----------------------------------------------------------------------
好了!可以使用[Build/build.xml]发布编译了。看结果吧!