基于EJB的企業(yè)級信息系統(tǒng)開發(fā)技術(shù)-課堂_第1頁
基于EJB的企業(yè)級信息系統(tǒng)開發(fā)技術(shù)-課堂_第2頁
基于EJB的企業(yè)級信息系統(tǒng)開發(fā)技術(shù)-課堂_第3頁
基于EJB的企業(yè)級信息系統(tǒng)開發(fā)技術(shù)-課堂_第4頁
基于EJB的企業(yè)級信息系統(tǒng)開發(fā)技術(shù)-課堂_第5頁
已閱讀5頁,還剩290頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

企業(yè)級信息系統(tǒng)開發(fā)技術(shù)liukun@回顧:Struts2、Hibernate和Spring整合應(yīng)用分層架構(gòu)模式添加Spring開發(fā)能力添加Hibernate開發(fā)能力生成Hibernate所需的POJO類和映射文件映射文件在Spring配置文件中注冊開發(fā)DAO層繼承HibernateDaoSupport類super.getHibernateTemplate()Spring配置文件中注入sessionFactory開發(fā)Service層依賴注入實現(xiàn)WEB層Action類(action類+spring配置文件+struts配置文件)過濾器(過濾器類+struts配置文件)數(shù)據(jù)校驗(xml+命名+位置)分頁(Pager類+DAO層+Action層+JSP)第3講基于EJB的企業(yè)級信息系統(tǒng)開發(fā)技術(shù)第7章

JSF應(yīng)用第8章開發(fā)EJB3.0應(yīng)用第9章JAVA持久API第7章

JSF應(yīng)用第7章

JSF應(yīng)用ServletAPI請求/響應(yīng)模型收集HTML頁信息servlet執(zhí)行業(yè)務(wù)邏輯在HTML上顯示結(jié)果HTMLServlet業(yè)務(wù)

邏輯第7章

JSF應(yīng)用ServletAPI缺點維護問題:HTML嵌入servlet代碼第7章

JSF應(yīng)用JavaServerPages體系結(jié)構(gòu)優(yōu)于ServletAPI模型-視圖-控制器(MVC)模式:表示層與業(yè)務(wù)邏輯層分離代碼重用易于維護JSPJSPJSPServletJavaBeanEJBWeb服務(wù)視圖控制器模型第7章

JSF應(yīng)用Struts2Struts是MVC設(shè)計模型的開放源代碼Struts是通過一組Java類和JSP標簽庫實現(xiàn)的Struts有助于管理Web應(yīng)用開發(fā)和維護,加快開發(fā)過程第7章

JSF應(yīng)用Web應(yīng)用開發(fā)截至目前,JavaWeb技術(shù)已被公認為具有:移植性擴展性靈活性可用于構(gòu)建大型企業(yè)解決方案但不適于快速應(yīng)用開發(fā)(RAD)縮短學習過程構(gòu)建中小企業(yè)(SMB)解決方案第7章

JSF應(yīng)用——學習要點1.JSF簡介2.第一個JSF程序3.ManagedBean4.JSF標簽第7章

JSF應(yīng)用JSF簡介7.1JSF簡介JavaServerFaces:JavaServerFaces(JSF)技術(shù)是構(gòu)建Web應(yīng)用的框架JSF將Web應(yīng)用框架開發(fā)推進了一步,以ServletAPI和JSP技術(shù)為基礎(chǔ)功能性體系結(jié)構(gòu)更理想,RAD,便于維護ServletAPIJSP/ServletAPIJSFStruts7.1JSF簡介JSF增強了JSP/ServletAPI更多內(nèi)置Java類更多標簽庫采用IBM工具提高操作能力ServletAPIJSP/ServletAPIStruts增加內(nèi)置功能JSF7.1JSF簡介JSF是一種開放標準:JSR(JavaSpecificationRequests)127JavaCommunityProcess網(wǎng)站:JSF包括在JavaEE中(以前稱為J2EE)JSF目標提高J2EEWeb應(yīng)用開發(fā)速度(RAD)拖放組件事件驅(qū)動模型消除大量手工編碼便于與數(shù)據(jù)源集成非J2EE程序員易于使用7.1JSF簡介JSF與StrutsJSF與Struts功能上有部分重疊JSF是一個更完整的模型開發(fā)團隊對Struts和JSF有不同的設(shè)計目標IBM工具和中間件都支持JSF與Struts,但更側(cè)重JSF數(shù)據(jù)庫JavaBeanFacesServletEJB模型視圖控制器JSPs7.1JSF簡介JSF特點:可以通過一組標準的、可重用的服務(wù)器端組件來創(chuàng)建用戶界面。提供了一組JSP標簽以訪問這些組件。在表單重新顯示時,透明的保存狀態(tài)信息并重新填充表單。提供了實現(xiàn)自定義組件的框架。封裝了事件處理和組建呈現(xiàn),以便可以使用標準的JSF組件或自定義組件來支持除HTML之外的標記語言。讓工具開發(fā)商可以開發(fā)針對標準WEB應(yīng)用開發(fā)程序框架的IDE。7.1JSF簡介JSF技術(shù)組成一組用于表示用戶界面組件并管理其狀態(tài)、處理事件和驗證輸入的JavaAPI,這些API支持國際化和可訪問性。一個用于JSP頁面中表示JSF組件的自定義標簽庫。補充:典型的JavaEE應(yīng)用系統(tǒng)層次結(jié)構(gòu)補充:JavaEE容器基于組件和平臺獨立的JavaEE使分層的企業(yè)分布式應(yīng)用程序容易開發(fā),因為各種應(yīng)用的功能邏輯被封裝在可重用的JavaEE組件中。另外JavaEE服務(wù)器以容器的形式為所有JavaEE組件提供底層公共服務(wù),因此您不必再為這些底層公共服務(wù)傷腦筋,而可以專注于解決應(yīng)用系統(tǒng)的商業(yè)問題。容器(Container)是組件和支持組件功能的底層特定平臺(如數(shù)據(jù)庫、分布式的網(wǎng)絡(luò)環(huán)境及Java虛擬機等)之間的接口。在運行Web組件、企業(yè)Bean組件或者JavaEE客戶端組件之前,您必須將它們裝配到一個JavaEE應(yīng)用程序中,并部署它們到容器中。補充:JavaEE容器JavaEE的容器類型補充:JavaEE應(yīng)用打包與部署JAR/WAR/EAR文件格式JAR是Java技術(shù)中的一種與平臺無關(guān)的文件格式,它允許將許多文件組合成一個壓縮文件。JAR文件格式以流行的

