EJB知識點大全

openkk 12年前發布 | 119K 次閱讀 EJB Java開發

Chapter01 企業級開發背景知識

一、什么是企業級程序(Enterprise Application)?

  具有以下特點的程序:

  (1) 圍繞商業目的;

  (2) 分布分層的程序架構。

二、企業級應用的架構發展歷史

Host/Terminal(主機/終端,終端不具備處理能力,數據由主機處理)

終端為啞終端,可接受命令,不處理命令

優點:安全(不能直接訪問)

    性能優越(目前關鍵應用仍在使用)

缺點:使用代價過高,設備昂貴1·

    升級維護困難

C/S(Client/Server客戶端/服務器端)

  終端擁有一定的計算能力,應用架構演變為C/S架構

Multi-layered(多層架構)

  Sample:Browser——Web Server——EJB Server——Database

三、為什么要使用EJB,即使用EJB的動機是什么?

  (1) 大型的企業級程序分解為分層分布的應用,必須使用EJB;

  (2) 構建多層程序架構;

  (3) 各層獨立,專注自己擅長的領域;

  (4) 采用EJB可以不用考慮中間件服務(Middleware Service)

Tips:中間件服務

1,RMI(Remote Method Invocations, 遠程調用)

2,Load Balancing(負載均衡,將訪問負荷分散到各個服務器中)

3,Transparent Fail-over(透明的故障切換)

4,Clustering(集群,用多個小的服務器代替大型機)

5,Back-end-Integration(后端集成,用現有的、新開發的系統如何去集成遺留的系統)

6,Transaction事務(全局/局部)全局事務(分布式事務)局部事務(在同一數據庫聯接內的事務)

7,Dynamic Redeployment(動態重新部署,在不停止原系統的情況下,部署新的系統)

8,System Management(系統管理)

9,Threading(多線程處理)

10,Message-oriented Middleware面向消息的中間件(異步的調用編程)

11,Component Life Cycle(組件的生命周期管理)

12,Resource pooling(資源池)

13,Security(安全)

14,Caching(緩存)

 

四、什么是EJB?

EJB是采用Java語言開發、部署服務器端的分布式組件的標準和框架。

分布式組件:

程序=業務+底層中間件服務

組件:按照一定的規范開發,并部署到相應的容器中適當的對象和相關部署文件。

分布式組件:

多個容器之間的組件需要進行跨容器調用。

EJB:動態可伸縮的、可靠、安全的組件框架。

   與中間件服務提供商無關,采用EJB開發,不用考慮容器。

五、EJB可以用在哪些地方?

  業務運算。

六、EJB的價值

  (1) 行業標準(Industry standard)

  (2) 便攜性

  (3) 快速開發

七、EJB的運行機制

  (1) 代理/委托模式

代理模式:存根(Stub)和攔截器(Request interceptor)都使用了同一個遠程接口(Remote Interface)。

委托模式:攔截器將業務請求委托EJB來負責。

 

  (2) 顯示中間件服務:

  缺點:生產率底下

        代碼維護困難(中間件服務與業務邏輯糾纏)

  優點:細粒度地控制中間件服務

    什么叫粒度:對象的相對大小,對客戶端暴露的細節的程度。

  (3) 隱式中間件服務:不直接調用中間件,采用配置文件來聲明中間件服務,容器自動調用。

  優點:相對與顯示中間件服務,開發進度加快,容易維護。

  缺點:粗粒度,只能在方法級來聲明中間件服務,稍微影響性能。

API:

Request interceptor:攔截器,攔截中間件服務,負責調用相應的中間件API,業務調用交給相應的API。

Stub/Skeleton:屏蔽了網絡調用的細節,攔截器屏蔽了中間件調用的細節,EJB只需考慮對象的調用,

Stub、Skeleton、Request Interceptor由容器生成。

編程需要寫的類:業務接口(Remote Interface),EJB,客戶端(Client,用于訪問EJB)。

 

  EJB是怎么運行的:

  (1) 開發出來的EJB對應的Stub被應用服務器或容器(如 Sun Application Server)綁定到JNDI服務器,名稱為全限定名。

  Stub相當于遠程對象在本地的代理,屏蔽了網絡調用,編碼,解碼,協議轉換等細節。

  (2) 客戶端通過上下文(Context),找到Stub。

八、EJB生態系統的八個角色

九、SOA(面向服務架構)

  (1) 程序由多個服務構成;

  (2) 服務是由一組相關的組件構成,完成某個特定的業務功能,服務可由不同的編程語言實現;

  服務通過HTTP協議,SOAP、WSDL等相關協議實現的一種分布式應用架構。

SOA(面向服務的架構)和EJB的關系

SOAP(簡單對象訪問協議)

WSDL(Web服務描述語言)(Web Services)

EJB發布為Web服務,從而實現SOA。

十、Java EE相關知識

  (1) Java EE是一個標準;

  (2) Java EE是用來開發多層、分布式企業應用的平臺。

Chapter02 EJB開發流程

一、開發EJB的步驟

第一大步:開發編譯業務接口和Bean類

(1) 編寫業務接口和Bean類

(2) 編譯

第二大步:打包部署到JNDI服務器

(3) 提供部署描述文件

(4) 打包(編譯后的字節碼文件和部署描述文件)成ejb-jar

(5) 部署ejb-jar到容器

第三大步:測試

(6) 檢測部署是否成功(看容器是否發現)

(7) 識別客戶端程序來調用EJB

業務接口(Business Interface):

(1) 對客戶端暴露可以調用的方法,它是一個普通的Java接口,POJO類,或POJI。

(2) 業務接口可以劃分為兩類:A、遠程業務接口

              B、本地業務接口

如果客戶端和EJB運行在同一個JVM中,我們應該用本地接口,否則只能用遠程業務接口。

二、EJB的編程模型和編程涉及的標注

Bean類(The Bean Class):

(1) Bean類也是一個POJO,實現了業務接口中的方法

(2) 在Bean類中一般帶有標注(Annotation),用于代替傳統的部署描述文件

 @stateless 無狀態(標注該類是一個無狀態的會話Bean)

 @Remote(XXX.class)(標注該Bean類的業務接口是XXX.class)

(3) Bean類要有缺省的構造方法

(4) Bean類可以不實現業務接口(因為標注已經說明),不過建議實現

(5) ejb-jar.xml(Optional)標準的部署描述文件

  我們可以用EJB3.0中的標注來代替對描述文件的編寫。

EJB3.0使用了JAVA SE 5.0 中的注釋新特性,只要在方法上寫EJB規范的注釋,就可以不用來寫標準的部署表述,ejb-jar.xml這個要放到jar文件的mate-inf文件夾里。

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar   xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   metadata-complete="true" version="3.0"   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">

 <enterprise-beans>

  <session>

    <display-name>HelloBean</display-name>

    <ejb-name>HelloBean</ejb-name>

    <business-remote>test.HelloRemote</business-remote>

    <ejb-class>test.HelloBean</ejb-class>

    <session-type>Stateless</session-type>

    <transaction-type>Container</transaction-type>

    <security-identity>

        <use-caller-identity/>

    </security-identity>

  </session>

 </enterprise-beans>

</ejb-jar>

EJB Client(客戶端):

  (1) EJB不能夠被客戶端直接訪問,客戶端必須通過業務接口來調用EJB

  (2) EJB客戶端分為兩類:

    A、EJB客戶端與EJB運行在同一個容器中→本地業務接口

    B、EJB客戶端與EJB運行在不同的JVM中→遠程業務接口

 

EJB 容器(EJB Container):

  (1) EJB容器是一個運行在JVM上的程序

  (2) EJB容器為EJB提供中間件服務。

 

EJB客戶端的編程步驟:

