J2EE達內18天筆記

 J2EE模式
Value Object(值對象)  用於把數據從某個對象/層傳遞到其他對象/層的任意Java對象。
通常不包含任何業務方法。
也許設計有公共屬性,或者提供可以獲取屬性值的get方法。
JSP
1.JSP的基礎知識   
               
                    __ 
             _____ |   directive  (指令)
            |      |-- scripting (腳本)
 JSP -------|      |__ action  (動作)
|
|_____Template data :除JSP語法外,JSP引擎不能解讀的東西
   
1)在JSP中使用的directive(指令)主要有三個:
a) page指令
b) include指令
c) taglib指令

在JSP的任何地方,以任何順序,一個頁面可以包含任意數量的page指令

    2)Scripting(腳本)包括三種類型
a) <%!declaraction  %>
b) <%  scriptlet     %>
c) <%= expression   %>

3)action(動作)
  標準的動作類型有:
        a)  <jsp:useBean>
b)  <jsp:setProperty>
d) <jsp:getProperty>
e) <jsp:param>
f) <jsp:include>
g) <jsp:forward>
h) <jsp:plugin>

1. 註釋: <% -----jsp comment-------%>
       <! -----html comment-------%>

2. <%@ page session = “true”  import =”java.util.*” %>
session可以不賦值,默認爲true,如果session=”false”,則在JSP頁面中,隱含的變量session就不能使用。

3. 請求控制器結構(Request Controller)
也被稱之爲JSP Model 2 Architecture
這種途徑涉及到使用一個Servlet或一個JSP作爲一個應用程序或一組頁面的入口點。

爲創建可維護的JSP系統,Request Controller是最有用的方式之一。

不是JSP,而是Java類纔是放置控制邏輯的正確的地方。

請求控制器的命名模式爲: xxxController.jsp
請求控制器類的命名模式爲: xxxRequestController

2.JSP中的JavaBean
JSP三種bean的類型
1) 頁面bean
2) 會話bean
3) 應用bean

大多數的系統會使用一個會話bean來保持狀態,而對每一個頁面使用一個頁面bean 來對複雜的數據進行表示。

頁面bean是一個模型,而JSP是一個視圖。

3.Custom tag

bean是信息的攜帶者,
而tag更適用於處理信息。

標記庫包含一個標記庫描述符(TLD)和用於實現Custom tag的Java類
在翻譯階段,JSP容器將使用TLD來驗證頁面中的所有的tag是否都被正確的使用。


   標記處理程序只是一個簡單的適配器,而真正的邏輯是在另一個類中實現的,標記處理程序只是提供了一個供其他的可複用的類的JSP接口
     
Servlet
1.ServletConfig
? 一個ServletConfig對象是servlet container在servlet initialization的時候傳遞給servlet的。

ServletConfig包涵 ServletContext 和 一些 Name/Value pair (來自於deployment descriptor)

? ServletContext接口封裝了Web應用程序的上下文概念。

2.會話跟蹤
1) Session
? 當一個Client請求多個Servlets時,一個session可以被多個servlet共享。

? 通常情況下,如果server detect到browser支持cookie,那麼URL就不會重寫。


2) cookie
? 在Java Servlet中,如果你光  Cookie cookie = new Cookie(name,value)
那麼當用戶退出Browser時,cookie會被刪除掉,而不會被存儲在客戶端的硬盤上。

如果要存儲 cookie,需加一句   cookie.setMaxAge(200)

? cookie是跟某一個server相關的,運行在同一個server上的servlet共享一個cookie.

3) URL Rewriting
在使用URL Rewriting來維護Session ID的時候,每一次HTTP請求都需要EncodeURL()
典型的用在兩個地方
1) out.print(“form action=/” ”);
out.print(response.encodeURL(“sessionExample”));
out.print(“form action=/” ”);
out.print(“method = GET>”);
2) out.print(“<p><a href=/” ”);
out.print(response.encodeURL(“SessionExample?database=foo&datavalue=bar”));
out.println(“/” >URL encoded </a>”);

3.SingleThreadModel
默認的,每一個servlet definition in a container只有一個servlet class的實例。
只有實現了SingleThreadModel,container纔會讓servlet有多個實例。

Servlet specification上建議,不要使用synchronized,而使用SingleThreadModel。

SingleThreadModel(沒有方法)
保證servlet在同一時刻只處理一個客戶的請求。
SingleThreadModel是耗費資源的,特別是當有大量的請求發送給Servlet時,SingleThreadModel的作用是使包容器以同步時鐘的方式調用service方法。
這等同於在servlet的service()方法種使用synchronized.

Single Thread Model一般使用在需要響應一個heavy request的時候,比如是一個需要和數據庫打交道的連接。


2. 在重載Servlet地init( )方法後,一定要記得調用super.init( );

3. the client通過發送一個blank line表示它已經結束request
而the server通過關閉the socket來表示response已結束了。

4. 一個Http Servlet可以送三種東西給Client
1) a single status code
2) any number of http headers
3) a response body

5. Servlet之間信息共享的一個最簡單的方法就是
System.getProperties().put(“key”,”value”);

6. Post和Get
Post:將form內各字段名稱和內容放置在html header內傳送給server
Get:  ?之後的查詢字符串要使用URLEncode,經過URLEncode後,這個字符串不再帶有空格,以後將在server上恢復所帶有的空格。
     
Get是Web上最經常使用的一種請求方法,每個超鏈接都使用這種方法。

7. Web.xml就是Web Applicatin 的deployment descriptor
作用有:組織各類元素
        設置init param
        設置安全性
 
8. Request Dispatcher用來把接收到的request forward processing到另一個servlet
要在一個response裏包含另一個servlet的output時,也要用到Request Dispatcher.

9. Servlet和Jsp在同一個JVM中,可以通過ServeltContext的
setAttribute( )
getAttribute( )
removeAttribute( )
來共享對象
10. 利用request.getParameter( )得到的String存在字符集問題。
可以用  strTitle = request.getParameter(“title”);
        strTitle = new String(strTitle.getBytes(“8859-1”),”gb2312”);

如果你希望得到更大得兼容性
        String encoding = response.getCharacterEncoding();    
//確定Application server用什麼編碼來讀取輸入的。
        strTitle = new String(strTitle.getBytes(encoding),”gb2312”);
XML
1.XML基礎知識
1. 一個xml文檔可以分成兩個基本部分:
首部( header )
內容( content )

2. xml名字空間規範中指定:
xml文檔中的每一個元素都處在一個名字空間中;如果沒有指定的名字空間,缺省的名字空間就是和該元素相關聯的名字空間。

3. A document that is well-formed obeys all of the rules of XML documents (nested tags, etc.)

" If a well-formed document uses a Document Type Definition (more on these in a minute), and it follows all the rules of the DTD, then it is also a valid document

4. A tag is the text between the <angle brackets>
" An element is the start tag, the end tag,and everything (including other elements) in between

5. 標籤( tags ) 實際上包含了“元素”( elements ) 和 “屬性”( attributes )兩部分。
用元素( elements )來描述有規律的數據。
用屬性( attributes ) 來描述系統數據。

如果你有一些數據要提供給某個應用程序,該數據就可能要用到一個元素。

如果該數據用於分類,或者用於告知應用程序如何處理某部分數據,或者該數據從來沒有直接對客戶程序公開,那麼它就可能成爲一種屬性。

6. CDATA (讀作:C data ) C是character的縮寫。

7.      org.xml.sax.Reader
/|/
       org.xm.l.sax.XMLReader
/|/
org.apche.xerces.parsers.SAXParser

2.WebService
2.1 WebService的基本概念
WebService是一種可以接收從Internet或者Intranet上的其它系統中傳遞過來的請求,輕量級的獨立的通訊技術。
這種技術允許網絡上的所有系統進行交互。隨着技術的發展,一個Web服務可以包含額外的指定功能並且可以在多個B2B應用中協作通訊。
Web服務可以理解請求中上下文的關係,並且在每一個特定的情況下產生動態的結果。這些服務會根據用戶的身份,地點以及產生請求的原因來改變不同的處理,用以產生一個唯一的,定製的方案。這種協作機制對那些只對最終結果有興趣的用戶來說,是完全透明的。

UDDI
在用戶能夠調用Web服務之前,必須確定這個服務內包含哪些商務方法,找到被調用的接口定義,還要在服務端來編制軟件。所以,我們需要一種方法來發布我們的Web服務。
UDDI (Universal Description, Discovery, and Integration) 是一個主要針對Web服務供應商和使用者的新項目。UDDI 項目中的成員可以通過UDDI Business Registry (UBR) 來操作Web服務的調用,UBR是一個全球性的服務。
Web服務供應商可以在UBR中描述並且註冊他們的服務。
用戶可以在UBR中查找並定位那些他們需要的服務。
UDDI是一種根據描述文檔來引導系統查找相應服務的機制。
UDDI包含標準的“白皮書”類型的商業查詢方式,
“黃皮書”類型的局部查找,以及
“綠皮書”類型的服務類型查找。
UDDI利用SOAP消息機制(標準的XML/HTTP)來發布,編輯,瀏覽以及查找註冊信息。它採用XML格式來封裝各種不同類型的數據,並且發送到註冊中心或者由註冊中心來返回需要的數據。

WSDL
對於商業用戶來說,要找到一個自己需要使用的服務,他必須知道如何來調用。
WSDL (Web Services Description Language) 規範是一個描述接口,語義以及Web服務爲了響應請求需要經常處理的工作的XML文檔。這將使簡單地服務方便,快速地被描述和記錄。
以下是一個WSDL的樣例:
<?xml version="1.0"?>
<definitions name="StockQuote"
                targetNamespace="http://example.com/stockquote.wsdl"
                xmlns:tns="http://example.com/stockquote.wsdl"
                xmlns:xsd1="http://example.com/stockquote.xsd"
                xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
   <schema targetNamespace=http://example.com/stockquote.xsd
                 xmlns="http://www.w3.org/2000/10/XMLSchema">
      <element name="TradePriceRequest">
        <complexType>
           <all>
                <element name="tickerSymbol" type="string"/>
              </all>
           </complexType>
        </element>
        <element name="TradePrice">
            <complexType>
                <all>
                   <element name="price" type="float"/>
                 </all>
              </complexType>
           </element>
        </schema>
     </types>
     <message name="GetLastTradePriceInput">
         <part name="body" element="xsd1:TradePriceRequest"/>
     </message>
     <message name="GetLastTradePriceOutput">
         <part name="body" element="xsd1:TradePrice"/>
    </message>
    <portType name="StockQuotePortType">
        <operation name="GetLastTradePrice">
            <input message="tns:GetLastTradePriceInput"/>
            <output message="tns:GetLastTradePriceOutput"/>
         </operation>
      </portType>
      <binding name="StockQuoteSoapBinding"
                    type="tns:StockQuotePortType">
         <soap:binding style="document"
                                 transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="GetLastTradePrice">
            <soap:operation
                           soapAction="http://example.com/GetLastTradePrice"/>
            <input>
               <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
         </operation>
      </binding>
     <service name="StockQuoteService">
        <documentation>My first service</documentation>
        <port name="StockQuotePort" binding="tns:StockQuoteBinding">
            <soap:address location="http://example.com/stockquote"/>
        </port>
     </service>
  </definitions>
它包含了以下的關鍵信息:
消息的描述和格式定義可以通過XML文檔中的<types>和<message> 標記來傳送。
<portType> 標記中表示了消息傳送機制。 (e.g. request-only, request-response, response-only) 。
<binding> 標記指定了編碼的規範 。
<service> 標記中表示服務所處的位置 (URL)。
WSDL在UDDI中總是作爲一個接口描述文檔。因爲UDDI是一個通用的用來註冊WSDL規範的地方,UDDI的規範並不限制任何類型或者格式描述文檔。這些文檔可能是一個WSDL文檔,或者是一個正規的包含導向文檔的Web頁面,也可能只是一個包含聯繫信息的電子郵件地址。
現在Java提供了一個 Java API for WSDL (JWSDL)規範。它提供了一套能快速處理WSDL文檔的方法,並且不用直接對XML文檔進行操作,它會比JAXP更方便,更快速。

SOAP
當商業用戶通過UDDI找到你的WSDL描述文檔後,他通過可以Simple Object Access Protocol (SOAP) 調用你建立的Web服務中的一個或多個操作。
SOAP是XML文檔形式的調用商業方法的規範,它可以支持不同的底層接口,象HTTP(S)或者SMTP。
之所以使用XML是因爲它的獨立於編程語言,良好的可擴展性以及強大的工業支持。之所以使用HTTP是因爲幾乎所有的網絡系統都可以用這種協議來通信,由於它是一種簡單協議,所以可以與任何系統結合,還有一個原因就是它可以利用80端口來穿越過防火牆。
SOAP的強大是因爲它簡單。SOAP是一種輕量級的,非常容易理解的技術,並且很容易實現。它有工業支持,可以從各主要的電子商務平臺供應商那裏獲得。
從技術角度來看,SOAP詳細指明瞭如何響應不同的請求以及如何對參數編碼。一個SOAP封裝了可選的頭信息和正文,並且通常使用HTTP POST方法來傳送到一個HTTP 服務器,當然其他方法也是可以的,例如SMTP。SOAP同時支持消息傳送和遠程過程調用。以下是一個SOAP請求。
POST /StockQuote HTTP/1.1
Host: www.stockquoteserver.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "Some-URI"
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    <SOAP-ENV:Header>
        <t:Transaction xmlns:t="some-URI" SOAP-ENV:mustUnderstand="1">
           5
        </t:Transaction>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <m:GetLastTradePrice xmlns:m="Some-URI">
            <symbol>SUNW</symbol>
        </m:GetLastTradePrice>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