ZIP文件格式為基礎(chǔ)。與

ZIP文件不同的是,JAR文件不僅用于壓縮和發(fā)布,而且還用于部署和封裝庫、組件和插件程序,并可被像編譯器和

JVM這樣的工具直接使用。在

JAR中包含特殊的文件,如

manifests和部署描述符,用來指示工具如何處理特定的

JAR。補充:JavaEE應(yīng)用打包與部署JAR/WAR/EAR文件格式WAR和EAR文件也是Java技術(shù)中的一種與平臺無關(guān)的文件格式,也同樣允許將許多文件組合成一個壓縮文件。與JAR文件不同的是,WAR文件除了可以組合JSP文件和servlet類文件等web組件程序文件之外,還可以包含GIF文件、靜態(tài)HTML文件等多種其它類型的文件。EAR文件則主要用于由多個JavaEE應(yīng)用模塊所構(gòu)成的一個完整應(yīng)用程序的打包,其可以包含多個JAR文件和WAR文件。從打包粒度上講,按由小至大的順序排列,分別是JAR、WAR和EAR。補充:JavaEE應(yīng)用打包與部署JAR、WAR和EAR文件的一般目錄結(jié)構(gòu)補充:JavaEE應(yīng)用開發(fā)角色企業(yè)Bean開發(fā)者提供企業(yè)Bean的EJBJAR文件Web組件開發(fā)者的工作任務(wù)是提供WAR文件JavaEE應(yīng)用程序客戶端開發(fā)者也提供一個JAR文件應(yīng)用程序組裝者將從組件開發(fā)者獲得的組件文件裝配成一個JavaEE應(yīng)用程序EAR文件。應(yīng)用程序部署者和系統(tǒng)管理員配置和部署JavaEE應(yīng)用程序,在程序運行時管理計算機和網(wǎng)絡(luò)結(jié)構(gòu),并且監(jiān)控運行時環(huán)境。包括設(shè)置事務(wù)控制、安全屬性和指定數(shù)據(jù)庫連接。補充:JavaEE應(yīng)用服務(wù)器補充:JavaEE應(yīng)用服務(wù)器SunGlassFish金蝶ApusicJBoss第8章開發(fā)EJB3.0應(yīng)用8.1EJB3.0概述8.2會話Bean8.3消息驅(qū)動Bean8.1EJB3.0概述EnterpriseJavaBeans(EJB)是一種服務(wù)器端的軟件組件模型,是J2EE的基礎(chǔ)和最重要的部分。如今開發(fā)電于商務(wù)平臺已大量使用組件技術(shù),這是因為組件技術(shù)提供了服務(wù)器上的自治、企業(yè)級和分布式功能,并幫助開發(fā)者在不同顆粒度級別上定義和封裝系統(tǒng)功能。8.1.1傳統(tǒng)的EJB引入EnterpriseJavaBeans(EJB)是為了構(gòu)建分布式組件。最初,該技術(shù)承諾可以解決CORBA的所有問題并降低其復(fù)雜性。作為J2EE的核心,EJB經(jīng)歷了幾次較大的修訂,并加入了許多特性,因而變得臃腫起來。隨著EJB規(guī)范的相繼發(fā)布,它還變得越來越復(fù)雜了。由于其復(fù)雜性和本身龐大的體系,傳統(tǒng)的EJB技術(shù)被喻為一頭笨重的大象。理解分布式EJB分布式特點:8.1.2EJB3.0簡介Domorewithlesswork——JavaEE5的正式宣言在JavaEE5中采用了EJB3.0技術(shù)規(guī)范實現(xiàn)的EJB技術(shù)在這方面作出了改進的努力。EJB3.0減輕了開發(fā)人員進行底層開發(fā)的工作量,它取消或最小化了很多(以前這些是必須實現(xiàn))回調(diào)方法的實現(xiàn),并且降低了實體Bean及O/R映射模型的復(fù)雜性。