1、運行客戶端前要加上在SUN的服務器文件夾中的lib下的javaee.jar和appserv-rt.jar

Tips:Java Runtime相關的包:javaee.jar(Java EE),appserw-rt.jar(Java 運行時) ,appserv-ws.jar appserv-jwsacc.jar(Web Service)

2、配置系統的JNDI的環境(客戶端所依賴的Object和Sun運行環境)

3、寫測試類,注意在測試類中也要有業務接口

  Step1:設置JNDI服務器入口信息( system.setProperty)

  Step2:初始化上下文

  Step3:查找JNDI服務器的Stub

  Step4:調用對象

EJB調用過程:

  (1) EJB容器將Stub綁定到JNDI服務器上,JNDI上使用的綁定(默認情況下)是遠程業務接口的全限定名。

  (2) 客戶端通過上下文(Context)的方法來查找JNDI服務器上綁定的Stub。

 

在廠商的部署描述中可以配置EJB的實例池,可以一次創建多個EJB的實例。

注意:EJB一定要先部署到服務器,EJB需要部署環境才能運行

EJB客戶端

public class Cilent {

    public static void main(String[] args) throws NamingException {

 

        System.setProperty("jndi.factory","com.sun.jndi.cosnaming.CNCtxFactory");

        System.setProperty("jndi.provider.url","corbaloc::localhost:3007/NameSpace");

        Context ctx=new InitialContext();

        HelloRemote hello=(HelloRemote)ctx.lookup("test.HelloRemote");

        System.out.println(hello.hello());

        System.out.println(hello.helloword("lichen"));

    }

   

}

 

注意:在寫客戶端時,要引入javaee.jar和appser-rt.jar還要引入已經編譯好的EJB的jar文件。

 

Chapter03 會話Bean

一、什么是會話Bean(Session)?

  會話Bean:

  (1) 會話Bean是EJB中一種用來建模、業務邏輯/業務流程的EJB類型。

  (2) 會話Bean實例的生成是客戶端調用的結果。

  (3) 會話Bean接受客戶端的請求,并作出響應,是一個業務處理對象(控制類,OO中類的一種(邊界類,實體類,控制類))

  (4) 會話Bean的存活時間很短。

常用的EJB類型:SessionBean,EntityBean,MessageDrivenBean,Entity Bean,JPA。

1、SessionBean(Statless/Statfull)

    無狀態的SessionBean是不會保存的信息的和狀態,無狀態的SessionBean是可以重用的,而不是被立刻銷毀

    有狀態的SessionBean只為一個用戶來服務。

2、MDB(Message Driver Bean)消息驅動Bean,可以進行異步的編程

3、Entity Bean 訪問數據庫,已經被JPA(JAVA持久化API)替代。

4、JPA基于ORM方式來實現對數據庫的訪問

 

1.SessionBean:

    用于對業務建模,表示過程。流程(動詞)

    作為門面(Facade)。

    負責接受遠程訪問,并操作EntityBean。同步的調用。

2.EntityBean:

    生命周期:持久化。過程結束后,數據仍存在。

    用于對數據建模,表示名詞。

    SessionBean與EntityBean組成動賓關系。

    爭論焦點:O/R較復雜。

    一般不直接接受遠程訪問。

3.MessageDrivenBean:

    用于封裝業務過程,動詞。

    為了完成異步調用:客戶調用,消息服務器緩存指令,發送消息給客戶端,消息服務器分發消息,Bean執行。

    責任同SessionBean,完成異步調用。

 

二、SessionBean的類型:

  (1) stateless Session Bean

(2) stateful Session Bean

 

(一)無狀態SessionBean(Statless)

  (1) 無狀態Session Bean單個方法調用就能完成一個完整的業務流程

(2) 無狀態Session是可以被重用,不能被客戶端并發共享,只可以串行共享,并不保留客戶端方法調用后的的狀態,而是直接返回。

(3) 無狀態的SessionBean是可以池化的(pooling),以優化性能,用以被多個客戶共享。

 

無狀態SessionBean的生命周期

 

如果實例不存在,就會調用構造方法,然后調用資源注入方法,接著會調用有@PostConstruct標注的方法,在銷毀時會調用有@PerDestroy標注的方法,

然后銷毀對象,如果實例存在就會從Bean實例池中取出實例并調用方法。

 

回調方法是基于事件機制的。

 

生命周期回調方法的規則

1、對于直接定義在Bean中的回調,其格式應該是public void <method()>,也就是直接寫在SessionBean中。

2、對于為Bean類單獨提供(單個或多個)回調監聽而言。其格式是public void <method(InvocationContext context)>

java.interceptor.InvocationContext,提供了調用的上下文信息。只在SessionBean類上加上@Interceptors(Xxxx.class)制定定義了回調方法的類。

3、回調方法不能夠拋出已檢查異常,但可以拋運行時異常。

 

在創建實例并注入資源之后,會回調這個方法。

@PostConstruct

public void constructed(){}

 

在銷毀對象時回調這個方法

@PerDestroy

public void destroy(){}

 

(二)有狀態的SessionBean(Statful)

 

有狀態的SessionBean只為一個客戶端服務,不能共享,并且會保留方法調用后的狀態。

  (1) 多個方法調用才能完成一個業務處理流程;

  (2) 需要保留客戶端的狀態

  (3) 不被多個客戶共享。

當有狀態的SessionBean暫時不被使用時,就會被存儲到緩存當中,也就是被存到虛擬內存或者是將信息同步到Session數據庫中(Session數據庫是應用服務器所提共的小型數據庫,用來保存Session的信息,多應用服務器共享Session數據庫,同步Bean的信息,達到集群處理)。

 

swap out passivation鈍化過程,保存SessionBean的狀態,在SessionBean處在事務中時是不會進行鈍化的。

swap in activation激活過程,提取保存的SessionBean到內存中,可以繼續被客戶端使用。

 

有狀態的Session,會保存成員變量(沒有加transient關鍵字,以及串行化的類型和基本類型),也會保存其他的SessionBean的引用。

 

對有狀態的SessionBean中有transient屬性時,就需要在Bean中提供激活的方法也就是

@Statful

Test implements TestRemote{

   transient private int a;

   @PostActivate

   public void activate(){

  a=5;

   }

}

 

在SessionBean中實現事務處理時要實現SessionSynchronization接口。

 

  關于有狀態會話Bean與無狀態會話Bean的比較:

  Stateless Session Bean

  (1) EJB容器可以預先實例化多個無狀態會話Bean的實例,組成一個pool;

  (2) 當客戶請求調用時,容器可以任選一個實例處理請求;

  (3) EJB容器可以依照請求量的大小來調整pooling中實例的個數;

     對于客戶端來講,這些stateless Session Bean毫無區別。

  (4) EJB容器可以通過pooling來達到使用少量實例來應對大量的請求。

  Stateful Session Bean

  對于有狀態的會話Bean,不能夠同時被多個客戶所共享。

  如果要讓stateful Session Bean能夠同時服務多個客戶,就要使用Swapping。

  鈍化:將會話Bean中客戶狀態鈍化到存儲設備(swap out)。

  激活:將存儲設備中的客戶狀態讀回到會話Bean中(swap in)。

使用有狀態會話Bean時如何維護客戶狀態?

  (1) 在默認狀況下,可以不用考慮,容器會自動維護客戶端的狀態

  Tips:容器自動維護的狀態

  A、非transient修飾的屬性

  B、EJB中的其他業務接口

  C、EJB中的home接口

  D、EJB中的會話上下文,事務對象

  E、JNDI上下文(Context)

  (2) 對于一些無法采用默認的swap機制鈍化、激活的狀態,應該采用回調方法手動實現激活和鈍化。

 

  1、何時需要使用有狀態的會話Bean?

  需要跨多個方法完成某個業務處理流程,并且需要保持客戶端狀態。

  2、有狀態會話Bean能否實現pooling?

  可以,但需要swping,不停地激活、鈍化。

  3、無狀態會話Bean的pooling性能優于有狀態會話Bean的pooling(swap有I/O瓶頸)。

  4、無狀態會話Bean可以有屬性,但是屬性的值被所有的客戶端共享。

 