JAXR
爲了支持UDDI在Java平臺上的功能,Java APIs for XML Registries (JAXR)允許開發者來訪問註冊中心。
值得注意的是,JAXR並不是建立Web服務必需的,你可以利用其他常用的XML APIs來直接集成這些協議。
JAXR是一個方便的API,它提供了Java API來發布,查找以及編輯那些註冊信息。它的重點在於基於XML的B2B應用,複雜的地址本查找以及對XML消息訂閱的支持等Web服務。
它也可以用來訪問其他類型的註冊中心,象ebXML註冊中心。
這些對Web服務的註冊信息進行的操作,可以使用當前的一些Web服務工具來完成(例如第三方的SOAP和ebXML消息工具)。另外,當JAXP提供了一致並具有針對性的API來完成這些操作,這將使開發變得更加容易。
JAX/RPC
爲了使開發人員專注於建立象SOAP那樣的基於XML的請求,JCP正在開發基於RPC (JAX/RPC) 的Java API。JAX/RPC是用來發送和接收方法調用請求的,它基於XML協議,象SOAP,或者其他的象XMLP (XML Protocol,要了解更多可以參考http://www.w3.org/2000/xp/)。JAX/RPC使你不用再關注這些協議的規範,使應用的開發更快速。不久,開發人員就不用直接以XML表示方法調用了。
目前有很多第三方實現了SOAP,開發人員可以在不同的層次上調用SOAP,並選擇使用哪一種。將來,JAX/RPC會取代這些APIs並提供一個統一的接口來構造以及處理SOAP RPC請求。
在接收一個從商業夥伴那裏過來的SOAP請求的時候,一個Java servlet用JAX/RPC來接收這個基於XML的請求。一旦接收到請求後,servlet會調用商務方法,並且把結果回覆給商業夥伴。
JAXM
當從商業合作伙伴那裏接收一個Web服務的請求時,我們需要Java API實現一個Servlet來處理ebXML消息,就象我們用JAX/RPC來處理SOAP請求一樣。
Java API for XML Messaging (JAXM) 是集成XML消息標準(象ebXML消息或者SOAP消息)的規範。
這個API是用來推動XML消息處理的,它檢測那些預定單的消息格式以及約束。它控制了所有的消息封裝機制,用一種直觀的方式分割了消息中的信息,象路由信息,發貨單。這樣,開發人員只要關注消息的有效負載,而不用去擔心那些消息的重複處理。
目前的開發人員用JAXP來實現JAXM將要提供的功能,JAXM將會提供一套非常具有針對性的API來處理基於XML的消息傳送。這將大大簡化開發人員的代碼,並使它們具有統一的接口。
JAXM和JAX/RPC的差別在於處理消息導向的中間件以及遠程過程調用的不同。JAXM注重於消息導向,而JAX/RPC是用來完成遠程過程調用的。以下是圖解。

 
請注意,在JAXM 和 JAX/RPC技術成熟之前,開發人員還是依賴於第三方的SOAP APIs,象Apache SOAP, IdooXOAP, 以及 GLUE。當JAXM 和 JAX/RPC正式發佈後,它將爲當前不同的SOAP和ebXML消息提供統一的接口。就象JDBC位多種不同的數據庫提供統一的接口。

JAXB
XML綁定技術可以把XML文檔和Java對象進行自由轉換。
用JAXB,你可以在後臺的EJB層,把XML文檔轉換成Java對象。同樣你也可以把從EJB中取出的Java對象轉換成XML文檔返回給用戶。
JAXB接口提供了比SAX和DOM更高級的方法來處理XML文檔。它提供的特性可以在XML數據和Java類之間互相映射,提供了一個簡單的方法來轉換XML數據。它比逐個解析標記更簡單。
2.2 建立WeService的步驟
在建立WeService的時候,有三個主要步驟:
1.建立客戶端聯接
爲了允許Applets,Applications,商業合作伙伴,瀏覽器和PDAs 使用Web服務。
2.實現Web服務
包括工作流,數據傳送,商業邏輯以及數據訪問。這些功能是隱藏在Web服務後,並且爲客戶端工作的。
3.聯接後臺系統
這個系統可能包括一個或多個數據庫,現存的企業信息系統,商業合作伙伴自己的系統或者Web服務,以及在多個系統中共享的數據。


基於J2EE的Web服務的核心構架:

 

RMI
1. RMI-IIOP
2. RMI 是在java中使用remote method invocation的最初的方法,RMI使用java.rmi包
RMI-IIOP 是RMI的一個特殊版本,RMI-IIOP可以和CORBA兼容,RMI-IIOP使用java.rmi包和javax.rmi


JAF(Java活動構架)
開發者可以使用JAF來決定任意一塊數據的類型、封裝對數據的訪問、尋找合適的操作、實例化相關的bean來執行這些操作等。
例如,JavaMail就是使用JAF根據MIME類型來決定實例化那一個對象。
EJB
1. EJB組件實現代碼的限制
    EJB組件的約束
    EJB的開發者並不需要在EJB的組件實現代碼中編寫系統級的服務,EJB提供商/開發
者需知道並且嚴格地遵守一些限制,這些限制與開發穩定的和可移植的EJB組件的利益有
關。
    以下是你應該回避使用的一些Java特色,並且在你的EJB組件的實現代碼中要嚴格限
制它們的使用:
    1.使用static,非final 字段。建議你在EJB組件中把所有的static字段都聲明爲final型的。這樣可以保證前後一致的運行期語義,使得EJB容器有可以在多個Java虛擬機之間分發組件實例的靈活性。
    2.使用線程同步原語來同步多個組件實例的運行。避免這個問題,你就可以使EJB容器靈活的在多個Java虛擬機之間分發組件實例。
    3.使用AWT函數完成鍵盤的輸入和顯示輸出。約束它的原因是服務器方的商業組件意味着提供商業功能而不包括用戶界面和鍵盤的I/O功能。
    4.使用文件訪問/java.io 操作。EJB商業組件意味着使用資源管理器如JDBC來存儲和檢索數據而不是使用文件系統API。同時,部署工具提供了在部署描述器(descriptor)中存儲環境實體,以至於EJB組件可以通過環境命名上下文用一種標準的方法進行環境實體查詢。所以,使用文件系統的需求基本上是被排除了。
    5.監聽和接收socket連接,或者用socket進行多路發送。EJB組件並不意味着提供網絡socket服務器功能,但是,這個體系結構使得EJB組件可以作爲socket客戶或是RMI客戶並且可以和容器所管理的環境外面的代碼進行通訊。
    6.使用映象API查詢EJB組件由於安全規則所不能訪問的類。這個約束加強了Java平臺的安全性。
    7.欲創建或獲得一個類的加載器,設置或創建一個新的安全管理器,停止Java虛擬機,改變輸入、輸出和出錯流。這個約束加強了安全性同時保留了EJB容器管理運行環境的能力。
    8.設置socket工廠被URL's ServerSocket,Socket和Stream handler使用。避免這個特點,可以加強安全性同時保留了EJB容器管理運行環境的能力。
    9.使用任何方法啓動、停止和管理線程。這個約束消除了與EJB容器管理死鎖、線程
和併發問題的責任相沖突的可能性。
    通過限制使用10-16幾個特點,你的目標是堵上一個潛在的安全漏洞:
    10.直接讀寫文件描述符。
    11.爲一段特定的代碼獲得安全策略信息。
    12.加載原始的類庫。
    13.訪問Java一般角色所不能訪問的包和類。
    14.在包中定義一個類。
    15.訪問或修改安全配置對象(策略、安全、提供者、簽名者和實體)。
    16.使用Java序列化特點中的細分類和對象替代。
    17.傳遞this引用指針作爲一個參數或者作爲返回值返回this引用指針。你必須使用
SessionContext或EntityContext中的getEJBObject()的結果。
    Java2平臺的安全策略
    以上所列的特點事實上正是Java編程語言和Java2標準版中的標準的、強有力的特色。EJB容器允許從J2SE中使用一些或全部的受限制的特色,儘管對於EJB組件是不可用的,但需通過J2SE的安全機制來使用而不是通過直接使用J2SE的API。
    Java2平臺爲EJB1.1規範中的EJB容器所制定的安全策略定義了安全許可集,這些許可在EJB組件的編程限制中出現。通過這個策略,定義了一些許可諸如:java.io.FilePermission,java.net.NetPermission,java.io.reflect.ReflectPermission,java.lang.security.SecurityPermission,以便加強先前所列出的編程限制。
    許多EJB容器沒有加強這些限制,他們希望EJB組件開發者能遵守這些編程限制或者是帶有冒險想法違背了這些限制。違背這些限制的EJB組件,比標準方法依賴過多或過少的安全許可,都將很少能在多個EJB容器間移植。另外,代碼中都將隱藏着一些不確定的、難以預測的問題。所有這些都足以使EJB組件開發者應該知道這些編程限制,同時也應該認真地遵守它們。
    任何違背了這些編程限制的EJB組件的實現代碼在編譯時都不能檢查出來,因爲這些特點都是Java語言和J2SE中不可缺少的部分。
    對於EJB組件的這些限制同樣適用於EJB組件所使用的幫助/訪問(helper/access)類,J2EE應用程序使用Java文檔(jar)文件格式打包到一個帶.ear(代表Enterprise Archive)擴展名的文件中,這個ear文件對於發送給文件部署器來說是標準的格式。ear文件中包括在一個或多個ejb-jar文件中的EJB組件,還可能有ejb-jar所依賴的庫文件。所有ear文件中的代碼都是經過深思熟慮開發的應用程序並且都遵守編程限制和訪問許可集。
未來版本的規範可能會指定通過部署工具來定製安全許可的能力,通過這種方法指定了一個合法的組件應授予的許可權限,也指定了一個標準方法的需求:如從文件系統中讀文件應有哪些要求。一些EJB容器/服務器目前在它們的部署工具中都提供了比標準權限或多或少的許可權限,這些並不是EJB1.1規範中所需要的。
  理解這些約束
    EJB容器是EJB組件生存和執行的運行期環境,EJB容器爲EJB組件實例提供了一些服務如:事務管理、安全持久化、資源訪問、客戶端連接。EJB容器也負責EJB組件實例整個生命期的管理、擴展問題以及併發處理。所以,EJB組件就這樣寄居在一個被管理的執行環境中--即EJB容器。
   
    因爲EJB容器完全負責EJB組件的生命期、併發處理、資源訪問、安全等等,所以與容器本身的鎖定和併發管理相沖突的可能性就需要消除,許多限制都需要使用來填上潛在的安全漏洞。除了與EJB容器責任與安全衝突的問題,EJB組件還意味着僅僅聚焦於商務邏輯,它依賴於EJB容器所提供的服務而不是自己來直接解決底層的系統層的問題。
    可能的問題
    通常,EJB組件在容器之間的移植不可避免地與如下問題相關:
    1.它需要依靠的受限制的特點在特定EJB容器中沒有得到加強。
    2.它需要依靠的非標準的服務從容器中可獲得。
    爲了保證EJB組件的可移植性和一致的行爲,你應該使用一個具有與Java2平臺安全
策略集相一致的策略集的容器來測試EJB組件,並且其加強了前述的編程限制。
    總結
    EJB組件開發者應該知道這些推薦的關於EJB組件的編程限制,明白它們的重要性,並且從組件的穩定性和可移植性利益方面考慮來遵循它們。因爲這些編程限制能阻止你使用標準的Java語言的特點,違背了這些編程限制在編譯時不會知道,並且加強這些限制也不是EJB容器的責任。所有這些原因都使你應很小心地遵守這些編程限制,這些限制在組件的合同中已經成爲了一個條款,並且它們對於建造可靠的、可移植的組件是非常重要的。
2. 優化EJB
entity bean爲在應用程序和設計中描述持久化商業對象(persistent business objec ts)提供了一個清晰的模型。在java對象模型中,簡單對象通常都是以一種簡單的方式進行處理但是,很多商業對象所需要的事務化的持久性管理沒有得到實現。entity bean將持久化機制封裝在容器提供的服務裏,並且隱藏了所有的複雜性。entity bean允許應用程序操縱他們就像處理一個一般的java對象應用。除了從調用代碼中隱藏持久化的形式和機制外,entity bean還允許EJB容器對對象的持久化進行優化,保證數據存儲具有開放性,靈活性,以及可部署性。在一些基於EJB技術的項目中,廣泛的使用OO技術導致了對entity bean的大量使用,SUN的工程師們已經積累了很多使用entity Bean的經驗,這篇文章就詳細闡述的這些卡發經驗:
*探索各種優化方法
*提供性能優化和提高適用性的法則和建議
*討論如何避免一些教訓。

法則1:只要可以,儘量使用CMP
CMP方式不僅減少了編碼的工作量,而且在Container中以及container產生的數據庫訪問代碼中包括了許多優化的可能。Container可以訪問內存緩衝中的bean,這就允許它可以監視緩衝中的任何變化。這樣的話就在事物沒有提交之前,如果緩存的數據沒有變化就不用寫到數據庫中。就可以避免許多不必要的數據庫寫操作。另外一個優化是在調用find方法的時候。通常情況下find方法需要進行以下數據庫操作:
查找數據庫中的紀錄並且獲得主鍵
將紀錄數據裝入緩存
CMP允許將這兩步操作優化爲一步就可以搞定。[具體怎麼做我也沒弄明白,原文沒有具體闡述]

法則2:寫代碼時儘量保證對BMP和CMP都支持
許多情況下,EJB的開發者可能無法控制他們寫的bean怎麼樣被部署,以及使用的container是不是支持CMP.
一個有效的解決方案是,將商業邏輯的編碼完全和持久化機制分離。再CMP類中實現商業邏輯,然後再編寫一個BMP類,用該類繼承CMP類。這樣的話,所有的商業邏輯都在CMP類中,而持久化機制在BMP中實現。[我覺得這種情況在實際工作中很少遇到,但是作者解決問題的思路值得學習]

法則3:把ejbStore中的數據庫訪問減小到最少。
如果使用BMP,設置一個緩存數據改變標誌dirty非常有用。所有改變數據庫中底層數據的操作,都要設置dirty,而在ejbStore()中,首先檢測dirty的值,如果dirty的值沒有改變,表明目前數據庫中的數據與緩存的一致,就不必進行數據庫操作了,反之,就要把緩存數據寫入數據庫。

法則4:總是將從lookup和find中獲得的引用進行緩存。(cache)
引用緩存對session bean和entity bean 都是適用的。
通過JNDI lookup獲得EJB資源。比如DataSource,bean的引用等等都要付出相當大的代價。因此應該避免多餘的lookup.可以這樣做:
將這些引用定義爲實例變量。
從setEntityContext(session Bean使用setSessionContext)方法查找他們。SetEntityContext方法對於一個bean實例只執行一次,所有的相關引用都在這一次中進行查找,這樣查找的代價就不是那麼昂貴了。應該避免在其他方法中查找引用。尤其是訪問數據庫的方法:ejbLoad()和ejbStore(),如果在這些頻繁調用的方法中進行DataSource的查找,勢必造成時間的浪費。
調用其他entity bean的finder方法也是一種重量級的調用。多次調用finder()方法的代價非常高。如果這種引用不適合放在setEntityContext這樣的初始化時執行的方法中執行,就應該在適當的時候緩存finder的執行結果。只是要注意的是,如果這個引用只對當前的entity有效,你就需要在bean從緩衝池中取出來代表另外一個實體時清除掉這些引用。,這些操作應該在ejbActivate()中進行。

法則5:總是使用prepare statements
這條優化法則適用於所有訪問關係數據庫的操作。
數據庫在處理每一個SQL Statement的時候,執行前都要對Statement進行編譯。一些數據庫具有緩存statement和statement的編譯後形式的功能。數據庫可以把新的Statement和緩存中的進行匹配。然而,如果要使用這一優化特性,新的Statement要必須和緩存中的Statement完全匹配。
對於Non-prepared Statement,數據和Statement本身作爲一個字符串傳遞,這樣由於前後調用的數據不同而不能匹配,就導致無法使用這種優化。而對於prepared Statement,數據和Statement是分開傳遞給數據庫的,這樣Statement就可以和cache中已編譯的Statement進行匹配。Statement就不必每次都進行編譯操作。從而使用該優化屬性。
這項技術在一些小型的數據庫訪問中能夠減少Statement將近90%的執行時間。

法則6:完全關閉所有的Statement
在編寫BMP的數據庫訪問代碼時,記住一定要在數據庫訪問調用之後關閉Statement,因爲每個打開的Statement對應於數據庫中的一個打開的遊標。

 

Security
1.加密
對稱加密
  (1)分組密碼
  (2)流密碼
常用的對稱加密算法:
   DES和TripleDES
   Blowfish
   RC4
   AES
非對稱加密
    常用的非對稱加密算法
RSA
ElGamal
      會話密鑰加密(對稱加密和非對稱加密一起使用)
常用的會話密鑰加密協議
S/MIME
PGP
SSL和TLS   SSL是在Application level protocal和Transport protocal之間的。
比如:Http和TCP/IP之間

SSL 提供了服務器端認證和可選的客戶端認證,保密性和數據完整性。

提供基於SSL方式的傳輸加密和認證,確保以下三種安全防護:
數據的機密性和準確性、
服務器端認證
客戶端認證。

客戶端認證比服務器端認證不很普遍的原因是每一個要被認證的客戶都必須有一張Verisign這樣的CA簽發的證書。

通常,在進行身份認證的時候,應當只接受一個CA,這個CA的名字包含在客戶證書中。
由於不可能隨意創建一個由指定CA簽發的證書,所以這可以有效的防禦通過僞造證書來進行的攻擊嘗試。
2.認證(Authentication)
認證就是確定一條消息或一個用戶的可靠性的過程。

1.消息摘要
   MD5
   SHA和SHA-1
2.消息認證碼(Message Authientication Codes,MAC)

3.數字簽名
用戶可以用自己的密鑰對信息加以處理,由於密鑰僅爲本人所有,這樣就產生了別人無法生成的文件,也就形成了數字簽名

數字簽名可以
1)保證數據的完整性
2)驗證用戶的身份