EJB3.0規(guī)范與JavaPersistence1.0的規(guī)范緊密結(jié)合,借鑒了輕量級企業(yè)數(shù)據(jù)對象的很多優(yōu)點,將JavaPersistence1.0的規(guī)范運用到EJB3.0的EntityBean中,大大提高了EntityBean的開發(fā)效率,也使EntityBean更加通用、簡潔、輕巧。32+18.1.3EJB3.0中的Bean類型EJB3.0中的組件分為三個主要類別:會話Bean消息驅(qū)動Bean實體Bean根據(jù)Bean處理狀態(tài)、事務(wù)和持久性的方式這些類別還可以進一步細分。會話Bean可分為無狀態(tài)會話Bean和有狀態(tài)會話Bean實體Bean可分為CMP(ContainerMangementPersitence)方式的實體Bean和BMP(BeanMangementPersitence)方式的實體Bean。第8章開發(fā)EJB3.0應(yīng)用8.1EJB3.0概述8.2會話Bean8.3消息驅(qū)動Bean8.2會話Bean8.2.1會話Bean的生命周期8.2.2無狀態(tài)會話Bean8.2.3有狀態(tài)會話Bean8.2.4會話Bean實例8.2.5將會話Bean發(fā)布為web服務(wù)8.2.1會話Bean的生命周期如果是無狀態(tài)無狀態(tài)sessionbean,其生命周期如下:1)當bean實例不存在時,容器調(diào)用bean類的newInstance()方法,開始bean的生命周期。2)接著,容器調(diào)用bean的setSessionContext()方法,進而調(diào)用ejbCreate()方法。此時,bean就創(chuàng)建完畢,其方法可供調(diào)用了。3)當容器不需要該bean實例的時候,容器調(diào)用bean的ejbRemove()方法,刪除該實例。8.2.1會話Bean的生命周期而有狀態(tài)sessionbean的生命周期則復(fù)雜一些,因為涉及到鈍化、激活和事務(wù),其生命周期如下:1)當客戶調(diào)用create(args)時,容器調(diào)用newInstance()方法,剩下來的創(chuàng)建過程同無狀態(tài)sessionbean。2)有狀態(tài)sessionbean的方法執(zhí)行分為事務(wù)與非事務(wù)兩種情況。3)鈍化與激活。bean長久沒有被操作時,容器會決定該bean是否應(yīng)該被鈍化。鈍化后一段時間仍然沒有被操作,容器會將其從存儲介質(zhì)中刪除。若鈍化后被調(diào)用,容器會激活該bean,讓其重新載入內(nèi)存。4)當容器不需要該bean實例的時候,容器調(diào)用ejbRemove()方法,刪除該實例。8.2.2無狀態(tài)會話Bean無狀態(tài)會話Bean是這樣一種EJB,其服務(wù)的業(yè)務(wù)過程只需要單個業(yè)務(wù)方法即可完成。由于它們不需維護客戶多個方法調(diào)用間的會話狀態(tài),因此它是無狀態(tài)的。在每次方法調(diào)用結(jié)束后,EJB容器可能會銷毀無狀態(tài)會話Bean實例,或者實例化新的實例,或者清除掉上次方法調(diào)用中的相關(guān)信息。當然,EJB容器還可能保留前一會話Bean實例,并且供其他所有客戶使用,從而實現(xiàn)同一會話Bean實例的重用,至于具體的實現(xiàn)策略則與具體EJB容器相關(guān)。8.2.3有狀態(tài)會話Bean有狀態(tài)會話Bean是這樣一種EJB,即其服務(wù)的業(yè)務(wù)過程能夠延伸到多個方法請求或者事務(wù)中。為完成這種業(yè)務(wù)過程,有狀態(tài)會話Bean需要為單個客戶保存狀態(tài)信息。如果在方法調(diào)用期間有狀態(tài)會話Bean的狀態(tài)發(fā)生改變,則這種改變必須反映到同一客戶的隨后調(diào)用中。8.2.4會話Bean實例在EJB3.0規(guī)范中,寫一個無狀態(tài)會話Bean(StatelessSessionBean)只需要為一個普通的Java類加上@Stateless注釋(annotation)就可以了。這個Bean可以實現(xiàn)某個業(yè)務(wù)接口(BusinessInterface)也可以不實現(xiàn)它。8.2.5將會話Bean發(fā)布為web服務(wù)在EJB2.1就規(guī)定了無狀態(tài)會話Bean(StatelessSessionBean)對WebService的支持,而在EJB3.0中運用注釋(annotation)就可以輕松把一個無狀態(tài)會話Bean發(fā)布為Web服務(wù)。需要注意的是:只有無狀態(tài)會話Bean可以發(fā)布成WebService;要暴露給Web服務(wù)客戶端的業(yè)務(wù)方法必須是public的;Bean類可以通過@WebService注釋的endpointInterface元素實現(xiàn)一個ServiceEndpointInterface(SEI),但這不是必須的,如果沒有這樣一個endpointInterface,SEI也能被隱含定義。例子:開發(fā)一個會話bean例子:開發(fā)一個會話bean首先我們先定義一個接口:HelloEjb.java然后實現(xiàn)該接口:HelloEjbBean.javapackage.ujn.ejb.test;public