在廠商的部署描述中可以配置EJB的實例池,可以一次創建多個EJB的實例。

SessionBean

 

SessionBean接受客戶端的請求,并作出響應,是商業過程處理對象。

 

無狀態SessionBean(Statless)

 

無狀態Session是可以被重用,不能被客戶端并發共享,只可以串行共享,并不保留客戶端方法調用后的的狀態,而是直接返回。

無狀態的SessionBean是可以池化的,以優化性能。

 

無狀態SessionBean的生命周期

 

如果實例不存在,就會調用構造方法,然后調用資源注入方法,接著會調用有@PostConstruct標注的方法,在銷毀時會調用有@PerDestroy標注的方法,然后銷毀對象,如果實例存在就會從Bean實例池中取出實例并調用方法。

 

回調方法是基于事件機制的。

 

生命周期回調方法的規則

1,對于直接定義在Bean中的回調,其格式應該是public void <method()>,也就是直接寫在SessionBean中。

2,對于為Bean類單獨提供(單個或多個)回調監聽而言。其格式是public void <method(InvocationContext context)>

java.interceptor.InvocationContext,提供了調用的上下文信息。只在SessionBean類上加上@Interceptors(Xxxx.class)制定定義了回調方法的類。

3,回調方法不能夠拋出已檢查異常,但可以拋運行時異常。

 

在創建實例并注入資源之后,會回調這個方法。

@PostConstruct

public void constructed(){}

 

在銷毀對象時回調這個方法

@PerDestroy

public void destroy(){}

 

有狀態的SessionBean(Statful)

 

有狀態的SessionBean只為一個客戶端服務,不能共享,并且會保留方法調用后的狀態。

 

當有狀態的SessionBean暫時不被使用時,就會被存儲到緩存當中,也就是被存到虛擬內存或者是將信息同步到Session數據庫中(Session數據庫是應用服務器所提共的小型數據庫,用來保存Session的信息,多應用服務器共享Session數據庫,同步Bean的信息,達到集群處理)。

 

swap out passivation鈍化過程,保存SessionBean的狀態,在SessionBean處在事務中時是不會進行鈍化的。

swap in activation激活過程,提取保存的SessionBean到內存中,可以繼續被客戶端使用。

 

有狀態的Session,會保存成員變量(沒有加transient關鍵字,以及串行化的類型和基本類型),也會保存其他的SessionBean的引用。

 

對有狀態的SessionBean中有transient屬性時,就需要在Bean中提供激活的方法也就是

@Statful

Test implements TestRemote{

   transient private int a;

   @PostActivate

   public void activate(){

  a=5;

   }

}

 

在SessionBean中實現事務處理時要實現SessionSynchronization接口。

java -Dorg.omg.CORBA.ORBInitialHost=192.168.12.41

 

Chapter04 Web Service

一、Web Service的概念和原理

1、什么是Web Service?

WebService是一個SOA(面向服務的編程)的架構,它是不依賴于語言,不依賴于平臺,可以實現不同的語言間的相互調用,通過Internet進行基于Http協議的網絡應用間的交互。

WebService實現不同語言間的調用,是依托于一個標準,webservice是需要遵守WSDL(web服務定義語言)/SOAP(簡單請求協議)規范的。

WebService=WSDL+SOAP+UDDI(webservice的注冊)

  Soap是由Soap的part和0個或多個附件組成,一般只有part,在part中有Envelope和Body。

  Web Service是通過提供標準的協議和接口,可以讓不同的程序集成的一種SOA架構。

2、Web Service的優點

  (1) 可以讓異構的程序相互訪問(跨平臺)

  (2) 松耦合

  (3) 基于標準協議(通用語言,允許其他程序訪問)

3、Web Service的基本原理

  (1) Service Provider采用WSDL描述服務

  (2) Service Provider 采用UDDI將服務的描述文件發布到UDDI服務器(Register server)

  (3) Service Requestor在UDDI服務器上查詢并 獲取WSDL文件

  (4) Service requestor將請求綁定到SOAP,并訪問相應的服務。

Tips:WSDL與SOAP

  WSDL:Web Service Description Language(Web服務描述語言)。

  作用:

  (1) 描述服務是什么,服務提供的操作(方法名,方法參數,返回值,數據類型等);

  (2) 如何訪問該服務→binding

  (3) 服務訪問的地址→service

  Banding:定義Web服務訪問采用的協議(SOAP)

  SOAP:Simple Object Access Protocol(簡單對象訪問協議)

4、如何編寫Web Service?

  (1) 先編寫Java類,然后利用工具生成WSDL文檔以及相關文檔

    或先編寫WSDL文檔,后利用工具生成Java類

  (2) @Web Method標注的方法要發布到WSDL描述中,如果沒有任何方法加注該標注,則所有方法均發布到WSDL上。

  @WebService標注該Session Bean要發布Web Service。

 

二、如何訪問Web Service?

  Dynamic Proxy:動態代理

  Dynamic invocation intenface:動態調用接口

  Dynamic Proxy:

  URL:Service的WSDL地址

  QName:全限定名

  Namespace:目標名字空間,Web Service的名字

  Service類:javax.xml.ws.Service

  實例:

Service greeterService=Service.create(wsdlLoction,serviceQName);

  helloWSBean hws=greeterService.getPort(helloWSBean.class)

  System.out.println(hws.sayHello());

 

EJB中使用WebService

@WebService(serviceName="",portName=""),使用這個標注可以將SessionBean中用@WebMethod標注來表示的方法發布成WebService

 

@Stateless

@WebService(serviceName="Greeter",portName="GreeterPost")

public class HelloSessionBean implements HelloSessionRemote {

    @WebMethod

    public String hello(String name) {

        return "Hello world "+name+"!";

    }

}

 

三、Web Service總結

1、Web Service的優缺點

優點:① 跨平臺,可以穿透防火墻,構建一個分布式系統

    ② 基于標準協議(HTTP,SOAP,WSDL,XML)

    ③ 松耦合

缺點:性能低下(SOAP協議XML解析,采用HTTP協議等原因)

分布式系統(EJB,DCOM,CORBA,Web Service)缺點:

  ① EJB不能穿透防火墻,而且限制編程語言只能是Java

  ② 技術不完全成熟

2、Web Service應用場合

  (1) 用于企業內部的應用集成

  (2) 用于企業間的應用集成

Chapter05  Entity 基礎

一、Entity的概念

  1、什么是Entity?

  Entity是一個POJO,JPA(Java Persistence API)可以使用實體來持久化。

  2、JPA的特點

  ① JPA是一種標準的持久化機制

  ② 在容器內外均可以運行

  ③ 持久化提供者(Hibernate等)不影響JPA的使用

  3、Entity與Session Bean的區別

  (1) Session Bean用來建模業務流程,是一個動作;

  (2) Entity表示被持久化的數據,也可以認為是在內存中的Java對象的表示;

  (3) Entity生命周期很長,會話Bean表示業務邏輯,它的生命周期很短;

  (4) Session Bean是可被遠程客戶調用的,Entity不能被遠程客戶調用;

  (5) 實體不是EJB,Session Bean是EJB。

EJB3.0的JPA(Java持久化API)

 

O/R Mapping(對象關系映射)

TopLink,JDO,Hibernate

