EJB知識點大全
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核心包