interfaceHelloEjb{ public

Stringhello(Stringname);}package.ujn.ejb.test.impl;import.ujn.ejb.test.HelloEjb;publicclassHelloEjbBeanimplementsHelloEjb{publicStringhello(Stringname){ //TODOAuto-generatedmethodstub

returnname+":helloEJB!";}}例子:開發(fā)一個會話bean剛才的實現(xiàn)類只是一個普通的Java類,并不是EJB。下面我們給實現(xiàn)類加入兩個注釋@Stateless,@Remote,第一個注釋定義這是一個無狀態(tài)會話Bean,第二個注釋指明這個無狀態(tài)Bean的remote接口。package.ujn.ejb.test.impl;import.ujn.ejb.test.HelloEjb;@Stateless@Remote(HelloEjb.class)publicclassHelloEjbBeanimplementsHelloEjb{publicStringhello(Stringname){ //TODOAuto-generatedmethodstub

returnname+":helloEJB!";}}例子:開發(fā)一個會話bean打包發(fā)布到JBoss中去(copy到JBoss的\server\default\deploy目錄下)。例子:開發(fā)一個會話bean我們寫一個client來測試該EJB首先把JBoss的client目錄下所有的jar包添加到該工程的classpath中然后新建一個測試類:TestClient.javapackagetest;//省略掉importpublicclassTestClient{publicstaticvoidmain(String[]args){ Propertiesprops=newProperties(); props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory"); props.setProperty("vider.url","localhost:1099"); InitialContextctx; try{ ctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbBean/remote"); System.out.println(helloejb.hello("劉鹍")); }catch(NamingExceptione){ System.out.println(e.getMessage()); }}}例子:開發(fā)一個會話bean著重說一下JbossEJBJNDI名稱默認的命名規(guī)則:1)如果EJB打包進后綴為*.ear的JavaEE發(fā)布文件,默認的JNDI路徑名稱是訪問本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local訪問遠程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote例:EJBHelloEjb打包進名為HelloEjb.ear的JavaEE應(yīng)用,訪問它遠程接口的JNDI名是:HelloEjb/HelloEjbBean/remote2)如果EJB應(yīng)用打包成后綴為*.jar的發(fā)布文件,默認的JNDI路徑名稱是訪問本地接口:EJB-CLASS-NAME/local訪問遠程接口:EJB-CLASS-NAME/remote例:HelloEjb應(yīng)用打包成HelloEjb.jar文件,訪問它遠程接口的JNDI名稱是:HelloEjbBean/remote另外有一點要注意:EJB-CLASS-NAME是不帶包名的,如.ujn.test.HelloEjbBean只需取HelloEjbBean。例子:開發(fā)一個會話bean運行結(jié)果:下面我們再看一個只存在Local接口的無狀態(tài)SessionBean,新建HelloEjbLocalBean.java,同樣實現(xiàn)HelloEjb這個接口。package.ujn.ejb.test.impl;importjavax.ejb.Local;importjavax.ejb.Stateless;import.ujn.ejb.test.HelloEjb;@Stateless@Local(HelloEjb.class)publicclassHelloEjbLocalBeanimplementsHelloEjb{ publicStringhello(Stringname){ returnname+":helloLocalStatelessEJB!"; }}例子:開發(fā)一個會話bean新建一個index.jsp<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%><%@pageimport="javax.naming.*,.ujn.ejb.test.HelloEjb"%><!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"><html><body><% Propertiesprops=newProperties(); props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory"); props.setProperty("vider.url","localhost:1099"); props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming"); InitialContextctx; try{ ctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbLocalBean/local"); out.println(helloejb.hello("劉鹍")); }catch(NamingExceptione){ System.out.println(e.getMessage()); }%></body></html>例子:開發(fā)一個會話bean通過eclipse把該webproject也部署到JBoss中去通過瀏覽器訪問該jsp頁面,結(jié)果如下:例子:開發(fā)一個會話bean思考:Spring跟EJB的bean管理思想對比Springxml管理EJBJNDI管理得到一個bean的實例:

Spring這樣得到:

EJB這樣得到:…

ApplicationContextctx=newFileSystemXmlApplicationContext("src/applicationContext.xml"); Humanhuman=null; human=(Human)ctx.getBean("chinese"); human.speak();……

InitialContextctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbLocalBean/local");…例子:開發(fā)一個會話bean下面我們來開發(fā)一個有狀態(tài)的會話bean:我們用課本上做加法的例子(適當修改)首先新建接口Add.java,該接口必須實現(xiàn)Serializable接口,并實現(xiàn)該接口:package.ujn.ejb.test;importjava.io.Serializable;publicinterfaceAddextendsSerializable{publicintdoAdd(inti,intj);publicintgetTotal();}package.ujn.ejb.test.impl;importjavax.ejb.Remote;importjavax.ejb.Stateful;import.ujn.ejb.test.Add;@Stateful@Remote(Add.class)publicclassAddBeanimplementsAdd{ privateinttotal=0; privateintaddresult=0; publicintdoAdd(inti,intj){ addresult=i+j; returnaddresult; } publicintgetTotal(){ total=total+addresult; returntotal; }}例子:開發(fā)一個會話bean新建一個client測試類TestStateful.java…publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstub Propertiesprops=newProperties(); props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory"); props.setProperty("vider.url","localhost:1099"); props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming"); InitialContextctx; try{ ctx=newInitialContext(props); Addaddejb=(Add)ctx.lookup("AddBean/remote"); System.out.println("addresult:"+addejb.doAdd(1,2)); System.out.println("total:"+addejb.getTotal()); System.out.println(""); Addaddejb1=(Add)ctx.lookup("AddBean/remote"); System.out.println("addresult:"+addejb1.doAdd(3,4)); System.out.println("total:"+addejb1.getTotal()); }catch(NamingExceptione){ System.out.println(e.getMessage()); }}…例子:開發(fā)一個會話bean把EJB打包,部署到JBoss的\server\default\deploy目錄下運行結(jié)果如下:企業(yè)級信息系統(tǒng)開發(fā)技術(shù)濟南大學信息學院劉鹍liukun@回顧:EJBJAR、WAR和EAREJB:32+1會話BeanSLSBSFSB會話Bean部署回顧:EJB會話bean調(diào)用InitialContextLookup與Spring對比Bean的管理方式SLSB、SFSB與Spring中對應(yīng)…