類型對應表,屬性對應字段,關系對應引用

BO(商業對象,操作數據對象)

DO(數據對象)

持久化的數據對象,也就是已將對象信息同步到數據庫中的對象,持久化對象也叫實體。

操作實體也就使操作實體在數據庫中所對應的數據。

實體和SessionBean的區別

實體本身不支持遠程訪問,他的生命周期是比較長的。

實體有唯一性標識,也就對應數據庫表中的主鍵。

注意:在實體中不要寫商業方法

 

實體的唯一標識,可以使用標簽@Id(標識屬性可以使用public描述,也可以完全封裝為其提供set,get方法),也可以使用XML文件來進行配置。

 

二、實體的編程

@Entity(name="Account"),實體類標注,其屬性name是指定實體名,在EJB-QL中使用,默認是類的全名

@Id,指定實體的唯一標識屬性,默認這個屬性會合數據庫中對應表的主鍵對應。

@GeneratedValue(strategy = GenerationType.AUTO)指定主鍵的生成策略。

@Colum(name="...",unique="true|false",nullable="true|false",insertable="true|false",

updateable="true|false",table="..."),指定類中屬性對應的列名以及約束,

name屬性指定類中屬性對應的列名,默認為屬性名

unique屬性指定類中屬性對應的列是否唯一,默認為false

nullable屬性指定類中屬性對應的列是否可空,默認為true

insertable="true|false"屬性指定類中該屬性是否會出現在insert語句中,也就是會不會被同步到數據庫,默認為true,也就數會同步到數據庫

updateable="true|false"屬性指定類中該屬性是否會出現在update語句中,也就是會不會被修改,默認為true可以被修改。

table屬性指定類中屬性的列所對應的表,默認為實體類所對應的表。

 

在使用實體同步到數據庫時,SessionBean中要寫EntityManager類型的屬性,這個屬性在Bean部署在容器中后,在運行時會容器依賴注入,如果沒有容器也可以使用,但需要為其賦值。

EntityManager是一個接口,也就是規則,可以有不同的實現,Hibernate3.2就實現了這些JPA的接口。

  實體必須提供默認的構造方法,getter,setter方法。

  實體可以有業務方法,用于屬性操作。

 

實體的狀態

 

new新建,也就是新建的實體實例,其信息還沒有持久到數據庫中。

managed受管狀態,也就是實體已經持久化到數據庫中,并且已經和持久化上下文進行了關聯。

detached分離狀態,也就是與持久化上下文解除關聯的實體的狀態

removed刪除,此時實體和持久化上下文進行了關聯,但是要從數據庫中刪除這個實體。

 

 

  new persist()  中止PersistenceContext >

  ——>新建————>受管========================分離

                     ||\   <  merge()

            remove()\|| persist()

                    刪除

 

@PersistenceContext,持久化上下文是內存中的實例和數據庫間的連接樞紐,就像是一快緩沖區,但這個緩沖區是由容器來進行管理的,在這個緩沖區中的實體是處在受管理狀態。

@PersistenceContext(type=PersistenceContextType.EXTENDED,unitName="PetPU")

type屬性使用來標識持久化上下文的類型的,持久化上下文有兩種類型事務范圍和擴展的。這兩種類型的持久化上下文的生命周期不同。unitName屬性是指定持久化單元的名字,其值是在持久化單元定義文件中persistence-unit標簽中的name屬性的值。

  Psersistence Context(持久化上下文):

  持久化上下文表示一組實體,這些實體被Entity Manager所管理。

  兩種Persistence Context:

  (1) 事務范圍的持久化上下文,一般用于五狀態的會話Bean。在默認情況下,EJB容器對每一個業務方法都會提供事務支持。

  (2) 可擴展的持久化上下文:用于有狀態的Session Bean,當方法結束,持久化對象還會存在。

  可擴展的持久化上下文會在各個方法中共享。

  Extended Persistence Context:

  當方法調用結束是,persistence Context會繼續存在。只有當EJB實例銷毀是,才會刪除。

  Extended Persistence Context可用在有狀態的會話Bean中,用來緩存客戶端的實體狀態。

  @persistence Context→持久化單元信息注入

  type=PersistenceContextType.EXTENDED 可擴展的持久化上下文

  unitName=“firstejb”→持久化單元的名字

  Tips:持久化單元(配置文件persistence.xml)的作用:

  (1) 持久化提供者

  (2) 持久化單元的名字

  (3) 設置表的生成機制

關于Extended Persistence Context:

  (1) 在容器管理下,由實體管理器(EntityManager)創建

  (2) @persistence Context注入

    可以脫離容器運行,有EntityManagerFactory來創建。

 

事務范圍的持久化上下文應用到無狀態SessionBean,一旦事務終結,就銷毀,其中的實體也會變成分離狀態。

擴展的持久化上下文應用在有狀態的SessionBean,只有在有狀態的SessionBean被容器銷毀是才會銷毀持久化上下文,也就使實體一直是被管理的。

 

持久化單元的定義文件,這個文件是描述數據庫連接和事務管理的文件

 

<persistence   version="1.0"   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">

  <persistence-unit name="PetPU" transaction-type="JTA">

    <!--transaction-type是事務管理的類型-->

    <provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>

    <!--SPI,持久化API的實現類的提供者-->

    <jta-data-source>my.jdbc</jta-data-source>

     <!--數據源的配置-->

    <properties>

      <property name="toplink.ddl-generation" value="create-tables"/>

    </properties>

  </persistence-unit>

</persistence>

三、EntityManager<interface>

EntityManager實體管理器,它是用來管理實體的,如果使用容器管理實體,容器就會注入EntityManager,EntityManager可以提供實體類生命周期管理,實現數據的同步,和實體的數據的查詢。

  EntityManager,一個用來操作實體,包括增刪查改以及實體的生命周期的管理的接口。

實體生命周期回調方法

 

實體的生命周期回調方法不是通用的。

在實體類中定義時,只在方法前加標注,并且方法的返回值為void,方法為public

也就是:

 

@PrePersist

public void save(){}

在另外的類中寫生命周期回調方法時,就需要以這個實體類為參數了

class AcountListenter{

@PrePersist

public void save(Acount a){}

}

 

@Entity

@EntityListenters(AcountListenter.class)

class Acount...

 

PostPersist

PreRemove

PostRemove

PreUpdate

PostUpdate

PostLoad

 

怎樣操作EntityManager?

  由容器依照持久化的單元信息來創建,以及實體生命周期管理。并且,可以用@Persistence Context來注入到程序中。

 

EntityManager API:

  (1) Entity life-cycle management 實體生命周期管理

  (2) Database syschronization operations 數據庫同步操作

  (3) Entity lookup and queries  實體查詢

 

Entity life-cycle:

  ① new(暫態):實體沒有納入容器的管理,沒有主鍵,數據庫無記錄

  ② managed(受管態/持久化狀態):處于容器管理之下,有主鍵,數據庫有記錄

  ③ removed(刪除狀態):處于容器管理之下,此時可以通過persist()方法返回managed狀態

  ④ detached(游離態):不處于容器管理下,數據庫不確定是否有對應記錄。

 

四、實體的回調

  回調是由持久化管理器來調用的,不是由EJB容器調用的。

  回調的作用是什么?

  在實體被JPA操作時,可以作預處理和后處理。

  回調方法可以定義在Entity內部,也可以定義在單獨的監聽器類中。如果定義在監聽器里,回調方法必須帶一個參數,即要監聽的實體。

  @EntityListeners(XXXLister.class)監聽器可以有多個,用{ ,,}表示。

 

五、實體的版本控制(鎖機制)