數字簽名採用一個人的私鑰計算出來,然後用公鑰去檢驗。
           hash算法                             私鑰加密
原報文 ――――――>報文摘要( Message Digest ) ―――――>數字簽名

原報文和數字簽名一起被髮送到接受者那裏,接受者用同樣的hash算法得到報文摘要,然後用發送者的公鑰解開數字簽名。
比較是否相同,則可以確定報文確定來自發送者。

驗證數字簽名必須使用公鑰,但是,除非你是通過安全的方式直接得到,否則不能保證公鑰的正確性。(數字證書可以解決這個問題)

一個接受者在使用公鑰(public key)檢查數字簽名(digital signature)的可信度時,通常先要檢查收到的公鑰(public key)是否可信的。
因此發送方不是單單地發送公鑰(public key),而是發送一個包含公鑰(public key)的數字證書(cetificate )。

4.數字證書
   數字證書是一個經證書授權中心數字簽名的包含公開密鑰所有者信息以及公開密鑰的文件。

數字證書Cetificate中包括:
I. 用戶的公鑰(public key)
II. 用戶的一些信息,如姓名,email
III. 發行機構的數字簽名(digital signature), 用於保證證書的可信度
IV. 發行機構的一些信息

數字證書的格式遵循X.509國際標準。
         
注意:一個數字證書certificate並不適用於多種browser,甚至一種Browser的多個版本。

數字標識由公用密鑰、私人密鑰和數字簽名三部分組成。
當在郵件中添加數字簽名時,您就把數字簽名和公用密鑰加入到郵件中。數字簽名和公用密鑰統稱爲證書。您可以使用 Outlook Express 來指定他人向您發送加密郵件時所需使用的證書。這個證書可以不同於您的簽名證書。
收件人可以使用您的數字簽名來驗證您的身份,並可使用公用密鑰給您發送加密郵件,這些郵件必須用您的私人密鑰才能閱讀。
要發送加密郵件,您的通訊簿必須包含收件人的數字標識。這樣,您就可以使用他們的公用密鑰來加密郵件了。當收件人收到加密郵件後,用他們的私人密鑰來對郵件進行解密才能閱讀。
在能夠發送帶有數字簽名的郵件之前,您必須獲得數字標識。如果您正在發送加密郵件,您的通訊簿中必須包含每位收件人的數字標識。
數字證書,可以是個人證書或 Web 站點證書,用於將身份與"公開密鑰"關聯。只有證書的所有者才知道允許所有者"解密"或進行"數字簽名"的相應"私人密鑰"。當您將自己的證書發送給其他人時,實際上發給他們的是您的公開密鑰,這樣他們就可以向您發送只能由您使用私人密鑰解密和讀取的加密信息。 
通過瀏覽器使用數字證書,必須先要設置瀏覽器軟件 Internet Explorer 或 NetScape使用此證書,才能開始發送加密或需要數字簽名的信息。訪問安全的 Web 站點(以"https"打頭的站點)時,該站點將自動向您發送他們的Web站點證書。
3.CA(證書授證中心)
CA機構,又稱爲證書授證(Certificate Authority)中心,作爲電子商務交易中受信任的第三方,承擔公鑰體系中公鑰的合法性檢驗的責任。CA中心爲每個使用公開密鑰的用戶發放一個數字證書,數字證書的作用是證明證書中列出的用戶合法擁有證書中列出的公開密鑰。CA機構的數字簽名使得攻擊者不能僞造和篡改證書。在SET交易中,CA不僅對持卡人、商戶發放證書,還要對獲款的銀行、網關發放證書。它負責產生、分配並管理所有參與網上交易的個體所需的數字證書,因此是安全電子交易的核心環節。


對證書的信任基於對根證書的信任. 例如在申請SHECA的個人數字證書前,需要先下載根證書,然後再進行各類證書的申請。

下載根證書的目的:
  網絡服務器驗證(S);安全電子郵件(E)

申請個人數字證書可以爲Internet用戶提供發送電子郵件的安全和訪問需要安全連接(需要客戶證書)的站點。


1)個人數字證書
a.個人身份證書 
個人身份證書是用來表明和驗證個人在網絡上的身份的證書,它確保了網上交易和作業的安全性和可靠性。可應用於:網上炒股、網上理財、網上保險、網上繳費、網上購物、網上辦公等等。個人身份證書可以存儲在軟盤或IC卡中。    

b.個人安全電子郵件證書  
個人安全電子郵件證書可以確保郵件的真實性和保密性。申請後一般是安裝在用戶的瀏覽器裏。用戶可以利用它來發送簽名或加密的電子郵件。
 
用戶在申請安裝完安全安全電子郵件數字證書後,就可以對要發送的郵件進行數字簽名。收信人收到該郵件後,就可以看到數字簽名的標記,這樣就可以證明郵件肯定來自發信者本人,而不是別人盜用該帳號僞造信件,同時也保證該郵件在傳送過程中沒被他人篡改過任何數據。

安全電子郵件中使用的數字證書可以實現:
保密性  通過使用收件人的數字證書對電子郵件加密。如此以來,只有收件人才能閱讀加密的郵件,在Internet上傳遞的電子郵件信息不會被人竊取,即使發錯郵件,收件人也無法看到郵件內容。

認證身份  在Internet上傳遞電子郵件的雙方互相不能見面,所以必須有方法確定對方的身份。利用發件人數字證書在傳送前對電子郵件進行數字簽名即可確定發件人身份,而不是他人冒充的。

完整性  利用發件人數字證書在傳送前對電子郵件進行數字簽名不僅可確定發件人身份,而且傳遞的電子郵件信息也不能被人在傳輸過程中修改。

不可否認性  由於發件人的數字證書只有發件人唯一擁有,故發件人利用其數字證書在傳送前對電子郵件進行數字簽名,發件人就無法否認發過這個電子郵件。

OutLook Express中的個人安全電子郵件證書
簽名郵件帶有簽名郵件圖標。

簽名郵件可能出現的任何問題都將在本信息之後可能出現的“安全警告”中得到描述。如果存在問題,您應該認爲郵件已被篡改,或並非來自所謂的發件人。

當收到一封加密郵件時,您應該可以自信地認爲郵件未被任何第三者讀過。Outlook Express 會自動對電子郵件解密, 如果在您的計算機上裝有正確的數字標識。
 
2)企業數字證書
a.企業身份證書
企業身份證書是用來表明和驗證企業用戶在網絡上身份的證書,它確保了企業網上交易和作業的安全性和可靠性。可應用於:網上證券、網上辦公、網上交稅、網上採購、網上資金轉帳、網上銀行等。企業身份證書可以存儲在軟盤和IC卡中。      

b.企業安全電子郵件證書  
企業安全電子郵件證書可以確保郵件的真實性和保密性。申請後一般是安裝在用戶的瀏覽器裏。企業可以利用它來發送簽名或加密的電子郵件。

可使用 Windows 2000 中的證書服務來創建證書頒發機構 (CA),它負責接收證書申請、驗證申請中的信息和申請者的身份、頒發證書、吊銷證書以及發佈證書吊銷列表 (CRL)。

通常,當用戶發出證書申請時,在其計算機上的加密服務提供程序 (CSP) 爲用戶生成公鑰和私鑰對。用戶的公鑰隨同必要的識別信息發送至 CA。如果用戶的識別信息符合批准申請的 CA 標準,那麼 CA 將生成證書,該證書由客戶應用程序檢索並就地存儲。
4.SET
安全接口層協議——SSL(Se cure SocketsLayer),並且已經幾乎成爲了目前WWW 世界的事實標準。這一標準使用公共密鑰編碼方案來對傳輸數據進行加密,在雙方之間建立一個Internet 上的加密通道,從而使第三方無法獲得其中的信息,其思路與目前流行的VPN方案大致相同,目的都是要保護數據不被未經授權的第三方所竊聽,或即使竊聽到也不知所云。但就象VPN 一樣,SSL 在認證方面沒有任何作爲,它們都需要通過另外的手段來確認身份和建立雙方彼此間的信任,然後再通過SSL 進行交易。

正是由於SSL 標準在認證方面的缺憾,所以SET 纔有存在的必要。SET(Secure Electronic Transactions) 規範由Masterc ard 和Visa 公司於1996 年發佈,專家們認爲SET 是保證用戶與商家在電子商務與在線交易中免受欺騙的重要手段。傳統的信用卡交易者總在擔心不誠實的店員會將自己的信用卡號碼透露給他人,而在線交易也是如此,持卡者總在擔心服務器端的管理員會將信用卡號碼泄露出去,或者擔心黑客會在管理員不知情的情況下盜取信用卡號碼。事實上這些擔心都是必要的,而SET 標準則可以保證用戶的信用卡號碼只傳送給信用卡公司進行認證,不會被系統管理員看到,也不會留在交易服務器的硬盤上給黑客以可乘之機。
5.PKI
PKI是一種易於管理的、集中化的網絡安全方案。它可支持多種形式的數字認證: 數據加密、數字簽字、不可否認、身份鑑別、密鑰管理以及交叉認證等。PKI可通過一個基於認證的框架處理所有的數據加密和數字簽字工作。P KI標準與協議的開發迄今已有15年的歷史,目前的PKI已完全可以向企業網絡提供有效的安全保障。

PKI是一種遵循標準的密鑰管理平臺,它能夠爲所有網絡應用透明地提供採用加密和數字簽名等密碼服務所必需的密鑰和證書管理。PKI必須具有
  1)CA、