InitialContextctx=newInitialContext(props); HelloEjbhelloejb=(HelloEjb)ctx.lookup("HelloEjbLocalBean/local");…回顧:EJBJNDIJavaNamingandDirectoryInterface為開發(fā)人員提供了查找和訪問各種命名和目錄服務(wù)的通用、統(tǒng)一的方式。借助于JNDI提供的接口,能夠通過名字定位用戶、機器、網(wǎng)絡(luò)、對象服務(wù)等。NamingDNSDirectory簡單的RDBMSJNDI的主要用途:使用JNDI獲得對JAVA事務(wù)API中的UserTransaction接口的引用借助于JNDI,連接到資源工廠,比如JDBC、JMS等。在EJB組件中,借助于JNDI查找其他的EJB組件回顧:EJBJNDI編程:JNDI類Javax.naming.Context(interface)

其中INITIAL_CONTEXT_FACTORY

和PROVIDER_URLJavax.naming.Naming(interface)Javax.naming.InitialContext(class)

其中l(wèi)ookup()、list()、bind()、createSubcontext()、unbind()

Java.util.Propertes(class)

其中setProperties()和getProperties()、list()回顧:EJBJNDI編程:設(shè)置JNDI訪問環(huán)境信息

在進行JNDI查找前,我們必須設(shè)置應(yīng)用服務(wù)器的上下文信息,主要是設(shè)置JNDI驅(qū)動的類名(java.naming.factory.initial)和命名服務(wù)提供者的URL(vider.url)。java.naming.factory.initial或Context.INITIAL_CONTEXT_FACTORY:環(huán)境屬性名,用于指定InitialContext工廠(作者稱它為JNDI驅(qū)動更容易理解),它類似于JDBC指定數(shù)據(jù)庫驅(qū)動類。因為本例子連接的是JbossNS(命名服務(wù)的實現(xiàn)者),所以使用Jboss提供的驅(qū)動類:erfaces.NamingContextFactory。vider.url或Context.PROVIDER_URL:環(huán)境屬性名,包含提供命名服務(wù)的主機地址和端口號。它類似于JDBC指定數(shù)據(jù)庫的連接URL。連接到JbossNS的URL格式為:jnp://host:port,該URL的“jnp:”部分是指使用的協(xié)議,JBoss使用的是基于Socket/RMI的協(xié)議。host為主機的地址,port為JNDI服務(wù)的端口。除了host之外,其他部分都是可以不寫的?;仡櫍篍JBJNDI編程:編程過程補充:JNDI的所有配置信息可以保存在perties中。//設(shè)置初始化上下文的參數(shù),主要是設(shè)置JNDI驅(qū)動的類名//Java.naming.factory.initial和提供命名服務(wù)的的URL-Jvider.url,//Java.naming.factory.initial的值因提供JNDI服務(wù)器的不同而不同,//Jvider.url的值包括提供命名服務(wù)的主機地址和端口號。Propertiesp=newProperties();p.setProperty("Java.naming.factory.initial","erfaces.NamingContextFactory");p.setProperty("Jvider.url","localhost:1099");//初始化上下文環(huán)境,生成一個上下文實例InitialContextjndiContext=newInitialContext(p);ObjectlookupObject=jndiContext.lookup(“jndiname”);回顧:EJB強調(diào)一下JbossEJBJNDI名稱默認的命名規(guī)則:1)如果EJB打包進后綴為*.ear的JavaEE發(fā)布文件,默認的JNDI路徑名稱是訪問本地接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local訪問遠程接口:EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote例:EJBHelloEjb打包進名為HelloEjb.ear的JavaEE應(yīng)用,訪問它遠程接口的JNDI名是:HelloEjb/HelloEjbBean/remote2)如果EJB應(yīng)用打包成后綴為*.jar的發(fā)布文件,默認的JNDI路徑名稱是訪問本地接口:EJB-CLASS-NAME/local訪問遠程接口:EJB-CLASS-NAME/remote例:HelloEjb應(yīng)用打包成HelloEjb.jar文件,訪問它遠程接口的JNDI名稱是:HelloEjbBean/remote另外有一點要注意:EJB-CLASS-NAME是不帶包名的,如.ujn.test.HelloEjbBean只需取HelloEjbBean。第8章開發(fā)EJB3.0應(yīng)用8.1EJB3.0概述8.2會話Bean8.3消息驅(qū)動Bean8.3消息驅(qū)動Bean8.3.1為什么要使用消息8.3.2Java消息服務(wù)8.3.3集成JMS和EJB8.3.4開發(fā)消息Bean8.3.1為什么要使用消息當服務(wù)器需要耗費較長的時間(幾小時或著有時甚至是幾天)來對這些請求作出響應(yīng)??蛻舳顺绦颍☉?yīng)用)要與服務(wù)器連接并耗費如此長的時間來等待結(jié)果,這是毫無意義的。因此通信應(yīng)該是異步發(fā)生的。動機:異步松耦合可靠性廣播面向消息8.3.1為什么要使用消息消息系統(tǒng)的運行機制:一旦請求被提交,它就被放置在隊列中,同時客戶端與服務(wù)器斷開連接。然后服務(wù)器從指定的隊列中選出請求進行處理,并將處理得到的消息放置在另一個消息隊列里。最后,客戶端程序從這個隊列中選出處理結(jié)果,獲得響應(yīng)。8.3.2Java消息服務(wù)Java消息服務(wù)(JavaMessageService,JMS)是一個JavaAPI,它定義了消息的客戶程序如何以一種標準化的形式與底層的消息服務(wù)提供者交互。JMS提供了一種接口,底層消息服務(wù)提供者通過該接口向客戶程序提供JMS消息服務(wù)。JMS提供了點對點消息模式(Point-to-Point)和發(fā)布-訂閱消息模式(Publish-Subscribe)。