(1) 在JPA中,我們可以使用樂觀鎖(Optimistic Locking),但必須是以下幾種類型:

  int,Integer,short,Short,long,Long,Timestamp

(2) 采用@version來標注version字段,程序不用是對version字段進行任何操作,version字段值由容器來維護。

@NamedQuery(name=”findAll”,query=”select……”)靜態查詢語句,可以用標注。

多條語句

@NamedQueries({@NamedQuery(),@NamedQuery()} )

Chapter06  消息驅動Bean

一、JMS(Java Message Service)

  MOM:Message Oriented Middleware(面向消息中間件)

  消息中間件的作用:

  (1) 接收消息發送方發送的消息

  (2) 將接收的消息可靠地發送給消息接收方

MOM系統中的角色:

  MOM消息中間件:Server程序

  消息客戶端:消息收發方,Client,消息發送方(消息生產者),消息接收方(消息消費者)

常見的MOM:

  IBM WebSphere MQ

  BEA tuxedo/Q

  Tibco Rendezvous

  Microsoft MSMQ

 

JMS API

  作用:消息程序不再依賴特定的MOM。

 

JMS支持的兩種編程模型:

  (1) Publish/Subscribe(pub/sub) 發布/訂閱模型

  (2) Point-to-Point(PTP)點對點模型

  pub/sub:

    ① 用Topic存放消息

    ② 允許有多個生產者和消費者,同一個消息可被多個消費者消費,且在Topic中不會因消費而刪除。

  PTP:

    ① 消息服務器上用Queue隊列來存放消息

    ② 允許多個消息的生產者發送消息到Queue,但是消息只允許一個消息消費者消費。一旦消息被消費,MOM會把消息從Queue中刪除。

 

JMS編程模型的共同點:

  消息生產者發送消息到MOM,并不關心消息消費者是誰,何時消費該消息,JMS也不會影響正常的業務邏輯代碼的運行。

 

JMS編程步驟:

Step1:配置管理對象(在Application server上)

  ConnectionFactory:消息連接工廠,負責創建連接

  Queue/Topic:消息目的地,負責存放消息

Step2:分別編寫消息發送/接收程序

TopicSession session=connection.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE);

  AUTO_ACKNOWLEDGE:不使用事務,使用自動應答的方式來確認消息

  默認情況下(使用事務),消息的確認:當事務結束,消息就會得到確認。

  對于pub/sub模型:

  訂閱者(消息接收者)必須先運行(原因是消息消費者要負責啟動消息連接)

  對于PTP模型:消息發送者和消息接收者無運行順序限制。

二、MDB(Message-Driven Bean)

Message-Driven Bean(消息驅動Bean)

  MDB是一種EJB,用來監聽消息目的地的消息,并且處理該消息(相當于消息消費者)。

消息驅動Bean,可以實現異步編程,也就是發送消息,而不必等待返回確認,也就像發郵件一樣,只是發出,而阻塞不必等待回應。

消息驅動Bean是在接受到消息之后再通過onMessage方法進行消息的處理,也就是消息的消費者,消息驅動Bean也是無狀態的。

  MDB的特點:

  (1) MDB不能被客戶端直接調用,因為MDB沒有本地/遠程接口;

(2) MDB是一個無狀態的EJB,不能保存客戶端狀態,可以方便地構造一個池(pooling)

(3) MDB不能返回異常給客戶端;

(4) MDB通過實現onmessage()方法來處理消息。

    public void onMessage(Message message)  {

        if(message instanceof TextMessage){

            TextMessage tm=(TextMessage)message;

            String s = null;

            try {

                s = tm.getText();

            } catch (JMSException ex) {

                ex.printStackTrace();

            }

            try {

                tm.setText("reserve"+s);

            } catch (JMSException ex) {

                ex.printStackTrace();

            }

        }

}

 

MDB編程:

  (1) javax.jms.ManagerListener必須實現這個接口

     javax.ejb.MessageDrivenBean(Opitional)

  (2) 必須提供缺省的構造方法(容器隨時會通過構造方法構造MDB)

  (3) 可以通過@MessageDriven標注該類為一個消息驅動Bean

    @MessageDriven(mappedName=“jms/Topic”)告訴容器,該MDB監聽消息的目的地。

  觀察者模式:只有實現了MessageListener,有消息就會處理消息。

  不要在onmessage()方法中拋出異常,應該在catch語句塊中處理異常。

 

三、MDB高級特性:

Transaction(事務)

  消息的發送與消息的接收不能處在同一個事務中(消息收發可能阻塞)。

Security(安全)

  MDB(消息消費者)不能組織非安全消息的發送。

Load balancing(負載均衡)

  MDB采用拉模型去構造負載均衡(監聽到有消息,就會進行“拉過去”處理),Session Bean采用推模型(在會話Bean的實例化池中,來一個客戶端請求就“推出去”一個Session Bean去處理請求),因此MDB是一種比Session Bean更好完成負載均衡功能的EJB。

Clustering(集群)

  在集群技術中,MDB常發生重復消費(Duplicate consumption in a cluster),用于保證業務(Stateful Session Bean)執行的連續性。

Chapter07  資源注入

一、EJB之間的相互調用

  1、EJB之間的相互調用可以采用以下四種方式:

  (1) 使用默認的JNDI上下文

  (2) 使用@EJB標注(推薦)

  (3) 使用EJB Context查找

  (4) 使用本地接口

 

EJB擴展組件

 

EJB的依賴注入,都是依賴于JNDI的。

在EJB組建中調用其他的EJB組件

2、EJB調用方式:標注

@EJB:

可以借助于JNDI,查找到其他EJB組件,也可以借助于業務接口,調用EJB實例中的業務方法,也可以直接引用其他的需要的EJB組件的業務接口,但是需要使用標注。

標注類型一:

@EJB

private TaxRateRemote taxRate;

需要配置ejb-ref值,配置文件是容器特定的,并且ejb-ref-name的值是 lab.morefunnction.PriceBean/taxRate,lab.morefunnction.PriceBean是要訪問的EJB的全限定名,taxRate是被訪問的EJB引用。

標注類型二:

@EJB(name=“taxRate”)

private TaxRateRemote taxRate;

同樣需要配置(sun-ejb-jar.xml)中的ejb-ref-name的值:“taxRate”,EJB引用名與JNDI名字之間的映射。

 

3、EJB調用方式:EJB Context查找

EJB Context<interface>

  EJB容器提供給EJB的一個對象,用來給EJB訪問EJB容器調用的一個接口。

 

二、EJB的固有標注

@Statless @Statful @MessageDriven

name=" ",mappedName=" " description=" "

name屬性是標識EJB的名字(可以通過JNDI來查找)。默認是EJB的名字。

mappedName屬性也是標識EJB的名字的是容器相關的,所以不要重置,降低可移植性。

description屬性是EJB的描述內容。

以上3個屬性是3個標簽共有的屬性。

 

@Remote @Local

這兩個標注是標注業務接口的,分別是標注遠程的和本地的商業接口的,如果不寫那就默認為本地的。

① 不能直接調用EJB,必須通過業務接口去訪問;

② 如果客戶端與EJB運行在同一個容器當中,用本地業務接口訪問,則性能更高。因為使用本地業務接口,就避免了RMI調用,即避免了網絡調用的性能損耗。通過Reference(引用),而不是Stub,Skeleton編碼解碼,網絡傳輸。

③ 一個EJB可以同時具有本地業務接口和遠程業務接口。

④ 如果有多個業務接口,可以采用@Remote({業務接口1,業務接口2})

  此時EJB在JNDI上綁定的JNDI名字為:“#”+業務接口的全限定名。

@Statful用于有狀態SessionBean的標注

有狀態會話Bean的標注:@Remove @PreDestory @Init

