<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    hk2000c技術專欄

    技術源于哲學,哲學來源于生活 關心生活,關注健康,關心他人

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      111 隨筆 :: 1 文章 :: 28 評論 :: 0 Trackbacks

    #

    Liferay 二次開發太困難,花了N*N個小時,除了搭建了一套可以調試部署的環境之外,部署了幾個示例實例之外,幾乎毫無建樹。
    liferay代碼可讀性是我見過最差的,乍看覺得可能是反編譯的代碼?;柽^去,我要罵娘了。什么編碼規范!嘔了?。。?br />網上support 的效率非常低,幾乎沒人幫忙,遇到問題簡直就是災難。繼續下去的信心簡直快要破滅了。

    Jetspeed 2 就比較好了 , 源代碼,文檔,二次開發比較容易。
    而且國內弄得人也多,可以相互交流支持,不像liferay 一條小道走不到底的感覺。

    不過Liferay 還是比較好的一個項目,速度比jetspeed2 不知道快多少,而且擁有很多很實用的portlet .
    但愿 Jetspeed2 會做得更好。畢竟開源需要眾人去做,才會有生命力。

    posted @ 2006-08-08 23:05 hk2000c 閱讀(3116) | 評論 (6)編輯 收藏

    準備每個知識點的幾個例子,梳理一下自己的知識樹結構,避免時間長了,技術生疏

    暫時需要整理的知識點例子有

    tag

    jms

    oscache

    hiberante

    spring

    SWF spring web flow

    struts tiles

    axis webservice

    準備閱讀相關的JSR標準
    編寫一個Axis的例子


    pdf liberay

    nutch search

    SSO


    posted @ 2006-08-08 15:25 hk2000c 閱讀(327) | 評論 (0)編輯 收藏

    Portlet 形態

    Portlet 的形態直白的說,就是 portlet 功能的表現形式。通常, portlet 根據他們自己功能的不同,執行不同的任務以及生成不同的內容。 Portlet 形態直接預示著他們擔任什么樣的功能并且將會顯示什么樣的內容。當 portlet 被調用的時候, portlet 容器會為其提供的一個的當前 portal 形態。 Portlet 可以很方便的在處理一個 action 請求的時候改變它的形態。

    ?????? Portal 規范定義了 3 portlet 形態。他們分別是 VIEW EDIT 以及 HELP 。 PortletMode 類定義了這些形態的常量。

    ?????? Portal 形態還用于對用戶的權限功能控制,比方說一個未認證用戶只能察看 portlet VIEW 以及 HELP 形態,而認證用戶則能訪問 portlet EDIT 形態。

    ?

    8.1 Portlet VIEW 形態

    ?????? Portlet VIEW 形態的主要功能是通過生成標記語言來顯示 portlet 的當前狀態。比方說,一個 portlet VIEW 形態可能包含一到兩個頁面,用戶可以瀏覽或者做某些操作。它也可能僅僅是一張靜態頁面而不做任何事情。

    ?????? 開發者可以簡單的通過重載 GenericPortlet doView() 方法來獲得這項功能

    ?????? Portlet 必須支持 VIEW 形態

    ?

    8.2 EDIT 形態

    ?????? EDIT 形態下面, portlet 應該提供相關的內容以及邏輯給用戶,以便能夠讓用戶可以自定義 portlet 行為。一個 EDIT 形態的 portlet 應該有 1 到多個窗口,這樣用戶就能從這些窗口進入他們自己自定義的數據了。

    ?????? 通常, EDIT 形態的 portlet 會設置或者更新 Portlet 參數。參考 portlet 參數一節獲得更多的細節。

    開發者可以簡單的通過重載 GenericPortlet doEdit() 方法來獲得這項功能

    Portlet 不必支持 EDIT 形態

    8.3 HELP 形態

    ?????? help 形態下面, portlet 應該提供 portlet 本身的相關幫助信息。一個 portlet 的幫助信息可以是介紹 portlet 的完整幫助或者是內容相關的幫助文本。

    開發者可以簡單的通過重載 GenericPortlet doHelp() 方法來獲得這項功能

    Portlet 不必支持 HELP 形態

    8.4 portlet 自定義形態

    ?????? Portlal 的提供者可以自定義 portlet 形態用來提供自己指定的功能

    ?????? 要使用自定義 Portlet 形態,首先需要在部署描述器中添加 custom-portlet-mode 元素 ,其次需要在運行期找到該形態的 portal 實現。如果在運行期間找不到該自定義形態的 portal 實現,這個 portlet 就不應該被調用

    ?????? 打個比方, portlet 應用需要支持 clipsboard 以及 config 形態的 portlet ,那么部署描述器里面可能這么寫:

    ?

    <portlet-app>

    ...

    <custom-portlet-mode>

    <description>Creates content for Cut and Paste</description>

    <name>clipboard</name>

    </custom-portlet-mode>

    <custom-portlet-mode>

    <description>Provides administration functions</description>

    <name>config</name>

    </custom-portlet-mode>

    ...

    </portlet-app>

    ?

    在《擴展 Portlet 形態》附錄中列出了建議的 portlet 形態的命名參考以及他們的使用參考。如果 portlet 在部署描述器中定義了一個自定義的形態,并且 portal 容器實現了這種形態的話,那么 Portal 容器可以立即自動地映射這種支持形態。

    ?

    ?

    8.5 GenericPorlet 渲染方法的處理

    ?????? GenericPorlet 通過 render 方法來分發用戶的請求給 doView , doEdit , doHelp 方法。這個指定形態分發的動作在 doDispatch 里面都會指明。如果 portal 容器提供者需要支持一種新的形態,那么必須重載 doDispatch 方法。

    ?

    8.6???? 定義 portlet 形態

    ?

    Portlet 通過在它的部署描述器內配置 portlet 形態來獲得它能使用的 portal 容器支持的形態。每個 Portlet 都必須支持 VIEW 形態,而且 VIEW 形態無需特別指定。

    下面的例子顯示了一個配置 Portlet 形態的樣本:

    ...

    <supports>

    <mime-type>text/html</mime-type>

    <portlet-mode>edit</portlet-mode>

    <portlet-mode>help</portlet-mode>

    ...

    </supports>

    <supports>

    <mime-type>text/vnd.wap.wml</mime-type>

    <portlet-mode>help</portlet-mode>

    ...

    </supports>

    ...

    ?

    以上的配置說明了,該 portlet html 標記語言下支持 edit ,help 形態,當然還支持默認的 view 形態。在 wml 語言環境下,支持 help 以及 view 形態。

    ?

    ?

    ?===


    以上是翻譯節選,以后會陸續刊出其它章節
    歡迎轉載共同交流

    ?

    posted @ 2006-07-12 11:01 hk2000c 閱讀(1711) | 評論 (0)編輯 收藏

    裝載JBoss 應用的時候出現經典log錯誤 org.apache.commons.logging.LogConfigurationException: Class org.apache. commons.logging.impl.Log4JCategoryLog does not implement Log

    檢查應用路徑 %App_path%/WEB-INF/lib ,把下面 log4j.jar以及 commons-logging.jar 均刪除,問題解決

    原理解釋文章在以下位置

    http://www.qos.ch/logging/thinkAgain.jsp

    以前也遇到類似問題

    如果是tomcat 5.x 版本,需要這樣處理

    刪除tomcat/webapps/%apps%/WEB-INF/lib/下面的
    commons-logging-api-1.0.4.jar 包
    然后換成

    log4j.jar以及 commons-logging.jar

    posted @ 2006-04-28 23:21 hk2000c 閱讀(281) | 評論 (0)編輯 收藏

         摘要: Java Authentication Authorization Service(JAAS,Java驗證和授權API)提供了靈活和可伸縮的機制來保證客戶端或服務器端的Java程序。Java早期的安全框架強調的是通過驗證代碼的來源和作者,保護用戶避免受到下載下來的代碼的攻擊。JAAS強調的是通過驗證誰在運行代碼以及他/她的權限來保護系統面受用戶的攻擊。它讓你能夠將一些標準的安全機制,例如Solar...  閱讀全文
    posted @ 2006-03-23 08:07 hk2000c 閱讀(6209) | 評論 (0)編輯 收藏

         摘要: 有一部分xml解析器使用者認為 JDOM 很慢,至少比起Dom4j來說效率不快。其實JDOM和DOM4J一樣,同屬優秀的開源XML解析器,?完全不必這樣擔心。?現在就實際拿一些實際使用的例子,作為簡單的測試用例,對JDOM以及DOM4J最基本的文檔解析功能來說明這個問題。?JDOM測試用例如下:??? ? public Document getDoc(String filename) throws...  閱讀全文
    posted @ 2005-03-21 05:00 hk2000c 閱讀(869) | 評論 (0)編輯 收藏

         摘要: Ant 介紹以及基本使用指南 Ant 是著名 Java 開源組織 Apache 的一個項目,是一個基于 java 的 build 工具。它可以使你通過 ant 腳本語言,自動你...  閱讀全文
    posted @ 2004-12-03 19:21 hk2000c 閱讀(256) | 評論 (0)編輯 收藏

    克服J2SE 1.3 ~ 1.4不兼容問題
    --從反射API和ANT獲得幫助



    概要
    ??? 如果你要實現JavaAPI中的一個,那么可能是件比較痛苦的事情。你經常會需要實現許多交叉依賴的接口。對新特性的需求促成了升級現有的JavaAPI,這就造成了提供這些API的供應商對他們的相關實現不斷的升級以維持相關功能。隨著這些API的升級更改越來越頻繁,API代碼的不兼容使你不得不分別維護新舊版本的代碼庫。這直接到導致了你維護成本和難度的增加。本文演示了解決此問題的技術,揭示了如何僅使用一個代碼庫編譯不同JavaAPI版本的代碼。



    ??? 現在非常多的API被加入到到Java的標準庫中,比如JDBC。這樣做的好處是,Java可選包在部署時不必被綁定到相關的部署應用中去。這些API由專門的專業開發小組實現,在實際的使用當中這些API變得越來越受歡迎,使用的深度及廣度也在不斷的增加。但是有時候對一些API升級會變得使一些類及方法不可用。開發小組寧愿讓這些API包成為可選組件而不是作為Java標準支持庫的形式來發布。但是一旦加入標準庫中的API包,就像是和用戶簽定了終生契約,想再成為可選包是不可能的。所以作為用戶的你,可能會突然發現你一下子自己的代碼庫變成了不兼容的2個代碼庫,一個是使用新API的代碼庫,另一個是使用舊API的代碼庫。你可能會以為情況不像你想象的那樣糟糕。我這里舉一個簡單的例子。J2SE1.4中由于對JDBC中的一些API的升級使的java.sql.Connection 不能同時被1.3 及 1.4 版本編譯通過。你可能會遇到我這樣的困境:我可能需要實現java.sql.Connection這個接口,但是我的代碼需要同時通過1.3 及1.4 得編譯。但是我不想同時維護2個版本的代碼庫。所以我開始尋找更好的解決方法。
    ??? 如果你依賴于javac來編譯你的應用的話,那么很不幸,Java著名的一次編寫,到處運行(WORA)并不包括WOCA(一次編寫,到處編譯^_^;)。
    不過別太沮喪,編碼的反射技巧以及編譯的Ant技巧是你能夠安然過關。我能夠僅僅使用一組Java文件以及Ant工具,就能使一個版本同時編譯
    在1.3 和1.4 版本下面。別急,在我結識解決辦法之前,讓我先詳細的解釋一下問題的描述。

    可憐人的連接池(PS:Poor man's connection pool ,很有意思的一句話)
    ??? 兩年前,我的公司需要一個連接池,但是又不肯出錢買一個。當時并沒有什么免費的東東可以使用,所以我們自己寫了一個連接池。為了能更好的跟蹤在整個應用中連接的情況,我們寫了一個com.icentris.sql.ConnectionWrapper類,它實現了java.sql.Connection 接口以及其他的一些包裝類(實現了另外的一些的java.sql 接口)。這些包裝類僅僅是跟蹤我們應用中的數據庫使用,以及通過方法調用真正的
    數據庫資源。
    ??? 當J2SE1.4來的時候,我們自然而然的想到升級我們提供給客戶的應用,使這些應用的性能得到很多提升。當然,我們也需要保留1.3版本,因為有些客戶根本不需要升級到1.4。我們氣惱的發現,如果我們不修改,我們的ConnectionWrapper 以及其他JDBC封裝類根本通不過J2SE1.4的編譯。
    ??? 為了文章的簡明,我通過使用ConnectionWrapper 這個類來演示我對所有其他不能夠通過J2SE1.4的類所使用的技術。如果我按照新的API標準,那么我不得不添加幾個方法到ConnectionWrapper中去,接下來2個大問題擺在了面前:
    1.因為我的包裝類需要經歷方法調用,我將不得不調用在J2SE1.3 sql類中并不存在的方法。
    2.因為一些新的方法涉及到一些新出現的類,我將不得不在編譯中面對那些在J2SE1.3中并不存在的類。

    反射提供了援助
    一些代碼可以很方便的解釋第一個問題。但是我的ConnectionWrapper 封裝了java.sql.Connection , 所有的我的例子
    依賴于在構造方法中的變量 realConnection :

    private java.sql.Connection realConnection = null;
    ?
    ? public ConnectionWrapper(java.sql.Connection connection) {
    ??? realConnection = connection;
    ? }

    ??? 為了看清楚我怎么做到解決版本不兼容問題,讓我們仔細看一下setHoldability(int)(這個在J2SE1.4被聲明的新方法)
    public void setHoldability(int holdability) throws SQLException {
    ??? realConnection.setHoldability( holdability );
    ? }

    ??? 很不幸,這個方法在J2SE1.3中顯然通不過編譯,這就陷入了2難的尷尬境地。為了解決這一情況,我假定setHoldability() 將只會在J2SE1.4
    下面被調用,所以我使用了反射機制來調用該方法。

    public void setHoldability(int holdability) throws SQLException {
    ??? Class[] argTypes = new Class[] { Integer.TYPE };
    ??? Object[] args = new Object[] {new Integer(holdability)};
    ??? callJava14Method("setHoldability", realConnection, argTypes, args);
    ? }

    ? public static Object callJava14Method(String methodName, Object instance,
    ? Class[] argTypes, Object[] args)
    ??? throws SQLException
    ? {
    ??? try {
    ????? Method method = instance.getClass().getMethod(methodName, argTypes);
    ????? return method.invoke(instance, args );
    ??? } catch (NoSuchMethodException e) {
    ????? e.printStackTrace();
    ????? throw new SQLException("Error Invoking method (" + methodName + "): "
    ????? + e);
    ??? } catch (IllegalAccessException e) {
    ????? e.printStackTrace();
    ????? throw new SQLException("Error Invoking method (" + methodName + "): "
    ????? + e);
    ??? } catch (InvocationTargetException e) {
    ????? e.printStackTrace();
    ????? throw new SQLException("Error Invoking method (" + methodName + "): "
    ????? + e);
    ??? }
    ? }

    ??? 現在我有了setHoldability() 方法,因此能順利通過J2SE1.4的編譯。原理是我并不直接調用J2SE1.3中間java.sql.Connection并不存在的方法,
    而是轉為通過讓setHoldability調用callJava14Method這個通用方法來調用,然后在一個SQLException 里封裝所有的異常。這樣就達到我預期的效果。
    現在所有的在J2SE1.4中新方法都工作的很好,在J2SE1.3的老版本下也能順利編譯而且工作正?!,F在我來著手解決第二個問題。
    就是如何在應用中能夠找到一個方法能夠使用J2SE1.3中并不存在的新的類。

    Ant 是答案
    在J2SE1.4中,java.sql.Connection 依賴于一個新的類java.sql.Savepoint。因為這個類在java.sql 包中,所以你不可能把它加入到J2SE1.3中去。Java不允許任何的第三方擴展包加入它的核心包(java.* 以及 javax.* )中去。 因此挑戰來了,在J2SE1.4下調用這個新的java.sql.Savepoint 類,但同時需要代碼能夠在J2SE1.3下面得到編譯以及能夠運行。很簡單,不是嗎?所有回答"Yes"的人都會得到一個榛仁巧克力餅(PS:哈哈,我回答了,可是沒有:P)。至少現在我找到了答案,使問題變得很簡單了。
    ? 首先我插入了下面一條有條件的import語句
    // Comment_next_line_to_compile_with_Java_1.3
    ? import java.sql.Savepoint;

    ??? 然后我找到了一個能夠在J2SE1.3下面注釋掉import的方法。非常簡單,使用如下Ant 語句就可以了:
    <replace>
    ??? <replacetoken>Comment_next_line_for_Java_1.3&#010;</replacetoken>
    ??? <replacevalue>Comment_next_line_for_Java_1.3&#010;//</replacevalue>
    ? </replace>

    ??? 這個Ant 的 replace 標簽 有好幾個標簽選項,在以后我給出的全部例子里有很多。在這里面最重要的是使用<replacevalue>來替換<replacetoken> 。&#010;在XML里面的意思是換行。在J2SE1.4下,沒什么會發生, 但是在J2SE1.3下面一個import聲明被注釋掉了。
    // Comment_next_line_to_compile_with_Java_1.3
    ? //import java.sql.Savepoint;

    ??? 但是我在代碼中Savepoint仍在使用public Savepoint setSavepoint(String name) throws SQLException { . . .}。不過我只在J2SE1.4使用這些方法類,在J2SE1.3中只要能編譯就可以了。我發現只要我有一個我自己的Savepoint 類在我的包中,我的代碼就能夠通過編譯,而且不用任何的import包。但是我又要同時在這條import 語句不被注釋的同時我自己的Savepoint類被忽略掉。因此我造了一個空的com.icentris.sql.Savepoint類,這個可能(除了JavaDoc)是最短的有效類:
    package com.icentris.sql;

    ? /** Dummy class to allow ConnectionWrapper to implement java.sql.Connection
    ?? * and still compile under J2SE 1.3 and J2SE 1.4. When compiled
    ?? * under J2SE 1.3, this class compiles as a placeholder instead of the
    ?? * missing java.sql.Savepoint (not in J2SE 1.3).? When compiled
    ?? * under J2SE 1.4, this class is ignored and ConnectionWrapper uses the
    ?? * java.sql.Savepoint that is new in J2SE 1.4.
    ?? */
    ? public class Savepoint {}

    ??? 在J2SE1.4下我能夠正確的import java.sql.Savepoint類,而在J2SE1.3下面Ant注釋了這條import語句。因此這個Savepoint就被替換成了我這個包里面寫的一個空的Savepoint類。所以我現在就能加入任何引用到Savepoint類的方法,同樣的在這些新方法中使用剛才所說的反射方法。
    // Comment_next_line_to_compile_with_Java_1.3
    ? import java.sql.Savepoint;

    ? . . .
    ??? public Savepoint setSavepoint() throws SQLException {
    ????? Class[] argTypes = new Class[0];
    ????? Object[] args = new Object[0];
    ????? return (Savepoint) callJava14Method("setSavepoint", realConnection,
    ????? argTypes, args);
    ??? }

    ??? public Savepoint setSavepoint(String name) throws SQLException {
    ????? Class[] argTypes = new Class[] { String.class };
    ????? Object[] args = new Object[] { name };
    ????? return (Savepoint) callJava14Method("setSavepoint", realConnection,
    ????? argTypes, args);
    ??? }

    ??? public void rollback(Savepoint savepoint) throws SQLException {
    ????? Class[] argTypes = new Class[] { Savepoint.class };
    ????? Object[] args = new Object[] { savepoint };
    ????? callJava14Method("rollback", realConnection, argTypes, args);
    ??? }

    ??? public void releaseSavepoint(Savepoint savepoint) throws SQLException {
    ????? Class[] argTypes = new Class[] { Savepoint.class };
    ????? Object[] args = new Object[] { savepoint };
    ????? callJava14Method("releaseSavepoint", realConnection, argTypes, args);
    ??? }

    ??? 現在我所要做的就是能夠使Ant 識別 J2SE1.3版,然后能夠使這條import 語句被注釋掉。
    <target name="compile">
    ??? <antcall target="undoJava13Tweaks" />
    ??? <antcall target="doJava13Tweaks" />
    ??? <javac srcdir="src" destdir="WEB-INF/classes" debug="on">
    ????? <classpath>
    ??????? <fileset dir="WEB-INF/lib">
    ????????? <include name="*.jar"/>
    ??????? </fileset>
    ????? </classpath>
    ??? </javac>
    ??? <antcall target="undoJava13Tweaks" />
    ? </target>

    ? <target description="Find out if we're being compiled on Java 1.3"
    ? name="isJava13">
    ??? <echo message="java.specification.version=[${java.specification.version}]"/>
    ??? <condition property="isJava13">
    ????? <equals arg1="${java.specification.version}" arg2="1.3" />
    ??? </condition>
    ? </target>

    ? <target description="There are a couple tweaks I have to do to compile under Java 1.3"
    ??? name="doJava13Tweaks" depends="isJava13" if="isJava13">
    ??? <echo message="This is Java 1.3, doing Tweaks!" />
    ??? <replace dir="src/com/icentris/" summary="true">
    ????? <include name="sql/ConnectionWrapper.java" />
    ????? <replacetoken>Comment_next_line_for_Java_1.3&#010;</replacetoken>
    ????? <replacevalue>Comment_next_line_for_Java_1.3&#010;//</replacevalue>
    ??? </replace>
    ? </target>

    ? <target description="Let's undo Java 1.3 tweaks" name="undoJava13Tweaks">
    ??? <replace dir="src/com/icentris/" summary="true">
    ????? <include name="sql/ConnectionWrapper.java" />
    ????? <replacetoken>Comment_next_line_for_Java_1.3&#010;//</replacetoken>
    ????? <replacevalue>Comment_next_line_for_Java_1.3&#010;</replacevalue>
    ??? </replace>
    ? </target>

    ??? 注意編譯目標在調用doJava13Tweaks的前后都調用了undoJava13Tweaks。如果萬一javac編譯失敗的話,我們可以恢復以前的編譯版本。

    你沒有必要同時維護2個應用實現
    ??? 對于Java來說,新的API升級所帶來的新的方法以及新的類/接口并不是新鮮事。一般而言,加入的新方法以及新的類的同時,會考慮到向上兼容的問題來照顧老API用戶。但是當升級的API屬于Java核心包內時,就會很麻煩。因為Java不允許對這些核心包的任何的外在更改或者是增加。通常這會引起針對不同版本API而維護不同版本代碼樹的需要。但是,就像上面的例子所演示的那樣,你只要維護一棵代碼樹就能夠在不同的版本的API下,編譯運行。這個反射的API允許你調用并不存在的方法,而Ant能通過識別不同的Java編譯版本而對相應的import包進行調整。雖然上面的所舉的例子僅僅是一個簡單的演示,但是在實際工作當中,利用這些簡單的技術,解決了許多J2SE1.4和J2SE1.3的版本問題。我相信通過這些技術,你可以在頻繁的Java版本升級中不必為同時維護兩棵代碼庫而煩惱。

    ?


    關于作者:
    Sam Mefford是iCentris的首席架構設計師。對于系統的兼容性重視程度,Sam Mefford是放在第一位的。他帶領的團隊致力于使用一個代碼庫
    向眾多的客戶公司提供應用發布方案。這些部署方案使用的應用服務器有Tomcat,Weblogic, Resin, Orion以及 Websphere;在數據庫方面有
    Oracle,PostgreSQL, MySQL,以及 Informix;以及多個Java運行期環境。

    譯者: SpikeWang (CSDN ID:hk2000c)

    東華大學計算機系畢業,現在同濟大學攻讀軟件工程碩士學位。致力于J2EE方面的企業級應用開發以及研究工作。


    About Copyright:
    原文章版權屬于作者 Sam Mefford
    譯文版權屬于譯者及原文作者共同所有,歡迎轉載,但要注上譯者及原文作者。


    參考資源:
    The API for java.sql.Connection (J2SE 1.3):
    http://java.sun.com/j2se/1.3/docs/api/java/sql/Connection.html

    The API for java.sql.Connection (J2SE 1.4):
    http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Connection.html

    The JDBC API:
    http://java.sun.com/products/jdbc/

    Java Core Reflection參考概要:
    http://java.sun.com/j2se/1.3/docs/guide/reflection/spec/java-reflectionTOC.doc.html

    the Reflection API指南:
    http://java.sun.com/docs/books/tutorial/reflect/

    The Javadoc (java.lang.reflect):
    http://java.sun.com/j2se/1.3/docs/api/java/lang/reflect/package-summary.html

    ?

    ?

    ?

    ?


    posted @ 2003-10-03 22:27 hk2000c 閱讀(157) | 評論 (0)編輯 收藏

    JDOM 介紹及使用指南

    一、JDOM 簡介
    JDOM是一個開源項目,它基于樹型結構,利用純JAVA的技術對XML文檔實現解析、生成、序列化以及多種操作。
    JDOM 直接為JAVA編程服務。它利用更為強有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效地結合起來。
    在使用設計上盡可能地隱藏原來使用XML過程中的復雜性。利用JDOM處理XML文檔將是一件輕松、簡單的事。
    JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter開發出來,以彌補DOM及SAX在實際應用當中的不足之處。
    這些不足之處主要在于SAX沒有文檔修改、隨機訪問以及輸出的功能,而對于DOM來說,JAVA程序員在使用時來用起來總覺得不太方便。
    DOM的缺點主要是來自于由于Dom是一個接口定義語言(IDL),它的任務是在不同語言實現中的一個最低的通用標準,并不是為JAVA特別設計的。JDOM的最新版本為JDOM Beta 9。最近JDOM被收錄到JSR-102內,這標志著JDOM成為了JAVA平臺組成的一部分。


    二、JDOM 包概覽
    JDOM是由以下幾個包組成的
    org.JDOM
    org.JDOM.input
    org.JDOM.output
    org.JDOM.adapters
    org.JDOM.transform

    三、JDOM 類說明

    org.JDOM
    這個包里的類是你解析xml文件后所要用到的所有數據類型。
    Attribute
    CDATA
    Coment
    DocType
    Document
    Element
    EntityRef
    Namespace
    ProscessingInstruction
    Text

    org.JDOM.transform
    在涉及xslt格式轉換時應使用下面的2個類
    JDOMSource
    JDOMResult

    org.JDOM.input
    輸入類,一般用于文檔的創建工作
    SAXBuilder
    DOMBuilder
    ResultSetBuilder

    org.JDOM.output
    輸出類,用于文檔轉換輸出
    XMLOutputter
    SAXOutputter
    DomOutputter
    JTreeOutputter

    使用前注意事項:
    1.JDOM對于JAXP 以及 TRax 的支持
    JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具類,默認情況下是JAXP的parser。
    制定特別的parser可用如下形式
    SAXBuilder parser
    ? = new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");
    ?Document doc = parser.build("http://www.cafeconleche.org/");
    ?// work with the document...
    JDOM也支持TRaX:XSLT可通過JDOMSource以及JDOMResult類來轉換(參見以后章節)
    2.注意在JDOM里文檔(Document)類由org.JDOM.Document 來表示。這要與org.w3c.dom中的Document區別開,這2種格式如何轉換在后面會說明。
    以下如無特指均指JDOM里的Document。


    四、JDOM主要使用方法
    1.Ducument類
    (1)Document的操作方法:
    Element root = new Element("GREETING");
    Document doc = new Document(root);
    root.setText("Hello JDOM!");
    或者簡單的使用Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));

    這點和DOM不同。Dom則需要更為復雜的代碼,如下:
    DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
    DocumentBuilder builder =factory.newDocumentBuilder();
    Document doc = builder.newDocument();
    Element root =doc.createElement("root");
    Text text = doc.createText("This is the root");
    root.appendChild(text);
    doc.appendChild(root);


    注意事項:JDOM不允許同一個節點同時被2個或多個文檔相關聯,要在第2個文檔中使用原來老文檔中的節點的話。首先需要使用detach()把這個節點分開來。

    (2)從文件、流、系統ID、URL得到Document對象:
    DOMBuilder builder = new DOMBuilder();
    Document doc = builder.build(new File("jdom_test.xml"));

    SAXBuilder builder = new SAXBuilder();
    Document doc = builder.build(url);
    在新版本中DOMBuilder 已經Deprecated掉 DOMBuilder.builder(url),用SAX效率會比較快。

    這里舉一個小例子,為了簡單起見,使用String對象直接作為xml數據源:

    ?public jdomTest() {
    ??? String textXml = null;
    ??? textXml = "<note>";
    ??? textXml = textXml +
    ??????? "<to>aaa</to><from>bbb</from><heading>ccc</heading><body>ddd</body>";
    ??? textXml = textXml + "</note>";
    ??? SAXBuilder builder = new SAXBuilder();
    ??? Document doc = null;
    ??? Reader in= new StringReader(textXml);
    ??? try {
    ????? doc = builder.build(in);
    ????? Element root = doc.getRootElement();
    ????? List ls = root.getChildren();//注意此處取出的是root節點下面的一層的Element集合
    ????? for (Iterator iter = ls.iterator(); iter.hasNext(); ) {
    ??????? Element el = (Element) iter.next();
    ??????? if(el.getName().equals("to")){
    ???????? System.out.println(el.getText());
    ??????? }
    ????? }
    ??? }
    ??? catch (IOException ex) {
    ????? ex.printStackTrace();
    ??? }
    ??? catch (JDOMException ex) {
    ????? ex.printStackTrace();
    ??? }
    ? }

    很簡單把。


    (3)DOM的document和JDOM的Document之間的相互轉換使用方法,簡單!
    DOMBuilder builder = new DOMBuilder();
    org.jdom.Document jdomDocument = builder.build(domDocument);
    // work with the JDOM document…

    DOMOutputter converter = new DOMOutputter();
    org.w3c.dom.Document domDocument = converter.output(jdomDocument);
    // work with the DOM document…

    2.XML文檔輸出
    XMLOutPutter類:
    JDOM的輸出非常靈活,支持很多種io格式以及風格的輸出
    Document doc = new Document(...);
    XMLOutputter outp = new XMLOutputter();
    // Raw output
    outp.output(doc, fileOutputStream);
    // Compressed output
    outp.setTextTrim(true);
    outp.output(doc, socket.getOutputStream());
    // Pretty output
    outp.setIndent(" ");
    outp.setNewlines(true);
    outp.output(doc, System.out);
    ......
    詳細請參閱最新的JDOM API手冊


    3.Element 類:
    (1)瀏覽Element樹
    //獲得根元素element
    Element root = doc.getRootElement();
    // 獲得所有子元素的一個list
    List allChildren = root.getChildren();
    // 獲得指定名稱子元素的list
    List namedChildren = root.getChildren("name");
    //獲得指定名稱的第一個子元素
    Element child = root.getChild("name");
    (這里的List是java.util.List)

    JDOM給了我們很多很靈活的使用方法來管理子元素
    List allChildren = root.getChildren();
    // 刪除第四個子元素
    allChildren.remove(3);
    // 刪除叫“jack”的子元素
    allChildren.removeAll(root.getChildren("jack"));

    root.removeChildren("jack"); // 便捷寫法
    // 加入
    allChildren.add(new Element("jane"));

    root.addContent(new Element("jane")); // 便捷寫法
    allChildren.add(0, new Element("first"));


    (2)移動Elements:
    在JDOM里很簡單
    Element movable = new Element("movable");
    parent1.addContent(movable); // place
    parent1.removeContent(movable); // remove
    parent2.addContent(movable); // add

    在Dom里
    Element movable = doc1.createElement("movable");
    parent1.appendChild(movable); // place
    parent1.removeChild(movable); // remove
    parent2.appendChild(movable); // 出錯!

    補充:
    糾錯性
    JDOM的Element構造函數(以及它的其他函數)會檢查element是否合法。
    而它的add/remove方法會檢查樹結構,檢查內容如下:
    1.在任何樹中是否有回環節點
    2.是否只有一個根節點
    3.是否有一致的命名空間(Namespaces)

    ?

    (3)Element的text內容讀取
    <description>
    A cool demo
    </description>

    // The text is directly available
    // Returns "\n A cool demo\n"
    String desc = element.getText();

    // There's a convenient shortcut
    // Returns "A cool demo"
    String desc = element.getTextTrim();

    (4)Elment內容修改
    element.setText("A new description");
    3.可正確解釋特殊字符
    element.setText("<xml> content");
    4.CDATA的數據寫入、讀出
    element.addContent(new CDATA("<xml> content"));
    String noDifference = element.getText();

    混合內容
    element可能包含很多種內容,比如說

    <table>
    <!-- Some comment -->
    Some text
    <tr>Some child element</tr>
    </table>

    取table的子元素tr
    String text = table.getTextTrim();
    Element tr = table.getChild("tr");

    也可使用另外一個比較簡單的方法
    List mixedCo = table.getContent();
    Iterator itr = mixedCo.iterator();
    while (itr.hasNext()) {
    Object o = i.next();
    if (o instanceof Comment) {
    ...
    }
    // 這里可以寫成Comment, Element, Text, CDATA,ProcessingInstruction, 或者是EntityRef的類型
    }
    // 現在移除Comment,注意這里游標應為1。這是由于回車鍵也被解析成Text類的緣故,所以Comment項應為1。
    mixedCo.remove(1);

    ?

    4.Attribute類
    <table width="100%" border="0"> </table>
    //獲得attribute
    String width = table.getAttributeValue("width");
    int border = table.getAttribute("width").getIntValue();
    //設置attribute
    table.setAttribute("vspace", "0");
    // 刪除一個或全部attribute
    table.removeAttribute("vspace");
    table.getAttributes().clear();

    ?

    5.處理指令(Processing Instructions)操作
    一個Pls的例子
    <?br?>
    <?cocoon-process type="xslt"?>
    ????????? |??????? |
    ????????? |??????? |
    ??????? 目標???? 數據

    處理目標名稱(Target)
    String target = pi.getTarget();
    獲得所有數據(data),在目標(target)以后的所有數據都會被返回。
    String data = pi.getData();
    獲得指定屬性的數據
    String type = pi.getValue("type");
    獲得所有屬性的名稱
    List ls = pi.getNames();

    6.命名空間操作
    <xhtml:html
    ?xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xhtml:title>Home Page</xhtml:title>
    </xhtml:html>

    Namespace xhtml = Namespace.getNamespace("xhtml", "http://www.w3.org/1999/xhtml");
    List kids = html.getChildren("title", xhtml);
    Element kid = html.getChild("title", xhtml);
    kid.addContent(new Element("table", xhtml));

    7.XSLT格式轉換
    使用以下函數可對XSLT轉換
    最后如果你需要使用w3c的Document則需要轉換一下。
    public static Document transform(String stylesheet,Document in)
    ??????????????????????????????????????? throws JDOMException {
    ???? try {
    ?????? Transformer transformer = TransformerFactory.newInstance()
    ???????????????????????????? .newTransformer(new StreamSource(stylesheet));
    ?????? JDOMResult out = new JDOMResult();
    ?????? transformer.transform(new JDOMSource(in), out);
    ?????? return out.getDeocument();
    ???? }
    ???? catch (TransformerException e) {
    ?????? throw new JDOMException("XSLT Trandformation failed", e);
    ???? }
    ?? }

    參考書目:

    1.JDOM官方網站: http://www.jdom.org

    2.<<Processing XML with Java>> Elliotte Rusty Harold 2002

    3.JDOM API Documentation

    4.<<JDOM Makes XML Easy>>Jason Hunter Co-Creator JDOM Project

    5.WSDP Tutorial

    ?

    ?

    ?

    ?

    posted @ 2003-09-27 07:19 hk2000c 閱讀(252) | 評論 (0)編輯 收藏

    僅列出標題
    共11頁: First 上一頁 3 4 5 6 7 8 9 10 11 
    主站蜘蛛池模板: 51精品视频免费国产专区| 夭天干天天做天天免费看| 亚洲福利视频网站| 成年女人看片免费视频播放器| 中文字幕在线观看亚洲视频| 在线观看免费精品国产| a成人毛片免费观看| 亚洲午夜在线一区| 亚洲av无码成人精品区在线播放 | 精品国产日韩亚洲一区| 无码人妻丰满熟妇区免费| 亚洲男同gay片| 久久精品国产亚洲夜色AV网站| 成人免费看片又大又黄| 国内精品免费久久影院| 亚洲综合色7777情网站777| 亚洲色偷拍区另类无码专区| 色影音免费色资源| 抽搐一进一出gif免费视频| 亚洲AV无码精品蜜桃| 亚洲国产无套无码av电影| 免费人成网站在线观看10分钟| 特级av毛片免费观看| 亚洲图片激情小说| 国产亚洲成人久久| 女人张开腿给人桶免费视频| 成人精品一区二区三区不卡免费看| 亚洲 欧洲 自拍 另类 校园| 亚洲AV综合色区无码一二三区| 亚洲一区二区三区香蕉| 免费理论片51人人看电影| 污污网站免费观看| 国产JIZZ中国JIZZ免费看| 亚洲午夜无码久久久久小说| 亚洲激情在线视频| 亚洲精品无码久久久久AV麻豆| 丁香花免费高清视频完整版| 日韩精品无码专区免费播放| sss日本免费完整版在线观看| 亚洲精品永久在线观看| 亚洲国产精品yw在线观看|