2)證書庫、
3)密鑰備份及恢復系統、
4)證書作廢處理系統、
5)客戶端證書處理系統
等基本成分,構建PKI也將圍繞着這五大系統來構建


一個PKI由衆多部件組成,這些部件共同完成兩個主要功能:
1)爲數據加密
2)創建數字認證。
服務器(即後端)產品是這一系統的核心,這些數據庫管理着數字認證、公共密鑰及專用密鑰( 分別用於數據的加密和解密)。
CA數據庫負責發佈、廢除和修改X.509數字認證信息,它裝有用戶的公共密鑰、證書有效期以及認證功能(例如對數據的加密或對數字簽字的驗證) 。爲了防止對數據簽字的篡改,CA在把每一數字簽字發送給發出請求的客戶機之前,需對每一個數字簽字進行認證。一旦數字認證得以創建, 它將會被自動存儲於X.500目錄中,X.500目錄爲樹形結構。LDAP(Lightweight Directory Access Protocol)協議將響應那些要求提交所存儲的公共密鑰認證的請求。CA爲每一用戶或服務器生成兩對獨立的公共和專用密鑰。其中一對用於信息的加密和解密, 另一對由客戶機應用程序使用,用於文檔或信息傳輸中數字簽字的創建。

大多數PKI均支持證書分佈,這是一個把已發佈過的或續延生命期的證書加以存儲的過程。這一過程使用了一個公共查詢機制,X.500目錄可自動完成這一存儲過程。影響企業普遍接受P KI的一大障礙是不同CA之間的交叉認證。假設有兩家公司,每一家企業分別使用來自不同供應商的CA,現在它們希望相互託管一段時間。如果其後援數據庫支持交叉認證, 則這兩家企業顯然可以互相托管它們的CA,因而它們所託管的所有用戶均可由兩家企業的CA所託管。 


* 認證機關 
    CA是證書的簽發機構,它是PKI的核心。衆所周知,構建密碼服務系統的核心內容是如何實現密鑰管理,公鑰體制涉及到一對密鑰,即私鑰和公鑰, 私鑰只由持有者祕密掌握,無須在網上傳送,而公鑰是公開的,需要在網上傳送,故公鑰體制的密鑰管理主要是公鑰的管理問題,目前較好的解決方案是引進證書(certificate)機制。 
   
    證書是公開密鑰體制的一種密鑰管理媒介。它是一種權威性的電子文檔,形同網絡計算環境中的一種身份證,用於證明某一主體(如人、服務器等)的身份以及其公開密鑰的合法性。在使用公鑰體制的網絡環境中, 必須向公鑰的使用者證明公鑰的真實合法性。因此,在公鑰體制環境中,必須有一個可信的機構來對任何一個主體的公鑰進行公證,證明主體的身份以及他與公鑰的匹配關係。C A正是這樣的機構,它的職責歸納起來有: 

   1、驗證並標識證書申請者的身份; 
   2、確保CA用於簽名證書的非對稱密鑰的質量; 
   3、確保整個簽證過程的安全性,確保簽名私鑰的安全性; 
   4、證書材料信息(包括公鑰證書序列號、CA標識等)的管理; 
   5、確定並檢查證書的有效期限; 
   6、確保證書主體標識的唯一性,防止重名; 
   7、發佈並維護作廢證書表; 
   8、對整個證書籤發過程做日誌記錄; 
   9、向申請人發通知。 
    
    其中最爲重要的是CA自己的一對密鑰的管理,它必須確保其高度的機密性,防止他方僞造證書。CA的公鑰在網上公開,整個網絡系統必須保證完整性。 

* 證書庫 
    證書庫是證書的集中存放地,它與網上"白頁”類似,是網上的一種公共信息庫,用戶可以從此處獲得其他用戶的證書和公鑰。 
構造證書庫的最佳方法是採用支持LDAP協議的目錄系統,用戶或相關的應用通過LDAP來訪問證書庫。系統必須確保證書庫的完整性,防止僞造、篡改證書。 

* 密鑰備份及恢復系統 
   
* 證書作廢處理系統 
   
* PKI應用接口系統 
PKI的價值在於使用戶能夠方便地使用加密、數字簽名等安全服務,因此一個完整的PKI必須提供良好的應用接口系統,使得各種各樣的應用能夠以安全、一致、可信的方式與P KI交互,確保所建立起來的網絡環境的可信性,同時降低管理維護成本。最後,PKI應用接口系統應該是跨平臺的。

       
許多權威的認證方案供應商(例如VeriSign、Thawte以及GTE)目前都在提供外包的PKI。外包PKI最大的問題是,用戶必須把企業託管給某一服務提供商, 即讓出對網絡安全的控制權。如果不願這樣做,則可建造一個專用的PKI。專用方案通常需把來自Entrust、Baltimore Technologies以及Xcert的多種服務器產品與來自主流應用程序供應商(如Microsoft、Netscape以及Qualcomm)的產品組合在一起。專用PK I還要求企業在準備其基礎設施的過程中投入大量的財力與物力。
7.JAAS
擴展JAAS實現類實例級授權   
“Java 認證和授權服務”(Java Authentication and Authorization Service,JAAS)
在 JAAS 下,可以給予用戶或服務特定的許可權來執行 Java 類中的代碼。在本文中,軟件工程師 Carlos Fonseca 向您展示如何爲企業擴展 JAAS 框架。向 JAAS 框架添加類實例級授權和特定關係使您能夠構建更動態、更靈活並且伸縮性更好的企業應用程序。

大多數 Java 應用程序都需要某種類實例級的訪問控制。例如,基於 Web 的、自我服務的拍賣應用程序的規範可能有下列要求:
任何已註冊(經過認證)的用戶都可以創建一個拍賣,但只有創建拍賣的用戶纔可以修改這個拍賣。

這意味着任何用戶都可以執行被編寫用來創建 Auction 類實例的代碼,但只有擁有該實例的用戶可以執行用來修改它的代碼。通常情況下,創建 Auction 實例的用戶就是所有者。這被稱爲類實例所有者關係(class instance owner relationship)。

該應用程序的另一個要求可能是:
任何用戶都可以爲拍賣創建一個投標,拍賣的所有者可以接受或拒絕任何投標。

再一次,任何用戶都可以執行被編寫用來創建 Bid 類實例的代碼,但只有擁有該實例的用戶會被授予修改該實例的許可權。而且,Auction 類實例的所有者必須能夠修改相關的 Bid 類實例中的接受標誌。這意味着在 Auction 實例和相應的 Bid 實例之間有一種被稱爲特定關係(special relationship)的關係。

不幸的是,“Java 認證和授權服務”(JAAS)— 它是 Java 2 平臺的一部分 — 沒有考慮到類實例級訪問控制或者特定關係。在本文中,我們將擴展 JAAS 框架使其同時包含這兩者。推動這種擴展的動力是允許我們將訪問控制分離到一個通用的框架,該框架使用基於所有權和特定關係的策略。然後管理員可以在應用程序的生命週期內更改這些策略。

在深入到擴展 JAAS 框架之前,我們將重溫一下 Java 2 平臺的訪問控制機制。我們將討論策略文件和許可權的使用,並討論 SecurityManager 和 AccessController 之間的關係。

Java 2 平臺中的訪問控制
在 Java 2 平臺中,所有的代碼,不管它是本地代碼還是遠程代碼,都可以由策略來控制。策略(policy)由不同位置上的代碼的一組許可權定義,或者由不同的簽發者定義、或者由這兩者定義。許可權允許對資源進行訪問;它通過名稱來定義,並且可能與某些操作關聯在一起。

抽象類 java.security.Policy 被用於表示應用程序的安全性策略。缺省的實現由 sun.security.provider.PolicyFile 提供,在 sun.security.provider.PolicyFile 中,策略被定義在一個文件中。清單 1 是一個典型策略文件示例:

清單 1. 一個典型的策略文件
// Grant these permissions to code loaded from a sample.jar file
// in the C drive and if it is signed by XYZ
grant codebase "file:/C:/sample.jar", signedby "XYZ" {
 // Allow socket actions to any host using port 8080
 permission java.net.SocketPermission "*:8080", "accept, connect,
   listen, resolve";
 // Allows file access (read, write, execute, delete) in
 // the user's home directory.
 Permission java.io.FilePermission "${user.home}/-", "read, write,
   execute, delete";
};


SecurityManager 對 AccessController
在標準 JDK 分發版中,控制代碼源訪問的機制缺省情況下是關閉的。在 Java 2 平臺以前,對代碼源的訪問都是由 SecurityManager 類管理的。SecurityManager 是由 java.security.manager 系統屬性啓動的,如下所示:

java -Djava.security.manager


在 Java 2 平臺中,可以將一個應用程序設置爲使用 java.lang.SecurityManager 類或者 java.security.AccessController 類管理敏感的操作。AccessController 在 Java 2 平臺中是新出現的。爲便於向後兼容,SecurityManager 類仍然存在,但把自己的決定提交 AccessController 類裁決。SecurityManager 和 AccessController 都使用應用程序的策略文件確定是否允許一個被請求的操作。清單 2 顯示了 AccessController 如何處理 SocketPermission 請求:

清單 2. 保護敏感操作

Public void someMethod() {
 Permission permission =
   new java.net.SocketPermission("localhost:8080", "connect");
 AccessController.checkPermission(permission);
 // Sensitive code starts here
 Socket s = new Socket("localhost", 8080);
}


在這個示例中,我們看到 AccessController 檢查應用程序的當前策略實現。如果策略文件中定義的任何許可權暗示了被請求的許可權,該方法將只簡單地返回;否則拋出一個 AccessControlException 異常。在這個示例中,檢查實際上是多餘的,因爲缺省套接字實現的構造函數也執行相同的檢查。

在下一部分,我們將更仔細地看一下 AccessController 如何與 java.security.Policy 實現共同合作安全地處理應用程序請求。

運行中的 AccessController
AccessController 類典型的 checkPermission(Permission p) 方法調用可能會導致下面的一系列操作:

AccessController 調用 java.security.Policy 類實現的 getPermissions(CodeSource codeSource) 方法。


getPermissions(CodeSource codeSource) 方法返回一個 PermissionCollection 類實例,這個類實例代表一個相同類型許可權的集合。

AccessController 調用 PermissionCollection 類的 implies(Permission p) 方法。

接下來,PermissionCollection 調用集合中包含的單個 Permission 對象的 implies(Permission p) 方法。如果集合中的當前許可權對象暗示指定的許可權,則這些方法返回 true,否則返回 false。

現在,讓我們更詳細地看一下這個訪問控制序列中的重要元素。

PermissionCollection 類
大多數許可權類類型都有一個相應的 PermissionCollection 類。這樣一個集合的實例可以通過調用 Permission 子類實現定義的 newPermissionCollection() 方法來創建。java.security.Policy 類實現的 getPermissions() 方法也可以返回 Permissions 類實例 — PermissionCollection 的一個子類。這個類代表由 PermissionCollection 組織的不同類型許可權對象的一個集合。Permissions 類的 implies(Permission p) 方法可以調用單個 PermissionCollection 類的 implies(Permission p) 方法。

CodeSource 和 ProtectionDomain 類
許可權組合與 CodeSource(被用於驗證籤碼(signed code)的代碼位置和證書)被封裝在 ProtectionDomain 類中。有相同許可權和相同 CodeSource 的類實例被放在相同的域中。帶有相同許可權,但不同 CodeSource 的類被放在不同的域中。一個類只可屬於一個 ProtectionDomain。要爲對象獲取 ProtectionDomain,請使用 java.lang.Class 類中定義的 getProtectionDomain() 方法。

許可權
賦予 CodeSource 許可權並不一定意味着允許所暗示的操作。要使操作成功完成,調用棧中的每個類必須有必需的許可權。換句話說,如果您將 java.io.FilePermission 賦給類 B,而類 B 是由類 A 來調用,那麼類 A 必須也有相同的許可權或者暗示 java.io.FilePermission 的許可權。

在另一方面,調用類可能需要臨時許可權來完成另一個擁有那些許可權的類中的操作。例如,當從另一個位置加載的類訪問本地文件系統時,我們可能不信任它。但是,本地加載的類被授予對某個目錄的讀許可權。這些類可以實現 PrivilegedAction 接口來給予調用類許可權以便完成指定的操作。調用棧的檢查在遇到 PrivilegedAction 實例時停止,有效地將執行指定操作所必需的許可權授予所有的後繼類調用。

使用 JAAS
顧名思義,JAAS 由兩個主要組件組成:認證和授權。我們主要關注擴展 JAAS 的授權組件,但開始我們先簡要概述一下 JAAS 認證,緊接着看一下一個簡單的 JAAS 授權操作。

JAAS 中的用戶認證
JAAS 通過添加基於 subject 的策略加強了 Java 2 中定義的訪問控制安全性模型。許可權的授予不僅基於 CodeSource,還基於執行代碼的用戶。顯然,要使這個模型生效,每個用戶都必須經過認證。

JAAS 的認證機制建立在一組可插登錄模塊的基礎上。JAAS 分發版包含幾個 LoginModule 實現。LoginModules 可以用於提示用戶輸入用戶標識和密碼。LoginContext 類使用一個配置文件來確定使用哪個 LoginModule 對用戶進行認證。這個配置可以通過系統屬性 java.security.auth.login.config 指定。一個示例配置是:
java -Djava.security.auth.login.config=login.conf


下面是一個登錄配置文件的樣子:
Example {
  com.ibm.resource.security.auth.LoginModuleExample required
    debug=true userFile="users.xml" groupFile="groups.xml";
};

認識您的主體
Subject 類被用於封裝一個被認證實體(比如用戶)的憑證。一個 Subject 可能擁有一個被稱爲主體(principal)的身份分組。例如,如果 Subject 是一個用戶,用戶的名字和相關的社會保險號可能是 Subject 的某些身份或主體。主體是與身份名關聯在一起的。