@Remove(retainIfExctption="true|false")

是否在Bean的實例拋出異常之后是否保留著個實例,@Remove標注能夠應用的有狀態SessionBean中的某個業務方法上。當調用到應用了這一注釋的方法時,EJB容器會將這個Bean的實例銷毀或是保留,

retainIfExctption屬性置為true,則會在調用Bean的業務方法中出現異常則會保留這個Bean的實例,置為false則會銷毀該實例。

 

EJB的依賴注入

@Resource標注能夠引用到EJB組件環境中的資源。

@Resource(name="" ,type="")

注意在使用資源引用的時候,也需要在廠商的部署描述文件中對資源進行配置,也就是配置資源的類型和名字,以及JNDIname

 

@EJB(name="",beanInterface="",beanName="",description="")

name屬性指定引用EJB組件的名字

beanInterface屬性用于指定被引用的EJB組件的接口類型

beanName屬性如果在要引入的EJB組件在相同模塊中也就是在同一個jar文件中,就需要自定beanName了

 

EJB攔截器(Intercepters)

 

EJB攔截器,使用來截取客戶的調用方法的,就像是過濾器,他只適用于SessionBean MDB。

對目標對象方法進行調用之前,攔截器先執行調用。

@Interceptors和@AroundInvoke

使用@AroundInvoke標注注釋方法,并且方法的返回值為Object

 

(1) 攔截器方法要用InvocationContext參數(Interface)

  InvocationContext的實現可以提供目標對象的相關信息。

(2) 攔截器方法需要用@AroundInvoke標注,表明為攔截器方法。

(3) 在攔截方法中用InvocationContext.proceed()來執行目標對象的方法。

(4) 攔截器方法可以定義在單獨的攔截器里,也可以定義在Bean類里。外部攔截方法優先級高。

  單獨的攔截器用@ Intercepters來標注屬于哪個Bean里。

(5) 假設目標對象有多個攔截器,按照先后順序執行。

public class Test{

  @AroundInvoke

        public Object test(InvocationContext inv){

               System.out.println("Intercepted call via external class to:"+

                inv.getMethod().getName());//打印客戶調用的方法的名字

                Object[] params=inv.getParameters();//獲得客戶調用的方法的參數表

                for(int i=0;i<param.length;i++){

                    System.out.println("\tparam: "+params[i]);//打印所有參數

                }

        }

}

 

三、依賴注入(DI,Dependency Injection)

  依賴注入,由容器將資源賦值給EJB。EJB的資源依賴容器來注入,因此稱為依賴注入。

  @Resource(name=“jdbc/sample”)

    private……

  資源的引用

  該引用名需要在容器特定的配置文件里配置,并指向真正的資源在JNDI的名字。

  @Resource(……)標注可以用在屬性,setter方法,類之前。

Chapter08  Entity高級特性

繼承映射策略(Inheritance Mapping Stategies)

(1) 單表映射

(2) 關聯關系映射

(3) 每個實體類一張表(不支持多態)

1、單表映射

優點:(1) 支持多態查詢/多態更新

    (2) 簡潔

    (3) 效率高(單表操作)

缺點:(1) 不適合深層次的繼承結構,會形成龐大的表

    (2) 要求列允許為空

@Inheritance

@DiscriminatorColumn(name="DISC", discri:

minatorType=STRING,length=20)//指定區別父子類的表述符的列名、類型和長度

@DiscriminatorValue("CUSTOMER")//指定本類描述符的值

以上兩個標注只適用于所有類建一個表的情況。

 

@Inheritance(strategy=JOINED|SINGLE_TABLE|TABLE_PER_CLASS)

SINGLE_TABLE也就是所有類建一張表

JOINED也就是每個類建一個表。

TABLE_PER_CLASS只針對對具體類建表。

 

@MappedSuperclass//映射子類型,這個標注沒有屬性

 

@AttributeOverride

@AttributeOverrides

2、關聯關系映射

一對一關聯

 

@OnetoOne(targetEntity="",cascade="CascadeType.ALL|MERGE|PERSIST|REFRESH|REMOVE",fetch="FetchType.EAGER|LAZY", mappedBy="",optional="true|false")

cascade級聯設置,

ALL對主對象的增刪該操作,都會級聯到子對象

PERSIST只有對主對象進行增加操作時,才級聯到子對象

REMOVE只有對主對象進行刪除操作時,才級聯到子對象

MERGE只有對主對象進行修改操作時,才級聯到子對象

REFRESH只有對主對象進更新操作時,才級聯到子對象

fetch加載策略,FetchType.EAGER是采取立即加載策略,FetchType.LAZY是采用延遲加載。一對一關系,在默認情況下,會采用Fetch操作立即加載。

 

一對多關聯

一對多單向關系需要中間表。

雙向一對多關系,也要注意(mappedBy=“”)關系維護方的問題。

mappedBy,是指定擁有關系的屬性,只需要在關聯的反方向(非主對象)一端指定使用mappedBy的屬性。

 

@JoinColumn(name="",referencedColumnName="",unique="true|false",nullable="true|false",updateable="true|false",table="...")// 用來指定根據類關系映射到表后和其他表關聯的列名,以及關聯的列名,以及本列的屬性

name屬性指定類中屬性對應的列名,默認為屬性名

referencedColumnName屬性指定類對應的表中的關聯引用的列的列名。

nullable屬性指定類中屬性對應的列是否可空,默認為true

updateable="true|false"屬性指定類中該屬性是否會出現在update語句中,也就是會不會被修改,默認為true可以被修改。

table屬性指定類中有關聯屬性的列所對應的表,默認為實體類所對應的表。

@PrimaryKeyJoinColumn主鍵關聯

 

例:

    引用外鍵

    @OneToOne(optional=false)

    @JoinColumn(name="CUSTREC_ID", unique=true, nullable=false, updatable=false)

    public CustomerRecord getCustomerRecord() { return customerRecord; }

 

 

    @OneToOne(optional=false, mappedBy="customerRecord")

    public Customer getCustomer() { return customer; }

 

    共享主鍵 

    @Entity

    public class Employee {

        @Id

  @OneToOne @PrimaryKeyJoinColumn

        Integer id;

        EmployeeInfo info;

        ...

    }

 

    On EmployeeInfo class:

 

   

    @Entity

    public class EmployeeInfo {

        @Id

        Integer id;

        ...

    }

 

@OneToMany(targetEntity="",cascade="CascadeType.ALL|MERGE|PERSIST|REFRESH|REMOVE",fetch="FetchType.EAGER|LAZY", mappedBy="")

    @OneToMany(cascade=ALL, mappedBy="customer")

    public Set getOrders() { return orders; }

    In Order class:

    @ManyToOne

    @JoinColumn(name="CUST_ID", nullable=false)

    public Customer getCustomer() { return customer; }

 

   @OneToMany(targetEntity=com.acme.Order.class, cascade=ALL,

            mappedBy="customer")

    public Set getOrders() { return orders; }

 

    In Order class:

 

    @ManyToOne

    @JoinColumn(name="CUST_ID", nullable=false)

    public Customer getCustomer() { return customer; }

 

 

多對多關聯

 

@ManyToMany(targetEntity="",cascade="CascadeType.ALL|MERGE|PERSIST|REFRESH|REMOVE",fetch="FetchType.EAGER|LAZY", mappedBy="",optional="true|false")

@JoinTable標注是標識多對多中間表的中對應的信息的。

對于雙向多對多關系,mappedBy=“”可以放在任意一方,@mappedBy與@JoinTable不能在同一個實體。

