http://blog.csdn.net/sinapaper/archive/2004/06/28/28659.aspxphp
http://blog.csdn.net/sinapaper/archive/2004/06/29/29634.aspxhtml
http://blog.csdn.net/sinapaper/archive/2004/06/30/30538.aspxjava
http://blog.csdn.net/sinapaper/archive/2004/07/01/31231.aspxmysql
http://blog.csdn.net/sinapaper/archive/2004/07/05/34109.aspx算法
http://blog.csdn.net/sinapaper/archive/2004/07/05/34202.aspxsql
http://blog.csdn.net/sinapaper/archive/2004/07/14/41058.aspx數據庫
http://blog.csdn.net/sinapaper/archive/2004/07/15/42234.aspxapache
爲了力求新的進步,我認爲從今天起開始學習EJB編程。編程
但願各位志同道合的朋友能一塊兒參加進來。設計模式
我選用的參考書是wrox的EJB編程指南。這個書有1000多頁,爭取能所有完畢他吧!
好了,很少說無用的了。現在開始進入第一章的學習。
第一章 Enterprise Javabeans 體系機構。
開始將講了一大堆廢話,從單層體系結構講到了多層體系結構,又講到了N層體系結構。這樣引出了主題(J2EE)。只是這句話翻譯的不錯:其餘需要特別注意的(是)server方資源包含線程,數據庫鏈接,安全、事務等等。定製處理這些資源的基礎結構是至關費勁的。這樣的工做在INTERNET環境中是不可能的。假設你的開發週期僅僅有三個月,可以對數據庫訪問創建鏈接池、對象緩衝區或「精彩的」對象層嗎?
暈!說了一大堆話最終引出了偉大的J2EE。只是要是不知道N層結構的真應該看看!
容器:說白了容器就是JAVA程序的執行環境。不知道個人理解是否正確。現在的程度就僅僅能理解到這了。
書上說J2EE規範定義了四種容器類型:
1. 小應用程序(APPLET)。
2. 應用程序客戶容器。(本身覺得就是SWING)
3. WEB容器(SERVLET 和 JSP)
4. EJB容器。
看來123都已經掌握了,現在就差4了,因此EJB容器仍是要學習的哦!~
書上對EJB寫了個更加深刻的解釋:EJB是個分佈式組件模型,可以開發安全的、可伸縮的、事務性的多用戶組件。簡單的說,EJB是包含業務邏輯的可複用軟件單元。就象JSP可以將應用程序與業務邏輯分開同樣,EJB可以將應用程序邏輯和系統層服務分開,使開發者集中考慮業務問題,而沒必要考慮系統編程。
J2EE API:
RMI/IIOP:Remote Method Invocation類似網絡鏈接使用的一些東西。
JNDI:Java Naming and Directory Interface。
JDBC:這個不用說了吧?
JAVAMAIL/JAF:JAVA的MAIL服務,JAF是郵件的附件。
JMS:JAVA MESSAGE SERVER。JAVA消息服務。
設計中爲什麼使用EJB:說了一大堆,我仍是不肯定是爲何。再接着看吧!
只是此次我更加的肯定了,原來EJB容器就至關於一個「功能「server,可以把一些業務功能寫在這個裏邊。而後用123來調用咯!(不知道這麼說是否是有點搞笑)。
哈哈,個人理解正確了,果真書的第8頁就說了,容器可以當作是執行環境!
EJB的容器服務:(這裏的容器服務都是不用編碼,而是容器管理本身實現的啊。不錯)
組件池和壽命週期管理:
哈哈,來點白話的,這是我我的理解的,組件池在容器啓動的時候就本身生成了好多的BEAN的實例,假如說是10個吧,這個時候客戶1來了,他就拿了BEAN1,這個時候別人是不能使用BEAN1的,再來了第2個客戶,他不能拿BEAN1了,就僅僅能拿BEAN2了。。。。。。。這個時候客戶11來了,容器發現已經沒有BEAN給他用了,因而就找個現在沒人用的BEAN給他用,但是發現全都在被佔用,沒辦法了,就僅僅好再生成一個給他用了。哈哈,就是這麼簡單,但是有人會問了,這不是越生成越多嗎?不要緊,容器發現生成的BEAN沒人用了,就會本身主動的給刪掉,釋放空間,釋放系統資源嘛!
客戶會話管理:
理解鈍化和激活便可了。
鈍化就是把客戶的BEAN狀態保存在池中。
激活就是把客戶的這個BEAN狀態再還給客戶。
數據庫鏈接池:
這個好象不用講了吧!數據資源共享!這個名起的COOL B了。
事務管理:
事務很是是昂貴啊!
驗證和訪問控制:
這個很是easy!
容器怎樣提供服務:這一部分先不寫,之後再寫,因爲我也不怎麼理解。哈哈
EJB類型:*****這但是關鍵的地方。*****
分爲3種類型:
會話BEAN:(壽命和所在客戶的會話同樣長啊)
1. 無狀態會話BEAN。
2. 狀態會話BEAN。
這兩個BEAN很是的重要,但是在第3章纔有講。哈哈,先擱這!
實體BEAN:
本身理解就好象是數據庫BEAN,就是把數據庫的內容都讀出來放在BEAN裏,也不知道它具體是怎麼讀的,這樣作會不會很是浪費系統資源!???
實體BEAN依據同步的不同又可以分爲:
CMP(容器管理的持久性):容器負責BEAN與基礎的數據庫同步。
BMP(BEAN管理的持久性):這裏要編程人員負責和基礎數據庫同步!容器在適當的時候調用編程人員寫好的SQL語句!
真不明確,爲何已經有CMP了還要出了個BMP,書上是這麼解釋的:
有時需要增長設計的靈活性或在非關係型存儲中支持持久性??這是人話嗎?
還有個例如:EJB規範V1.1僅僅容許實例變量和表格列之間的一對一映射。這樣,使用這個版本號時,假設要在實體BEAN中表示在多個表格中存儲狀態的累計對象,則沒法使用CMP,而要使用BMP。EJB2.0規範定影了複雜的查詢語言!仍是很是費解!~~~~只是應該是實用吧!!之後預計就能搞明確!呵呵!~~
消息驅動BEAN。第6章講!等着吧!兄弟們~~~~
哈哈!看完第一章了。明天再看第2章!
先說點題外話, bromon說的真有點恐怖,不知道消息來源的真實性,假設真是那樣我想國內的人也不會當即就所有跑去轉用EJB3吧。呵呵,只是仍是要謝謝bromon 和個人鐵杵個人針 ,個人第一篇文章最終有人看了,但願愈來愈多的人的增長!J
第一章 EJB開發
EJB的角色:(規定了6種開發和部署的角色)
l 企業BEAN提供者(Enterprise Bean Provider)
工做任務例如如下:
1.編寫BEAN的主接口。
2.編寫BEAN的組件接口,聲明應用程序需要的各類業務方法。
3.編寫實現遠程接口中定義的各類業務方法的實現類。
4.編寫部署描寫敘述項。
5.打包。
事實上就是編寫EJB的編程人員。至於什麼是主接口,什麼是組件接口,什麼是實現類之後再說吧!先死記吧!
l 應用程序彙編者:事實上就是把BEAN提供者寫好的東西組織在一塊兒的人了。沒什麼大用,還號稱是行業專家!(開玩笑了)
l 部署者
l 系統管理員
l EJB服務提供者,容器提供者(書上是分兩條的,但是我認爲他們應該是同樣的東西,至少臨時是同樣的東西)
事實上話說回來了,別的人都不怎麼重要,咱們要作的人就是企業BEAN提供者。
開發第一個EJB
高興,最終有個HELLOWORLD了!
你們必定要記住BEAN提供者的那幾個要素啊!很是關鍵的,全是從那幾個要素之間展開的。
HELLOWORD的題目是:依據年薪、公積金和所得稅計算每個月的淨收入。(無狀態會話BEAN)。
EJB客戶視圖:
本地客戶:使用本地接口和本地主接口。按引用傳遞值。
遠程客戶:使用遠程接口和遠程主接口。按變量傳遞值。會有java.rmi.RemoteException錯誤。
標準的設計模式是,業務邏輯層的所有訪問使用會話BEAN,這些會話BEAN需要發表遠程接口,使客戶層可以訪問這些會話BEAN。其他實體和無狀態會話BEAN可以當作「實施細節」,僅僅發表本地接口。
這是書上原話,你們明確嗎?反正我就僅僅能明確個80%。哈哈~~~再接着來。
開發主接口:
倒!前邊講了一大堆主接口,現在纔想起來解釋,不知道老外這個書是怎麼寫的。
主接口負責控制BEAN的壽命週期操做:生成,刪除和尋找。主接口是客戶在BEAN中的第一個聯繫點。客戶經過JNDI取得引用。事實上是在部署的時候肯定JNDI的,不着急。
當客戶引用了主接口以後,就可以經過這個接口對BEAN進行下列操做:
l 生成新的實例或者尋找現有的BEAN實例。(本地或者遠程)
l 訪問EJBMetaData接口(遠程)。
l 取得BEAN實例的序列化引用(遠程)。
l 刪除BEAN實例。
l 執行主業務方法。
在這個樣例中僅僅使用主接口生成BEAN的新實例。
EJB裏定義了本地接口和遠程接口。(EJBHome 和EJBLocalHome)。這兩個接口的源程序書上有。
EJBHome接口中的方法:
getEJBMetaData():返回EJBMetaData接口的引用,取得BEAN信息。(仍是不知道EJBMetaData是什麼東西。查字典是元數據的意思)。
getHomeHandle():返回主對象的句柄。
remove():很是easy,刪除了。哈哈,玩笑,事實上對不一樣BEAN結果不同啦,會話BEAN是將BEAN再放回池中,而實體BEAN則是從數據庫中刪除數據。此次纔對嘛!
下邊就是程序了,我先試試程序到底是怎麼回事再給你們講啊!
經過本人對書本上演示樣例程序的分析,自我感受書上的演示樣例程序實在是沒有說服力,主要是部署工具出奇的麻煩,在這個JAVA不花錢的年代,怎麼能用J2EE自帶的部署工具,一大堆的配置實在是另人煩躁!呵呵。
說了一大堆,開始進入關鍵議題了,各位聽好了。
我選用的是ECLIPSE,這個免費的東西實在作的不錯,在我但是作STRUTS的時候就發現他的好多長處,但是實在遺憾,本人沒實用過JBUILDER,也不知道他們是否是同樣。
ECLIPSE有個LOMBOZ的插件,這個插件裏邊包含有所有server的配置方案。可以配置WEB MODEL,和EJB MODEL,這裏邊我選用JBOSSserver吧,因爲據說他也是不要錢的。
至於ECLIPSE下JBOSS是怎麼培植,這很是easy,僅僅要上GOOGLE上搜索‘ECLIPSE部署‘就有好多,聯想公司姜巍巍先生就寫了一篇配置,但是你們不要看他的EJB部署,實在是垃圾。依照他說的要想讓剛開始學習的人學會第一個EJB是有難度的!
你們仍是來看個人HELLOWORLD吧!
摘自http://www.objectlearn.com/support/docs/firstEJB.jsp
事實上我僅僅是幫你們翻譯一下,呵呵。看原文可以上上邊這個網址。
好了,很少說廢話了。現在開始。對了,必定要保證你的LOMBOZ和ECLIPSE都已經配置好了啊。
1. 新建一個Lomboz J2EE Project,叫"MyFirstEJBProject"。其餘的地方都不要改,NEXT。
2. 而後就能進入這個界面:
看見了吧,在這個的EJB MODULES中加一個新的MODULES,叫mybeans。
而後再選擇TARGET SERVER選項。就是這。
選擇咱們剛纔說的已經配置好的JBOSS。
3. 好了,現在假設不報錯的話。就點FINISH吧!
4. 第一個EJB模塊已經完畢,它可以給你生成EJB和EJB HOME,但是開發的實現類需要本身寫!下邊就是怎麼寫一個實現類。
5.
這副圖能明確吧,但是有人要問了,這個東西哪兒來的?主界面,WINDOW菜單下的PERFERNECE,點他!哈哈,把裏邊有LOMBOZ的全選上就有了。
6.OK拉,依照下邊的圖把名字輸上:
這個時候FINISH就會生成一個TestSessionBean.java。這個就是生成的實現類了。
7.而後就是給這個實現類填加一些方法了。怎麼填呢?別改源碼,行不通,要這麼作:
而後,
這樣就可以增長方法了,千萬別手動加代碼啊,這樣會讓你組件接口找不到你寫的方法!
而後把這個實現類的方法改爲:
public String helloWorld(){
return "Hello from lomboz!";
}//這個都知道是什麼意思吧?
到現在爲止就算咱們已經作出來一個EJB程序了,僅僅只是是缺乏主接口,組件接口的一些東西,但是不要怕,ECLIPSE會給你本身主動生成的。厲害吧?接下來咱們就需要作這麼幾步:
a) 把剛纔寫的這個EJBBEAN增長到EJB中.
b) 生成主接口,組件接口.
c) 把他部署到server上.
d) 寫一個客戶程序來實驗他.
EASY吧!真的很是EASY啊!
8.這是a)那一步,把他增長到EJB中。就是剛纔咱們在EJB MODULES中創建的那個EJB。
9.各位觀衆,現在你們以最快的速度把這個界面找到。
而後作這個操做:
這個操做就是完畢任務b)的任務。
10.OK了,現在開始作c)了,就是把剛纔寫好的EJB部署到server上,依照下邊兩個圖來作。
找控制檯,看看你的部署成功不成功,要是成功的話。就可以作d)了。不成功的話,再來一遍!要是還不成功的話。找我吧。
11.現在咱們就要寫一個客戶程序來實驗他了,真是興奮啊!
先又一次創建一個JAVA項目,這樣才幹顯示出EJB的功能嘛。
新創建的項目叫這個名MyEjbClientProject,事實上隨便叫什麼名了。
點NEXT進下一頁的時候一個要在PROJECT裏邊把咱們剛纔作的MyEJBClientProject給加上啊!不然白作了。
而後在NEW 菜單下找這個ITEM,CREATE AN EJB TEST CLIENT。點上。
12.這麼配置。這個事實上根本都不用說。
FINISH以後就能看見這個類:TestClient.java。
改動這種方法
public void testBean() {
try {
com.testing.session.TestSession
myBean = getHome().create();
//--------------------------------------
//This is the place you make your calls.
System.out.println(myBean.helloWorld());
} catch (RemoteException e) {
e.printStackTrace();
} catch (CreateException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
}
OK,SAVE而後執行!!!!成功!!!
OK,一個最簡單的EJB完畢。最終可以進入到第三章了啊!
前邊的程序好用吧,我認爲比書上寫的麻煩的程序強多了,因此仍是得用工具的。
最終有了點EJB方面的成就,趁熱打鐵,現在當即就看第三章。
第一章 開發會話BEAN
你們都知道了,會話BEAN又分爲狀態會話BEAN和無狀態會話BEAN。
書上總結了他們的共同點是:
1. 二者均可實現javax.ejb.SessionBean接口,所以具備一樣的容器回調。容器回調?現在中國的翻譯啊!
2. 二者都表示生成BEAN的客戶的專用資源。
3. 二者都可以構造一個進程或一個任務模型
4. 二者都可以更新共享數據,但不象實體BEAN中同樣表示共享數據。
NND,說了這麼多的共同點,說實話,我一點都不知道他說的是什麼意思?爲何要這麼專業??:(
只是不一樣點但是很是清楚:
狀態會話BEAN可以在客戶訪問之間保存數據,而無狀態則不可以!
管他呢,從樣例上找切入點。
無狀態會話BEAN的一個簡單樣例是計算數字,數字可以隨意複雜,但是僅僅在客戶程序中存放。哦!是這樣啊,事實上就至關沒有SESSION拉,但是好象還不能這麼說,姑且先這麼理解。
好拉,此次我決定採用書上的樣例,書上的樣例至關於一個BANK的系統!誇張,事實上就是加減數字的BEAN。
這樣,咱們仍是用(三)裏邊講的方法來部署他:
記得是一個無狀態會話BEAN的樣例啊。
新建一個實現類,個人是這麼寫的:
package com.testing.fund;
import javax.ejb.SessionBean;
/**
* @ejb.bean name="FundManger"
* jndi-name="FundMangerBean"
* type="Stateless"
*
*--
* This is needed for JOnAS.
* If you are not using JOnAS you can safely remove the tags below.
* @jonas.bean ejb-name="FundManger"
* jndi-name="FundMangerBean"
*
*--
**/
public abstract class FundMangerBean implements SessionBean {
/**
* @ejb.interface-method
* view-type="remote"
**/
public double add(double b,double a){
b=b+a;
return b;
}
/**
* @ejb.interface-method
* view-type="remote"
**/
public double withdraw(double b,double a){
b=b-a;
return b;
}
}
要記得這裏邊的ADD和WITHDRAW方法不是手動加上的啊,是用WIZARD的啊。要是不會的話,看個人(三)去!!!!
而後依照(三)裏邊的方法部署到JBOSS上邊去!
一切成功的話,仍是依照(三)的方法寫一個實現類!個人是這樣寫的,和書上有點不同,只是實現方法是全然同樣的!
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.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import com.testing.fund.FundManger;
public class FundTest extends JFrame implements ActionListener{
public FundTest(){
super("fund manger");
}
private com.testing.fund.FundMangerHome getHome() throws NamingException {
return (com.testing.fund.FundMangerHome) getContext().lookup(
com.testing.fund.FundMangerHome.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 testBean() {
buildGUI();
addWindowListener(new WindowAdapter(){public void WindowClosing(WindowEvent evt){System.exit(0);}});
CreateFund();
addFund.addActionListener(this);
withdraw.addActionListener(this);
currencyFomat=NumberFormat.getCurrencyInstance();
String currency=currencyFomat.format(0);
status.setText(msg+currency);
pack();
show();
}
public void actionPerformed(ActionEvent e){
String str=amout.getText();
try{
if(e.getSource()==addFund){
balance=(double)myBean.add(balance,Double.parseDouble(str));
currencyFomat=NumberFormat.getCurrencyInstance();
strBar=currencyFomat.format(balance);
status.setText(msg+strBar);
}
if(e.getSource()==withdraw){
balance=(double)myBean.withdraw(balance,Double.parseDouble(str));
currencyFomat=NumberFormat.getCurrencyInstance();
strBar=currencyFomat.format(balance);
status.setText(msg+strBar);
}
}catch(Exception ex){}
}
public void CreateFund(){
try {
myBean = getHome().create();
//--------------------------------------
//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 static void main(String[] args) {
FundTest test = new FundTest();
test.testBean();
}
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;
FundManger myBean;
NumberFormat currencyFomat;
}
執行爲JAVA 應用程序!成功了!界面例如如下:
現在來想一想爲何是無狀態會話BEAN了,事實上這個EJB就至關於一個簡單的應用程序後臺數據處理器!你的所有數據記錄信息所有都在前臺了,也就是上邊這個界面上邊。
OK,下節課就是狀態會話BEAN了。
哈哈,過了一個輕鬆的週末,又要開始寫東西咯。
週末原本也想寫,但是仍是認爲玩有意思,姑且放幾天假。
上次講的是無狀態會話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 生命週期:
OK,狀態會話BEAN就是這麼回事。應該是很是easy的東西,全然可以理解。
呵呵,你們看見了那個總回我帖子的QUGHOST了嗎?他是個人好朋友。
他有好多的搞笑故事,我和他商議了一下,準備把他的搞笑經歷發在個人一個新版塊裏,但是不知道他容許不容許。
OK,話歸正傳。我當即就要把第三章結束了,事實上第三章的會話BEAN到5就已經講完了,但是這裏邊另外一個很是關鍵的東西,那就是序列化。
序列化 (Serialization)
事實上很是easy了,就是把某個對象的所有東西都輸出到一個文件上。這裏也可以是別的東西。好多。
而後當你還想用他的時候,就再在這個文件上把這個對象的狀態等等的一些信息所有找回來。
真正發生了什麼
什麼會被序列化?
部分序列化
這些全是我從IBM抄下來的。但願對你們理解序列化有幫助。
把個人程序也給大家吧,我用的仍是那個狀態會話BEAN的那個EJB。
/*
* 建立日期 2004-7-5
*
* 更改所生成文件模板爲
* 窗體 > 首選項 > Java > 代碼生成 > 代碼和凝視
*/
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 com.test.session.*;
import java.io.*;
import javax.ejb.Handle;
/**
* @author sy
*
* 更改所生成類型凝視的模板爲
* 窗體 > 首選項 > Java > 代碼生成 > 代碼和凝視
*/
public class HandleTest {
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 testBean() {
try {
com.test.session.Stateful myBean = getHome().create(1000);
//System.out.println("adding 1000");
myBean.addFunds(1000);
System.out.println("adding 1000");
System.out.println("Now Account is:"+myBean.getBalance());
myBean.withdrawFunds(100);
System.out.println("withdrawing 100");
System.out.println("Now Account is:"+myBean.getBalance());
System.out.println("saving Handle");
saveHandle(myBean);
System.out.println("saving success");
myBean=null;
System.out.println("loading Handle");
myBean=loadHandle();
System.out.println("loading success");
System.out.println("Now Account is:"+myBean.getBalance()+",withdrawing 100");
myBean.withdrawFunds(100);
System.out.println("Now Account is:"+myBean.getBalance());
//--------------------------------------
//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 static void main(String[] args) {
HandleTest test = new HandleTest();
test.testBean();
}
private static void saveHandle(Stateful mybean){
try{
FileOutputStream fos=new FileOutputStream("symic");
ObjectOutputStream out=new ObjectOutputStream(fos);
out.writeObject(mybean.getHandle());
out.close();
}catch(Exception e){}
}
private static Stateful loadHandle(){
try{
FileInputStream fis =new FileInputStream("symic");
ObjectInputStream in =new ObjectInputStream(fis);
Handle handle=(Handle)in.readObject();
Stateful mybean=(Stateful)handle.getEJBObject();
in.close();
return mybean;
}catch(Exception x){}
return null;
}
}
事實上很是easy,看個人程序就好,而後找找SYMIC文件,看看他裏邊寫了些什麼東西。哈哈~~~~
說點別的,我近期發現原來ITLAY真的是個不錯的國家。但是好象在中國根本就沒有機會去吧!
在他那買東西很是合適啊!據說PRADA,AMANI在那有很是多TAX REBATE的店啊,僅僅有國內的一半價錢,並且東西全是最TOP 的CLASS。
真想去啊~~~~~~~~~~
呵呵!~~~
最終可以又出新東西了。上個禮拜一直沒忙,公司帶咱們出去HAPPY了。只是現在水好涼,不能下水。纔下去兩分鐘瞬間就被凍上來了。特別的冷。
恩,言歸正傳。我一直在看CMP,實體BEAN,但是發現要弄好ENTITYBEAN首先要作的是知道怎麼配置server,我找到了一篇配置JBOSSserver的指南,認爲不錯,就在這給你們SHARE一下。
http://www.uml.org.cn/j2ee/j2ee121505.htm
JBoss3.07的配置
這裏需要對JBoss進行配置的地方有兩處,一處爲JBoss的日誌信息選項,使得咱們從此在部署EJB時可以獲得關於部署的具體信息;另外一處爲JBoss中的數據源,使得咱們可以使用容器持久化管理的EntityBean對數據庫中的數據進行操做。
(1)首先咱們講述日誌信息選項的更改,進入JBoss所在文件夾下的server/default/conf文件夾,找到文件log4j.xml,將其用文本編輯器打開,將屬性做例如如下改動:
改動一:
< category name="org.jboss" >
< priority value="INFO" / >
< / category >
改動爲:
< category name="org.jboss" >
< priority value="INFO" / >
< / category>
改動二:
< appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender" >
< param name="Threshold" value="INFO" / >
< param name="Target" value="System.out" / >
改動爲:
< appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
< param name="Threshold" value="DEBUG"/>
< param name="Target" value="System.out"/>
將這些屬性進行改動以後,當咱們部署CMP EntityBean的時候將能看見JBoss針對所部署的CMP EntityBean本身主動產生的SQL插入語句與CMP EntityBean中包含的EJB-QL語句;並且在EntityBean被使用時發生的SQL查詢語句。
(2)接着咱們講述數據源的配置,第一步:咱們進入JBoss的文件夾下的docs/examples/jca文件夾,用文本編輯器打開mysql-service.xml,將當中的部份內容做例如如下改動:
< attribute name="JndiName">MySqlDS(數據源名稱)< / attribute>
< attribute name="ManagedConnectionFactoryProperties">
< properties>
< config-property name="ConnectionURL" type="java.lang.String" >jdbc:mysql://localhost:3306/resultmanager
(數據庫URL)
< / config-property>
< config-property name="DriverClass" type="java.lang.String" >com.mysql.jdbc.Driver
(數據庫驅動程序)
< / config-property>
< config-property
name="UserName" type="java.lang.String">DataBase(數據庫用戶)
< / config-property>
< config-property
name="Password" type="java.lang.String" >
sailing(數據庫用戶密碼)
< / config-property>
< / properties>
< /attribute>
將改動好的內容保存後,複製mysql-service.xml文件至JBoss文件夾下server/default/deploy 文件夾,此時deploy文件夾中的文件例如如下圖所看到的:
第二步,咱們將含有MySQL JDBC 2.0.14驅動程序的jar文件拷貝到JBoss安裝文件夾的server/default/lib文件夾下,此時lib文件夾中的文件例如如下圖所看到的:
現在咱們已經完畢了前期的配置工做,接下來咱們將講述CMP EntityBean的開發。
你們先依照以上的方法把JBOSS配置好,而後作好準備,咱們要開始CMP了,是數據庫的東西啊!!!
這個禮拜發生了好多事情啊。因此一直沒有時間寫。只是好多人問我怎麼不寫了啊?我是要寫的,現在就開始寫。(五)裏邊有個弟兄問個人IBM的站點在哪兒,個人收藏夾被DEL了,在GOOGLE上找了很久也沒找到,等我找到了,再發上去!
只是我之後會把我所有引用網址都給打上去。
好了,現在進入個人第4章咯。
開發EJB1.1實體BEAN,好象關於EJB實體BEAN還要分版本號的,只是現在我也不清楚爲何分版本號。
因爲數據庫BEAN這個地方的部署我也沒有搞清楚,因此我找了LOMBOZ上邊有個演示樣例程序,我們先把這個實驗好了,而後再照書作,OK?
摘自:http://www.objectlearn.com/support/docs/cmp.jsp
1-9步和我曾經寫的同樣,是怎樣創建J2EE項目的,這在我曾經的我文章裏有寫。
從第10步開始寫吧:
現在選中CMP這一項。 而後打上你本身中意的名字和包名,作NEXT。
而後就會進入到CMP這個界面了:事實上這個界面一看就知道是怎麼回事:
寫上表名,加上字段,一切簡單的OK了。記得啊,這裏DATASOURCE必定要和表裏邊的字段同樣。
還有相應的數據類型。可以加好多的字段,但是這個樣例裏邊就給了兩個字段,咱們也姑且用他這兩個字段。
對對了,還有就是設置一個PRIMARY KEY。搞定。FINISH。
這個時候ECLIPSE會本身就把你剛纔創建的AddressBean給打開。
而後你照着這個樣例改代碼,事實上不講爲何這麼改你們也都能明確:
package com.testing.cmp;
import javax.ejb.EntityBean;
/**
* @ejb.bean name="Address"
* jndi-name="AddressBean"
* type="CMP"
* primkey-field="name"
* schema="addressSchema"
* cmp-version="2.x"
*
* @ejb.persistence
* table-name="address"
*
* @ejb.finder
* query="SELECT OBJECT(a) FROM addressSchema as a"
* signature="java.util.Collection findAll()"
*
**/
public abstract class AddressBean implements EntityBean {
...
Modify the ejbCreate and ejbPostcreate methods to accepts two parameters:
/**
* The ejbCreate method.
*
* @ejb.create-method
*/
public java.lang.String ejbCreate(String name, String phone)
throws javax.ejb.CreateException {
setName(name);
setPhone(phone);
return null;
}
/**
* The container invokes this method immediately after it calls ejbCreate.
*
*/
public void ejbPostCreate(String name, String phone) throws javax.ejb.CreateException {
}
必須改POST和CREATE方法的內容啊。等下再告訴大家爲何要這樣作,對了,他裏邊還都幫你寫好了
setName();
setPhone();方法。直接用就行了。
而後SAVE,把剛纔寫的BEAN加到EJB裏邊,就是用J2EE->Add Ejb to Modules ,而後選擇你剛纔創建的EJB就行了。
下邊是最討厭的東西了,就是寫個EJBDOCLET,演示樣例給的是要改ejbGenerate.xml,NND,我根本就沒有這個文件,後來查了好多的資料,才知道,原來他那個是舊版本號,鬱悶~~~~~~舊版本號還要往上貼。
咱們3.X要改的是xdoclet.xml這個文件,這個文件保證有,你們找到以後就能看見,他裏邊有好多種配置server的數據庫的XML,我用的是JBOSS,因此就改這塊了。
< jboss
version="3.0"
unauthenticatedPrincipal="nobody"
xmlencoding="UTF-8"
destdir="${ejb.dd.dir}"
validatexml="false"
datasource="java:/MySqlDS"
datasourcemapping="mySQL"
preferredrelationmapping="PLEASE_MODIFY_THIS"
/ >
對了對了,講到這我找到了文章也不錯,是個小J寫的。給大家地址:
http://nemuneko.com/jboss/lomboz_cmp.html
因爲我近期在學日語,因此能看明確點,看不明確的就看圖理解咯~~~~~
注意啊,這裏是最關鍵的地方,我認爲,多是因爲我比較的笨。呵呵。
這裏的MySqlDS是我在(7)裏邊寫的在JBOSS裏邊配置的DEFUALT DATASOUCE,對了,我依照7裏邊寫的把mysql-service.xml這個配置文件放的位置好象不可以,我查了很久才找到,原來是你的EJB部署到哪一個文件夾下,這個mysql-service.xml文件就要跟着放到那個文件夾下,我機器上的是:D:/jboss-3.0.8/server/default/deploy
這個文件夾。最後就是把你的DB DRIVER放在和這個文件夾相應的LIB裏邊。
我機器上是這個:
D:/jboss-3.0.8/server/default/lib
我用的是Mysql 的driver,沒有問題的。
這樣配置就應該是沒問題了。
對了,把建表的語句也給大家:create table address ( name varchar(40) , phone varchar(40));
而後SAVE你的XDOCLET.XML。作GENERATE EJB FILES,和DEPLOY。
假如你成功的話,就能看見這麼一段的輸出:
22:50:11,031 INFO [MainDeployer] Starting deployment of package: mybeans.jar
22:50:11,302 INFO [EjbModule] Creating
22:50:11,342 INFO [EjbModule] Deploying Address
22:50:11,392 INFO [EjbModule] Created
22:50:11,392 INFO [EjbModule] Starting
22:50:11,822 INFO [Address] Table 'ADDRESS' already exists
22:50:11,842 INFO [EjbModule] Started
22:50:11,842 INFO [MainDeployer] Deployed package: mybeans.jar
必定要看輸出啊!很是關鍵的地方。
這樣就完畢了咱們的EJB CMP的BEAN了。再寫個CLIENT測試他就OK了。
把個人CLIENT程序給大家。
public void testBean() {
try {
Address address = getHome().create("John Smith", "+212 223 4455");
Collection all = getHome().findAll();
Iterator it = all.iterator();
while (it.hasNext()) {
Address element = (Address) it.next();
System.out.println("Name:" +
element.getName() + " Phone: " +element.getPhone() );
}
} catch (Exception e) {
e.printStackTrace();
}
}
IMPORT本身記得加啊~哈哈。
執行,成功!!!!!!
下次又的寫些理論上的東西,說實話,我最討厭理論的東西,因爲看上去真的很是頭大!~~
http://nemuneko.com/jboss/lomboz_cmp.html
下邊這段文字是在CN-JAVA下COPY過來的。(http://www.cn-java.com/target/news.php?news_id=2174)
1、entity Bean 表明了以持久存儲機制保存的一個實體,一般爲一個DB。客戶機經過entity bean的remote接口訪問它,實現該remote接口的對象被稱爲EJB對象。每一個
entity 對象都有一個標識符。
Entity Bean的特徵:持久的(分爲BMP和CMP),容許共享訪問,並且有一個主鍵。
2、編寫規則:
1.(1)實現EntityBean的接口。
(2).類定義爲PUBLIC。
(3).類不能定義爲abstract 和final。
(4).實現finaler方法(僅用於BMP)。
(5).實現商業方法。
(6).含有一個空構造器。
(7).不能實現finalize方法。
2.ejbCreate應知足的規則:
(1).訪問控制修飾符必須爲public 。
(2).返回類型必爲主鍵(僅對於BMP)。
(3).參數必須爲僉的JAVA RMI類型。
(4).方法修飾符不能爲final或static。
(5).throws子句可以包含CreateException以及應用程序中指定的其餘異常。
3.ejbPostCreate:每一個ejbCreate必須相應一個ejbPostCreate方法,一般爲空。
(1).參數的數量和類型必與相應ejbCreate方法匹配。
(2).訪問控制修飾符必須爲public。
(3).方法修飾符不能爲final和 static。
(4).返回類型必須爲void。
(5).throws子句包含CreateException以及應用程序中指定的其餘Exception。
4.ejbRemove方法:當EJB客戶調用此方法時,將刪除DB中該實體的狀態或EntityBean
被一個DB刪除直接移走。
5.ejbLoad方法:利用DB刷新實體變量。
ejbStore方法:將變量寫到DB中。
這兩個方法用於同步與存貯在DB中的值所相應的EntityBean實體變量。
6.finder方法的規則:
(1).必須ejbFindByPrimaryKey方法。
(2).finder方法務必須以ejbFind爲前綴。
(3).訪問控制修飾符必須爲public。
(4).方法修飾符不能爲final和 static。
(5).參數必須是合法的Java RMI類型。
(6).返回類型必須爲主鍵或主鍵的集合。
(7).throws子句包含FinderException以及應用程序中指定的其餘Exception。
7.商業方法
(1).方法名不能與EJB結構定義的方法名衝突。
(2).訪問控制修飾必爲public.
(3).方法修飾不能final 或static。
(4).參數必須爲合法的Java RMI類型。
三.Home接口的編寫規則:
1.Create方法的編寫規則:
(1).它與enterprise Bean類中相應的方法同樣,含有一樣的參數。
(2).返回Remote接口類型。
(3).throws子句包含相應的ejbCreate和 ejbPostCreate方法的異常。
2.finder講法的編寫規則:
(1).Remote接口中的每一個方法必須與enterpriseBean類中的方法匹配。
(2).每一個方法命名規則與enterprise Bean類中的方法的命名規則同樣。
(3).參數和返回類型必須是合法的Java RMI類型。
(4).throws子句包含RemoteException。