Principal 實現類及其名稱都是在 JAAS 策略文件中指定的。缺省的 JAAS 實現使用的策略文件與 Java 2 實現的策略文件相似 — 除了每個授權語句必須與至少一個主體關聯在一起。javax.security.auth.Policy 抽象類被用於表示 JAAS 安全性策略。它的缺省實現由 com.sun.security.auth.PolicyFile 提供,在 com.sun.security.auth.PolicyFile 中策略定義在一個文件中。清單 3 是 JAAS 策略文件的一個示例:

清單 3. 示例 JAAS 策略文件

// Example grant entry
grant codeBase "file:/C:/sample.jar", signedby "XYZ",
  principal com.ibm.resource.security.auth.PrincipalExample "admin" {
    // Allow socket actions to any host using port 8080
    permission java.net.SocketPermission
      "*:8080", "accept, connect, listen, resolve";
    // Allows file access (read, write, execute, delete) in
    // the user's home directory.
    Permission java.io.FilePermission
      "${user.home}/-", "read, write, execute, delete";
};

這個示例與清單 1 中所示的標準 Java 2 策略文件相似。實際上,唯一的不同是主體語句,該語句聲明只有擁有指定主體和主體名字的 subject(用戶)被授予指定的許可權。

再一次,使用系統屬性 java.security.auth.policy 指出 JAAS 策略文件駐留在何處,如下所示:

java -Djava.security.auth.policy=policy.jaas

Subject 類包含幾個方法來作爲特殊 subject 執行工作;這些方法如下所示:


public static Object
  doAs(Subject subject, java.security.PrivilegedAction action)
public static Object
  doAs(Subject subject, java.security.PrivilegedAction action)
  throws java.security.PrivilegedActionException 

注意,用來保護敏感代碼的方法與“Java 2 代碼源訪問控制”(Java 2 CodeSource Access Control)概述中描述的方法相同。請參閱參考資料部分以瞭解更多關於 JAAS 中代碼源訪問控制和認證的信息。

JAAS 中的授權
清單 4 顯示一個授權請求的結果,該請求使用清單 3 中顯示的 JAAS 策略文件。假設已經安裝了 SecurityManager,並且 loginContext 已經認證了一個帶有名爲“admin”的 com.ibm.resource.security.auth.PrincipalExample 主體的 Subject。

清單 4. 一個簡單的授權請求
public class JaasExample {
 public static void main(String[] args) {
  ...
  // where authenticatedUser is a Subject with
  // a PrincipalExample named admin.
  Subject.doAs(authenticatedUser, new JaasExampleAction());
  ...
 }
}

public class JaasExampleAction implements PrivilegedAction {
 public Object run() {
  FileWriter fw = new FileWriter("hi.txt");
  fw.write("Hello, World!");
  fw.close();
 }


這裏,敏感代碼被封裝在 JaasExampleAction 類中。還要注意,調用類不要求爲 JaasExampleAction 類代碼源授予許可權,因爲它實現了一個 PrivilegedAction。

擴展 JAAS
大多數應用程序都有定製邏輯,它授權用戶不僅僅在類上執行操作,而且還在該類的實例上執行操作。這種授權通常建立在用戶和實例之間的關係上。這是 JAAS 的一個小缺點。然而,幸運的是,這樣設計 JAAS 使得 JAAS 可以擴展。只要做一點工作,我們將可以擴展 JAAS,使其包含一個通用的、類實例級的授權框架。

在文章開頭處我已經說明了,抽象類 javax.security.auth.Policy 被用於代表 JAAS 安全性策略。它的缺省實現是由 com.sun.security.auth.PolicyFile 類提供。PolicyFile 類從 JAAS 格式的文件(象清單 3 中顯示的那個一樣)中讀取策略。

我們需要向這個文件添加一個東西爲類實例級授權擴展策略定義:一個與許可權語句相關的可選關係參數。

缺省 JAAS 許可權語句的格式如下:

permission <permission implementation class> [name], [actions]; 

我們在這個許可權語句的末尾添加一個可選的關係參數來完成策略定義。下面是新許可權語句的格式:

permission <permission implementation class>
  [name], [actions], [relationship];


在爲類實例級授權擴展 JAAS 時要注意的最重要的一點是:許可權實現類必須有一個帶三個參數的構造函數。第一個參數是名稱參數,第二個是行爲參數,最後一個是關係參數。

解析新文件格式
既然文件格式已經改變,就需要一個新的 javax.security.auth.Policy 子類來解析文件。

爲簡單起見,我們的示例使用了一個新的 javax.security.auth.Policy 子類 com.ibm.resource.security.auth.XMLPolicyFile,來從 XML 文件讀取策略。在實際的企業應用程序中,關係數據庫更適合執行這個任務。

使用 XMLPolicyFile 類代替缺省的 JAAS 訪問控制策略實現的最容易的方法是向 java.security 屬性文件添加 auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile 條目。java.security 屬性文件位於 Java 2 平臺運行時的 lib/security 目錄下。清單 5 是與 XMLPolicyFile 類一起使用的樣本 XML 策略文件:

清單 5. 一個 XML 策略文件
<?xml version="1.0"?>
<policy>
    <grant codebase="file:/D:/sample_actions.jar">
      <principal classname=
        "com.ibm.resource.security.auth.PrincipalExample" name="users">
        <permission classname=
          "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Auction"
          actions="create" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Auction"
          actions="read" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Auction"
          actions="write"
          relationship="owner" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="create" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="read" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="write"
          relationship="owner" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="accept"
          relationship="actionOwner" />
    </principal>
  </grant>
</policy> 

在這個示例策略文件中,任何與名爲 PrincipalExample 的用戶有關的用戶(Subject)都可以創建並讀取一個 Auction.class 實例。但是,只有創建該實例的用戶纔可以更新(寫)它。這是第三個 permission 元素定義的,該元素包含值爲 owner 的 relationship 屬性。Bid.class 實例也是一樣,除了相應 Auction.class 實例的所有者可以更改投標接受標誌。

Resource 接口
要求類實例級訪問控制的類必須實現 Resource 接口。該接口的 getOwner() 方法返回類實例的所有者。fulfills(Subject subject, String relationship) 方法被用於處理特定關係。另外,這些類使用 com.ibm.resource.security.auth.ResourcePermission 類保護敏感代碼。例如,Auction 類擁有下列構造函數:

public Auction() {
  Permission permission =
    new ResourcePermission("com.ibm.security.sample.Auction", "create");
  AccessController.checkPermission(permission);
 } 

所有者關係
ResourcePermission 類的 implies(Permission p) 方法是這個框架的關鍵。implies() 方法就等同性比較名稱和行爲屬性。如果定義了一個關係,那麼必須把受保護的類實例(Resource)傳遞到 ResourcePermission 構造函數中。ResourcePermission 類理解所有者關係。它將類實例的所有者與執行代碼的 subject(用戶)進行比較。特定關係被委託給受保護類的 fulfills() 方法。

例如,在清單 5 中所示的 XML 策略文件中,只有 Auction 類實例的所有者可以更新(寫)文件。該類的 setter 方法使用清單 6 中顯示的保護代碼:

清單 6. 運行中的 implies(Permission) 方法
public void setName(String newName) {
  Permission permission =
    new ResourcePermission("com.ibm.security.sample.Auction", "write", this);
  AccessController.checkPermission(permission);
  // sensitive code
  this.name = newName;
}


被傳遞到 ResourcePermission 構造函數中的 this 引用代表 Auction 類實現的 Resource 接口。由於策略文件中列出的關係是 owner,所以 ResourcePermission 類使用這個引用檢查當前 Subject(用戶)是否擁有與實例所有者相匹配的主體。如果指定了另一個關係,那麼 ResourcePermission 類調用 Auction 類的 fulfills(Subject subject, String relationship) 方法。由 Resource 實現類提供 fulfills() 方法中的邏輯。

XML 策略文件中列出的 Bid 類擁有清單 7 中所示的方法(假設 Bid 類實例有一個對相應 Auction 類實例的引用 — auction)。

清單 7. 處理特定關係
public void setAccepted(boolean flag) {
  Permission permission =
    new ResourcePermission("com.ibm.security.sample.Auction", "accept", this);
  AccessController.checkPermission(permission);
  // sensitive code
  this.accepted = flag;
  }
 
public boolean fulfills(Subject user, String relationship) {
  if( relationship.equalsIgnoreCase("auctionOwner") ) {
    String auctionOwner = auction.getOwner();
    Iterator principalIterator = user.getPrincipals().iterator();
    while(principalIterator.hasNext()) {
      Principal principal = (Principal) principalIterator.next();
      if( principal.getName().equals(auctionOwner) )
        return true;
    }
  }
  return false;
}


傳遞到 fulfills() 方法中的關係字符串是策略文件中列出的關係。在這個案例中,我們使用了“auctionOwner”字符串。

缺省情況下,XMLPolicyFile 類在當前工作目錄中查找名爲 ResourcePolicy.xml 的文件。系統屬性 com.ibm.resource.security.auth.policy 可以用於指定另一個不同的文件名和位置。

WebSphere Application Server 示例

除命令行示例之外,您可能還想運行這個簡單的程序,該程序爲了 IBM WebSphere Application Server,version 4.0.2 而被優化。
 
一個可運行的示例
綜合這些信息,我們將運行一個簡單的命令行示例。該示例程序包含三個 jar 文件:

resourceSecurity.jar
example.jar
exampleActions.jar
resourceSecurity.jar 文件包含允許實例級訪問控制的 JAAS 擴展框架。它還包含一個 LoginModuleExample 類,這個類從 XML 文件讀取用戶認證信息。用戶標識和密碼存儲在 users.xml 文件中。用戶組存儲在 groups.xml 文件中。關於 LoginModuleExample 的更多信息,請參閱參考資料部分。

該示例包含四個附加的文件:

login.conf
policy
resourcePolicy.xml
run.bat
在試圖運行這個示例程序之前,請確保更新了 run.bat、policy 和 resourcePolicy.xml 文件中的路徑。缺省情況下,所有的密碼都是“passw0rd”。

示例如何工作
該示例程序提示輸入用戶標識和密碼。它用 users.xml 文件中的條目覈對所提供的用戶標識和密碼。在認證了用戶之後,程序設法創建一個 UserProfile 類實例,修改它並從中讀取。缺省情況下,UserProfile 類的所有者是 Jane(jane)。當 Jane 登錄時,三個操作全部成功。當 John(john)登錄時,只有創建操作成功。當 Jane 的經理 Lou(lou)登錄時,只有第一個和最後一個操作成功。當系統管理員(admin)登錄時,操作全部成功。當然,只有當提供的 ResourcePolicy.xml 文件未被修改時,上述這些才都是真的。

示例安裝
下面的安裝指導假設您正在使用 JDK 1.3 並且已經把文件解壓縮到 d:/JaasExample 目錄。通過將文件解壓縮到這個目錄,您可以省去一些工作;否則您就必須使用正確的路徑名修改 policy 和 ResourceSecurity.xml 策略文件。

下面是運行該示例需要做的工作:

下載這個示例的源文件。

把 jaas.jar 和 jaasmod.jar 複製到 JDK jre/lib/ext 目錄(即 D:/JDK1.3/jre/lib/ext)。

向位於 JDK 的 jre/lib/security 目錄(即 D:/JDK1.3/jre/lib/security)中的 java.security 文件的末尾添加下面的字符串:auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile。

執行 run.bat 文件。

結束語
類實例級授權把訪問控制分離到一個通用框架(該框架使用基於所有權和特定關係的策略)中。然後管理員可以在應用程序的生命週期內更改這些策略。用這種方法擴展 JAAS 減少了您或另一個程序員必須在應用程序生命週期內業務規則發生更改時重寫代碼的可能性。

通過將關係字符串抽象爲類可以進一步擴展特定關係這個概念。不調用 Resource 實現類的 fulfills(Subject user, String relationship) 方法,而只要調用 Relationship 實現類中定義的新 fulfills(Subject user, Resource resource) 方法。這樣就會允許許多 Resource 實現類使用相同的關係邏輯。

6.Java的安全性
1. the security manager是一個application-wide object ( java.lang.SecurityManager)
每個Java Application都可以有自己地Security Manager,但是默認地Java Application沒有一個Security Manager

可以通過下面地代碼得到一個Security Manager
try
{
  System.setSecurityManager(new SecurityManager(“--”));
}
catch( )
{}

2.
JDBC
在 JDBC 2 開發的過程中,SQL99 還處在一種變化不定的情況下。現在規範已經完成了,而且數據庫廠商已經採用了部分標準。所以自然地,JDBC 規範就跟着將自己與 SQL99 功能的一部分相統一。最新的 JDBC 規範已經採用了 SQL99 標準中那些已經被廣泛支持的功能,還有那些在五年內可能會獲得支持的功能。
1. DataSource
在JDBC2.0 Optional Package中,提供了透明的連接池(Connection pooling)。
一旦配置了J2EE應用服務器後,只要用DataSource獲取連接(Connection),連接池(Connection pooling)就會自動的工作。

如果用戶希望建立一個數據庫連接,通過查詢在JNDI服務中的DataSource,可以從DataSource中獲取相應的數據庫連接。
DataSource被認爲是從JNDI中獲取的網絡資源。

DataSource在池中保存的對象都實現了PooledConnection接口。
當應用程序向DataSource請求一個Connection時,它會找到一個可用的PooledConnection對象。
如果連接池空了,它就向ConnectionPoolecDataSource請求一個新的PooledConnection對象

通過使用 DataSource 接口 (JDBC 2.0) 或 DriverManager (JDBC 1.0) 接口,J2EE 組件可以獲得物理數據庫連接對象(Connection)。要獲得邏輯(合用的)連接,J2EE 組件必須使用以下這些 JDBC 2.0 合用管理器接口:

javax.sql.ConnectionPoolDataSource 接口,該接口充當合用的 java.sql.Connection 對象的資源管理器連接 factory。每家數據庫服務器供應商都提供該接口的實現
(例如,Oracle 實現 oracle.jdbc.pool.OracleConnectionPoolDataSource 類)。
javax.sql.PooledConnection 接口,該接口封裝到數據庫的物理連接。同樣,數據庫供應商提供其實現。
對於那些接口和 XA 連接的每一個,都存在一個 XA(X/Open 規範)等價定義。

2. ResultSet
在JDBC2.0中,爲了獲得一個Uptatable Result,在Query語句裏必須包含Primarykey,並且查詢的內容裏必須來自一個table

ava.sql.ResultSet接口中定義了三種類型的結果集
TYPE_FORWARD_ONLY
TYPE_SCROLL_INSENSITIVE   這種類型的結果集支持雙向滾動
TYPE_SCROLL_SENSITIVE

如果要建立一個雙向滾動的ResultSet,一定要在建立Statement的時候使用如下參數
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);

