| « | November 2025 | » | | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | | | | | | |
|
| 公告 |
我近期在研究Maven、Turbine、EJB,如果有朋友想一起交流学习,请加我的MSN:moshco_zhu@hotmail.com!
你为什么来,你何必来,叫我怎么见你!
--《小城之春》 |
| 
|
本站首页 管理页面 写新日志 退出
[01 技术文档]在Weblogic 10中做EJB3的开发 之基础开发 (2) |
在Weblogic 10中做EJB3的开发 之基础开发 (2)
---------------------------------------------------------------------------
3.有状态会话Bean的使用
3.1 有状态会话Bean与无状态会话Bean的差异
在EJB的容器中,服务器启动以后,容器会预先创建一些EJB对象在容器中,其目的是让调用者能更高效率的使用EJB对象。创建的的这些EJB对象有的是有状态会话Bean,有的是无状态会话Bean,它们的区别主要在于:有状态会话Bean被一个使用者调用后,它就不会再被其它使用者调用;而无状态会话Bean,可以被多个使用者调用,一个用完了,另一个可以接着使用。由此大家可以看出,简单的从效率方面讲,无状态会话Bean明显更好。但是,在有些时候,用户会有一些这样的需求,他们希望在某段时间内,保存一些他自己的信息,而这些信息只能他自己修改使用,不能被其它使用者修改使用,而这一点使用无状态会话Bean是做不到的。
下面我设想一个需求:用户有一个资金账户,他消费后账户资金会减少,他充值后账户资金会增加。 设计方案如下:创建一个EJB对象,定义一个成员变量来保存资金数额,定义三个业务方法,一个冲值,一个是消费,一个获取剩余资金数额。 测试方案:使用一个Servlet创建两个EJB对象,对两个对象交叉进行通过一系列冲值和消费改变金额数量。 观察:如果是有状态会话Bean,两个EJB对象无论你如何冲值消费,它们的金额互不受到影响。如果是无状态会话Bean,它们的金额会被另一个EJB的操作影响。 结论:有状态会话Bean它会记录与操作者之间的联系,直到不再使用,只提供给一个用户使用;无状态会话Bean可以被多个用户同时操作,能够重复使用,效率极高。
接下来实现这个业务,看具体效果。
创建有状态会话Bean的远程接口。 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/statefull/AccountMoney.java] 包名:[com.mh.ejb3.test.statefull] 名称:[AccountMoney] 内容如下: ---------------------------------------------------------------------- /** * */ package com.mh.ejb3.test.statefull;
import java.io.Serializable;
/** * @author moshco zhu * */ public interface AccountMoney extends Serializable {
/** * @描述:冲值 * @return */ public float charge(float fMoney);
/** * @描述:消费 * @return */ public float pay(float fMoney);
/** * @描述:剩余资金 * @return */ public float account();
} ---------------------------------------------------------------------- 需要注意的一点是:有状态会话Bean一定要实现序列化接口,因为用户可能中间很长时间不使用,容器需要把它保存在硬盘上,以提高效率。
下面是有状态会话Bean的Bean类。 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/statefull/AccountMoneyBean.java] 包名:[com.mh.ejb3.test.statefull] 名称:[AccountMoneyBean] EJB类型:[无状态会话Bean] 实现接口:[远程接口] 内容如下: ---------------------------------------------------------------------- package com.mh.ejb3.test.statefull;
import javax.ejb.Remote; import javax.ejb.Stateful;
@SuppressWarnings("serial") @Stateful(mappedName = "AccountMoneyBean") @Remote(AccountMoney.class) public class AccountMoneyBean implements AccountMoney {
private float money = 0; // 账户金额
/** * @描述:冲值 */ public float charge(float fMoney) {
money += fMoney;
// 返回函数值 return money; }
/** * @描述:消费 */ public float pay(float fMoney) {
money -= fMoney;
// 返回函数值 return money; }
/** * @描述:剩余资金 * @return */ public float account() {
// 返回函数值 return money; }
} ----------------------------------------------------------------------
创建无状态会话Bean。
创建无状态会话Bean的远程接口 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/statefull/AccountMoneyStateless.java] 包名:[com.mh.ejb3.test.statefull] 名称:[AccountMoneyStateless] 内容如下: ---------------------------------------------------------------------- /** * */ package com.mh.ejb3.test.statefull;
/** * @author moshco zhu * */ public interface AccountMoneyStateless {
/** * @描述:冲值 * @return */ public float charge(float fMoney);
/** * @描述:消费 * @return */ public float pay(float fMoney);
/** * @描述:剩余资金 * @return */ public float account();
} ---------------------------------------------------------------------- 无状态会话Bean的Bean类。 文件地址:[EJB3/JavaSource/com/mh/ejb3/test/statefull/AccountMoneyStatelessBean.java] 包名:[com.mh.ejb3.test.statefull] 名称:[AccountMoneyStatelessBean] EJB类型:[无状态会话Bean] 实现接口:[远程接口] 内容如下: ---------------------------------------------------------------------- package com.mh.ejb3.test.statefull;
import javax.ejb.Remote; import javax.ejb.Stateless;
@Stateless(mappedName = "AccountMoneyStatelessBean") @Remote(AccountMoneyStateless.class) public class AccountMoneyStatelessBean implements AccountMoneyStateless {
private float money = 0; // 账户金额
/** * @描述:冲值 */ public float charge(float fMoney) {
money += fMoney;
// 返回函数值 return money; }
/** * @描述:消费 */ public float pay(float fMoney) {
money -= fMoney;
// 返回函数值 return money; }
/** * @描述:剩余资金 * @return */ public float account() {
// 返回函数值 return money; }
} ----------------------------------------------------------------------
到这里,我们已经创建完成了两个EJB,一个是用状态会话Bean[AccountMoney],一个是无状态会话Bean[AccountMoneyStateless],它们都实现了远程接口。
下面我们实现这个业务的控制和表示层。
首先,我们创建一个EJB的工具类。 文件地址:[Java/JavaSource/com/mh/ejb/ejbutil.java] 包名:[com.mh.ejb] 名称:[ejbutil] 内容如下: ---------------------------------------------------------------------- /** * */ package com.mh.ejb;
import java.util.Properties;
import javax.naming.Context; import javax.naming.InitialContext;
/** * @author moshco zhu * */ public class ejbutil {
public static String Host = "localhost"; static { Host = "localhost"; }
/** * @功能 获取EJB对象从默认的应用服务器 * * @param strJNDI * @return * @throws Exception */ public static 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://" + Host + ":7001");
// 创建上下文环境对象 InitialContext ctx; ctx = new InitialContext(props);
// 本地接口 Object oEJB = ctx.lookup(strJNDI);
// 返回函数值 return oEJB; }
/** * @功能 获取本地EJB对象 * * @param strJNDI * @return * @throws Exception */ public static Object getEJBLocalObject(String strJNDI) throws Exception {
// 创建上下文环境对象 InitialContext ctx; ctx = new InitialContext();
// 本地接口 Object oEJB = ctx.lookup(strJNDI);
// 返回函数值 return oEJB; }
} ---------------------------------------------------------------------- 这个类主要是提供几种方式,让使用者可以直接通过JNDI获取自己想要的EJB,并可以扩展功能用来管理分布在不同计算机上的EJB的访问。
下面要写一个Servelt,用来控制并客户端各种请求,返回结果。 文件地址:[WebContext/JavaSource/com/mh/servlet/test/ejb3statefull/AccountMoneySV.java] 包名:[com.mh.servlet.test.ejb3statefulls] 名称:[AccountMoneySV] 内容如下: ---------------------------------------------------------------------- /** * */ package com.mh.servlet.test.ejb3statefull;
import java.io.IOException; import java.io.PrintWriter;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import com.mh.ejb3.test.statefull.AccountMoney; import com.mh.util.ejbutil;
/** * @author moshco zhu * */ public class AccountMoneySV extends HttpServlet {
@Override public void destroy() { // TODO 自动生成方法存根 super.destroy(); }
@Override public void init() throws ServletException { // TODO 自动生成方法存根 super.init(); }
@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 request * @param response * @throws ServletException * @throws IOException */ 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 = "";
try {
// 获取账户EJB对象 HttpSession session = request.getSession(true);
// 获取参数 String strPara = (String) request.getParameter("dowith");
// 通过参数实现业务 if (strPara != null && strPara.equals("isInitAccount")) { // 判断账户是否已经初始化
// 获取账户A AccountMoney accountA = (AccountMoney) session .getAttribute("A"); // 获取账户B AccountMoney accountB = (AccountMoney) session .getAttribute("B"); if (accountA == null || accountB == null) { message = "no"; } else { message = "yes"; }
} else if (strPara != null && strPara.equals("initAccount")) { // 初始化账户
// 通过JNDI获取EJB对象 AccountMoney accountA = (AccountMoney) ejbutil .getEJBObject("AccountMoneyBean#com.mh.ejb3.test.statefull.AccountMoney"); // 保存EJB对象在Session中 session.setAttribute("A", accountA);
// 通过JNDI获取EJB对象 AccountMoney accountB = (AccountMoney) ejbutil .getEJBObject("AccountMoneyBean#com.mh.ejb3.test.statefull.AccountMoney"); // 保存EJB对象在Session中 session.setAttribute("B", accountB);
// 返回信息 message += "账户A、B初始化成功!\n<br>"; message += "账户[A]的余额:" + accountA.account() + "\n<br>"; message += "账户[B]的余额:" + accountB.account() + "\n<br>";
} else if (strPara != null && strPara.equals("delAccount")) { // 删除账户
// 删除账户 session.removeAttribute("A"); session.removeAttribute("B");
// 返回信息 message += "账户A、B已经成功删除!";
} else if (strPara != null && strPara.equals("charge")) { // 冲值
// 获取账户 String strAccount = (String) request.getParameter("account"); AccountMoney account = null; if (strAccount != null && strAccount.equals("A")) { // 获取账户A account = (AccountMoney) session.getAttribute("A"); } else if (strAccount != null && strAccount.equals("B")) { // 获取账户B account = (AccountMoney) session.getAttribute("B"); }
// 冲值 if (account != null) { float fMoney = (float) Float.parseFloat(request .getParameter("money")); account.charge(fMoney);
// 获取当前余额 message += "冲值成功!账户[" + strAccount + "]当前余额是:" + account.account(); } else if (strAccount != null && strAccount.equals("ALL")) { // 给两个账户冲值
// 获取金额 float fMoney = (float) Float.parseFloat(request .getParameter("money"));
// 冲值 account = (AccountMoney) session.getAttribute("A"); if (account != null) { account.charge(fMoney); message += "给所有账户冲值,账户[A]冲值成功!账户余额:" + account.account(); } else { message += "给所有账户冲值,冲值失败!账户[A]不存在!"; }
account = (AccountMoney) session.getAttribute("B"); if (account != null) { account.charge(fMoney); message += "给所有账户冲值,账户[B]冲值成功!账户余额:" + account.account(); } else { message += "给所有账户冲值,冲值失败!账户[B]不存在!"; }
} else { message += "冲值失败!账户[" + strAccount + "]不存在!"; } } else if (strPara != null && strPara.equals("pay")) { // 消费
// 获取账户 String strAccount = (String) request.getParameter("account"); AccountMoney account = null; if (strAccount != null && strAccount.equals("A")) { // 获取账户A account = (AccountMoney) session.getAttribute("A"); } else if (strAccount != null && strAccount.equals("B")) { // 获取账户B account = (AccountMoney) session.getAttribute("B"); }
// 消费 if (account != null) { float fMoney = (float) Float.parseFloat(request .getParameter("money")); account.pay(fMoney);
// 获取当前余额 message += "扣款成功!账户[" + strAccount + "]当前余额是:" + account.account(); } else { message += "扣款失败!账户[" + strAccount + "]不存在!"; }
} else if (strPara != null && strPara.equals("account")) { // 获取账户余额
// 获取账户 String strAccount = (String) request.getParameter("account"); AccountMoney account = null; if (strAccount != null && strAccount.equals("A")) { // 获取账户A account = (AccountMoney) session.getAttribute("A"); } else if (strAccount != null && strAccount.equals("B")) { // 获取账户B account = (AccountMoney) session.getAttribute("B"); }
// 获取账户余额 if (account != null) { message += "当前账户[" + strAccount + "]的余额是:" + account.account(); } else {
// 账户A account = (AccountMoney) session.getAttribute("A"); message += "账户[A]的余额是:" + account.account();
// 账户B account = (AccountMoney) session.getAttribute("B"); message += "\n<br>账户[B]的余额是:" + account.account(); }
}
} catch (Exception e) { e.printStackTrace(); message += e.toString(); } finally { }
// 输出 out.print(message); out.flush(); out.close();
} } ---------------------------------------------------------------------- 这个Servlet用来处理使用有状态会话Bean来实现的业务控制层。
文件地址:[WebContext/account.jsp] 内容如下: ---------------------------------------------------------------------- package com.mh.servlet.test.ejb3statefull;
import java.io.IOException; import java.io.PrintWriter;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import com.mh.ejb3.test.statefull.AccountMoneyStateless; import com.mh.util.ejbutil;
public class AccountMoneyStatelessSV extends HttpServlet {
@Override public void destroy() { // TODO 自动生成方法存根 super.destroy(); }
@Override public void init() throws ServletException { // TODO 自动生成方法存根 super.init(); }
@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 request * @param response * @throws ServletException * @throws IOException */ 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 = "";
try {
// 获取账户EJB对象 HttpSession session = request.getSession(true);
// 获取参数 String strPara = (String) request.getParameter("dowith");
// 通过参数实现业务 if (strPara != null && strPara.equals("isInitAccount")) { // 判断账户是否已经初始化
// 获取账户A AccountMoneyStateless accountA = (AccountMoneyStateless) session .getAttribute("A"); // 获取账户B AccountMoneyStateless accountB = (AccountMoneyStateless) session .getAttribute("B"); if (accountA == null || accountB == null) { message = "no"; } else { message = "yes"; }
} else if (strPara != null && strPara.equals("initAccount")) { // 初始化账户
// 通过JNDI获取EJB对象 AccountMoneyStateless accountA = (AccountMoneyStateless) ejbutil .getEJBObject("AccountMoneyStatelessBean#com.mh.ejb3.test.statefull.AccountMoneyStateless"); // 保存EJB对象在Session中 session.setAttribute("A", accountA);
// 通过JNDI获取EJB对象 AccountMoneyStateless accountB = (AccountMoneyStateless) ejbutil .getEJBObject("AccountMoneyStatelessBean#com.mh.ejb3.test.statefull.AccountMoneyStateless"); // 保存EJB对象在Session中 session.setAttribute("B", accountB);
// 返回信息 message += "账户A、B初始化成功!\n<br>"; message += "账户[A]的余额:" + accountA.account() + "\n<br>"; message += "账户[B]的余额:" + accountB.account() + "\n<br>";
} else if (strPara != null && strPara.equals("delAccount")) { // 删除账户
// 删除账户 session.removeAttribute("A"); session.removeAttribute("B");
// 返回信息 message += "账户A、B已经成功删除!";
} else if (strPara != null && strPara.equals("charge")) { // 冲值
// 获取账户 String strAccount = (String) request.getParameter("account"); AccountMoneyStateless account = null; if (strAccount != null && strAccount.equals("A")) { // 获取账户A account = (AccountMoneyStateless) session.getAttribute("A"); } else if (strAccount != null && strAccount.equals("B")) { // 获取账户B account = (AccountMoneyStateless) session.getAttribute("B"); }
// 冲值 if (account != null) { float fMoney = (float) Float.parseFloat(request .getParameter("money")); account.charge(fMoney);
// 获取当前余额 message += "冲值成功!账户[" + strAccount + "]当前余额是:" + account.account(); } else if (strAccount != null && strAccount.equals("ALL")) { // 给两个账户冲值
// 获取金额 float fMoney = (float) Float.parseFloat(request .getParameter("money"));
// 冲值 account = (AccountMoneyStateless) session.getAttribute("A"); if (account != null) { account.charge(fMoney); message += "给所有账户冲值,账户[A]冲值成功!账户余额:" + account.account(); } else { message += "给所有账户冲值,冲值失败!账户[A]不存在!"; }
account = (AccountMoneyStateless) session.getAttribute("B"); if (account != null) { account.charge(fMoney); message += "给所有账户冲值,账户[B]冲值成功!账户余额:" + account.account(); } else { message += "给所有账户冲值,冲值失败!账户[B]不存在!"; }
} else { message += "冲值失败!账户[" + strAccount + "]不存在!"; } } else if (strPara != null && strPara.equals("pay")) { // 消费
// 获取账户 String strAccount = (String) request.getParameter("account"); AccountMoneyStateless account = null; if (strAccount != null && strAccount.equals("A")) { // 获取账户A account = (AccountMoneyStateless) session.getAttribute("A"); } else if (strAccount != null && strAccount.equals("B")) { // 获取账户B account = (AccountMoneyStateless) session.getAttribute("B"); }
// 消费 if (account != null) { float fMoney = (float) Float.parseFloat(request .getParameter("money")); account.pay(fMoney);
// 获取当前余额 message += "扣款成功!账户[" + strAccount + "]当前余额是:" + account.account(); } else { message += "扣款失败!账户[" + strAccount + "]不存在!"; }
} else if (strPara != null && strPara.equals("account")) { // 获取账户余额
// 获取账户 String strAccount = (String) request.getParameter("account"); AccountMoneyStateless account = null; if (strAccount != null && strAccount.equals("A")) { // 获取账户A account = (AccountMoneyStateless) session.getAttribute("A"); } else if (strAccount != null && strAccount.equals("B")) { // 获取账户B account = (AccountMoneyStateless) session.getAttribute("B"); }
// 获取账户余额 if (account != null) { message += "当前账户[" + strAccount + "]的余额是:" + account.account(); } else {
// 账户A account = (AccountMoneyStateless) session.getAttribute("A"); message += "账户[A]的余额是:" + account.account();
// 账户B account = (AccountMoneyStateless) session.getAttribute("B"); message += "\n<br>账户[B]的余额是:" + account.account(); }
}
} catch (Exception e) { e.printStackTrace(); message += e.toString(); } finally { }
// 输出 out.print(message); out.flush(); out.close();
} } ---------------------------------------------------------------------- 这个Servlet是用无状态会话Bean实现业务的控制层。
|
阅读全文(3262) | 回复(0) | 编辑 | 精华 |
|