@JoinTable所在的實體稱為主控方。

    例:

    @JoinTable(

    name="CUST_PHONE"http://中間表表名,

    joinColumns=

        @JoinColumn(name="CUST_ID", referencedColumnName="ID"),

       //指明本方id關聯的列名及引用自哪一列

    inverseJoinColumns=

        @JoinColumn(name="PHONE_ID", referencedColumnName="ID")

       //指明關聯方id所對應的列名及引用自哪一列

    )

 

    關聯的兩個類Customer用戶,和用戶的電話號碼PhoneNumber

    例 1:

    In Customer class:

    @ManyToMany

    @JoinTable(name="CUST_PHONES")

    public Set getPhones() { return phones; }

    In PhoneNumber class:

    @ManyToMany(mappedBy="phones")

    public Set getCustomers() { return customers; }

 

    例 2:

    In Customer class:

 

    @ManyToMany(targetEntity=com.acme.PhoneNumber.class)

    public Set getPhones() { return phones; }

 

    In PhoneNumber class:

    @ManyToMany(targetEntity=com.acme.Customer.class, mappedBy="phones")

    public Set getCustomers() { return customers; }

 

    例 3:

    In Customer class:

 

    @ManyToMany

    @JoinTable(name="CUST_PHONE",

        joinColumns=

            @JoinColumn(name="CUST_ID", referencedColumnName="ID"),

        inverseJoinColumns=

            @JoinColumn(name="PHONE_ID", referencedColumnName="ID")

        )

    public Set getPhones() { return phones; }

 

    In PhoneNumberClass:

 

    @ManyToMany(mappedBy="phones")

    public Set getCustomers() { return customers; }

 

在實體中,兩種類型的屬性需要進行特殊標注,也就是Date和Calendar

需要使用@Temporal(Date),@Temporal(Calendar)

 

EJB QL語句

EJB3.0中的QL,可以使用order by和having字句,對得出的結果進行分組處理。

EJB3.0中的QL關聯查詢和hibernate的HQL的寫法基本相同。

Bulk updates or deletes:

優點:批處理操作直接在數據庫進行,避免了內存的大量占用,提高了性能。

缺點:沒有緩存操作。

Group by

  Group by中分組的字段必須在select中出現

例:

Query query = em.createQuery("select o from Order o left join o.orderItems where                               o.ower.age=26 order by o.orderid");

EJB QL也可以使用構造器查找。

把查詢結果構造成一個對象,類必須使用全限定名。

例:

Query   query=em.createQuery("select    new com.foshanshop.ejb3.bean.SimplePerson(p.name,p.sex) from Person p order by p.personid desc");

 

chapter09 事務

一、事務的基本知識

1、什么是事務?

  通常,我們把一組連續不可分的數據庫操作稱為一個事務。

事務解決了兩大問題,原子操作,數據共享

原子操作,是由不可分操作組成的,使這些不可分的操作,一同操作成功或者一同失敗。

2、事務的ACID特性

  A(Atomicity)原子性:操作不可分割,一連串操作當作一個整體執行;

  C(Consistency)一致性:數據庫的數據在事務完成前后保持一致;

  I(insulation)隔離性:多個事務獨立地執行,一個事務的執行不影響另一個事務的執行結果,隔離性即一個事務對另一個事務的可見性;

  D(durability)持久性:事務操作的結果應該保留下來。

3、事務的類型

  (1) 扁平式事務:事務要么成功,要么失敗,不允許包含子事務;

  (2) 嵌套式事務:一個大事務里潛逃多個小事務,允許子事務回滾。各個子事務必須都成功,整個事務才能成功提交;

  Tips:EJB不支持嵌套式事務。

4、分布式事務(Distributed Transaction)

  (1) 什么是分布式事務?

  跨越多個數據資源的事務叫做分布式事務。

數據資源:對數據進行存儲、管理的空間(如Database,JMS中的主題隊列,File System,后端系統等)。

JDBC只支持本地事務。

本地事務:只負責處理單個數據資源(Data Resource)的事務。

(2) 為什么要使用分布式事務?

企業級應用中,業務需要跨越多個數據資源,并且要作為一個整體來執行,就需要使用分布式事務。

(3) 分布式事務的原理

兩階段提交協議(Two-phrase commit protocol)

① 四個角色:A、Data Resource(數據存取的目的地,通常為Database)

       B、Resource Manager(負責數據資源管理,通常為Database device)

       C、Transaction Manager(負責對資源管理器施加事務的管理)

       D、Transaction Coordinator(事務協調器,負責對多個事務管理器進行協調,保證分布式事務能夠執行)

②Two-phrase commit protocol執行過程(類似于投票機制中的一票否決制)

第一階段:事務準備階段

a、事務協調器(Transaction Coordinator)向各個事務管理器(Transaction Manager)發送事務準備提交的信息;

b、Transaction Manager向Transaction Coordinator回應是否提交事務;

c、Transaction Coordinator記錄日志(各個Transaction Manager的回應);

第二階段:事務提交階段

d、Transaction Coordinator向各個Transaction Manager發送事務提交信息;

e、Transaction Manager將執行結果返回給Transaction Coordinator。

 

二、EJB中的事務機制

  1、JTS(Java Transaction Service)

  JTS協議基于OTS協議,JTS協議即Java中分布式事務服務的協議。

  JTA(Java Transaction API):

  ① UserTransaction(EJB或其他組件用該接口使用分布式事務)

  ② TrasactionManager:應用服務器與分布式事務服務器的接口

  ③ ResourceManager

EJB事務調用流程:EJB→UserTransaction→JTA→JTS→OTS

2、EJB的事務

  ① EJB事務的特點

  提供聲明式事務與編程式事務

  聲明式事務:應用程序只需要關心業務邏輯,由容器來負責事務的管理。

  編程時事務:應用程序編碼人員自己寫事務代碼。

  ② EJB事務編程的類型

  A、CMT    容器管理事務

  B、BMT    Bean管理事務

  C、Client-MT    Client-Controlled Transaction客戶端管理事務

  實體Bean只能用CMT。

  CMT:

  由容器實現的遠程對象/攔截器,負責調用中間件服務。

  優點:在應用程序代碼中,不用編寫事務服務代碼;

  缺點:粗粒度,只能在方法級別控制事務。

 

  EJB Bean類中編程方式來使用事務(BMT):

  優點:細粒度地控制事務

  缺點:事務代理與業務代碼糾纏

  Client-controlled Transaction:

  優點:客戶端可以精確控制事務

  缺點:可能會因為網絡問題引起是事務的回滾。

3、EJB事務邊界的劃分

  事務邊界:事務邊界是指事務從哪里開始。

  CMT的事務特性:

  Required:Bean類的方法必須要在事務環境下運行,這是容器默認的事務機制。

  事務特性只能使用在CMT。

  RequiredNew:Bean類中的方法必須在一個新的事務環境下運行。

  Supports:Bean類的方法不需要支持事務。如果客戶端有事務,則繼續沿用原事務環境。

  Mandatory:Bean類中方法必須要在事務環境下運行。客戶端不啟動事務則報錯。

  NoSupported:Bean類中方法不支持事務。如果客戶端啟動了事務,則掛起該事務。

  Never:Bean類中的方法不支持事務。如果客戶端啟動了事務,則報錯。

三、EJB事務的編程

  1、CMT

    @TransationManagement  用在類前,標注該EJB事務管理方式為Bean | Container(默認)

    @TrasactionAttribute    用在方法前,標注事務特性(事務的邊界)

    @SessionContext.setRollbackOnly()  回滾標識,setRollbackOnly()方法必須在事務環境下運行。

    EJB容器對于非受查異常(主要指RuntimeException)會回滾,事務對于受查異常則會提交事務。

  2、BMT

  UserTransaction:

  ① interface

  ② 提供控制事務的方法

  ③ 由容器實現,可以使用@Resource注入

    UserTransaction.begin()| commit()| .rollback()

  3、客戶端控制事務

  調用EJB的方法,要求EJB必須采用CMT形式。

  4、事務的隔離性

  事務的隔離級別:

  A、Read uncommitted:性能最高

  B、Read committed:解決臟讀問題

  C、Repeatable read:解決重復讀取問題

  D、Serializable:解決幻讀問題

  EJB本身不提供隔離級別的設置,可以通過直接設置數據庫(連接池)的隔離級別。

  SessionSynchronization接口:

  在有狀態會話Bean中,如果事務失敗,可以恢復其狀態。