3. JDBC驅動程序
連通oracle8.1.6的JDBC
把oracle8.1.6/lib/jdbc/*.zip copy 到 %JAVA_HOME%/jre/lib/ext/*.jar

如果光copy不ren爲.jar是沒有用的。
4. 事務處理
本地事務
  java.sql.Connection接口可以控制事務邊界(即開始和結束)。
在事務開始的時候調用setAutoCommit( false ), 而在中止事務時調用rollback或commit()方法。這類事務叫本地事務。

分佈式事務
 但是,在特定的情況下,可能有多個客戶(例如兩個不同的servlet或EJB組件)參與了同一個事務。
 或者,客戶在同一個事務中可能會執行跨越多個數據庫的數據庫操作。
 JDBC2.0 Optional Package 同JTA一起來實現分佈式樣事務。

5. 一些技巧
檢索自動產生的關鍵字
爲了解決對獲取自動產生的或自動增加的關鍵字的值的需求,JDBC 3.0 API 現在將獲取這種值變得很輕鬆。要確定任何所產生的關鍵字的值,只要簡單地在語句的 execute() 方法中指定一個可選的標記,表示您有興趣獲取產生的值。您感興趣的程度可以是 Statement.RETURN_GENERATED_KEYS,也可以是 Statement.NO_GENERATED_KEYS。在執行這條語句後,所產生的關鍵字的值就會通過從 Statement 的實例方法 getGeneratedKeys() 來檢索 ResultSet 而獲得。ResultSet 包含了每個所產生的關鍵字的列。清單 1 中的示例創建一個新的作者並返回對應的自動產生的關鍵字。

清單 1. 檢索自動產生的關鍵字

Statement stmt = conn.createStatement();

// Obtain the generated key that results from the query.

stmt.executeUpdate("INSERT INTO authors " +

           '(first_name, last_name) " +

           "VALUES ('George', 'Orwell')",

           Statement.RETURN_GENERATED_KEYS);

ResultSet rs = stmt.getGeneratedKeys();

if ( rs.next() ) {

    // Retrieve the auto generated key(s).

    int key = rs.getInt();

}

JTA/JTS
1.JTA/JTS基本知識
服務器實現JTS是否對應用程序開發人員來說不是很重要的。
對你來說,應該把JTA看作是可用的API。

JTA是用來開發distributed tansaction的 API.
而JTS定義了支持JTA中實現Transaction Manager 的規範。

JavaTransaction Service (JTS) specifies the implementation of a Transaction Manager which supports the Java Transaction API (JTA) 1.0 Specification at the high-level and implements the Java mapping of the OMG Object Transaction Service (OTS) 1.1 Specification at the low-level. JTS uses the standard CORBA ORB/TS interfaces and Internet Inter-ORB Protocol (IIOP) for transaction context propagation between JTS Transaction Managers.

A JTS Transaction Manager provides transaction services to the parties involved in distributed transactions: the application server, the resource manager, the standalone transactional application, and the Communication Resource Manager (CRM).
2.JTA
1.1 事務處理的概念
JTA實際上是由兩部分組成的:一個高級的事務性客戶接口和一個低級的 X/Open XA接口。

我們關心的是高級客戶接口,因爲bean可以訪問它,而且是推薦的客戶應用程序的事務性接口。
低級的XA接口是由EJB服務器和容器使用來自動協調事務和資源(如數據庫)的

1.1.1事務劃分
a.程序劃分
  使用UserTransaction啓動JTA事務
  The UserTransaction interface defines the methods that allow an application to explicitly manage transaction boundaries.(from j2ee API document)

b.聲明劃分
  EJB容器使用TransactionManager啓動JTA事務
  The TransactionManager interface defines the methods that allow an application server to manage transaction boundaries. (from j2ee API document)

1.1.2事務上下文及其傳播
事務上下文是一種對資源上的事務操作之間和調用操作的組件之間的聯繫。

1.1.3資源加入
資源加入(resource enlistment)是一個過程,在這個過程中資源管理器通知事務管理器它要參與事務。

1.1.4兩階段提交
兩階段提交是事務管理器和所有加入到事務中的資源之間的協議,確保要麼所有的資源管理器都提交了事務,要麼都撤銷了事務。

如果在一個事務內部只是訪問一個單一資源管理器,不需要執行一個兩階段提交。
如果在一個事務內部只是訪問多個資源管理器,兩階段提交是有益的。

1.2事務處理系統中的構件模塊
應用組件

資源管理器
  資源管理器管理持久和穩定的數據存儲系統,並且與事務管理器一起參與兩階段提交和恢復協議。典型的資源管理器如數據庫系統和消息隊列。

事務管理器
3.JTS
JTS 是一個組件事務監視器(component transaction monitor)。
這是什麼意思?在第 1 部分,我們介紹了事務處理監視器(TPM)這個概念,TPM 是一個程序,它代表應用程序協調分佈式事務的執行。
TPM 與數據庫出現的時間長短差不多;在 60 年代後期,IBM 首先開發了 CICS,至今人們仍在使用。經典的(或者說程序化)TPM 管理被程序化定義爲針對事務性資源(比如數據庫)的操作序列的事務。隨着分佈式對象協議,如 CORBA、DCOM 和 RMI 的出現,人們希望看到事務更面向對象的前景。將事務性語義告知面向對象的組件要求對 TPM 模型進行擴展 — 在這個模型中事務是按照事務性對象的調用方法定義的。
JTS 只是一個組件事務監視器(有時也稱爲對象事務監視器(object transaction monitor)),或稱爲 CTM。

JTS 和 J2EE 的事務支持設計受 CORBA 對象事務服務(CORBA Object Transaction Service,OTS)的影響很大。實際上,JTS 實現 OTS 並充當 Java 事務 API(Java Transaction API)— 一種用來定義事務邊界的低級 API — 和 OTS 之間的接口。使用 OTS 代替創建一個新對象事務協議遵循了現有標準,並使 J2EE 和 CORBA 能夠互相兼容。

乍一看,從程序化事務監視器到 CTM 的轉變好像只是術語名稱改變了一下。然而,差別不止這一點。當 CTM 中的事務提交或回滾時,與事務相關的對象所做的全部更改都一起被提交或取消。但 CTM 怎麼知道對象在事務期間做了什麼事?象 EJB 組件之類的事務性組件並沒有 commit() 或 rollback() 方法,它們也沒向事務監視器註冊自己做了什麼事。那麼 J2EE 組件執行的操作如何變成事務的一部分呢?

透明的資源徵用
當應用程序狀態被組件操縱時,它仍然存儲在事務性資源管理器(例如,數據庫和消息隊列服務器)中,這些事務性資源管理器可以註冊爲分佈式事務中的資源管理器。在第 1 部分中,我們討論瞭如何在單個事務中徵用多個資源管理器,事務管理器如何協調這些資源管理器。資源管理器知道如何把應用程序狀態中的變化與特定的事務關聯起來。

但這只是把問題的焦點從組件轉移到了資源管理器 — 容器如何斷定什麼資源與該事務有關,可以供它徵用?請考慮下面的代碼,在典型的 EJB 會話 bean 中您可能會發現這樣的代碼:

清單 1. bean 管理的事務的透明資源徵用
    InitialContext ic = new InitialContext();
    UserTransaction ut = ejbContext.getUserTransaction();
    ut.begin();

    DataSource db1 = (DataSource) ic.lookup("java:comp/env/OrdersDB");
    DataSource db2 = (DataSource) ic.lookup("java:comp/env/InventoryDB");
    Connection con1 = db1.getConnection();
    Connection con2 = db2.getConnection();
    // perform updates to OrdersDB using connection con1
    // perform updates to InventoryDB using connection con2
    ut.commit();


注意,這個示例中沒有徵用當前事務中 JDBC 連接的代碼 — 容器會爲我們完成這個任務。我們來看一下它是如何發生的。

資源管理器的三種類型
當一個 EJB 組件想訪問數據庫、消息隊列服務器或者其它一些事務性資源時,它需要到資源管理器的連接(通常是使用 JNDI)。而且,J2EE 規範只認可三種類型的事務性資源 — JDBC 數據庫、JMS 消息隊列服務器和“其它通過 JCA 訪問的事務性服務”。後面一種服務(比如 ERP 系統)必須通過 JCA(J2EE Connector Architecture,J2EE 連接器體系結構)訪問。對於這些類型資源中的每一種,容器或提供者都會幫我們把資源徵調到事務中。

在清單 1 中,con1 和 con2 好象是普通的 JDBC 連接,比如那些從 DriverManager.getConnection() 返回的連接。我們從一個 JDBC DataSource 得到這些連接,JDBC DataSource 可以通過查找 JNDI 中的數據源名稱得到。EJB 組件中被用來查找數據源(java:comp/env/OrdersDB)的名稱是特定於組件的;組件的部署描述符的 resource-ref 部分將其映射爲容器管理的一些應用程序級 DataSource 的 JNDI 名稱。

隱藏的 JDBC 驅動器
每個 J2EE 容器都可以創建有事務意識的池態 DataSource 對象,但 J2EE 規範並不向您展示如何創建,因爲這不在 J2EE 規範內。瀏覽 J2EE 文檔時,您找不到任何關於如何創建 JDBC 數據源的內容。相反,您不得不爲您的容器查閱該文檔。創建一個數據源可能需要向屬性或配置文件添加一個數據源定義,或者也可以通過 GUI 管理工具完成,這取決於您的容器。

每個容器(或連接池管理器,如 PoolMan)都提供它自己的創建 DataSource 機制,JTA 魔術就隱藏在這個機制中。連接池管理器從指定的 JDBC 驅動器得到一個 Connection,但在將它返回到應用程序之前,將它與一個也實現 Connection 的虛包包在一起,將自己置入應用程序和底層連接之間。當創建連接或者執行 JDBC 操作時,包裝器詢問事務管理器當前線程是不是正在事務的上下文中執行,如果事務中有 Connection 的話,就自動徵用它。

其它類型的事務性資源,JMS 消息隊列和 JCA 連接器,依靠相似的機制將資源徵用隱藏起來,使用戶看不到。如果要使 JMS 隊列在部署時對 J2EE 應用程序可用,您就要再次使用特定於提供者的機制來創建受管 JMS 對象(隊列連接工廠和目標),然後在 JNDI 名稱空間內發佈這些對象。提供者創建的受管對象包含與 JDBC 包裝器(由容器提供的連接池管理器添加)相似的自動徵用代碼。

透明的事務控制
兩種類型的 J2EE 事務 — 容器管理的和 bean 管理的 — 在如何啓動和結束事務上是不同的。事務啓動和結束的地方被稱爲事務劃分(transaction demarcation)。清單 1 中的示例代碼演示了 bean 管理的事務(有時也稱爲編程(programmatic)事務)。Bean 管理的事務是由組件使用 UserTransaction 類顯式啓動和結束的。通過 ejbContext 使 UserTransaction 對 EJB 組件可用,通過 JNDI 使其對其它 J2EE 組件可用。

容器根據組件的部署描述符中的事務屬性代表應用程序透明地啓動和結束容器管理的事務(或稱爲宣告式事務(declarative transaction))。通過將 transaction-type 屬性設置爲 Container 或 Bean 您可以指出 EJB 組件是使用 bean 管理的事務性支持還是容器管理的事務性支持。

使用容器管理的事務,您可以在 EJB 類或方法級別上指定事務性屬性;您可以爲 EJB 類指定缺省的事務性屬性,如果不同的方法會有不同的事務性語義,您還可以爲每個方法指定屬性。這些事務性屬性在裝配描述符(assembly descriptor)的 container-transaction 部分被指定。清單 2 顯示了一個裝配描述符示例。trans-attribute 的受支持的值有:

Supports
Required
RequiresNew
Mandatory
NotSupported
Never
trans-attribute 決定方法是否支持在事務內部執行、當在事務內部調用方法時容器會執行什麼操作以及在事務外部調用方法時容器會執行什麼操作。最常用的容器管理的事務屬性是 Required。如果設置了 Required,過程中的事務將在該事務中徵用您的 bean,但如果沒有正在運行的事務,容器將爲您啓動一個。在這個系列的第 3 部分,當您可能想使用每個事務屬性時,我們將研究各個事務屬性之間的區別。

清單 2. EJB 裝配描述符樣本
<assembly-descriptor>
  ...
  <container-transaction>
    <method>
      <ejb-name>MyBean</ejb-name>
      <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
  </container-transaction>
  <container-transaction>
    <method>
      <ejb-name>MyBean</ejb-name>
      <method-name>updateName</method-name>
      </method>
   <trans-attribute>RequiresNew</trans-attribute>
  </container-transaction>
  ...
</assembly-descriptor>

 功能強大,但很危險
與清單 1 中的示例不同,由於有宣告式事務劃分,這段組件代碼中沒有事務管理代碼。這不僅使結果組件代碼更加易讀(因爲它不與事務管理代碼混在一起),而且它還有另一個更重要的優點 — 不必修改,甚至不必訪問組件的源代碼,就可以在應用程序裝配時改變組件的事務性語義。

儘管能夠指定與代碼分開的事務劃分是一種非常強大的功能,但在裝配時做出不好的決定會使應用程序變得不穩定,或者嚴重影響它的性能。對容器管理的事務進行正確分界的責任由組件開發者和應用程序裝配人員共同擔當。組件開發者需要提供足夠的文檔說明組件是做什麼的,這樣應用程序部署者就能夠明智地決定如何構建應用程序的事務。應用程序裝配人員需要理解應用程序中的組件是怎樣相互作用的,這樣就可以用一種既強制應用程序保持一致又不削弱性能的方法對事務進行分界。在這個系列的第 3 部分中我們將討論這些問題。

透明的事務傳播
在任何類型的事務中,資源徵用都是透明的;容器自動將事務過程中使用的任意事務性資源徵調到當前事務中。這個過程不僅擴展到事務性方法使用的資源(比如在清單 1 中獲得的數據庫連接),還擴展到它調用的方法(甚至遠程方法)使用的資源。我們來看一下這是如何發生的。

容器用線程與事務相關聯
我們假設對象 A 的 methodA() 啓動一個事務,然後調用對象 B 的 methodB()(對象 B 將得到一個 JDBC 連接並更新數據庫)。B 獲得的連接將被自動徵調到 A 創建的事務中。容器怎麼知道要做這件事?

當事務啓動時,事務上下文與執行線程關聯在一起。當 A 創建事務時,A 在其中執行的線程與該事務關聯在一起。由於本地方法調用與主調程序(caller)在同一個線程內執行,所以 A 調用的每個方法也都在該事務的上下文中。

櫥中骸骨
如果對象 B 其實是在另一個線程,甚至另一個 JVM 中執行的 EJB 組件的存根,情況會怎樣?令人吃驚的是,遠程對象 B 訪問的資源仍將在當前事務中被徵用。EJB 對象存根(在主調程序的上下文中執行的那部分)、EJB 協議(IIOP 上的 RMI)和遠端的骨架對象協力要使其透明地發生。存根確定調用者是不是正在執行一個事務。如果是,事務標識,或者說 Xid,被作爲 IIOP 調用的一部分與方法參數一起傳播到遠程對象。(IIOP 是 CORBA 遠程-調用協議,它爲傳播執行上下文(比如事務上下文和安全性上下文)的各種元素而備;關於 RMI over IIOP 的更多信息,請參閱參考資料。)如果調用是事務的一部分,那麼遠程系統上的骨架對象自動設置遠程線程的事務上下文,這樣,當調用實際的遠程方法時,它已經是事務的一部分了。(存根和骨架對象還負責開始和提交容器管理的事務。)

事務可以由任何 J2EE 組件來啓動 — 一個 EJB 組件、一個 servlet 或者一個 JSP 頁面(如果容器支持的話,還可以是一個應用程序客戶機)。這意味着,應用程序可以在請求到達時在 servlet 或者 JSP 頁面中啓動事務、在 servlet 或者 JSP 頁面中執行一些處理、作爲頁面邏輯的一部分訪問多個服務器上的實體 bean 和會話 bean 並使所有這些工作透明地成爲一個事務的一部分。圖 1 演示了事務上下文怎樣遵守從 servlet 到 EJB,再到 EJB 的執行路徑。

圖 1.單個事務中的多個組件
 

最優化
讓容器來管理事務允許容器爲我們做出某些最優化決定。在圖 1 中,我們看到一個 servlet 和多個 EJB 組件在單個事務的上下文中訪問一個數據庫。每個組件都獲得到數據庫的 Connection;很可能每個組件都在訪問同一個數據庫。即使多個連接是從不同的組件到同一個資源,JTS 也可以檢測出多個資源是否和事務有關,並最優化該事務的執行。您可以從第 1 部分回憶起來,單個事務要包含多個資源管理器需要使用兩階段提交協議,這比單個資源管理器使用的單階段提交代價要高。JTS 能夠確定事務中是不是隻徵用了一個資源管理器。如果它檢測出所有與事務相關的資源都一樣,它可以跳過兩階段提交併讓資源管理器自己來處理事務。

結束語
這個慮及透明事務控制、資源徵用和透明傳播的魔術不是 JTS 的一部分,而是 J2EE 容器如何在幕後代表 J2EE 應用程序使用 JTA 和 JTS 服務的一部分。在幕後有許多實體合力使這個魔術透明地發生;EJB 存根和骨架、容器廠商提供的 JDBC 驅動器包裝器、數據庫廠商提供的 JDBC 驅動器、JMS 提供器和 JCA 連接器。所有這些實體都與事務管理器進行交互,於是應用程序代碼就不必與之交互了。

4.事務的特性ACID
原子性(automic)
 事務內部的操作必須被看作一個單一的,原子性的單元。
這意味着,如果在其中的每個操作都被成功的執行,事務就能被認爲是完整的並且允許提交。

一致性(consistent)
當作爲一個整體執行一個事務的操作時,這些操作必須把它們處理的數據從一個一致性的狀態轉移到另一個一致性的狀態

隔離性(isolated)
隔離對資源的訪問
事務應該與其他事務的效用隔離。
隔離級別描述了通過併發事務對一個資源的訪問被隔離的程度。
如果你熟悉Java中的線程同步或是關係數據庫中的行鎖設計的概念,隔離性與這樣的概念類似。
在EJB1.1中,如果容器管理事務,配置器設置事務隔離層
如果bean管理事務,bean配置器設置事務隔離層
       
事務隔離可用隔離條件來定義,這些條件有:
A. dirty read(髒讀,不清楚的讀)
B.  repeatable read(可重複的讀)
C.  phantom read(幻影,有名無實的讀?)
四種隔離層
b. Read Uncommitted
c. Read Committed
d. Repeatable Read
e. Serializable
這些隔離層和JDBC定義的隔離層相同,在java.sql.Connection類中定義了相應的靜態變量。
Serializable的隔離層確保數據不被事務併發訪問,這樣可以確保數據永遠是一致的。

get方法的隔離層的等級可以非常低,如Read Uncommited
set方法所作的修改必須防止其他事務的不清楚的讀取,因此將使用最大約束的隔離層Serializable


通常來說,隨着隔離層變得更有約束,系統的性能也將降低。

  
   持久性(durable)
當提交事務時,該事務所作的任何數據更新必須是“耐久性”的。
這意味着不管它結束之後發生任何錯誤,被提交事務的結果必須保留。
更通俗的說法是:所有再事務過程中所作的數據修改必須在事務成功完成之前寫入某種類型的物理介質。

  理解:
1.事務系統通過確保事務是原子的,隔離的和持久的來實現事務的一致性

現實程序中主要考慮的是原子性

JCA(J2EE連接體系結構)
J2EE Connector Architecture基礎
J2EE連接體系結構,目前正在修改,將期盼着包括J2EE未來版本的規範,這個連接
體系結構定義了標準的資源適配器和依附於連接、事務、安全管理的合同,所以應用服務器將以標準和統一的方式插入各種企業信息系統,包括ERP(如SAP R/3),主框架事務處理系統和數據庫系統。


理想的做法是內置一個可用於任何資源類型和所有連接管理功能(包括合用)的通用連接接口。這就是即將出現的 J2EE Connector Architecture 1.0 規範的目標之一。
 
圖  顯示了體系結構內部的主要概念,資源適配器。應用服務器所支持的每一種資源類型的可插入組件,資源適配器,都在應用服務器地址空間中執行。訪問那些適配器的客戶機 API 可以是 Common Client Interface (CCI) 或(爲了向後兼容)特定於資源的 API(例如 JDBC 2.0)。
例如,CCI 定義 javax.resource.cci.ConnectionFactory 和 javax.resource.cci.Connection ,分別作爲連接 factory 和連接的接口 -- 與JDBC 2.0 接口類似。

JDBC和JCA關係
大多數應用程序開發人員不需要知道 JDBC 和 J2EE 連結器體系結構之間的關係,就可以很好地使用 JDBC API。但是,由於 JDBC 3.0 規範已經考慮到這項新的體系結構,這使得開發人員能更好地理解 JDBC 在哪裏適合 J2EE 標準,以及這個規範的發展方向是什麼。
JCA指定了一組協議,允許企業的信息系統以一種可插入的方式連接到應用服務器上。這種體系結構定義了負責與外部系統連接的資源適配器。連接器服務提供者接口(The Connectors Service Provider Interface,SPI)恰好和 JDBC 接口提供的服務緊密配合。
JDBC API 實現了連結器體系結構定義的三個協議中的兩個。
第一個是將應用程序組件與後端系統相連接的連接管理,它是由 DataSource 和 ConnectionPoolDataSource 接口來實現的。
第二個是支持對資源的事務性訪問的事務管理,它是由 XADataSource 來處理的。
第三個是支持後端系統的安全訪問的安全性管理,在這點上,JDBC 規範並沒有任何對應點。儘管有最後那個不足,JDBC 接口仍能映射到連接器 SPI 上。
如果一個驅動程序廠商將其 JDBC 驅動程序映射到連接器系統協議上,它就可以將其驅動程序部署爲資源適配器,並立刻享受可插性、封裝和在應用服務器中部署的好處。這樣,一個標準的 API 就可以在不同種類的的企業信息系統中,供企業開發人員使用。
JMS
THE basic building blocks of a JMS application are as follows:
? Administered objects (connection factories and destinations)
? Connections
? Sessions
? Message producers
? Message consumers
? Messages


消息系統允許分開的未耦合的應用程序之間可靠地異步通信。類同郵件系統.
 通常有兩種消息類型。
 1.發佈/訂閱(publish/subscribe)
 發佈/訂閱消息系統支持一個事件驅動模型,消息產生者和使用者都參與消息的傳遞。  產生者發佈事件,而使用者訂閱感興趣的事件,並使用事件。產生者將消息和一個特定的主題(Topic)連在一起,消息系統根據使用者註冊的興趣,將消息傳給使用者。
 2.點對點(Peer to peer)
 在點對點的消息系統中,消息分發給一個單獨的使用者。它維持一個"進入"消息隊列。消息應用程序發送消息到一個特定的隊列,而客戶端從一個隊列中得到消息JMS和EJB一樣是WEBLOGIC 提供的服務,客戶端通過JNDI名字查找。
在控制檯 先創建一個JMS的主題,設定一個JNDI(參照提示做啊,跟前邊的介紹雷同)
  一個典型的JMS客戶端由下面的幾個基本步驟來創建:
  創建一個到消息系統提供者的連接(Connection)
  創建一個Session,用於接收和發送消息
  創建MessageProducer和MessageConsumer來創建和接收消息
  當完成了上述步驟後,一個消息產生者客戶端將創建併發布消息到一個主題,(JNDI)
而消息使用者客戶端會接收與一個主題相關的消息。

1.創建一個Connection
A connection encapsulates a virtual connection with a JMS provider. It could represent an open TCP/IP socket between a client and a provider service daemon. You use a connection to create one or more sessions.

一個Connection提供客戶端對底層的消息系統的訪問。並實現資源的分配和管理。通過使用一個ConnectionFactory來創建一個Connection,通常用JDNI來指定:
Connection message=new initialContext();
TopicConnectionFactory topicConnectionFactory=(TopicConnectionFactory);
topic = (Topic) jndiContext.lookup(topicName);
topicConnection =topicConnectionFactory.createTopicConnection();
  
2.創建一個Session
    A session is a single-threaded context for producing and consuming messages. You use sessions to create message producers, message consumers, and messages.
Session是一個比較大的JMS對象,他提供了生產和消費消息的手段。
用於創建消息使用者和消息產生者。
topicSession =
topicConnection.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
  兩個參數用於控制事務和消息確認。
  
3.定位一個Topic
  用JDNI來定位一個Topic,Topic用於識別發送或接收的消息,在發佈/訂閱系統中。
訂閱者訂閱一個給定的Topic,而發佈者將它發佈的消息與一個Topic相連。
  下面是創建一個Topic "WeatherReport"
  Topic weatherTopic=messaging.lookup("WeatherReport");
  
4.啓動Connection
  在上面的初始化步驟之後,消息流是禁止的,用於防止在初始化時發生不可預料的行爲。
一旦初始化結束,必須讓Connection啓動消息系統。
  topicConnection.start();
  
5.創建一個消息產生者
  在發佈/訂閱裏,一個產生者發佈消息到一個指定的Topic。
下面的代碼顯示創建一個產生者,以及後續的建立和發佈一個簡單文本消息。
  TopicPublisher publisher=session.createPublisher(weatherTopic);
  TexeMessage message=session.createMessage();
  message.setText("ssss");
publisher.publish(message);

下面是一個消息使用者的代碼

topicConnection =topicConnectionFactory.createTopicConnection();
topicSession = topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
topicSubscriber = topicSession.createSubscriber(topic);
topicListener = new MsgListener();
topicSubscriber.setMessageListener(this);
topicConnection.start();
JNDI
1.JNDI的基本知識
JNDI――Java的命名和目錄接口

命名服務是一種應用程序,該程序包含一個對象集合或對象引用的集合,還對每個對象關聯了一個對用戶友好的名稱。
目錄服務只是命名服務所提供的一個擴展功能。
  
  
在JDK1.3中,JNDI支持以下三種Service Provider
LDAP
CORBA的COS Naming Service
RMI Registry


目錄服務實現的常見的功能
  LDAP
  NDS
  NIS+
  X.500

2.避免在程序中顯式的設置JNDI Factory
      Context ctx = null;
      try
      {
        Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
        env.put(Context.PROVIDER_URL, "t3://localhost:7001");
        ctx = new InitialContext(env);
        System.out.println("成功創建Initial context");
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
可以在jndi.properties文件中添加如下兩行
 java.naming.factory.initial= weblogic.jndi.WLInitialContextFactory
 java.naming.provider.url= t3://localhost:7001
     

     其他的如文件系統訪問的例子參看《EJB2.0企業級應用程序開發》
3.關閉InitialContext
在結束InitialContext對象的使用後,總要關閉該對象。
這類似於關閉其他的有限資源,比如JDBC連接。
即使拋出了某個異常,也要保證關閉InitialConext對象
Application Server
1.WebSphere
1.1初步安裝
6.29.2002
安裝developerWorks toolbox sample CD(disk1)上的
Websphere application server advanced single server

在server機器上進行“典型安裝”,安裝很順利,比websphere application server 3.0要好很多
由於wingate可能使用了7000端口,第一次啓動WAS沒有成功,把wingate stop掉,就可以啓動WAS了 (後來修改server-config.xml,把7000端口改爲別的端口,即使wingate starting ,也可以啓動WAS)
現在WAS典型安裝的時候自動安裝了 IBM HttpServer,比以前方便多了(以前還要擔心IBM HttpServer的安裝問題,況且這次我是安裝在win2000 prefessional上面的,本來機器上就沒有 IIS)。
可以使用http://server:9090/admin 進行管理

在gu機器上進行“定製安裝”,不安裝IBM HttpServer,也順利搞定。

安裝忘了可以在IE中訪問以下網址測試
http://localhost:9080/webapp/examples/
http://localhost:9080/estore/

http://localhost:9080/estore/是不需要配置就可以使用的,況且用到了數據庫,根據petstore.ear中的customerEjb.jar中的ibm-web-bnd.xmi中看來,使用的數據源爲
jdbc/EstoreDataSource
說明在WAS安裝完後,這個DataSource就是可用的,可供測試
1.2配置樣本
可以通過“樣本”(http://localhost/WSsamples/index.html)來學習WAS

Database Configuration
選擇“Start Samples.ear SQL Server with Merant Database Configuration”

JDBC 驅動程序(Microsoft SQLServer via Merant SequeLink JDBC Driver)
服務器類路徑:${WAS_ROOT}/lib/sljc.jar;${WAS_ROOT}/lib/sljcx.jar


1.3 部署示例應用(MyBank)
根據“將應用安裝到 WebSphere 4.0 高級單服務器版(AEs) .pdf”的指導,可以順利的部署應用程序
   
1.3.1停止WAS服務
可以在命令行下用stopserver。
1.3.2 db2的JDBC版本
  When IBM DB2 Universal Database Version 7 is first installed, it uses the JDBC 1.0 API for connections.  WebSphere V4.0 and J2EE require JDBC 2.0.  Stop the DB2 JDBC Applet Server, then run a batch file to change from JDBC 1.0 to JDBC 2.0.
__ Click the Windows Start button, and select Settings --> Control Panel.
__ In the Control Panel, double-click Services.
__ In the Services window, select the DB2 JDBC Applet Server, and click Stop.
__ Click Yes, you are sure you want to stop the DB2 JDBC Applet Server service.
__ Verify the WebSphere Server is stopped.  In a Command window, type: stopserver.
__ In a Command window, change directories to where DB2 is installed.
     For example: cd  C:/SQLLIB (Could be C:/Program Files/SQLLIB on your system.)
__ In the Command window, type: cd  java12
__ In the Command window, type: usejdbc2
     Six files are copied, and a file named inuse is updated.
__ In the Command window, type: type inuse.
     This should display: JDBC 2.0
__ In the Control Panel, double-click Services.
__ In the Services window, select the DB2 JDBC Applet Server, and click Start.

1.3.3設置DataSource
When you created the DataSource, you specified that the Default User ID for the application database is USERID, and the Default Password is PASSWORD.You need to create this User ID in the operating system registry.

1.4 開發和部署自己的應用
成功的在WAS4.0中部署bidding2.ear,使用的是通過Web頁面部署,而不是通過SEAppInstall命令行方式
看來JBuilder7和WAS4.0集成開發還是比較方便的。

簡單的還行,複雜一點就不行了,例如開發WebApplication的時候,ibm-web-bnd.xmi和ibm-web-ext.xmi根本不知道怎麼寫,也沒有資料可以查
看來,開發WebSphere的東西,還是要使用WSAD.

可以在Jbuilder中開發後,使用“應用程序組裝工具”(assembly.bat)來配置程序,然後再安裝到WebSphere中去。

也可以不使用“應用程序組裝工具”,不管ibm-web-bnd.xmi和ibm-web-ext.xmi,直接通過http:localhost:9090/admin來安裝應用程序的時候,會提示你輸入對應的實際的jndi資源名

在WebSphere中部署了bidding2企業應用程序後,關閉重新啓動WAS還是不行,bidding2還是無法運行,結果,重新啓動一下計算機就可以了,這一點不如Weblogic


1.4.1 JSP中的訪問DataSource和EJB
(1)在Web Application程序的java bean裏有這樣一句
DataSource source = (DataSource)initCtx.lookup("java:comp/env/jdbc/sample" );

注意:紅字部分是和web.xml中的紅字部分對應的

(2)在web.xml中有這樣
  <resource-ref  id="ResourceRef_1" >
    <res-ref-name>jdbc/sample</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>CONTAINER</res-auth>
  </resource-ref>
 
 (3)在ibm-web-bnd.xmi中有這樣
    <resRefBindings xmi:id="ResourceRefBinding_1" jndiName="jdbc/sample">
    <bindingResourceRef href="WEB-INF/web.xml#ResourceRef_1"/>
    </resRefBindings>
  注意:綠字部分是和web.xml中的綠字部分對應的
至於ibm-web-bnd.xmi中jndiName="jdbc/sample",這個指向的是具體的WAS中已定義的DataSource的JNDI名字,可以是任何名字,只要有效。
   
可以順利找到DataSource


(1)在Web Application程序的java bean裏有這樣一句
CustomerManagerHome home =
(CustomerManagerHome)initCtx.lookup("java:comp/env/ejb/CustomerManager" );
CustomerManager CustomerManager = home.create();

注意:紅字部分是和web.xml中的紅字部分對應的
(2)在web.xml中有這樣
 <ejb-ref id="EjbRef_1">
    <ejb-ref-name>ejb/CustomerManager</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>         <home>com.hmautomation.bidding2.controller.CustomerManagerHome</home>         <remote>com.hmautomation.bidding2.controller.CustomerManager</remote>
 </ejb-ref>
    
  (3)在ibm-web-bnd.xmi中有這樣
  <ejbRefBindings xmi:id="EjbRefBinding_1" jndiName="CustomerManager">
    <bindingEjbRef href="WEB-INF/web.xml#EjbRef_1"/>
  </ejbRefBindings>
  注意:綠字部分是和web.xml中的綠字部分對應的
至於ibm-web-bnd.xmi中jndiName="CustomerManager ",這個指向的是具體的WAS中已有的EJB的JNDI名字,可以是任何名字,只要有效。
   
可以順利找到EJB
1.4.2 launchClient.bat
在開發j2ee應用時,如果你的客戶端程序是java Client形式的,你應該通過客戶端程序的容器來執行客戶端程序。在WebSphere ad 4.0中,你應該用launchClient.bat來執行你的程序

    j2ee客戶端程序有兩種形式,web形式和java客戶端形式。java客戶端形式是你自己編寫的擁有main函數的類。WebSphere的launchClient.bat在WebSphere安裝目錄/AppServer/bin下
1.4.3 WebSphere中的JNDI
參看《WebSphere Version 4 Application Development Handbook》
Chapter13:Guidelines for coding WebSphere applications
Using JNDI

參考infocenter中的信息,輕易解決這個問題,在jndi.properties中寫
java.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory
java.naming.provider.url=iiop://localhost:900

實例代碼片斷:
         ctx = new InitialContext();
         System.out.println("成功創建Initial context");

Object objref = ctx.lookup("jdbc/sample");  //這裏的jdbc/sample就是WAS安裝
//已有的instantDB的sample datasource
         System.out.println("成功找到DataSource sample");
1.4.4 WebSphere中的重新安裝ear
很麻煩!
“應用程序安裝”嚮導

Application 或 Application 目錄已存在。

與所選應用程序同名的目錄已存在。
目錄中的文件可能已由應用程序服務器鎖定。
要安裝此應用程序,您將需要執行下列步驟:
1. 如果您還未卸載此應用程序,則現在卸載它。
2. 保存此配置。
3. 停止應用程序服務器進程。
4. 刪除與要安裝的應用程序相應的目錄(在 installedApps 目錄下)。
5. 重新啓動應用程序服務器並返回到管理應用程序。
6. 再次安裝應用程序。
1.4.5 WebSphere中的User Profile
《IBM Websphere and VisualAge for Java Database Integration with DB2, Oracle and SQLServer》有一章專門講如何使用User Profile

1.5 WebSphere實現的一些服務
   WebSpher是OMG Specification的一個Light Implenentation
   而Componet Broker是一個Complete Implementation
1.4.3 Directory Service
LDAP Directory可以通過存儲user ID和password而被用作一個authientication 的 centralized point

IBM Secureway Directory是LDAP的一個實現,它使用IBM DB2作爲後端存儲。

1.6 WebSphere的文檔
Web 上的文檔
要獲取提供了所有支持語言的整個文檔集,請參閱:

http://www.ibm.com/software/webservers/appserv/infocenter.html
當您進入此 Web 頁面時,可在線瀏覽信息中心,或將它下載到您的機器上。
在信息中心中,您會找到下列信息:

發行說明
此文檔包括問題描述和解決方法,以及產品限制。在開始產品安裝之前,請閱讀此文件。發行說明的最新版本在產品 Web 站點上。
“歡迎”頁面
“歡迎”頁面突出顯示了所有用戶特別關注的信息(包括從版本 3.5 遷移到版本 4.0,以及用於通過教程和代碼樣本的“邊幹邊學”的實踐指示。)
步進式安裝文檔
此安裝文檔爲安裝和配置此產品提供了說明性、步進式的幫助。每個 PDF 文檔涉及到不同的操作系統和數據庫組合,如在安裝有 IBM DB2 數據庫的 Windows NT 上安裝此產品。
內容更深入的文檔
這些主題包括編程、安全性、管理、遷移和多機器環境(不適用於高級單服務器版)。
幫助文件更新
與此產品一起安裝的幫助文件已更新版本在信息中心中提供。各種界面的幫助主題按管理部分下面的對象類型(如“Web 模塊”)組織。特別地,請參閱章節 6.7。
1.7 WebSphere和SQLServer
1.7.1使用Merant Driver
1.安裝sql server 2000;完畢後安裝sql server 2000 sp2;
(注:我沒有安裝sql server 2000 SP2,安裝merant driver的時候,它提示我要MDAC-Microsoft Data Access Component,我又下載了一個MDAC2.6)

2. 安裝Merant SequeLink Server 5.1 (這是裝在SQLServer的那臺機器上的),命令行下輸入setup /v”IPE=NO”,按提示直至安裝完畢

問OEM/Serial Number的時候, 敲入1111,但是敲入1111似乎是evaluation,只能用一個月,server上可以用到2002.8.10

3.配置DataSource
   我作了如下填寫:
JDBC 驅動程序(Microsoft SQLServer via Merant SequeLink JDBC Driver)
服務器類路徑:${WAS_ROOT}/lib/sljc.jar;${WAS_ROOT}/lib/sljcx.jar
(後來程序又說WAS4.01帶這兩個jar文件和Merant SequeLink Server5.1不匹配,IBM老是出這樣的問題,我用eFix PQ62295 Update中sequelink.zip的兩個jar文件取代才解決了問題,但還是有中文問題)

但是程序告訴我找不到文件,一發狠,就把這兩個文件拷到WAS所帶的JDK的ext目錄中去,結果 javax.sql.DataSource又找不到,只能把j2ee.jar也拷到WAS所帶的JDK的ext目錄中去,OK。(有待改進)

com.merant.sequelink.jdbc.SequeLinkDriver.class
Jdbc:sequelink//hostname:19996


總結:Merant似乎已經放棄了JDBC Driver這一塊,已有另一個新的公司在作這個產品(http://www.datadirect-technologies.com/
IBM也意識到了這一點,在eFix PQ62295 Update中提供了它自己的JDBC Driver

1.7.2使用MicroSoft的Driver
com.microsoft.jdbcx.sqlserver.SQLServerDataSource
基本是不行的,IBM的程序不能實例化上面的類。

2.  Weblogic
1)Weblogic安裝
在startWeblogic.cmd裏找到下面這句,寫上你的密碼即可。
set WLS_PW=
或在startWeblogic.cmd同級目錄下加一個文件password.ini
裏面寫一句話,就是你的密碼即可,(只是密碼字串,不要別的)

有關weblogic在jb6中調用出錯的一點添加:
安裝上面的方法可能會出現java.lang.NullException(可能)。只要你把工程中jdk換成weblogic自帶的jdk即可消除這個問題。
weblogic和jb6自帶的jdk,雖然版本一樣,可能存在差異!
大家還是裝個7.0來用吧,好象沒有時間限制,只不過是有連接限制,呵

2)Weblogic中的安全問題
配置SSL
a. 每個需要配置SSL的Weblogic Server Deployment,你需要一個私鑰和一個數字證書

私鑰和數字證書生成存放在PEM或者Definite Encoding Rules (DER) 格式的文件中。.
PEM文件是文本的。
DER文件是二進制的。
b. 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章