8.3.2Java消息服務(wù)消息處理的類型:發(fā)布/訂閱點對多注冊者注冊到一定的Topic,發(fā)布者將消息分發(fā)到訂閱者點對點通過消息隊列實現(xiàn)Producer1Producer2TopicConsumer1Consumer2Producer1Producer2QueueConsumer18.3.3集成JMS和EJB會話Bean可以發(fā)送JMS消息并同步接收JMS消息,但不是異步方式。為避免占用服務(wù)器資源,可能希望在服務(wù)器端組件中使用異步接收。要異步接收消息,就使用消息驅(qū)動型Bean。異步接收8.3.4開發(fā)消息Bean消息驅(qū)動Bean的業(yè)務(wù)接口已經(jīng)被定義,對于使用JMS來說那就是MessageListener接口,這個接口定義了OnMessage方法。EJB2.0:強制要求必須實現(xiàn)MessageDrivenBean接口。EJB3.0:可以實現(xiàn)也可以不實現(xiàn),但實現(xiàn)類必須使用MessageDriven注釋。EJB3.0中開發(fā)消息驅(qū)動Bean:實現(xiàn)MessageListener接口,實現(xiàn)OnMessage方法。使用MessageDriven注釋。8.3.4開發(fā)消息Bean8.3.4開發(fā)消息Bean開發(fā)一個消息驅(qū)動Bean新建一個EJBProject新建一個MDB類,實現(xiàn)MessageListener接口,類型選擇Queue(Point-to-Point)8.3.4開發(fā)消息Bean完成HelloMDB.java的代碼8.3.4開發(fā)消息Bean……@MessageDriven(activationConfig={ @ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Auto-acknowledge"), @ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination",propertyValue="queue/myQueue")

})publicclassHelloMDBimplementsMessageListener{ publicvoidonMessage(Messagemsg){

try{ if(msginstanceofTextMessage){ TextMessagetmsg=(TextMessage)msg; Stringcontent=tmsg.getText(); System.out.println(content); } }catch(Exceptione){ e.printStackTrace(); } }}修改jbossmq-destinations-service.xml(該文件在jboss安裝目錄\server\default\deploy\jms下)打包,發(fā)布該消息驅(qū)動bean8.3.4開發(fā)消息Bean<mbeancode="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=myQueue"><dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends></mbean>測試該消息驅(qū)動Bean,新建測試類TestMDB.java8.3.4開發(fā)消息Beanpublicstaticvoidmain(String[]args){QueueConnectionconn=null;QueueSessionsession=null;Propertiesprops=newProperties();props.setProperty("java.naming.factory.initial","erfaces.NamingContextFactory");props.setProperty("vider.url","localhost:1099");props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:erfaces");try{InitialContextctx=newInitialContext(props);QueueConnectionFactoryfactory=(QueueConnectionFactory)ctx.lookup("ConnectionFactory");conn=factory.createQueueConnection();session=conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);Destinationdestination=(Queue)ctx.lookup("queue/myQueue");MessageProducerproducer=session.createProducer(destination);TextMessagemsg=session.createTextMessage("這是我的第一個MessageDrivenBean!");producer.send(msg);}catch(Exceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}finally{try{session.close();conn.close();}catch(JMSExceptione){e.printStackTrace();}}}運行結(jié)果:8.3.4開發(fā)消息Bean8.3.4開發(fā)消息Bean注意:設(shè)置Queue可以不在jbossmq-destinations-service.xml文件中,也可以放在自己的EJB中,方法如下:在META-INF下新建test-service.xml<?xmlversion="1.0"encoding="UTF-8"?><server><mbeancode="org.jboss.mq.server.jmx.Queue"name="jboss.mq.destination:service=Queue,name=myQueue"><attributename="JNDJName">queue/myQueue</attribute><dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends></mbean></server>8.3.4開發(fā)消息Bean補充:META-INF中的配置文件ejb-jar.xml配置EJB的mappedName,默認通過注釋指定。*-service.xml配置消息到達的目標地址。jboss.xml為EJB指定JNDI名稱,默認JBoss會自動生成JNDI名稱。8.3.4開發(fā)消息Beanejb-jar.xml例子:<?xmlversion="1.0"encoding="UTF-8"?><ejb-jarxmlns="/xml/ns/javaee"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/xml/ns/javaee/xml/ns/javaee/ejb-jar_3_0.xsd"version="3.0"><enterprise-beans><session><ejb-name>HelloEjbBean</ejb-name><mapped-name>HelloEjbBean</mapped-name></session></enterprise-beans></ejb-jar>8.3.4開發(fā)消息Bean*-service.xml<?xmlversion="1.0"encoding="UTF-8"?><server><mbeancode="org.jboss.mq.server.jmx.Queue"name="jboss.mq.destination:service=Queue,name=myQueue"><attributename="JNDJName">queue/myQueue</attribute><dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends></mbean></server>8.3.4開發(fā)消息Beanjboss.xml<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEjbossPUBLIC"-//JBoss//DTDJBOSS4.2//EN""/j2ee/dtd/jboss_4_2.dtd"><jboss> <enterprise-beans> <session>

<ejb-name>HelloEjbBean</ejb-name> <jndi-name>helloEjb/remote</jndi-name> </session> </enterprise-beans></jboss>下面我們傳遞一下對象,新建一個對象User.java,該對象要實現(xiàn)Serializable接口。8.3.4開發(fā)消息BeanUser.java代碼:8.3.4開發(fā)消息BeanpublicclassUserimplementsSerializable{privateStringname;//姓名privateStringaddress;//地址publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}publicStringgetAddress(){returnaddress;}publicvoidsetAddress(Stringaddress){this.address=address;}}修改HelloMDB.java8.3.4開發(fā)消息Bean……publicclassHelloMDBimplementsMessageListener{ publicvoidonMessage(Messagemsg){ try{ if(msginstanceofTextMessage){ TextMessagetmsg=(TextMessage)msg; Stringcontent=tmsg.getText(); System.out.println(content); }elseif(msginstanceofObjectMessage){ ObjectMessageomsg=(ObjectMessage)msg; Userme=(User)omsg.getObject(); Stringcontent="Name:"+me.getName()+"||Address:"+me.getAddress(); System.out.println(content); } }catch(Exceptione){ e.printStackTrace(); } }}新建測試類QueueTestObject.java8.3.4開發(fā)消息Beanpublicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubQueueConnectionconn=null;QueueSessionsession=null;try{ InitialContextctx=newInitialContext(); QueueConnectionFactory factory=(QueueConnectionFactory)ctx.lookup("ConnectionFactory"); conn=factory.createQueueConnection(); session=conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE); Destinationdestination=(Queue)ctx.lookup("queue/myQueue"); MessageProducerproducer=session.createProducer(destination);

Userme=newUser(); me.setName("劉鹍"); me.setAddress("濟南大學信息學院"); producer.send(session.createObjectMessage(me));}catch(Exceptione){ e.printStackTrace();}finally{ try{ session.close(); conn.close(); }catch(JMSExceptione){ e.printStackTrace(); }}}8.3.4開發(fā)消息Bean下面我們來看一個topic的例子:新建一個HelloMDBTopicBean.java,類型選擇Topic8.3.4開發(fā)消息BeanHelloMDBTopicBean.java代碼如下……@MessageDriven(mappedName="jms/HelloMDBTopicBean",activationConfig={@ActivationConfigProperty(propertyName="acknowledgeMode",propertyValue="Auto-acknowledge"),@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Topic"),@ActivationConfigProperty(propertyName="subscriptionDurability",propertyValue="Durable"),@ActivationConfigProperty(propertyName="clientId",propertyValue="HelloMDBTopicBean"),@ActivationConfigProperty(propertyName="subscriptionName",propertyValue="HelloMDBTopicBean"),@ActivationConfigProperty(propertyName="destination",propertyValue="topic/myTopic")})publicclassHelloMDBTopicBeanimplementsMessageListener{ publicvoidonMessage(Messagemessage){

try{ TextMessagetopicmsg=(TextMessage)message; Stringcontent=topicmsg.getText(); System.out.println(this.getClass().getName()+":"+content); }catch(Exceptione){ e.printStackTrace(); } }}8.3.4開發(fā)消息Bean在META-INF的test-service.xml中配置該消息到達的目標地址打包,部署<mbeancode="org.jboss.mq.server.jmx.Topic"name="jboss.mq.destination:service=Topic,name=myTopic"> <attributename="JNDIName">topic/myTopic</attribute> <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager </depends></mbean>8.3.4開發(fā)消息Bean測試類:TestMDBTopic.javapublicstaticvoidmain(String[]args){TopicConnectionconn=null;TopicSessionsession=null;try{ InitialContextctx=newInitialContext(); TopicConnectionFactoryfactory=(TopicConnectionFactory)ctx.lookup("TopicConnectionFactory"); conn=factory.createTopicConnection(); session=conn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE); Destinationdestination=(Topic)ctx.lookup("topic/myTopic"); MessageProducerproducer=session.createProducer(destination); TextMessagemsg=session.createTextMessage("你好TopicMDB!"); producer.send(msg);}catch(Exceptione){System.out.println(e.getMessage());}finally{ try{ session.close(); conn.close(); }catch(JMSExceptione){ e.printStackTrace(); }}}8.3.4開發(fā)消息Bean運行結(jié)果:8.3.4開發(fā)消息Bean企業(yè)級信息系統(tǒng)開發(fā)技術(shù)濟南大學信息學院劉鹍liukun@回顧:消息驅(qū)動Bean消息驅(qū)動Bean異步接收第9章JAVA持久API學習要點:實體Bean實體類實體的生命周期事務(wù)處理直接操縱實體數(shù)據(jù)并發(fā)訪問和鎖查找實體和QueryAPI命名查詢EJB-QL語言第9章JAVA持久API9.1Java持久化API概述9.2數(shù)據(jù)庫同步9.1Java持久化API概述9.1.1實體Bean9.1.2實體類9.1.3實體的生命周期9.1.4事務(wù)處理9.1.1實體Bean實體Bean有著一組屬性并且每個屬性與數(shù)據(jù)庫表中的每個字段一一對應(yīng)。公開get和set方法供外界訪問。每一個屬性對應(yīng)數(shù)據(jù)庫表中的一個字段,這樣一個Bean實例就對應(yīng)了表中的一條記錄。并不是固定的一個實例對應(yīng)一條記錄。9.1.1實體Bean保持實體Bean可以手工完成持久化操作可以讓EJB容器完成持久化操作實體bean和會話bean的比較實體bean不允許保存每個客戶端的信息。會話bean允許保存客戶端的狀態(tài)信息。實體bean允許保存記錄的,會話bean既可以保存客戶端的信息又可以保存數(shù)據(jù)庫記錄的信息。會話bean也不能提供在相同或不同的EJB類調(diào)用間進行全局的事務(wù)控制。實體Bean的分類1)CMP類型的實體Bean2)BMP類型的實體Bean9.1.2實體類實體類用于表示數(shù)據(jù)庫中的表,實體類的編寫主要確定如下信息:該實體與數(shù)據(jù)庫中的哪個表對應(yīng);實體類中的屬性與表中的哪個字段對應(yīng);實體類中的哪個屬性是主鍵。9.1.2實體類編寫實體類的主要知識點聲明該類為實體類:@Entity聲明該實體類與哪個表對應(yīng):@Table(name="userinfo")聲明該實體類與表中的哪個列對應(yīng),如:聲明主鍵,如:@Column(name="userid",nullable=false)