afterbegin():在事務剛啟動是,容器調用該方法,一般做狀態初始值的保存。

beforeCompletion():在事務完成之前,容器回調。

afterCompletion():在事務提交之后調用,boolean值由容器提供。true表示事務提交成功,false則表示事務失敗。在此方法中,做狀態的恢復。

 

chapter10 Security

一、Security(安全)的概念

  1、Violations(侵害):

  Violations,系統運行中,需要避免發生的事件(事件一旦發生,會侵害系統的安全)。

  2、Vulnerabilities(弱點):

  Vulnerabilities,系統中存在的漏洞或缺陷(如默認數據庫管理員密碼忘記修改)

  3、Risk(風險)

  Risk,是指發生侵害型事件的概率與發生后的危害的乘積。

  4、Controls(控制)

  Controls,發生侵害事件、弱點、風險采取何種方式去避免侵害的發生。

  ① Authentication(認證/驗證)

    系統要求訪問這提供身份信息(通常為用戶名和密碼),系統采取某種方式去檢驗該身份信息(常利用Database),如IDAP,驗證完后,將身份信息標識為一個主體/實體。

  ② Authorization(授權)

    授權是系統根據認證后形成的主體找到主體對應的角色。角色與系統資源是一一對應的。

  授權流程:

  (認證):訪問者→主體| |(授權):→角色→資源

  系統依據角色賦予訪問者相應的系統資源訪問權限。

  ③ Data integrity protection(數據集成性保護)

  系統對資源寫操作進行相應的控制。

  ④ Data confidentiality protection(數據機密性保護)

  系統對資源讀操作進行相應的控制。

二、編程式與聲明式安全

 

Web Application Security

1、Web中認證的方式

  ① 基本認證/摘要認證

  a、通過配置web.xml來配置一個基本認證的方案;

  b、系統提供一個默認的表單接受用戶輸入的認證信息;

  c、系統對用戶輸入的數據(用戶名/密碼等)不作輸入加密操作,傳送到后臺處理;

  d、認證信息存放在HTTP請求頭當中。

  基本認證常用在企業內部環境,少有惡意破壞的應用環境,性能較高。

  ② 基于表單的認證

  a、系統需要編程人員提供表單程序(表單定制);

  b、系統將用戶認證信息存放在HTTP請求體中;

  c、不加密傳送到后臺處理。

  ③ 基于HTTPS協議的認證

  a、系統采用HTTPS協議來傳遞信息(信息會加密);

  b、系統采用公鑰、私鑰來對信息加密,采用證書來驗證。

  這種認證很常用,認證的方式也很可靠。

2、Web當中的授權

  Declarative security(聲明式授權)

  ① 只需要在web.xml中配置相關元素

  ② 需要在容器特定配置文件中作主體與角色的映射。

配置步驟:

  ① 在容器中配置主體(容器中的用戶)以及角色和主體對應關系;

  ② 在web.xml中配置角色,資源,角色與資源的對應關系

  ③ 在sun-web.xml中配置主體與角色的對應關系。

關于聲明式授權:

  缺點:① 粗粒度,只能控制到頁面級;

      ② 只適用與簡單的應用情況。

 

EJB Security

EJB中的認證與授權:

  ① Web容器對客戶端進行認證

  ② Web容器將認證后的主體傳遞給EJB容器

  ③ EJB容器按照主體來控制EJB的調用

 

Web主要作認證,EJB主要作授權。

EJB認證

  JAAS(Java Authentication Authorization Service,Java授權認證服務)

  采用了策略模式

  作用:在具體的認證與授權方案之前,提供一個抽象層(JAAS),可以使具體的認證授權方案與應用層解耦。

EJB授權

1、EJB中的編程式授權

  ① 在EJB Bean類中編寫安全的邏輯

  ② 在EJB Bean類中,申明安全角色

  ③ 映射安全角色與主體的關系

@DeclareRoles(’manager’)→申明安全角色(可以是多個)

  SessionContext.isCallerInRole()→邏輯安全角色

isCallerRole()方法可以用來判斷調用這(客戶端)的角色是否為安全角色

① ejb-jar.xml中配置邏輯安全角色與實際安全角色的對應關系;

② 配置實際安全角色;

    ③ 配置實際安全角色與主體(Principal)的對應關系(sun-ejb-jar.xml中)

       主體是容器中配置的用戶。

  2、EJB中的聲明式授權

    ① 聲明安全角色

    ② 使用標注來聲明方法權限

    例如,@RuleAllowed(“employee”),即哪些安全角色可以訪問該方法

    ③ 在配置文件中,映射安全角色與主體的對應關系

    @Declare Roles 聲明角色

    @DenyAll 標注任何角色都不能訪問該方法

    @PermitAll 標注任何角色都可以調用該方法

    @RuleAllowed()指定哪些角色可訪問該方法

    @RunAs 將角色暫時轉換為……調用

chapter11 Time Service

Time Service(定時服務)

EJB如何調用EJB容器通過的定時服務?

在指定的某個時間點,執行相應的人任務。

常用的定時服務框架:

  EJB(Since EJB2.1)

  QuantZ(Open Source)

  腳本(如UINX中的cron at)

1、EJB定時服務的原理

  采用了模板方法

  ① 容器提供定時服務功能

  ② EJB要注冊到定時服務器上

  ③ 到達指定時刻,容器會回調EJB中的方法

2、EJB定時服務的編程

TimerService API

  javax.ejb.TimerService<intenface>

  ① TimerService生成并返回一個Timer對象

  ② 構造在指定的時間點執行的Timer 或

     構造演示一段事件后重復執行的Timer

  ③ 定義回調方法 TimeObject<interface> 或

    a、EJB實現該接口

    b、容器回調TimeObject也可以采用標注@Timeout來定義回調方法

 

    通過EJBContext來獲得定時服務

  @Resource private TimerService ts;

  ts.createTimer(Date date,long interval,String meetingNote)創建定時服務邏輯并注冊

  @Timeout 標注該方法為定時服務方法,導師EJB容器會回調這個方法。

 

EJB定時服務的優缺點:

  優點:與平臺無關,底層定時服務與EJB無關

  缺點:粗粒度,不能在配置文件中配置時間

chapter12 EJB補充知識

一、將.war(Web模塊)與.jar(EJB模塊)打包成.ear(企業級模塊)

  方式1、先定義企業級程序框架,然后再將已有的.war,.jar加進來,最后打包成.ear

  方式2、從企業級框架建立開始,新建.war,.jar,最后打包成.ear文件

 

二、在容器外(脫離容器),使用JPA

1、配置庫文件:A、EntityManager 持久化提供者的庫文件

         B、持久化的包

         C、數據庫的包(數據庫驅動程序)

         D、連接池的包

2、編程一個單獨的Java程序

  使用到的API:

  (1) persistence

  (2) EntityManagerFactory

  (3) EntityManager

  (4) EntityTransaction

(5) Entity  Query

hibernate-entitymanager_3.2.1GA.zip  用于支持JPA的包

hibernate-annotation_3.2.1GA.zip    用于標注的包

hibernate_3.2.1.zip            Hibernate核心包

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!