哈哈,过了一个轻松的周末,又要开始写东西咯。
周末本来也想写,可是还是觉得玩有意思,姑且放几天假。
上次讲的是无状态会话BEAN。
好象还是有点不明白为什么要分无状态和状态会话BEAN这两种BEAN,不过不要紧,看完状态会话BEAN的程序就能明白了。对了,还有一点要说的。我周五那天搞了一天的ECLIPSE3,听说他出新版本了,所以赶紧下载试验试验,他在里边新加了功能叫EJB
EDITOR,这个东西不错,有好多新东西。可是唯一另我费解的是为什么用他CREATE
CLIENT TEST PROGRAMM的时候却总是报错!所以还是比较的烦躁的!也不知道是ECLIPSE的毛病还是我机器自己运行环境的毛病,大家也试试然后告诉我啊!
我的这个状态会话BEAN还是用ECLIPSE2.1写的拉。
我先把程序写给大家,然后再分析吧,我好象是那种喜欢先看程序然后再看理论的人。不知道是不是有人和我一样。
这是客户端的实现程序:
package
com.test.session;
import
javax.ejb.*;
/**
*
@ejb.bean name="Stateful"
*
jndi-name="StatefulBean"
*
type="Stateful"
*
*--
*
This is
needed for
JOnAS.
*
If you
are not
using JOnAS
you can
safely remove
the tags
below.
*
@jonas.bean ejb-name="Stateful"
*
jndi-name="StatefulBean"
*
*--
**/
public
abstract class
StatefulBean implements
SessionBean {
/**
*
@ejb.create-method
*
view-type="remote"
**/
public
void ejbCreate(double
amout) throws
CreateException{
this.amout=amout;
}
/**
*
@ejb.interface-method
*
view-type="remote"
**/
public
void addFunds(double
amout){
this.amout+=amout;
}
/**
*
@ejb.interface-method
*
view-type="remote"
**/
public
void withdrawFunds(double
amout){
this.amout-=amout;
}
/**
*
@ejb.interface-method
*
view-type="remote"
**/
public
double getBalance(){
return
this.amout;
}
double
amout;
}
对了,ejbCreate(double
amout)方法是在BEAN生成过程中,容器调用ejbCreate(double
amout)方法的。
就好象是初始化的方法一样。
还有你一定要确保在主接口中有个Create(double
amout)方法和ejbCreate(double
amout)对应啊!这段是必须的,如果不明白的话,赶紧找资料。你这个ejbCreate(double
amout)方法在新建的时候要选择CREATE哦!
在把客户端的测试程序给你们:
package
com.testing.client;
import
java.rmi.RemoteException;
import
java.util.Hashtable;
import
javax.ejb.CreateException;
import
javax.naming.InitialContext;
import
javax.naming.NamingException;
import
javax.swing.JFrame;
import
javax.swing.*;
import
java.awt.*;
import
java.awt.event.*;
import
java.text.*;
import
com.test.session.*;
/**
*
@author sy
*
*
更改所生成类型注释的模板为
*
窗口 >
首选项 >
Java >
代码生成 >
代码和注释
*/
public
class testStateful
extends JFrame
implements ActionListener{
public testStateful(){
super("fund
manger");
}
private com.test.session.StatefulHome
getHome() throws
NamingException {
return (com.test.session.StatefulHome)
getContext().lookup(
com.test.session.StatefulHome.JNDI_NAME);
}
private InitialContext
getContext() throws
NamingException {
Hashtable props
= new
Hashtable();
props.put(
InitialContext.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(InitialContext.PROVIDER_URL,
"jnp://127.0.0.1:1099");
// This establishes the
security for authorization/authentication
//
props.put(InitialContext.SECURITY_PRINCIPAL,"username");
//
props.put(InitialContext.SECURITY_CREDENTIALS,"password");
InitialContext initialContext
= new
InitialContext(props);
return initialContext;
}
public void
CreateFund() {
try {
myBean =
getHome().create(1000);
//--------------------------------------
//This is the place you make
your calls.
//System.out.println(myBean.callYourMethod());
} catch
(RemoteException e)
{
e.printStackTrace();
} catch
(CreateException e)
{
e.printStackTrace();
} catch
(NamingException e)
{
e.printStackTrace();
}
}
public void
testBean() {
buildGUI();
addWindowListener(new
WindowAdapter(){public
void WindowClosing(WindowEvent
evt){System.exit(0);}});
CreateFund();
addFund.addActionListener(this);
withdraw.addActionListener(this);
currencyFomat=NumberFormat.getCurrencyInstance();
try{
String currency=currencyFomat.format(myBean.getBalance());
status.setText(msg+currency);
}catch(Exception
e){}
pack();
show();
}
public void
actionPerformed(ActionEvent e){
String str=amout.getText();
try{
if(e.getSource()==addFund){
myBean.addFunds(Double.parseDouble(str));
currencyFomat=NumberFormat.getCurrencyInstance();
strBar=currencyFomat.format(myBean.getBalance());
status.setText(msg+strBar);
}
if(e.getSource()==withdraw){
myBean.withdrawFunds(Double.parseDouble(str));
currencyFomat=NumberFormat.getCurrencyInstance();
strBar=currencyFomat.format(myBean.getBalance());
status.setText(msg+strBar);
}
}catch(Exception
ex){}
}
public void
buildGUI(){
GridBagLayout gl=new
GridBagLayout();
GridBagConstraints gc=new
GridBagConstraints();
Container container=getContentPane();
container.setLayout(gl);
gc.fill=GridBagConstraints.BOTH;
JLabel label=new
JLabel("enter
amout");
gl.setConstraints(label,gc);
container.add(label);
gc.gridwidth=GridBagConstraints.REMAINDER;
gl.setConstraints(amout,gc);
container.add(amout);
gl.addLayoutComponent(addFund,gc);
container.add(addFund);
gl.addLayoutComponent(withdraw,gc);
container.add(withdraw);
status=new
JLabel(msg);
gl.addLayoutComponent(status,gc);
container.add(status);
}
double balance=100;
JTextField amout=new
JTextField(10);
JButton addFund=new
JButton("add
funds");
JButton withdraw=new
JButton("withdraw
funds");
String msg="current
funds is:";
String strBar="0";
JLabel status;
Stateful myBean;
NumberFormat currencyFomat;
public static
void main(String[]
args) {
testStateful test
= new
testStateful();
test.testBean();
}
}
看出来门道了吗?我终于知道为什么这个要叫做:状态会话BEAN了。因为,因为。。。。。哈哈,他有个amout变量,这个完全是EJB内部的变量,在EJB容器中保存!而和那个无状态会话BEAN不一样的地方就是,无状态会话BEAN是在客户端保存数据。很大的区别!这就是问题的关键!也不知道你们看懂了没有!反正我觉得真的很明显。
下边这个是我在IBM文章库里找的一副图,感觉不错,完全讲明白了状态BEAN是怎么回事拉:
这些是些讲解,和书上的差不多,省得我打字了。
有状态会话
Bean 生命周期:
- Bean
在下列情况下被回收:
- 超时
(无论是激活的或钝化的)
- 被调用
remove()
- Passivation
是根据 Least-Recently-Used 算法
- Activation
由对 Bean 的方法调用产生
- afterBegin()
beforeCompletion()
afterCompletion()
方法仅对实现 SessionSynchronization 接口的 Bean
有效
- 在一个事务环境下,调用的方法必需具有相同的事务类型
OK,状态会话BEAN就是这么回事。应该是很简单的东西,完全可以理解。