privateStringuserid;

@Column(name="username",nullable=false)

privateStringusername;

@Column(name="userpass",nullable=false)

privateStringuserpass;

@Column(name="usertype",nullable=false)privatecharusertype;

@Id@GeneratedValue(strategy=GenerationType.AUTO)9.1.3實體的生命周期受管新建刪除分離new()persist()persist()remove()終止PersistenceContextmerge()第9章JAVA持久API9.1Java持久化API概述9.2數(shù)據(jù)庫同步9.2數(shù)據(jù)庫同步9.2.1直接操縱實體數(shù)據(jù)9.2.3查找實體和QueryAPI9.2.4命名查詢9.2.5EJB-QL語言9.2.1直接操縱實體數(shù)據(jù)實體數(shù)據(jù)RDBMS實體持久化提供者O/RMapping現(xiàn)有應(yīng)用直接修改數(shù)據(jù)庫9.2.2并發(fā)訪問和鎖借助于事務(wù)隔離總是能夠保護對RDBMS數(shù)據(jù)的并發(fā)訪問。正確使用事務(wù),應(yīng)用便不用考慮有關(guān)并發(fā)控制方面的設(shè)計問題。如果應(yīng)用沒有做任何特殊處理,則實體將會受到容器管理事務(wù)的保護,并且事務(wù)能夠使用到持久化提供者和EJB容器事務(wù)服務(wù)提供的隔離級別。事務(wù)隔離級別要合適Serializable——性能下降,死鎖ReadUnCommitted——數(shù)據(jù)不一致,應(yīng)用行為不正確ReadCommitted——不能避免不可重復(fù)讀和幻影讀RepeatableRead——不能避免幻影讀9.2.2并發(fā)訪問和鎖JPA定義了用于處理并發(fā)訪問實體的兩個重要特征:使用version屬性實現(xiàn)樂觀鎖寫數(shù)據(jù)時探測是否存在寫操作沖突與Subversion對比不能防止不可重復(fù)讀和幻影讀的發(fā)生顯式讀鎖和寫鎖9.2.2并發(fā)訪問和鎖臟讀表9-1

出現(xiàn)在事務(wù)T2中的臟讀T1T2account=manager.find(Account.class,1234);//更新account.withdraw(100,000);manager.flush()//查找和讀數(shù)據(jù)account=manager.find(Account.class,1234);System.out.printIn(account.balance);//觸發(fā)回滾thrownewRuntimeException();9.2.2并發(fā)訪問和鎖不可重復(fù)讀T1T2Account=manager.find(Account.class,1234);Account.withdraw(100,000);Queryquery=manager.createQuery(“SelectafromAccountaWHEREa.balance>1000”);System.out.printIn(“Got”+query.getResultList().size()+“records.”)//…System.out.printIn(“Got”+query.getResultList().size()+“records.”)圖9-3

出現(xiàn)在事務(wù)T2中的不可重復(fù)讀9.2.3查找實體和QueryAPIfind()操作的方法簽名。EntityManagerAPI的使用步驟:從EntityManager獲得javax.persistence.Query實例。自定義Query實例。比如,設(shè)置查詢參數(shù)、控制結(jié)果集的大小。執(zhí)行查詢。使用EJB-QL和SQL創(chuàng)建查詢的EntityManager操作:/**通過主鍵進行查找*/public<T>Tfind(Class<T>entityClass,ObjectprimaryKey);/**創(chuàng)建執(zhí)行EJBQL語句的Query*/publicQuerycreateQuery(StringejbqlString);/**創(chuàng)建執(zhí)行原生SQL語句的Query*/publicQuerycreateNativeQuery(StringsqlString);9.2.3查找實體和QueryAPI從數(shù)據(jù)庫中返回所有Account實體的簡單EJB-QL查詢實例。重載createNativeQuery()方法。將SQL結(jié)果集數(shù)據(jù)映射到實體,從而返回給客戶。publicList<Account>listAccounts(){Queryquery=manager.createQuery("SELECTaFROMAccounta");returnquery.getResultList();}publicQuerycreateNativeQuery(StringsqlString,ClassresultClass);publicQuerycreateNativeQuery(StringsqlString,StringresultSetMapping);9.2.4命名查詢可能需要在整個持久化單元中使用單個查詢語句,或者需要為部署者或管理員提供變更查詢語句的便利,這時我們可以使用靜態(tài)查詢(StaticQuery),靜態(tài)查詢也被稱之為命名查詢(NamedQuery)。9.2.4命名查詢從外部的命名查詢字符串創(chuàng)建Query對象,需要使用EntityManager提供的如下操作。在調(diào)用createNamedQuery之前,開發(fā)者必須定義好相應(yīng)的命名查詢。比如,在如下給出的listAccounts()方法中使用了這一操作。/**創(chuàng)建命名查詢(EJBQL或原生SQL)*/publicQuerycreateNamedQuery(Stringname);publicList<Account>listAcco

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論