亚洲精品一级无码鲁丝片,亚洲国产精品尤物yw在线,久久久久亚洲AV无码麻豆http://www2.blogjava.net/kapok/category/696.html垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!zh-cnWed, 28 Feb 2007 03:21:05 GMTWed, 28 Feb 2007 03:21:05 GMT60為大型項目提供的 Ant 1.6 新特性http://www.tkk7.com/kapok/archive/2005/06/14/6106.html笨笨笨笨Tue, 14 Jun 2005 04:22:00 GMThttp://www.tkk7.com/kapok/archive/2005/06/14/6106.htmlhttp://www.tkk7.com/kapok/comments/6106.htmlhttp://www.tkk7.com/kapok/archive/2005/06/14/6106.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/6106.htmlhttp://www.tkk7.com/kapok/services/trackbacks/6106.htmlhttp://www.oracle.com/technology/global/cn/pub/articles/bodewig_ant1.6.html

為大型項目提供的 Ant 1.6 新特性

作者:Stefan Bodewig

了解 Ant 1.6 的新特性以及它們如何影響您組織編譯過程的方式。

雖然 Ant 版本的 1.5.x 系列在任務級方面有很大的改善,但它沒有改變人們使用 Ant 的方式。而 Ant 1.6 卻有所不同。它增加了幾個新特性,以支持大型或非常復雜的編譯情況。但是,要充分利用它們的功能,用戶可能需要稍微調整它們的編譯過程。

本文重點介紹了其中的三種新特性 — <macrodef>、<import>、<subant> 任務,表明使用它們可以有什么收獲,以及它們如何影響您組織編譯設置的方式。

大多數編譯工程師遲早會面臨必須執行相同的任務組合但在幾個地方配置稍微有點不同的情況。一個常見的例子是創建一個web 應用程序存檔,對于開發系統、測試系統和生產系統有著不同的配置。

讓我們假設 web 應用程序擁有依賴于目標系統的不同的 web 部署描述符,并為開發環境使用了一個不同的 JSP 集合以及一個不同的資料庫集合。配置信息將放在屬性中,創建 web 存檔的任務看起來將類似于

  <target name="war" depends="jar">
    <war destfile="${war.name}"
         webxml="${web.xml}">
      <lib refid="support-libraries"/>
      <lib file="${jar.name}"/>
      <fileset dir="${jsps}"/>
    </war>
</target>

其中 support-libraries 是引用一個在其它位置定義的 <fileset> ,該引用指向您的應用程序所需的附加資料庫的一個公共集合。

如果您只想一次創建一個 web 存檔,那么您只需要正確地設置屬性。比如說,您可以從一個您的目標專有的屬性文件中加載它們。

利用 Ant 1.5 創建存檔

現在,假定您想為測試系統和生產系統同時創建存檔,以確保您真正為兩個系統打包了相同的應用程序。利用 Ant 1.5,您可能使用 <antcall> 來調用擁有不同屬性設置的 "war" 目標,類似:

  <target name="production-wars">
    <antcall target="war">
      <param name="war.name" value="${staging.war.name}"/>
      <param name="web.xml" value="${staging.web.xml}"/>
    </antcall>
    <antcall target="war">
      <param name="war.name" value="${production.war.name}"/>
      <param name="web.xml" value="${production.web.xml}"/>
    </antcall>
</target>

當然,這假定兩個目標系統都將使用相同的 jar 和 JSP。

但這種方法有一個主要缺點 — 就是速度慢。<antcall> 重新分析編譯文件,并為每一次調用重新運行調用的目標所依賴的所有目標。在上面的例子中,"jar" 目標將被運行兩次。我們希望這對第二次調用沒有影響,因為 "war" 目標依賴于它。

利用 Ant 1.6 創建存檔

使用 Ant 1.6,您可以忘掉用 <antcall> 來實現宏的方法,相反您可以通過參數化現有的任務來創建一個新的任務。因而上面的例子將變為:

  <macrodef name="makewar">
    <attribute name="webxml"/>
    <attribute name="destfile"/>
    <sequential>
      <war destfile="@{destfile}"
           webxml="@{webxml}">
        <lib refid="support-libraries"/>
        <lib file="${jar.name}"/>
        <fileset dir="${jsps}"/>
      </war>
    </sequential>
  </macrodef>

這定義了一個名稱為 makewar 的任務,該任務可以和任何其它的任務一樣使用。該任務有兩個必需的屬性,webxml 和 destfile。要使屬性可選,我們必需在任務定義中提供一個默認值。這個示例假定 ${jar.name}${jsps} 在編譯期間為常量,從而它們仍然作為屬性指定。注意,屬性在使用任務時展開而不是在定義宏的地方展開。

所用任務的特性幾乎完全和屬性一樣,它們通過 @{} 而不是 ${} 展開。與屬性不同,它們是可變的,也就是說,它們的值可以(并將)隨著每一次調用而改變。它們也只在您的宏定義程序塊內部可用。這意味著如果您的宏定義還包含了另一個定義了宏的任務,那么您內部的宏將看不到包含的宏的屬性。

于是新的 production-wars 目標將類似于:

  <target name="production-wars">
    <makewar destfile="${staging.war.name}"
             webxml="${staging.web.xml}"/>
    <makewar destfile="${production.war.name}"
             webxml="${production.web.xml}"/>
</target>

這個新的代碼段不僅執行得快一些,而且也更易讀,因為屬性名稱提供了更多的信息。

宏任務還可以定義嵌套的元素。<makewar> 定義中的 <war> 任務的嵌套 <fileset> 可以是這種嵌套元素的一種。可能開發目標需要一些額外的文件或想從不同的位置中挑選 JSP 或資源。以下代碼段將一個可選的嵌套 <morefiles> 元素添加到了 <makewar> 任務中

  <macrodef name="makewar">
    <attribute name="webxml"/>
    <attribute name="destfile"/>
    <element name="morefiles" optional="true"/>
    <sequential>
      <war destfile="@{destfile}"
           webxml="@{webxml}">
        <lib refid="support-libraries"/>
        <lib file="${jar.name}"/>
        <fileset dir="${jsps}"/>
        <morefiles/>
      </war>
    </sequential>
  </macrodef>

調用將類似于:

  <makewar destfile="${development.war.name}"
           webxml="${development.web.xml}">
    <morefiles>
      <fileset dir="${development.resources}"/>
      <lib refid="development-support-libraries"/>
    </morefiles>
  </makewar>

這就像 <morefiles> 的嵌套元素直接在 <war> 任務內部使用的效果一樣。

即使迄今為止的示例僅顯示了包裝單個任務的 <macrodef>,但它不限于此。

下面的宏不僅將創建 web 存檔,還將確保包含最終存檔的目錄在試圖寫入之前存在。在一個實際的編譯文件中,您可能在調用任務之前使用一個設置目標來完成這個操作。

  <macrodef name="makewar">
    <attribute name="webxml"/>
    <attribute name="destfile"/>
    <element name="morefiles" optional="true"/>
    <sequential>
      <dirname property="@{destfile}.parent"
               file="@{destfile}"/>
      <mkdir dir="${@{destfile}.parent}"/>
      <war destfile="@{destfile}"
           webxml="@{webxml}">
        <lib refid="support-libraries"/>
        <lib file="${jar.name}"/>
        <fileset dir="${jsps}"/>
        <morefiles/>
      </war>
    </sequential>
  </macrodef>

這里注意兩件事情:

首先,特性在屬性展開之前展開,因此結構 ${@{destfile}.parent} 將展開一個名稱包含了 destfile 特性的值和 ".parent" 后綴的屬性。這意味著您可以將特性展開嵌入到屬性展開中,而不是將屬性展開嵌入特性展開中。

其次,這個宏定義了屬性,該屬性的名稱基于一個特性的值,因為 Ant 中的屬性是全局的并且不可改變。第一次嘗試使用

      <dirname property="parent"
               file="@{destfile}"/>

相反將不會在 "production-wars" 目標中的第二次 <makewar> 調用產生期望的結果。第一次調用將定義一個新的名稱為 parent 的屬性,該屬性指向父目錄 ${staging.war.name}。第二次調用將查看這個屬性但不會修改它的值。

預期 Ant 未來的版本將支持某些類型的限定范圍的屬性,這種屬性只在宏執行期間定義。在此之前,使用特性的名稱來構建屬性名稱是一種變通辦法,潛在的副作用是要創建大量的屬性。

提示:如果您查看您的編譯文件時發現使用了 <antcall> 代替宏,那么強烈建議您考慮使用 macrodef 將其轉換成真正的宏。性能影響可能非常顯著,并且還可能產生更易讀和更易于維護的編譯文件。
導入

將一個編譯文件分成多個文件有幾個原因。

  1. 文件可能變得太大,需要分成幾個單獨的部分,以便更易于維護。
  2. 您有某個功能集是多個編譯文件公用的,您想共享它。

共享公用功能/在 Ant 1.6 之前包含文件

在 Ant 1.6 之前,您唯一的選擇是實體包含的 XML 方法,類似于:

  <!DOCTYPE project [
      <!ENTITY common SYSTEM "file:./common.xml">
  ]>
  
  <project name="test" default="test" basedir=".">
  
    <target name="setup">
      ...
</target>
  
    &common;
  
    ...
  
</project>

摘自 Ant 常見問題解答。

這種方法有兩個主要的缺點。您不能使用 Ant 屬性指向您想包含的文件,因此被迫在您的編譯文件中對位置進行硬編碼。您想包含的文件只是一個 XML 文件的一部分,它可能沒有一個根元素,因而使用支持 XML 的工具進行維護更加困難。

共享公用功能/使用 Ant 1.6 包含文件

Ant 1.6 自帶了一個名稱為 import 的新任務,您現在可以使用它。上面的示例將變為

  <project name="test" default="test" basedir=".">
  
    <target name="setup">
      ...
</target>
  
    <import file="common.xml"/>
  
    ...
  
</project>

因為它是一個任務,因此您可以使用 Ant 所有的特性來指定文件位置。主要的差異是被導入的文件本身必須是一個有效的 Ant 編譯文件,因而必須有一個名稱為 project 的根元素。如果您想從實體包含轉換到導入,那么您必須在導入的文件的內容首尾放上 <project> 標記;然后 Ant 將在讀取文件時再次劃分它們。

注意文件名稱由 Ant 任務根據編譯文件的位置(而不是指定的基本目錄)確定。如果您沒有設置項目的 basedir 屬性或將其設為 ".",那么您將不會注意到任何差異。如果您需要根據基本目錄解析一個文件,那么您可以使用一個屬性作為變通辦法,類似于:

  <property name="common.location" location="common.xml"/>
  <import file="${common.location}"/>

屬性 common.location 將包含文件 common.xml 的絕對路徑,并已根據導入項目的基本目錄解析。

使用 Ant 1.6,所有的任務都可能放在目標之外或之內,除了兩個例外。<import> 一定不能嵌入到目標中,<antcall> 一定不能在目標外使用(否則它將創建一個無限循環)。

而 <import> 可做的不僅僅是導入另一個文件。

首先,它定義了名稱為 ant.file.NAME 的特殊屬性,其中 NAME 替換為每一個導入文件的 <project> 標記的名稱屬性。這個屬性包含了導入文件的絕對路徑,導入文件可用來根據它自己的位置(而不是導入文件的基本目錄)定位文件和資源。

這意味著 <project> 的名稱屬性在 <import> 任務環境中變得更加重要。它還用來為在被導入的編譯文件中定義的目標提供別名。如果導入了以下文件

<project name="share">
    <target name="setup">
      <mkdir dir="${dest}"/>
</target>
</project>

導入編譯文件可以查看作為 "setup" 或 "share.setup" 的目標。后者在目標覆蓋的上下文中變得非常重要。

讓我們假定有一個包含了多個獨立的組件(每個組件擁有它自己的編譯文件)的編譯系統。這些編譯文件幾乎相同,因此我們決定將公用功能轉移到一個共享和已導入的文件中。為了簡單起見,我們只介紹 Java 文件的編譯和創建結果的一個 JAR 存檔。共享的文件將類似于

  <project name="share">
    <target name="setup" depends="set-properties">
      <mkdir dir="${dest}/classes"/>
      <mkdir dir="${dest}/lib"/>
</target>
    <target name="compile" depends="setup">
      <javac srcdir="${src}" destdir="${dest}/classes">
        <classpath refid="compile-classpath"/>
</javac>
</target>
    <target name="jar" depends="compile">
      <jar destfile="${dest}/lib/${jar.name}" basedir="${dest}/classes"/>
</target>
</project>

這個文件不會作為一個獨立的 Ant 編譯文件進行工作,因為它沒有定義 "setup" 所依賴的 "set-properties" 目標。

組件 A 的編譯文件可能類似于

  <project name="A" default="jar">
    <target name="set-properties">
      <property name="dest" location="../dest/A"/>
      <property name="src" location="src"/>
      <property name="jar.name" value="module-A.jar"/>
      <path id="compile-classpath"/>
</target>
    <import file="../share.xml"/>
</project>

它僅設置適當的環境,然后將全部的編譯邏輯交給被導入的文件負責。注意該編譯文件創建了一個空的路徑作為編譯 CLASSPATH,因為它是自包含的。模塊 B 依賴于 A,它的編譯文件將類似于

  <project name="B" default="jar">
    <target name="set-properties">
      <property name="dest" location="../dest/B"/>
      <property name="src" location="src"/>
      <property name="jar.name" value="module-B.jar"/>
      <path id="compile-classpath">
        <pathelement location="../dest/A/module-A.jar"/>
      </path>
</target>
    <import file="../share.xml"/>
</project>

您將注意到該編譯文件與 A 的編譯文件幾乎一樣,因此似乎有可能將大多數的 set-properties 目標也推送到 shared.xml 中。實際上,我們可以假定有一個對 dest 和 src 目標一致的命名慣例,以實現這一目的。

  <project name="share">
    <target name="set-properties">
      <property name="dest" location="../dest/${ant.project.name}"/>
      <property name="src" location="src"/>
      <property name="jar.name" value="module-${ant.project.name}.jar"/>
</target>

    ... contents of first example above ...
</project>

ant.project.name 是一個內置的屬性,它包含了最外面的 <project> 標記的名稱屬性的值。因此,如果模塊 A 的編譯文件導入了 share.xml,那么它將擁有值 A。

注意,所有的文件都與導入編譯文件的基本目錄相關,因此 scr 屬性的實際值依賴于導入文件。

為此,A 的編譯文件將簡單地變為

<project name="A" default="jar">
    <path id="compile-classpath"/>
    <import file="../share.xml"/>
</project>

B 的編譯文件將變為

  <project name="B" default="jar">
    <path id="compile-classpath">
      <pathelement location="../dest/A/module-A.jar"/>
    </path>
    <import file="../share.xml"/>
</project>

現在假定 B 增加了一些 RMI 接口,需要在編譯類之后但在創建 jar 之前運行 <rmic>。這就是目標覆蓋能派上用場的地方。如果我們在導入編譯文件中定義了一個目標,該目標與被導入的編譯文件中的一個目標名稱相同,那么將使用導入編譯文件中的目標。例如,B 可以使用:

  <project name="B" default="jar">
    <path id="compile-classpath">
      <pathelement location="../dest/A/module-A.jar"/>
    </path>
    <import file="../share.xml"/>

    <target name="compile" depends="setup">
      <javac srcdir="${src}" destdir="${dest}/classes">
        <classpath refid="compile-classpath"/>
</javac>
      <rmic base="${dest}/classes" includes="**/Remote*.class"/>
</target>
</project>

在上面的示例中將使用 "compile" 目標,而不是 share.xml 中的目標;然而,不幸的是,這只是從共享那里復制 <javac> 任務。一種更好的解決方案是:

  <project name="B" default="jar">
    <path id="compile-classpath">
      <pathelement location="../dest/A/module-A.jar"/>
    </path>
    <import file="../share.xml"/>

    <target name="compile" depends="share.compile">
      <rmic base="${dest}/classes" includes="**/Remote*.class"/>
</target>
</project>

這只是使 B 的 "compile" 在原來的 "compile" 目標使用之后運行 <rmic>。

如果我們想在編譯之前生成一些 Java 源代碼(例如通過 XDoclet),我們可以使用類似下面的方法:

    <import file="../share.xml"/>

    <target name="compile" depends="setup,xdoclet,share.compile"/>
    <target name="xdoclet">
       .. details of XDoclet invocation omitted ..
</target>

因此您可以完全覆蓋一個目標或通過在原始目標之前或之后運行任務來增強它。

這里要注意一個危險。目標覆蓋機制使導入編譯文件依賴于在導入文件中使用的名稱屬性。如果任何人修改了導入文件的名稱屬性,那么導入編譯文件將被破壞。Ant 開發社區目前正在討論在 Ant 的一個未來的版本中為此提供一個解決方案。

提示:如果您在編譯文件中發現了非常常見的結構,那么值得嘗試將文件重構為一個(一些)共享文件,并在必要時使用目標覆蓋。這可以使您的編譯系統更加一致,并讓您能夠重用編譯邏輯。
Subant

在某種意義上,subant 是兩種任務合二為一,因為它了解操作的兩種模式。

如果您使用 <subant> 的 genericantfile 屬性,那么它的工作方式和 <antcall> 一樣,調用包含任務的同一個編譯文件中的目標。與 <antcall> 不同,<subant> 獲取目錄的列表或集合,并將為每一個目錄調用一次目標,以設定項目的基本目錄。如果您想在任意數量的目錄中執行完全一樣的操作,那么這非常有用。

第二種模式不使用 genericantfile 屬性,而獲取一個編譯文件的列表和集合進行迭代,以在每一個編譯文件中調用目標。這種工作方式類似于在一個循環中使用 <ant> 任務。

第二種形式的典型情景是幾個能夠獨立編譯的模塊的一個編譯系統,但是該系統需要一個主編譯文件來一次性編譯所有的模塊。

接下來的步驟

使用以下資源了解關于 Ant 的更多信息,并開始編譯和部署 Java 項目。

Ant 業界趨勢
對這個跨平臺編譯工具的形成進行幕后觀察

閱讀關于 JDeveloper 中的 Ant 集成的更多信息
Oracle JDeveloper 中的 Ant 集成是通過在 JDeveloper 項目中添加一個 Ant 編譯文件或通過從一個現有的 JDeveloper 項目中創建一個新的 Ant 編譯文件來實現的。

下載 Oracle JDeveloper 10g
Oracle JDeveloper 10g 是一個集成開發環境,它提供了對建模、開發、調試、優化和部署 Java 應用程序及 Web 服務的端到端支持。

測試驅動:將 Ant 用于編譯
這個 viewlet 演示了已擁有 Ant 項目的用戶如何能夠在 JDeveloper 內部使用這些項目。

Ant 入門第 1 部分
這里開始將這個非常有用的工具用于構建和部署 Java 項目。本文介紹了您可能在 Java 開發過程期間執行的一些基本的 Ant 任務。

Ant 入門第 2 部分
這里是我們的系列中的第 2 部分,這個系列介紹用于構建和部署 Java 項目的一個非常有用的工具。本文討論在 Ant 的兩個任務程序包(核心的任務程序包和可選的任務程序包)中提供的一些 Ant 的更高級的特性。

在 Linux 上創建 Java 應用程序的命令行方法
本文可用作使用 Ant 在 Linux 上開發和部署 Java 客戶端應用程序的一個不錯的上機操作指南。

閱讀關于 Ant 的更多信息
訪問官方 Apache Ant 站點,獲取更多的項目詳細信息。

相關文章與下載

Blog:到 OC4J 的 Ant 部署

Blog: 如何從一個 JDeveloper 項目文件中將屬性動態檢索到一個 ant 編譯文件中?

Viewlet:將 CVS 用于軟件配置

在 Ant 1.6 之前構建主編譯文件

在導入部分中討論的例子使用了這樣一個主編譯文件。

  <target name="build-all">
    <ant dir="module-A" target="jar"/>
    <ant dir="module-B" target="jar"/>
</target>

在 Ant 1.6 之前的 Ant 中。

使用 Ant 1.6 構建主編譯文件

在 Ant 1.6 中使用 <subant>,這可以重寫為

 
  <target name="build-all">
    <subant target="jar">
      <filelist dir=".">
        <file name="module-A/build.xml"/>
        <file name="module-B/build.xml"/>
      </filelist>
    </subant>
</target>

這看起來并沒有很大的改善,因為您仍然必須單獨指定每一個子編譯文件。相反如果您轉用 <fileset>,那么情況將有所改觀。

  <target name="build-all">
    <subant target="jar">
      <fileset dir="." includes="module-*/build.xml"/>
    </subant>
</target>

這將自動發現所有模塊的編譯文件。如果您增加了一個模塊 C,主編譯文件中的目標不需要修改。

但小心。與 <filelist> 或 <path>(也被 <subant> 支持)不同,<fileset> 是無序的。在我們的例子中,模塊 B 依賴于模塊 A,因此我們需要確保首先編譯模塊 A,而使用 <fileset> 沒有辦法這么做。

如果編譯完全彼此獨立或者它們對于一個給定的操作彼此獨立,那么 <fileset> 仍然有用。模塊 B 的文檔目標可能完全不依賴于模塊 A,同樣還有從您的 SCM 系統中更新源代碼的目標。

如果您想將編譯文件的自動發現與根據編譯的相互依賴性對編譯進行排序結合在一起,那么您將必須編寫一個定制的 Ant 任務。基本的想法是編寫一個使用 <fileset> 的任務(讓我們目前稱之為 <buildlist>),確定依賴關系并計算 <subant> 必須使用的順序。然后它創建一個以正確的順序包含編譯文件的 <path>,然后將對這個路徑的一個引用放到項目中。調用將類似于

  <target name="build-all">
    <buildlist reference="my-build-path">
      <fileset dir="." includes="module-*/build.xml"/>
    </buildlist>
    <subant target="jar">
      <buildpath refid="my-build-path"/>
    </subant>
</target>

這個假想的 buildlist 任務已經在 Ant 用戶郵件列表和 bug 跟蹤系統中進行了討論。很有可能 Ant 的一個將來的版本中將包含這樣的一個任務。

在 Ant 1.6 中已經增加了大量的新特性。這些新功能中的許多功能使得編譯模板易于創建、構造和定制。特別是 <import> 和 <target> 進行了覆蓋。<import>、<macrodef> 和 <subant> 特性很有可能使得 Ant 編譯可高度重用。<scriptdef>(本文中未討論)對于需要一些腳本但不想用 Java 編寫定制任務的人而言可能非常有吸引力。



笨笨 2005-06-14 12:22 發表評論
]]>
Appfuse實踐(一)——配置安裝http://www.tkk7.com/kapok/archive/2005/06/14/6105.html笨笨笨笨Tue, 14 Jun 2005 04:09:00 GMThttp://www.tkk7.com/kapok/archive/2005/06/14/6105.htmlhttp://www.tkk7.com/kapok/comments/6105.htmlhttp://www.tkk7.com/kapok/archive/2005/06/14/6105.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/6105.htmlhttp://www.tkk7.com/kapok/services/trackbacks/6105.htmlhttp://bbs.mbig.cn/topic_20008.html
我使用的是webwork+spring+hibernate,其他的可以參考相關tutorial。

一、系統環境準備
  從http://java.sun.com下載,我使用1.4.2_05.
  從latest Tomcat release 下載tomcat,目前的版本是5.0.28。最好不要用LE版本否則你要添加DBCP和JavaMail的JAR包.
  下載最近的Appfuse版本,我使用的是 AppFuse 1.6。
  下載mysql。

  將會使用 Ant, XDoclet, Spring, Hibernate (or iBATIS), JUnit, Cactus, StrutsTestCase, Canoo's WebTest, Struts Menu, Display Tag Library, OSCache, JSTL and Struts (or Spring MVC)這些組件。



二、開始安裝配置Appfuse
   download appfuse 并且解壓
   需要啟動Mysql服務器
   建立自己的應用程序數據庫默認字符集是UTF8,這個問題很關鍵,因為Appfuse支持多語言否則程序無法正常運行。所以Mysql服務器的默認的字符集也應該是UTF8,大家使用mysql怎么更改到UTF8字符集我不知道,我是通過命名行參數啟動的:
   mysqld --default-character-set=utf8

  此時可以用ant建立自己的應用了:
ant new -Dapp.name=myApp -Ddb.name=mydb

如果需要改變數據庫可以修改build.properties文件中這部分的參數:
代碼
#database.jar=${postgresql.jar}
#database.type=postgresql
#database.name=myApp
#database.host=localhost
#database URL for creating other databases (doesn't work with pgsql)
#database.admin.url=jdbc:${database.type}://${database.host}/template1
#database.admin.username=postgres
#database.admin.password=postgres

#hibernate.dialect=net.sf.hibernate.dialect.PostgreSQLDialect
#database.driver_class=org.postgresql.Driver
#database.url=jdbc:${database.type}://${database.host}/${database.name}


建立數據庫database, 在tomcat上發布應用

運行
ant setup

出錯了,無法自動建立數據庫mydb。出錯信息如下:
BUILD FAILED: D:\myfile\myApp\build.xml:830: org.dbunit.dataset.NoSuchTableException: app_user

檢查執行過程,把自動執行的創建app_user的sql語句放到mysql control center中執行
SQL代碼
create table app_user (
username varchar(20) not null,
version integer not null,
password varchar(255),
first_name varchar(50),
last_name varchar(50),
address varchar(150),
city varchar(50),
province varchar(100),
country varchar(100),
postal_code varchar(15),
email varchar(255) not null unique,
phone_number varchar(255),
website varchar(255),
password_hint varchar(255),
primary key (username)
);
執行失敗,錯誤提示:
[root@localhost:3306] 錯誤 1071: Specified key was too long. Max key length is 500
作如下修改,成功了,
email varchar(255) not null unique改成
email varchar(100) not null unique,

經過測試,長度超過166(包括)就出錯了!
不知道是不是UTF8字符集造成的原因,一個UTF8字符被認為占用了三個字節(500/3<167)??
就是說聲明為 not null unique的字段長度不能超過166。


由于sql語句根據POJO的tag自動創建:

找到org.appfuse.model.User的源程序

修改
@hibernate.column name="email" not-null="true" unique="true"

改成:
@hibernate.column name="email" not-null="true" length="166" unique="true"

運行
ant setup-db

成功了!ok!



啟動tomcat 5.0.25
運行
ant setup

出錯了

BUILD FAILED: D:\edu\edu\build.xml:33: Please copy junit.jar into C:\ant/lib

完成拷貝

成功了!excellent!
打開瀏覽器FireFox run一下:

輸入:http://127.0.0.1:8080/myApp

沒有反應??怎么回事??

命令行下面啟動tomcat,看看有什么錯誤提示:

unregistering logger Catalina:type=Logger,path=/myApp,host=localhost

打開C:\Tomcat\conf\Catalina\localhost\myAqpp.xml

修改:注釋掉 logger信息
代碼
<!-- Logger className="org.apache.catalina.logger.FileLogger" prefix="myApp_log." suffix=".txt" timestamp="true"/ -->


重新啟動tomcat

還是不對

更換版本tomcat 5.0.5.28
錯誤信息變了
Application 沒有啟動??

運行任務

ant install


沒有成功!出錯信息如下:

BUILD FAILED: D:\myfile\myApp\build.xml:1221: java.io.IOException: Server returned HTTP response code: 401 for URL: http://localhost:8080/manager/deploy?path=%2FmyApp


直接在瀏覽器中輸入http://localhost:8080/manager/deploy?path=%2FmyApp

??出現窗口要求輸入用戶名和密碼
查看myApp\tomcat.properties 管理員用戶密碼為admin,admin

修改 tomcat\conf\tomcat-users.xml 增加管理員admin

增加兩個角色

代碼
<role rolename="admin"/>
 <role rolename="manager"/>


增加admin用戶
代碼
<user username="admin" password="admin" roles="role1,tomcat,admin,manager"/>


刪除tomcat下面myApp目錄和conf\Catalina\localhost下的myApp.xml文件,重新啟動tomcat

運行

ant install

成功了!!



但是tomcat報錯:
2004-11-14 19:59:49 org.apache.catalina.core.StandardHostDeployer install
信息: Processing Context configuration file URL file:/C:/Tomcat/conf/Catalina/localhost/myApp.xml
2004-11-14 19:59:49 org.apache.catalina.core.StandardHostDeployer install
信息: Installing web application from URL jar:file:/C:/Tomcat/webapps/myApp.war!
/
2004-11-14 20:00:04 org.apache.catalina.core.StandardContext listenerStart
嚴重: Skipped installing application listeners due to previous error(s)
2004-11-14 20:00:04 org.apache.catalina.core.StandardContext start
嚴重: Error listenerStart
2004-11-14 20:00:04 org.apache.catalina.core.StandardContext start
嚴重: Context startup failed due to previous errors
2004-11-14 20:00:04 org.apache.catalina.logger.LoggerBase stop
信息: unregistering logger Catalina:type=Logger,path=/myApp,host=localhost

為什么呢??

tomcat版本不對??

運行struts安裝程序,正常運行

重新運行ant install-webwork

BUILD FAILED: D:\myfile\myApp\build.xml:1391: Basedir D:\myfile\myApp\extras\webwork does not exist

嗯~~

更改extras\viewgen目錄名稱為webwork

重新運行ant install-webwork

再運行ant install

打開firefox,輸入 http://127.0.0.1:8080/myApp。成功了!



輸入用戶名mraible
密碼tomcat

OK!!進入主界面(界面沒有上傳,不好意思了^_^)


笨笨 2005-06-14 12:09 發表評論
]]>
Servlet 2.3過濾器編程http://www.tkk7.com/kapok/archive/2005/04/15/3334.html笨笨笨笨Fri, 15 Apr 2005 15:50:00 GMThttp://www.tkk7.com/kapok/archive/2005/04/15/3334.htmlhttp://www.tkk7.com/kapok/comments/3334.htmlhttp://www.tkk7.com/kapok/archive/2005/04/15/3334.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/3334.htmlhttp://www.tkk7.com/kapok/services/trackbacks/3334.html2005年3月17日  作者:l_walker  Matrix-與Java共舞

 

你可以在兩種情況下使用本文:學習過濾器的功用,或者作為你寫過濾器時的輔助。我將從幾個簡單的例子開始然后繼續更多高級的過濾器。最后,我將向你介紹我為了支持多路請求而寫的一個文件上傳過濾器。

 

Servlet 過濾器

也許你還不熟悉情況,一個過濾器是一個可以傳送請求或修改響應的對象。過濾器并不是servlet,他們并不實際創建一個請求。他們是請求到達一個servlet前的預處理程序,和/或響應離開servlet后的后處理程序。就像你將在后面的例子中看到的,一個過濾器能夠:

·在一個servlet被調用前截獲該調用

·在一個servlet被調用前檢查請求

·修改在實際請求中提供了可定制請求對象的請求頭和請求數據

·修改在實際響應中提供了可定制響應對象的響應頭和響應數據

·在一個servlet被調用之后截獲該調用

 

    你可以一個過濾器以作用于一個或一組servlet,零個或多個過濾器能過濾一個或多個servlet。一個過濾器實現java.servlet.Filter接口并定義它的三個方法:

1.              void init(FilterConfig config) throws ServletException:在過濾器執行service前被調用,以設置過濾器的配置對象。

2.              void destroy();在過濾器執行service后被調用。

3.              Void doFilter(ServletRequest req,ServletResponse res,FilterChain chain) throws IOException,ServletException;執行實際的過濾工作。

 

服務器調用一次init(FilterConfig)以為服務準備過濾器,然后在請求需要使用過濾器的任何時候調用doFilter()。FilterConfig接口檢索過濾器名、初始化參數以及活動的servlet上下文。服務器調用destory()以指出過濾器已結束服務。過濾器的生命周期和servelt的生命周期非常相似 ——在Servlet API 2.3 最終發布稿2號 中最近改變的。先前得用setFilterConfig(FilterConfig)方法來設置生命周期。

 

在doFilter()方法中,每個過濾器都接受當前的請求和響應,而FilterChain包含的過濾器則仍然必須被處理。doFilter()方法中,過濾器可以對請求和響應做它想做的一切。(就如我將在后面討論的那樣,通過調用他們的方法收集數據,或者給對象添加新的行為。)過濾器調用

chain.doFilter()將控制權傳送給下一個過濾器。當這個調用返回后,過濾器可以在它的doFilter()方法的最后對響應做些其他的工作;例如,它能記錄響應的信息。如果過濾器想要終止請求的處理或或得對響應的完全控制,則他可以不調用下一個過濾器。

 

循序漸進

如果想要真正理解過濾器,則應該看它們在實際中的應用。我們將看到的第一個過濾器是簡單而有用的,它記錄了所有請求的持續時間。在Tomcat 4.0發布中被命名為ExampleFilter。代碼如下:

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class TimerFilter implements Filter {

 

  private FilterConfig config = null;

 

  public void init(FilterConfig config) throws ServletException {

    this.config = config;

  }

 

  public void destroy() {

    config = null;

  }

 

  public void doFilter(ServletRequest request, ServletResponse response,

                     FilterChain chain) throws IOException, ServletException {

    long before = System.currentTimeMillis();

    chain.doFilter(request, response);

    long after = System.currentTimeMillis();

 

    String name = "";

    if (request instanceof HttpServletRequest) {

      name = ((HttpServletRequest)request).getRequestURI();

    }

    config.getServletContext().log(name + ": " + (after - before) + "ms");

  }

}

 

當服務器調用init()時,過濾器用config變量來保存配置類的引用,這將在后面的doFilter()方法中被使用以更改ServletContext。當調用doFilter()時,過濾器計算請求發生到該請求執行完畢之間的時間。該過濾器很好的演示了請求之前和之后的處理。注意doFilter()方法的參數并不是HTTP對象,因此要調用HTTP專用的getRequestURI()方法時必須將request轉化為HttpServletRequest類型。

 

使用此過濾器,你還必須在web.xml文件中用<filter>標簽部署它,見下:

   
 <filter>

        <filter-name>timerFilter</filter-name>

        <filter-class>TimerFilter</filter-class>

</filter>


 

這將通知服務器一個叫timerFiter的過濾器是從TimerFiter類實現的。你可以使用確定的URL模式或使用<filter-mapping>標簽命名的servelt 來注冊一個過濾器,如:

<filter-mapping>

    <filter-name>timerFilter</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>


 

這種配置使過濾器操作所有對服務器的請求(靜態或動態),正是我們需要的計時過濾器。如果你連接一個簡單的頁面,記錄輸出可能如下:

2001-05-25 00:14:11 /timer/index.html: 10ms

 

在Tomcat 4.0 beta 5中,你可以在server_root/logs/下找到該記錄文件。

 

此過濾器的WAR文件從此下載:

    
http://www.javaworld.com/jw-06-2001/Filters/timer.war

 

誰在你的網站上?他們在做什么?

我們下一個過濾器是由OpenSymphony成員寫的clickstream過濾器。這個過濾器跟蹤用戶請求(比如:點擊)和請求隊列(比如:點擊流)以向網絡管理員顯示誰在她的網站上以及每個用戶正在訪問那個頁面。這是個使用LGPL的開源庫。

 

在clickstream包中你將發現一個捕獲請求信息的ClickstreamFilter類,一個像操作結構一樣的Clickstream類以保存數據,以及一個保存會話和上下文事件的ClickstreamLogger類以將所有東西組合在一起。還有個BotChecker類用來確定客戶端是否是一個機器人(簡單的邏輯,像“他們是否是從robots.txt來的請求?”)。該包中提供了一個clickstreams.jsp摘要頁面和一個viewstream.jsp詳細頁面來查看數據。

 

我們先看ClickstreamFilter類。所有的這些例子都做了些輕微的修改以格式化并修改了些可移植性問題,這我將在后面將到。

import java.io.IOException;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class ClickstreamFilter implements Filter {

  protected FilterConfig filterConfig;

  private final static String FILTER_APPLIED = "_clickstream_filter_applied";

 

  public void init(FilterConfig config) throws ServletException {

    this.filterConfig = filterConfig;

  }

 

  public void doFilter(ServletRequest request, ServletResponse response,

                   FilterChain chain) throws IOException, ServletException {

    // 確保該過濾器在每次請求中只被使用一次

    if (request.getAttribute(FILTER_APPLIED) == null) {

      request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

      HttpSession session = ((HttpServletRequest)request).getSession();

      Clickstream stream = (Clickstream)session.getAttribute("clickstream");

      stream.addRequest(((HttpServletRequest)request));

    }

 

    // 傳遞請求

    chain.doFilter(request, response);

  }

 

  public void destroy() { }

}


 

doFilter()方法取得用戶的session,從中獲取Clickstream,并將當前請求數據加到Clickstream中。其中使用了一個特殊的FILTER_APPLIED標記屬性來標注此過濾器是否已經被當前請求使用(可能會在請求調度中發生)并且忽略所有其他的過濾器行為。你可能疑惑過濾器是怎么知道當前session中有clickstream屬性。那是因為ClickstreamLogger在會話一開始時就已經設置了它。ClickstreamLogger代碼:

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class ClickstreamLogger implements ServletContextListener,

                                          HttpSessionListener {

  Map clickstreams = new HashMap();

 

  public ClickstreamLogger() { }

 

  public void contextInitialized(ServletContextEvent sce) {

    sce.getServletContext().setAttribute("clickstreams", clickstreams);

  }

 

  public void contextDestroyed(ServletContextEvent sce) {

    sce.getServletContext().setAttribute("clickstreams", null);

  }

 

  public void sessionCreated(HttpSessionEvent hse) {

    HttpSession session = hse.getSession();

    Clickstream clickstream = new Clickstream();

    session.setAttribute("clickstream", clickstream);

    clickstreams.put(session.getId(), clickstream);

  }

 

  public void sessionDestroyed(HttpSessionEvent hse) {

    HttpSession session = hse.getSession();

    Clickstream stream = (Clickstream)session.getAttribute("clickstream");

    clickstreams.remove(session.getId());

  }

}

 


     logger(記錄器)獲取應用事件并將使用他們將所有東西幫定在一起。當context創建中,logger在context中放置了一個共享的流map。這使得clickstream.jsp頁面知道當前活動的是哪個流。而在context銷毀中,logger則移除此map。當一個新訪問者創建一個新的會話時,logger將一個新的Clickstream實例放入此會話中并將此Clickstream加入到中心流map中。在會話銷毀時,由logger從中心map中移除這個流。

 

下面的web.xml部署描述片段將所有東西寫在一塊:

   
 <filter>

         <filter-name>clickstreamFilter</filter-name>

         <filter-class>ClickstreamFilter</filter-class>

    </filter>



 

   
 <filter-mapping>

         <filter-name>clickstreamFilter</filter-name>

         <url-pattern>*.jsp</url-pattern>

    </filter-mapping>

 

    <filter-mapping>

         <filter-name>clickstreamFilter</filter-name>

         <url-pattern>*.html</url-pattern>

    </filter-mapping>

 

    <listener>

         <listener-class>ClickstreamLogger</listener-class>

    </listener>

 

    這注冊了ClickstreamFilter并設置其處理*.jsp和*.html來的請求。這也將ClickstreamLogger注冊為一個監聽器以在應用事件發生時接受他們。

 

   兩個JSP頁面從會話中取clickstream數據和context對象并使用HTML界面來顯示當前狀態。下面的clickstream.jsp文件顯示了個大概:

<%@ page import="java.util.*" %>

<%@ page import="Clickstream" %>

<%

Map clickstreams = (Map)application.getAttribute("clickstreams");

String showbots = "false";

 

if (request.getParameter("showbots") != null) {

  if (request.getParameter("showbots").equals("true"))

    showbots = "true";

  else if (request.getParameter("showbots").equals("both"))

    showbots = "both";

}

%>

 

<font face="Verdana" size="-1">

<h1>All Clickstreams</h1>

 

<a href="clickstreams.jsp?showbots=false">No Bots</a> |

<a href="clickstreams.jsp?showbots=true">All Bots</a> |

<a href="clickstreams.jsp?showbots=both">Both</a> <p>

 

<% if (clickstreams.keySet().size() == 0) { %>

        No clickstreams in progress

<% } %>

 

<%

Iterator it = clickstreams.keySet().iterator();

int count = 0;

while (it.hasNext()) {

  String key = (String)it.next();

  Clickstream stream = (Clickstream)clickstreams.get(key);

 

  if (showbots.equals("false") && stream.isBot()) {

    continue;

  }

  else if (showbots.equals("true") && !stream.isBot()) {

    continue;

  }

  count++;

  try {

%>

 

<%= count %>. 

<a href="viewstream.jsp?sid=<%= key %>"><b>

<%= (stream.getHostname() != null && !stream.getHostname().equals("") ?

     stream.getHostname() : "Stream") %>

</b></a> <font size="-1"><%= stream.getStream().size() %> reqs</font><br>

 

<%

  }

  catch (Exception e) {

%>

  An error occurred - <%= e %><br>

<%

  }

}

%>



這個包很容易從OpenSymphony下載并安裝。將Java文件編譯并放在

WEB-INF/classes下,將JSP文件放到Web應用路徑下,按幫助修改web.xml文件。為防止在這些工作前的爭論,你可以從

http://www.javaworld.com/jw-06-2001/Filters/clickstream.war處找到打好包的WAR文件。

 

為能讓此過濾器能在Tomcat 4.0 beta 5下工作,我發現我不得不做一些輕微的改動。我做的改動顯示了一些在servlet和過濾器的可移植性中通常容易犯的錯誤,所以我將他們列在下面:

·我不得不將在JSP中添加一個額外的導入語句:<%@ page import=”Clickstream” %>。在Java中你并不需要導入在同一包下的類,而在服務器上JSP被編譯到默認包中,你并不需要這句導入行。但在像Tomcat這樣的服務器上,JSP被編譯到一個自定義的包中,你不得不明確地從默認包中導入類。

·我不得不將<listener>元素移動到web.xml文件中的<filter>和<filter-mapping>元素之后,就像部署描述DTD要求的那樣。并不是所有服務器對元素都要求固定的順序。但Tomcat必須要。

·我不得不將web.xml中的映射由/*.html和/*.jsp改成正確的*.html和*.jsp。一些服務器會忽略開頭的/,但Tomcat強硬的規定開頭不能有/。

·最后,我得將ClickstreamFilter類升級到最新的生命周期API,將setFilterConfig()改成新的init()和destory()方法。

 

可下載的WAR文件已經包含了這些修改并能通過服務器在包外運行,雖然我并沒有廣泛的進行測試。

 

壓縮響應

第三個過濾器是自動壓縮響應輸出流,以提高帶寬利用率并提供一個很好的包裝響應對象的示例。這個過濾器是由來自SUN的Amy Roh編寫的,他為Tomcat 4.0 的“examples”Web程序做出過貢獻。你將從webapps/examples/WEB-INF/classes/compressionFilters下找到原始代碼。這里的例子代碼以及WAR下的都已經為了更清晰和更簡單而編輯過了。

 

CompressionFilter類的策略是檢查請求頭以判定客戶端是否支持壓縮,如果支持,則將響應對象用自定義的響應來打包,它的getOutputStream()和getWriter()方法已經被定義為可以利用壓縮過的輸出流。使用過濾器允許如此簡單而有效的解決問題。

 

我們將從init()開始看代碼:

  
public void init(FilterConfig filterConfig) {

    config = filterConfig;

    compressionThreshold = 0;

    if (filterConfig != null) {

      String str = filterConfig.getInitParameter("compressionThreshold");

      if (str != null) {

        compressionThreshold = Integer.parseInt(str);

      }

      else {

        compressionThreshold = 0;

      }

    }

  }

 

注意在檢索請求頭前必須把request轉化為HttpServletRequest,就想在第一個例子里那樣。過濾器使用wrapper類CompressResponseWrapper,一個從

HttpServletResponseWrapper類繼承下來的自定義類。這個wrapper的代碼相對比較簡單:

public class CompressionResponseWrapper extends HttpServletResponseWrapper {

 

  protected ServletOutputStream stream = null;

  protected PrintWriter writer = null;

  protected int threshold = 0;

  protected HttpServletResponse origResponse = null;

 

  public CompressionResponseWrapper(HttpServletResponse response) {

    super(response);

    origResponse = response;

  }

 

  public void setCompressionThreshold(int threshold) {

    this.threshold = threshold;

  }

 

  public ServletOutputStream createOutputStream() throws IOException {

    return (new CompressionResponseStream(origResponse));

  }

 

  public ServletOutputStream getOutputStream() throws IOException {

    if (writer != null) {

      throw new IllegalStateException("getWriter() has already been " +

                                      "called for this response");

    }

 

    if (stream == null) {

      stream = createOutputStream();

    }

    ((CompressionResponseStream) stream).setCommit(true);

    ((CompressionResponseStream) stream).setBuffer(threshold);

    return stream;

  }

 

  public PrintWriter getWriter() throws IOException {

    if (writer != null) {

      return writer;

    }

 

    if (stream != null) {

      throw new IllegalStateException("getOutputStream() has already " +

                                      "been called for this response");

    }

 

    stream = createOutputStream();

    ((CompressionResponseStream) stream).setCommit(true);

    ((CompressionResponseStream) stream).setBuffer(threshold);

    writer = new PrintWriter(stream);

    return writer;

  }

}


 

所有調用getOutputStream() 或者getWriter()都返回一個使用

CompressResponseStream類的對象。CompressionResponseStrteam類沒有顯示在這個例子中,因為它繼承于ServletOutputStream并使用java.util.zip.GZIPOutputStream類來壓縮流。

 

Tomcat的”examples”Web程序中已經預先配置了這個壓縮過濾器并加載了一個示例servlet。示例servlet響應/CompressionTestURL(確定先前的路徑是/examples)。使用我制作的有用的WAR文件,你可以用/servlet/compressionTest(再次提醒,別忘了適當的前導路徑)訪問此測試servlet。你可以使用如下的web.xml片段來配置這個測試:

<filter>

    <filter-name>compressionFilter</filter-name>

    <filter-class>CompressionFilter</filter-class>

    <init-param>

      <param-name>compressionThreshold</param-name>

      <param-value>10</param-value>

    </init-param>

</filter>

 

<filter-mapping>

    <filter-name>compressionFilter</filter-name>

    <servlet-name>compressionTest</servlet-name>

</filter-mapping>

 

<servlet>

  <servlet-name>

    compressionTest

  </servlet-name>

  <servlet-class>

    CompressionTestServlet

  </servlet-class>

</servlet>

 

CompressionTestServlet(這里沒有顯示)輸出壓縮是否可用,如果可用,則輸出壓縮響應成功! 
 

 

//~~~~~~~~~~CSDN這里到底有多少字數限制?

請各位斧正了:)

來自:csdn

笨笨 2005-04-15 23:50 發表評論
]]>
struts-menuhttp://www.tkk7.com/kapok/archive/2005/04/08/3003.html笨笨笨笨Fri, 08 Apr 2005 08:46:00 GMThttp://www.tkk7.com/kapok/archive/2005/04/08/3003.htmlhttp://www.tkk7.com/kapok/comments/3003.htmlhttp://www.tkk7.com/kapok/archive/2005/04/08/3003.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/3003.htmlhttp://www.tkk7.com/kapok/services/trackbacks/3003.htmlhttp://struts-menu.sourceforge.net/

https://appfuse.dev.java.net/

笨笨 2005-04-08 16:46 發表評論
]]>
WebWork開工大吉http://www.tkk7.com/kapok/archive/2005/03/27/2500.html笨笨笨笨Sun, 27 Mar 2005 05:18:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/27/2500.htmlhttp://www.tkk7.com/kapok/comments/2500.htmlhttp://www.tkk7.com/kapok/archive/2005/03/27/2500.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/2500.htmlhttp://www.tkk7.com/kapok/services/trackbacks/2500.html今天開始開工.
在webwork.property中加入
webwork.configuration.xml.reload=true之后,原來正常的action突然間不能正確執行, 后來發現原來是定義該action的xml還處于打開狀態的緣故(也可能是其他原因?), 可能重建config對象的時候必須獲得對該文件的獨享訪問??

PS:剛剛做了一次重新測試,以上原因排除,為什么尚未找到,反正現在好了.

2.

<action name="hello" class="helloworld.HelloWorldAction">
   <result name="success" type="dispatcher">
    <param name="location">/greetings.jsp</param>
   </result>
  </action>

這段代碼有另外一種調用方式:
http://localhost:8080/webwork_test/hello/hello!noHello.action

這樣就是調用hello這個action指定類的noHello方法了.
如果要帶參數的話,還沒找到如何配置.呵呵.

3.
明確指定調用那個方法的配置文件寫法:

<!-- action指定了調用action哪個方法-->
  <action name="nohello" class="helloworld.HelloWorldAction" method="noHello">
   <result name="success" type="dispatcher">
    <param name="location">/greetings.jsp</param>
   </result>
  </action>


4.
指定全局的資源文件方法:
http://wiki.opensymphony.com/display/WW/webwork.properties
### Load custom default resource bundles
#webwork.custom.i18n.resources=testmessages,testmessages2

如果ApplicationResources的資源文件放在src/resources文件夾里面,在頁面上面寫
<ww:i18n name="'resources.ApplicationResources'">
 <ww:text name="'delete'">
 </ww:text>
</ww:i18n>
可以正確的找到中文字符集. 如果寫成<ww:i18n name="ApplicationResources'">,則會提示:  Could not find the bundle 'ApplicationResources'.以上操作并沒有設置webwork.custom.i18n.resources屬性.如果指定webwork.custom.i18n.resources=resources.ApplicationResources而不指定i18n標簽的name是不允許的.i18n標簽的name屬性是必須的選項,并且要寫全路徑.

但是如果僅僅寫<ww:text name="'add'"/>頁面上僅僅是顯示add, 不會顯示對應的中文. 原因正在找.
(這個問題在tomcat重新啟動之后消失,在資源文件中配置了webwork.custom.i18n.resources=resources.ApplicationResources屬性之后,頁面上的<ww:text name="'add'"/>標簽生效了.注意配置屬性的時候前后左右不要寫多余的空格).

另外一個國際化的參考鏈接:
http://wiki.opensymphony.com/display/WW/Internationalization
基本上涉及到資源文件的修改都需要重新啟動服務器.
如果不想重啟的話可以參考這個鏈接:
http://forum.javaeye.com/viewtopic.php?t=6417&highlight=locale

5.
上面的試驗表示多語言的第一步是成功的,接下來的問題是中文顯示成?.以及手工控制多語言的問題.

webwork.i18n.encoding=UTF-8
測試頁面中的文字如下:

中國
<p></p>
<ww:text name="'add'"/>

在這個頁面里面沒有指定頁面的編碼方式,只是頁面本身的編碼方式在IDE中指定,當在ie中選擇UTF-8編碼時,中文"中國"顯示正常.
(原來把頁面設置成IDE里面的UFT-8,結果如果用myeclipse的jsp編輯器打開,默認時ISO編碼).

<%@ page contentType='text/html;charset=UTF-8'%>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
頁面里面添加以上兩句,把jsp的文件屬性設置成UTF-8,再用myeclipse打開該jsp文件輸入中文"中國",這個時候可以正確保存中文,瀏覽器可以正確的選擇UFT-8編碼.另外從ApplicationResources文件中選擇出來的中文顯示也正常了(該資源文件為UFT-8編碼,利用Java ResourceBuddle Editor插件編輯).

中文問題解決,沒有使用filter. 注意: 我的webwork版本為2.1.7.有些老版本的估計還是得用filter來處理.以后有空可以試一下.

6.
繼續上面的試驗, 所有條件不變,在helloworld.HelloWorldAction所在包中新建與該action名字想同的資源文件,本例中叫做HelloWorldAction_en.properties和HelloWorld_zh_CN.properties,然后在里面加兩個跟全局resource相同key的資源文件,頁面上會優先從這里來取國際化文字,也就是說即使指定了全局resource文件,如果在action執行的包內存在同名的key也會覆蓋同名全局資源文件中的key定義.
同樣,如果雖然action包中存在資源文件,但是沒有定義請求的key的國際化文字,則會到全局資源文件里面進行查找.

結論: webwork可以支持很好的全局資源文件, 并且每個action可以根據需要覆蓋某些key的定義. 在資源文件的搜索路徑中是action的資源文件優先,其次是全局資源文件

原文
http://wiki.opensymphony.com/display/WW/Internationalization
WebWork supports internationalization (in short, i18n) in two different places: the UI tags and the action/field error messages.

UI Tags
Validation Examples

Resource bundles are searched in the following order:

1.) ActionClass.properties
2.)BaseClass.properties (all the way to Object.properties)
3.) Interface.properties (every interface and sub-interface)
4.) package.properties (every of every base class, all the way to java/lang/package.properties)

7.
http://forum.javaeye.com/viewtopic.php?t=11073&start=0
http://www.opensymphony.com/webwork/wikidocs/Transparent%20web-app%20I18N.html

http://localhost:8080/webwork_test/hello/hello.action?set_locale=zh_CN
http://localhost:8080/webwork_test/hello/hello.action?set_locale=en_US

測試通過,自定義語種問題解決.


相關鏈接:
http://forum.javaeye.com/viewtopic.php?t=11073&start=0



8.
今天發現5.8.4版本的myeclipse的tag屬性面板挺好用的.good.


9.
有關webwork的javascript驗證能力參看以下帖子:
http://www.hibernate.org.cn/viewtopic.php?t=9126&postdays=0&postorder=asc&start=0

http://forum.javaeye.com/allbloglist.php?page=15

http://scud.blogdriver.com/scud/index.html



笨笨 2005-03-27 13:18 發表評論
]]>
AppFuse中集成ValueList的問題http://www.tkk7.com/kapok/archive/2005/03/18/2211.html笨笨笨笨Fri, 18 Mar 2005 15:40:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/18/2211.htmlhttp://www.tkk7.com/kapok/comments/2211.htmlhttp://www.tkk7.com/kapok/archive/2005/03/18/2211.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/2211.htmlhttp://www.tkk7.com/kapok/services/trackbacks/2211.htmlhttp://rabbit8.blogchina.com/blog/article_144619.1140620.html

如果按照我上一篇筆記所說的方法,可以在Tocmat下集成ValueList,但使用AppFuse的ant setup會有問題,我今天找到了原因,解決方法見內

在執行 ant setup的時候,在compile-module的時候,總是說找不到valuelist的類,后來發現AppFuse的jar都添加到了builde.xml中,于是我也把valuelist.jar添加過去了,發現問題解決了,方法如下:

AppFuse執行Setup后自動將valuelist.jar復制到Tomcat下:

在appfuse\lib\lib.properties中添加如下內容:

#
# ValueList
#
valuelist.version=0.1.7
valuelist.dir=${lib.dir}
valuelist.jar=${valuelist.dir}/valuelist.jar


將properties.xml中添加:
<!-- Web -->
<path id="web.compile.classpath">
    <pathelement location="${dist.dir}/${webapp.name}-dao.jar"/>
    <pathelement location="${dist.dir}/${webapp.name}-service.jar"/>
    <pathelement location="${struts.jar}"/>
    <pathelement location="${strutsmenu.jar}"/>
    <pathelement location="${displaytag.jar}"/>
    <pathelement location="${jakarta-oro.jar}"/>
    <pathelement location="${commons-digester.jar}"/>
    <pathelement location="${commons-logging.jar}"/>
    <pathelement location="${commons-beanutils.jar}"/>
    <pathelement location="${commons-collections.jar}"/>
    <pathelement location="${commons-fileupload.jar}"/>
    <pathelement location="${commons-lang.jar}"/>
    <pathelement location="${commons-validator.jar}"/>
    <pathelement location="${servletapi.jar}"/>
    <pathelement location="${valuelist.jar}"/>                    //這是我添加的
    <fileset dir="${javamail.dir}" includes="*.jar"/>
    <fileset dir="${spring.dir}" includes="*.jar"/>
    <fileset dir="${jstl.dir}/lib" includes="jstl.jar"/>
</path>

在builde.xml中添加:
<war destfile="${webapp.dist}/${webapp.war}"
            webxml="${webapp.target}/WEB-INF/web.xml" compress="true">
            <fileset dir="${webapp.target}" excludes="**/web.xml,**/*-resources.xml"/>
            <metainf dir="${webapp.dist}" includes="context.xml"/>

            <classes dir="${build.dir}/web/classes">
                <exclude name="**/database.properties"/>
            </classes>

            <lib file="${dist.dir}/${webapp.name}-dao.jar"/>
            <lib file="${dist.dir}/${webapp.name}-service.jar"/>

            <webinf dir="${struts.dir}" includes="*.xml"/>
            <webinf dir="web/WEB-INF" includes="*-resources.xml"/>
           
            <lib file="${clickstream.jar}"/>
            <lib dir="${struts.dir}" includes="*.jar"/>
            <lib dir="${jstl.dir}/lib">
                <include name="jstl.jar"/>
                <include name="standard.jar"/>
            </lib>
            <lib dir="${javamail.dir}" includes="*.jar"/>  
            <lib file="${log4j.jar}"/>
            <lib file="${strutsmenu.jar}"/>
     <lib file="${valuelist.jar}"/>                             //這是我添加的內容
            <lib dir="${displaytag.dir}" includes="*.jar"/>
            <lib file="${hibernate.jar}"/>
            <lib dir="${hibernate.dir}/lib">
                <include name="odmg*.jar"/>
                <include name="dom4j*.jar"/>
                <include name="cglib*.jar"/>
                <include name="ehcache*.jar"/>
                <include name="oscache*.jar"/>
            </lib>
            <lib dir="${spring.dir}" includes="*.jar"/>
            <lib file="${sitemesh.jar}"/>
            <lib dir="${velocity.dir}" includes="*.jar"/>  
            <lib file="${urlrewrite.jar}"/>
        </war>
    </target>

 

                                                                                                    兔八哥



笨笨 2005-03-18 23:40 發表評論
]]>
Aceqihttp://www.tkk7.com/kapok/archive/2005/03/18/2190.html笨笨笨笨Fri, 18 Mar 2005 05:41:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/18/2190.htmlhttp://www.tkk7.com/kapok/comments/2190.htmlhttp://www.tkk7.com/kapok/archive/2005/03/18/2190.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/2190.htmlhttp://www.tkk7.com/kapok/services/trackbacks/2190.htmlhttp://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseSecurity

笨笨 2005-03-18 13:41 發表評論
]]>
再談URLEncoderhttp://www.tkk7.com/kapok/archive/2005/03/09/1864.html笨笨笨笨Tue, 08 Mar 2005 16:44:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1864.htmlhttp://www.tkk7.com/kapok/comments/1864.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1864.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1864.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1864.html http://rabbit8.blogchina.com/blog/article_144619.859489.html
再談URLEncoder
2005年 02月16日 有個朋友說在百度上提交的數據進行編碼后不是我說的那樣,我試了一下,找到原因如下

關于URLEncoder的解析問題     

      http://rabbit8.blogchina.com/blog/article_144619.789425.html后,有個朋友留言,說在百度試驗的結果和我文章中說的不一致,我做了個實驗,證實JDK的幫助沒錯,原因如下:


我的試驗代碼如下:
public static void main(String[] args) {
        URLEncoder urle = null;
       
        //得到默認:%A8%B9
        System.out.println("默認:" +   urle.encode("ü")); 
        try {
            //得到GBK:%A8%B9
            System.out.println("GBK:" +  urle.encode("ü", "GBK"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            //得到UTF-8:%C3%BC
            System.out.println("UTF-8:" +  urle.encode("ü", "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
 
      如果用UltraEdit來查看"ü"的ASCII的話,得到的結果如圖:
 
      可見,UltraEdit使用的是操作系統默認的編碼方式(實際上,MS采用的也不是GBK,而是另一種編碼,但效果和GBK差不多),所以它顯示的ASCII的編碼為A8 B9,就是第一和第二種情況的結果。而第三種情況才是JDK幫助中所聲明的情況。
 
      我查看了百度,提交了一下,結果和我預期的是一樣的!

      如果你查看頁面的源文件,會看到百度的charset為gb2312,而幫助中明確提到例子使用的是UTF-8編碼,所以出現了不一致的問題,也正是因為這個原因,所以JDK中決定要廢棄public static String encode(String s)方法,因為這個方法的編碼的字符集依賴于程序運行的系統的默認的字符集!
 
                                                                     兔八哥
                                                             2005-2-15 17:41
 



笨笨 2005-03-09 00:44 發表評論
]]>
DisplayTag、Tomcat中編碼的問題http://www.tkk7.com/kapok/archive/2005/03/09/1863.html笨笨笨笨Tue, 08 Mar 2005 16:41:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1863.htmlhttp://www.tkk7.com/kapok/comments/1863.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1863.html#Feedback2http://www.tkk7.com/kapok/comments/commentRss/1863.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1863.html DisplayTag、Tomcat中編碼的問題 2005年 02月04日 對DisplayTag、Tomcat中編碼問題的總結

關于AppFuse中使用中文編碼的問題

 

      這2個月一直被DisplayTag折騰,如果DisplayTag的鏈接或者排序的列中有漢字,那么排序或者翻頁都會查詢不到結果或報錯(如果你處理的好,可能會顯示沒有可以顯示的數據)。

      我一直以為這個問題是因為DisplayTag的開發者們沒有考慮到中文的問題,因為項目進度很緊,所以就把排序的功能給屏蔽了,雖然經過了大量的測試,但都沒有發現翻頁時候也存在這個問題(AppFuse自動生成的頁面的默認顯示25行,如果超過25行會自動分頁),直到前天,測試人員才發現這個問題,按照我的理解要修改DisplayTag的源碼,后來又想通過自己寫過濾器試試,幸運的是在我動手干之前,先和倦兔聊了幾句,結果倦兔說他也遇到過這個問題,指出如果在server.xml中添加URIEncoding="GBK"就可以解決問題,我試了一下,果然可以,但這是為什么呢?

      在AppFuse中有一個Spring的過濾器,對請求的編碼進行轉換,這種做法很通用,即使是在以前,我們自己寫這個過濾器也不麻煩,而且這個代碼在網上隨處可見,難道是Spring的過濾器沒有起作用嗎?也不是,如果沒起作用,那么我在Struts中的Action中通過request.getParmeter接收到參數應該是亂碼?而且我記得這種做法在Tomcat4.1.24中沒有任何問題,那是為什么?和倦兔討論了一下,我們都沒有找到答案。

      于是,我就通過google搜索"URIEncoding",找到一堆文章,我讀了幾篇文章,其中有一篇提到:Tomcat5中對PostGet請求不再采用相同的處理策略了,而在Tomcat4中采用的處理策略是相同的。于是我想:"我的提交的請求明明是Post,我又沒有用Get請求,那Spring的過濾器就應該起作用,為什么結果會這樣呢?",我的一個jsp中的Form的代碼如下:

    <html:form action="editGj" method="post" styleId="gjForm"
        focus="mc" onsubmit="return validateGjForm(this)">
    看,我的代碼明明是使用的是Post方法,為什么結果不正確呢?
      我的跳轉到下一頁的代碼是:
      <a href="?d-449687-p=2&mc=%D7%A8%D2%B5&;
                  excelname=%D7%A8%D2%B5%C3%FB%B3%C6.xls">下一頁</a>
      加粗的部分就是我的翻頁的鏈接。如果你立刻就看出了我的問題,那么你就可以不用往下看了,呵呵。如果你沒有看出問題,請繼續,Come On Baby!!!
      我采用的真的是Post方法嗎?我的form的提交采用的是Post方法,這是沒錯的,那么鏈接采用的是Post方法嗎?

      不是!!!!它采用的是Get方法進行提交的,這就是問題的答案了!
      Post和Get提交有什么區別嗎?

      簡單的說:Post是將地址傳送一次,將form的數據單獨提交,而Get則是將地址和參數一起傳送,傳送的不止是form的數據,但傳送的數據的長度有字節限制,另外還有安全問題。如果感興趣,你可以用google搜一下,會找到很多資料。

      當我想到這個區別時,我又檢查了一下我的顯示列表的頁面,發現這個頁面沒有form,只有,這說明我的提交的確是Get的,于是,Tomcat5對我的Get請求執行的是另外的處理方式,和Post的處理方式不再一樣了!
      Tomcat5對Get請求是怎么處理的?
      默認情況下,Tomcat對請求采用的默認編碼是ISO-8859-1,我們的JSP頁面上聲明的


     <meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
只在顯示漢字時有用,而且這2種寫法的作用在理論上應該時一致的,但是由于各個軟件廠商對Web標準都按照自己的理解進行了修改,所以,常常這2種寫法作用就不一致了,使我們在開發Web程序時備感混亂。如果你想了解詳情,請查看《網站重構》一書。

 

這樣我們提交的漢字被認為是ISO-8859-1的編碼,所以在程序中接收時顯示亂碼,如果使用過濾器,在過濾器中調用request.setCharacterEncoding("GBK")的話,那么Post上來的漢字將被認為是GBK編碼,而Tomcat5對于Get請求上來的編碼并不根據過濾器的設定辨認編碼方式,默認的依然是ISO-8859-1Tomcat5中處理Get請求的源代碼如下:

 tomcat5中處理Get請求的函數

      上面的代碼中,enc代表Tomcat5server.xmlConnector部分的URIEnocodeing項設定的值,可以看出,如果沒有設定URIEncoding項的話,那么Tomcat5也并沒有使用默認的ISO-8859-1編碼,而是一段fast conversion,所以,即使你的頁面使用默認的編碼方式進行編碼,然后使用ISO-8859-1進行解碼,得到的結果也不對,這可能是Tomcat5的一個Bug。如果想繞過這個Bug,那么只有在server.xmlConnector部分設定URIEncoding的值,根據編碼方式指定自己的值,在我的程序中我使用的是GBK,所以我修改后的部分如下:

    acceptCount="100"
    connectionTimeout="20000"
    disableUploadTimeout="true"
    port="80"
    redirectPort="8443"
    enableLookups="false"
    minSpareThreads="25"
    maxSpareThreads="75"
    maxThreads="150"
    maxPostSize="0"
    URIEncoding="GBK">

 

 

      這個問題我參考了這篇文章:

http://www.javaworld.com.tw/jute/post/view?age=0&bid=9&ppg=1&sty=1&id=44042&tpg=1

http://www.javaworld.com.tw/jute/post/view?age=0&bid=9&ppg=1&sty=1&id=44042&tpg=1

      另外,對于編碼解碼的問題,我還有一句要說,理論上,如果編碼的charset和解碼的charset是一致的話,那么就應該沒有亂碼的問題,但是,對于某些特殊的字符來說,如果采用的charset不對,則可能在解碼的時候不能顯示,所以要選擇好字符集,我推薦在處理簡體漢字的時候使用GBK。網上也有推薦UTF-8的,具體使用哪種依情況而定。

 

       以上是我的總結,若有錯誤,請指正,謝謝!

 

      明天,我就放假了,祝我的朋友們春節快樂,萬事勝意!

 

                                                                                   兔八哥

                                                           20052414:04

 
 

      另外,我昨晚看了看Tomcat5自帶的Servlet Example中過濾器的實現,其中就有關于處理編碼的過濾器SetCharacterEncodingFilter,還有另外一個是處理用戶輸入的過濾器,叫HTMLFilter,用于將用戶輸入的字符轉化為HTML格式的字符,如將">"轉換為">",這個過濾器稍加修改就可以用在自己的項目上了,呵呵!



笨笨 2005-03-09 00:41 發表評論
]]>
在AppFuse中集成ValueList的方法http://www.tkk7.com/kapok/archive/2005/03/09/1860.html笨笨笨笨Tue, 08 Mar 2005 16:29:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1860.htmlhttp://www.tkk7.com/kapok/comments/1860.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1860.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1860.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1860.html http://rabbit8.blogchina.com/blog/article_144619.1057775.html
在AppFuse中集成ValueList的方法
2005年 03月08日 怎樣在AppFuse中集成ValueList

1.在web.xml中添加,/WEB-INF/classes/standardJspApplicationContext.xml。
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext-*.xml,/WEB-INF/classes/standardJspApplicationContext.xml</param-value>
</context-param>
   
2.把valuelist.tld拷貝到WEB-INF下。
3.在taglibs.jsp中添加valuelist.tld。
4.將standardJspApplicationContext.xml、i18n.properties、microsoftLook.properties、simpleLook.properties、classicLook.properties文件復制到/WEB-INF/classes下。
5.在applicationContext-resources.xml的<beans></beans>中添加:
  <bean id="resourceI18nBundle" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename"><value>i18n</value></property>
  </bean>
  和
   
  <bean id="valueListHandler" singleton="true"
        class="net.mlw.vlh.DefaultValueListHandlerImpl">   
    <property name="config.adapters">
      <map>
     
        <entry key="userlist">
          <bean class="net.mlw.vlh.adapter.hibernate.Hibernate20Adapter">
            <property name="sessionFactory"><ref bean="sessionFactory"/></property>
            <property name="defaultNumberPerPage"><value>2</value></property>
            <property name="defaultSortColumn"><value>lastName</value></property>
            <property name="defaultSortDirection"><value>asc</value></property>
            <property name="hsql">
              <value>
                FROM org.appfuse.model.User AS vo
                /~name: WHERE vo.lastName LIKE {name} ~/
                /~sortColumn: ORDER BY vo.[sortColumn] [sortDirection]~/
              </value>
            </property>
          </bean>
        </entry>
       
        <!--entry key="players2">
          <bean class="net.mlw.vlh.adapter.hibernate.Hibernate20Adapter">
            <property name="sessionFactory"><ref bean="mySessionFactory"/></property>
            <property name="defaultNumberPerPage"><value>20</value></property>
            <property name="defaultSortColumn"><value>lastName</value></property>
            <property name="defaultSortDirection"><value>asc</value></property>
            <property name="namedQuery"><value>playerList</value></property>
          </bean>
        </entry-->
       
       
      </map>
    </property>
   
  </bean>
 
  上面配置中的"sessionFactory"為原來配置好的。
  "defaultNumberPerPage"為每頁顯示的記錄行數。
  "defaultSortColumn"排序列。
  "org.appfuse.model.User"為POJO的名字。
 
6.將相關的樣式表的內容合并到原有的樣式表中。
7.將valuelist.jar添加到類路徑下。

 


8:如果為行添加onclick事件,注意要對"&"進行轉義-document.location='editUser.html?username=<c:out value="${User.username}"/>\&from=list';:
<vlh:root value="valueList" configName="classicLook" url="?" includeParameters="*" >


<table width="600" border="0" cellspacing="0" cellpadding="0">
      <tr>
        <td align="left" nowrap="true">
          <c:out value="${list.valueListInfo.totalNumberOfEntries}"/> Total
          - Page (<c:out value="${list.valueListInfo.pagingPage}"/> of <c:out value="${list.valueListInfo.totalNumberOfPages}"/>)
          &nbsp;
        </td>
        <td align="right">
          <vlh:paging pages="5"><c:out value="${page}"/>&nbsp;</vlh:paging>
        </td>
      </tr>
      <tr>
        <td colspan="2">
          Export to: &nbsp;&nbsp;
    <vlh:filter url="example-export-format.jsp?format=excel&">
      <img src="images/export_excel.png" border="0"> Excel
    </vlh:filter>
    <vlh:filter url="example-export-format.jsp?format=csv&">
      <img src="images/export_csv.png" border="0"> CSV
    </vlh:filter>
   
    <table width="450" class="classicLook" cellspacing="0" cellpadding="0">
      <vlh:row bean="User">
 <vlh:attribute name="onclick">
   document.location='editUser.html?username=<c:out value="${User.username}"/>\&from=list';
        </vlh:attribute>

        <vlh:column title="username"   property="username"   sortable="desc" />
        <vlh:column title="firstName"   property="firstName"   sortable="desc" />
        <vlh:column title="lastname"   property="lastName"   sortable="desc" />
        <vlh:column title="email"     property="email"     sortable="desc" />
      </vlh:row>
    </table>
 </td>
      </tr>
    </table>
   
  </vlh:root>


======================================================================
為ValueList添加高亮
1.添加vlh:attribute:<vlh:attribute name="onmouseout">javascript:mouseout(this);</vlh:attribute>。
添加完attribute后的內容如下:

  <vlh:root value="list" url="?" includeParameters="*" >
    <vlh:retrieve name="nbaPlayers" />
   
    <table width="650" class="classicLook" cellspacing="0" cellpadding="0">
      <vlh:row bean="player">
        <vlh:attribute name="onmouseover">javascript:toggle(this);</vlh:attribute>
 <vlh:attribute name="onmouseout">javascript:mouseout(this);</vlh:attribute>
        <vlh:attribute name="id"><%=("player-"+playerRowNumber)%></vlh:attribute>
        <vlh:attribute name="align" value="center" />
       
        <vlh:column title="playerid"   property="playerid"   sortable="desc"/>
        <vlh:column title="teamname"   property="teamname"   sortable="desc" />
        <vlh:column title="firstname"  property="firstname"  sortable="desc">
          <vlh:attribute name="width" value="150"/>
        </vlh:column>
        <vlh:column title="lastname"   property="lastname"   sortable="desc" attributes="width='150'"/>
        <vlh:column title="status"     property="status"     sortable="desc" />
        <vlh:column title="pos"        property="pos"        sortable="desc" />
      </vlh:row>
    </table>
  </vlh:root>


2.添加js函數,添加完函數后的內容如下:
<script>
  var lastId;
  var lastStyle;
  var previousClass = null;
  function toggle(object)
  {
  if( lastId != undefined )
  {
  document.getElementById(lastId).className = lastStyle;
  }
  lastId = object.id;
  lastStyle = object.className;
  previousClass=this.className;
  object.className = "selected";
  }

  function mouseout(object){
   object.className = previousClass;
  }
</script>

 

 



笨笨 2005-03-09 00:29 發表評論
]]>
DT編譯成功了!!!http://www.tkk7.com/kapok/archive/2005/03/09/1858.html笨笨笨笨Tue, 08 Mar 2005 16:28:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1858.htmlhttp://www.tkk7.com/kapok/comments/1858.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1858.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1858.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1858.html DT編譯成功了!!! 2005年 03月01日

DT編譯成功了,Struts Menu從數據庫取數據組建菜單的試驗成功了......

這幾天又開始做技術實驗了,被折磨的有點情緒化,不過一切還算順利,多虧朋友們的幫忙!

昨晚在家讀DisplayTag的源代碼,發現DisplatyTag(以下簡稱DT)翻頁時候不是從緩存中讀取的數據,它又重新向數據庫發出請求,和我調試程序時發現的一樣,它的動作大致是這樣的:

      向數據庫發送請求,一次讀取所有數據的所有字段(我強調"所有"字段,并不是select *,而是讀取你的語句中指定的全部的字段,我強調的是相對于lazy-load方式的部分讀取),然后根據pagesize(一頁顯示數據的行數)和當前頁號讀取數據的子集,當翻到其他頁時,又獲取所有數據的所有字段,再過濾出顯示的子集......,這樣的效率不是差,而是很差,我昨天看了一下DT的JIRA的文字,發現這個問題早在2004年的5月份就有人提出了,而那個人就是ValueList的作者,而且你還會發現很多開發者提供的改進方案和參考實現,而且DT的開發組也同意添加提高分頁效率的特性,但到現在也還沒有實現,有些讓人失望!據說ValueList對這方面做的很好,但ValueList的文檔太少了,而且集成到AppFuse中還要自己改寫模板,目前有些騎虎難下,明天開始折騰ValueList,希望一切順利,菩薩保佑,呵呵

      今天試了一下從數據庫中讀取數據來生成Struts Menu的菜單,結果發現如果一頁中放入2個Struts Menu的菜單,則會有一個有問題,我看了一下源碼,發現是在一個js文件中的函數引起的,Struts Menu首先初始化菜單,然后擴展,在擴展的時候,把點擊的菜單寫到Cookies中,如果同一個頁面有2個的聲明,則第二個菜單的折疊的部分不能展開,我的一個同事折騰了將近一周,就是因為這個問題。

      昨晚終于在倦兔的幫助下,使用Maven編譯DT成功了,這樣我可以放心的修改DT,然后編譯、打包。但我要權衡一下和改用ValueList的工作量,目前暫不打算修改DT了。

      Maven把所有下載的jar文件放在Window的Documents and Settings/你的用戶名/.mave目錄下,你可以把其他人的這個目錄下的文件都拷貝過來(注意要保持原來的目錄結構)直接用就行了。

      Matt Raible關于DT、ValueList、DataGrid的簡短介紹:http://raibledesigns.com/comments/rd/sunsets/there_s_a_new_sorting

                                                                                                               兔八哥

                                                                                                       2005-3-1 18:21

 



笨笨 2005-03-09 00:28 發表評論
]]>
ValueList的實驗做完了,但是……http://www.tkk7.com/kapok/archive/2005/03/09/1859.html笨笨笨笨Tue, 08 Mar 2005 16:28:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1859.htmlhttp://www.tkk7.com/kapok/comments/1859.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1859.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1859.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1859.html ValueList的實驗做完了,但是…… 2005年 03月07日

今天,同事終于把ValueList的實驗做完了,ValueList0.1.7新添了許多新功能,但是,今天看到"王者之劍"的留言,又讀了一下源碼,發現ValueList也是取回數據庫的全部數據,只是把需要返回頁面的數據返回了,并不是我想的使用Hibernate的分頁方法進行查詢數據庫的

    今天,同事終于把ValueList的實驗做完了,ValueList0.1.7新添了許多新功能,但是,今天看到"王者之劍"在我的Blog上的留言,有點不太相信ValueList也是取回所有的數據。
   
    剛才,我抽空看了一下ValueList的Hibernate20Adapter的源碼,結果發現果然是把所有的數據都取回來了,但比DT稍強一些的是,它沒有把所有的Object都放入request中,只是把當前頁要顯示的Object放入了,但這樣也同樣耗費數據庫資源,同樣需要循環,不同的是,耗費的網絡資源少些,因為,它傳回的對象只有一頁的對象。

    但結果并不是我想像的,我以為,它會自己像Hibernate那樣,根據不同的數據庫采用分頁算法,使用Criteria Query設定返回在指定范圍的數據。
實驗結果有點讓我失望,但畢竟比DT要強一些,不知道DT的1.1是不是也是這樣解決的,如果是的話,那不用等它的正式版本了,在JIRA上已經有參考實現了。

    但學習ValueList還是有所收獲的,看到了另一種顯示實現的方式,而且ValueList的確比DT強,界面雖然不漂亮(0.1.7已經很有DT的意思了,通過自己定制樣式表,可以作出漂亮的外觀),但比較靈活,這個工具值得繼續關注。
   
    使用ValueList需要注意的一點是,如果使用MVC框架(不知道其他的框架是否這樣),從一個Controller轉發到一個View上,如果ValueList的URL屬性為""或者"?",翻頁圖標的URL為上一個操作的URL,這和ValueList中提到的刷新按鈕有點相似,我又看了一下DT的用法,也需要指定URL,對于解決重復提交的問題,可以使用Struts的token來解決,我問了一下倦兔,倦兔說WebWork和Spring都有類似的解決方案,在此也感謝倦兔推薦ValueList!^_^

    剛才和天天加班的段兄(SkyHero)聊了一下,感覺實在不行要自己改代碼了,比較郁悶(本來想偷懶的,呵呵。
祝段兄的加班生活早點結束,你的女朋友還在茫茫人海中等你去找她,不要把大好時光都浪費在計算機上!^_^

    昨天,和朋友開車去天津,在濱江路上轉了一天,我在94年取過一次,發現十年后再看天津已經不是以前的那個城市了,看來是我的看法變了!不過昨天天津的氣溫有15度,很是舒服,好久沒有這樣放松了,希望每隔2個月,能出去轉轉!

 

                                                                                                                                   兔八哥

                                                                                                                             2005-3-7 19:38



笨笨 2005-03-09 00:28 發表評論
]]>
AppFuse最新版本的幫助http://www.tkk7.com/kapok/archive/2005/03/09/1857.html笨笨笨笨Tue, 08 Mar 2005 16:27:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1857.htmlhttp://www.tkk7.com/kapok/comments/1857.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1857.html#Feedback1http://www.tkk7.com/kapok/comments/commentRss/1857.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1857.htmlhttp://rabbit8.blogchina.com/blog/article_144619.988706.html


http://blog.blogchina.com/upload/2005-02-28/20050228111036159066.rar

笨笨 2005-03-09 00:27 發表評論
]]>
URLEncode的問題解決了http://www.tkk7.com/kapok/archive/2005/03/09/1856.html笨笨笨笨Tue, 08 Mar 2005 16:19:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1856.htmlhttp://www.tkk7.com/kapok/comments/1856.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1856.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1856.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1856.html http://rabbit8.blogchina.com/blog/article_144619.790247.html
URLEncode的問題解決了
2005年 02月02日 URLEncode的問題解決了,倦兔的解決方法竟然如此簡單!!!

和倦兔聊了一下,他告訴我的解決方法竟然如此簡單:在Tomcat的server.xml的Connector部分添加URIEncoding="GBK",我的server.xml添加后內容如下:

<Connector  URIEncoding="GBK" port="8080"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               debug="0" connectionTimeout="20000"
               disableUploadTimeout="true" />

 

不用讀DisplayTag的源碼了,也可以安心過個年了,謝謝倦兔!!!



笨笨 2005-03-09 00:19 發表評論
]]>
Java中的URLEncoder和URLDecoder類 http://www.tkk7.com/kapok/archive/2005/03/09/1855.html笨笨笨笨Tue, 08 Mar 2005 16:18:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1855.htmlhttp://www.tkk7.com/kapok/comments/1855.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1855.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1855.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1855.html http://rabbit8.blogchina.com/blog/article_144619.789425.html
Java中的URLEncoder和URLDecoder類
2005年 02月02日 為了解決DisplayTag的問題,可能要使用這2個類了,本篇繼續分析URL編碼的問題

以下內容是我翻譯的JDK的幫助。

URLEncoder類:

用于HTML的form中數據編碼的類。

這個類包含將字符串轉換為application/x-www-form-urlencoded MIME 格式的靜態方法.

如果想了解HTML的編碼細則,請參考HTML規范。

編碼規則如下:

字符"a"-"z","A"-"Z","0"-"9",".","-","*",和"_" 都不被編碼,維持原值,

空格" "被轉換為加號"+"。

所有其他的字符都被認為是不安全的,首先都根據指定的編碼scheme被轉換為1個或者多個字節。[憑什么認為其他的字符都是不安全的?看來這些規范的制訂者中沒有中國人呀!]

然后每個字節都被表示成"%xy"格式的由3個字符組成的字符串,xy是字節的2位16進制的表達(xy is the two-digit hexadecimal representation of the byte),推薦的編碼scheme為UTF-8,然而,出于兼容性的考慮,如果沒有制定編碼的scheme,那么將使用當前操作系統的編碼的scheme。

如:如果編碼scheme是UTF-8,

"The string ü@foo-bar"將被轉換為"The+string+%C3%BC%40foo-bar" 。

因為載UTF-8中字符ü被編碼成2個字節C3 (十六進制) 和BC (十六進制), 字符@被編碼成一個字節40 (十六進制)。

起始于:JDK1.0

 

這個類共有2個重載方法:

public static String encode(String s,  String enc)  throws UnsupportedEncodingException。起始于:JDK1.4

和即將被廢棄的方法:public static String encode(String s)。(因為這個方法的編碼的字符集依賴于程序運行的系統的默認的字符集)。

第一個方法的作用是:根據指定的encode scheme 將一個字符串翻譯成application/x-www-form-urlencoded格式。

注意: W3C推薦UTF-8。

參數:

s - 將要被翻譯的字符串。

enc - 編碼用的character。

 返回:翻譯后的字符串。

拋出異常: UnsupportedEncodingException - 如果不支持制定的編碼

起始于:1.4

另請參考:URLDecoder.decode(java.lang.String, java.lang.String)

 

類URLDecoder的作用和URLEncoder的作用相反,方法類似,這里就不再贅述了。

      如果你想知道你的字符串被編碼后的值是什么樣,你可以打開www.baidu.com,然后輸入你要編碼后的數值,然后提交,你可以在地址欄看到你被編碼后的字符串,這個方法是Jason告訴我的,呵呵!

如果想解決DisplayTag的問題,就要修改源代碼了,下一步就是讀源代碼,頭疼ing......

 

                                                                                                           兔八哥

                                                                                                   2005-2-2下午16:30

ltf_ty 于16 : 01 發表 已被瀏覽249次 評論(3) / 引用(0) 加入博采中心     [回復]
   

在百度提交:The string ü@foo-bar
并不是您說的結果.

    匿名網友 | 2005年 02月05日 16 : 58


     回復 [回復]
   

請看:http://rabbit8.blogchina.com/blog/article_144619.859489.html

    兔八哥 | 2005年 02月16日 08 : 51


     [回復]
   

不錯不錯,附上實現代碼
static String HEX_DIGITS =  "0123456789ABCDEF";
   protected static String urlEncode( byte[] rs )
   {
       StringBuffer result = new StringBuffer();

       // Does the URLEncoding.  We could use the java.net one, but
       // it does not eat byte[]s.

       for( int i = 0; i < rs.length; i++ )
       {
           char c = (char) rs[i];

           switch( c )
           {
             case '_':
             case '.':
             case '*':
             case '-':
               result.append( c );
               break;

             case ' ':
               result.append( '+' );
               break;

             default:
               if( (c >= 'a' && c <= 'z') ││
                   (c >= 'A' && c <= 'Z') ││
                   (c >= '0' && c <= '9') )
               {                    
                   result.append( c );
               }
               else
               {
                   result.append( '%' );
                   result.append( HEX_DIGITS.charAt( (c & 0xF0) >> 4 ) );
                   result.append( HEX_DIGITS.charAt( c & 0x0F ) );
               }
           }

       } // for

       return result.toString();
   }



笨笨 2005-03-09 00:18 發表評論
]]>
關于DisplayTag:新的郁悶開始了……http://www.tkk7.com/kapok/archive/2005/03/09/1854.html笨笨笨笨Tue, 08 Mar 2005 16:17:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1854.htmlhttp://www.tkk7.com/kapok/comments/1854.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1854.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1854.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1854.html http://rabbit8.blogchina.com/blog/article_144619.789350.html
關于DisplayTag:新的郁悶開始了……
2005年 02月02日 DisplayTag的默認的URL為上一次的URL,而上一次的URL中包含被編碼后的漢字,所以,將編碼后的漢字再次進行編碼,肯定查不到結果,所以也不能翻頁,看來要修改DisplayTag了,本來想年后再弄的......

DisplayTag的默認的URL默認為上一次的URL,如果上一次的URL包含中文的話,則會被進行URLEncode,所以在翻頁的時候,又會把進行了URLEncode后的數據再次進行URLEncode,所以翻頁就沒有數據,因為這部分功能被封裝在DisplayTag中,于是,我又開始郁悶了......

如漢字"專業"被編碼后為"%D7%A8%D2%B5",于是DisplayTag就將這個編碼作為連接的關鍵字,如果再次提交,則這個編碼還會被編碼,所以查詢結果一定就不對了!!!

下面的內容是我分析這個問題的由來:

---------------------------------------------------------------------------------------------------

剛才到網上查找了些資料,找到HTML4.0.1的規范中關于URLEncode的部分,我把我關心的內容翻譯了一下:

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1

其中相關內容如下在17.13.3 Processing form data

提交時,HTML的規范處理如下:

1.標識successful controls (概念可以在上文中查找)。

2.構建form的數據集。

3.根據form的enctype的設置,對form的數據集進行Encode。

4.提交已經Encode的數據集。

 

HTML規范中指出Content type和Languange code是不區分大小寫的。

詳情參見:http://www.w3.org/TR/html401/types.html#type-content-type

"&" 表示"&"。關于charset的詳細內容見:http://www.w3.org/TR/html401/charset.html#entities

 

有一個小發現:Frame中的target的值的列表原來是在HTML的規范中制定的,呵呵:

http://www.w3.org/TR/html401/types.html#type-content-type
6.16 Frame target names

下面的target的名字是規范中聲明的有特殊含義的保留字。

_blank  在一個沒有指定名字的新窗口中打開頁面。(new, unnamed window)

_self  在同一個窗口中打開。(load the document in the same frame as the element that refers to this target)

_parent  在當前窗口的父窗口中打開,如果當前窗口沒有父窗口,那么就等同于_self

_top  在最開始的窗口中轉載,如果當前框架沒有parent,那就等于_self

 

關鍵部分在這里了:http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1

form的默認的content type是:application/x-www-form-urlencoded

form提交content type的數據必須用下列規則進行編碼(encode):

空格被封裝為"+",其他的保留字封裝后的值在 [RFC1738]中可以查到。RF1738的規范:http://www.ietf.org/rfc/rfc1738.txt

其他的非英文字符和非數字的字符都被編碼為"%HH",

HH是將字符的ASCII的編碼轉換為16進制后的字符。行尾是"CR LF"  (如:`%0D%0A')。

控件的名字和數值之間使用"="分隔,多個控件之間用"&"分隔。

------------------------------------------------------------------------------------------------------------------

                                                                                                    兔八哥

                                                                                                2005-2-2下午

 



笨笨 2005-03-09 00:17 發表評論
]]>
記事貼2:Struts的Validator并不好用!http://www.tkk7.com/kapok/archive/2005/03/09/1853.html笨笨笨笨Tue, 08 Mar 2005 16:16:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/09/1853.htmlhttp://www.tkk7.com/kapok/comments/1853.htmlhttp://www.tkk7.com/kapok/archive/2005/03/09/1853.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1853.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1853.html http://rabbit8.blogchina.com/blog/article_144619.782661.html
記事貼2:Struts的Validator并不好用!
2005年 02月01日 使用正則表達式,使email字段中不能輸入漢字。最近用AppFuse開發一個BS的系統,用的是Struts的MVC部分,使用Validator進行驗證,結果發現Validator的驗證EMail并不好,EMail中可以輸入漢字,然后到服務器端驗證,我配置了客戶端驗證,也可以驗證Email的格式,但如果輸入的是正確的格式,但是包含漢字它卻驗證不出來,但到了后臺又管用了,不知道為什么,時間緊,我也沒時間去研究它,找到一個方法可以解決這個問題,雖不完美,卻也湊合:

使用正則表達式,將原代碼
            <html:text property="email" styleId="email" size="50"/>
注釋,換成

            <input type="text" name="email" value='<c:out value="${userForm.email}"/>' onkeyup="value=value.replace(/[\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[\u4E00-\u9FA5]/g,''))"
 />
就解決了問題,用戶如果輸入漢字,則自動刪除漢字,而且如果使用向左的箭頭向前移動使光標前移,則根本移動不了,光標始終在行尾,只能刪除后面的字符,再重新寫,其實最好是在EMail的自動生成的腳本中提示,目前先這樣實現吧,將來再說!

笨笨 2005-03-09 00:16 發表評論
]]>
使用AppFuse進行開發的總結http://www.tkk7.com/kapok/archive/2005/03/08/1852.html笨笨笨笨Tue, 08 Mar 2005 15:53:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/08/1852.htmlhttp://www.tkk7.com/kapok/comments/1852.htmlhttp://www.tkk7.com/kapok/archive/2005/03/08/1852.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1852.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1852.html使用AppFuse進行開發的總結
http://rabbit8.blogchina.com/blog/article_144619.796348.html

AppFuse是一個集成了當前最流行的Web應用框架的一個更高層次的Web開發框架,也可以說是一個Web開發基礎平臺,它與之所集成的各種框架相比,它提供了一部分所有Web系統開發過程中都需要開發的一些功能,如登陸、用戶密碼加密,用戶管理、更具不同的用戶可以展現不同的菜單,可以自動生成40-60%左右的代碼,自帶了默認的一些在CSS中設定的樣式,使用這些樣式能很快的改變整個系統的外觀,還有自動化測試的功能。

      它最大的價值就是為我們提供了一個Web開發的新的方式和思路,盡管這些技術在國外都已進很流行了,但在國內能夠將HibernateStrutsSpringDBUnitAntLog4JStruts MenuXdocletSiteMeshVelocityJUnitJSTLWebWork這些技術集成到一個框架中的還不多見,所以即使不使用它的全部功能,它也給我們提供了一個很好的借鑒、學習的機會。

      AppFuse的作者 matt raible是當今開源世界一個比較活躍的開發者,它是AppFuse、Struts Menu的作者,也是XDoclet、DisplayTag等一些著名開源項目的積極參與者,《Hibernate In Action》的作者就在感謝的名單里面提到他,XDoclet的下載版本中所帶的Hibernate標簽部分的例子就是他寫的,他還是2004年Apache技術年會的主講人之一。(這些都是我這2個多月來搜集到的,呵呵)

 

       通過關注AppFuse,我們可以看到目前國外的主流開發都使用了哪些技術,開發方式是什么樣的,可能達到什么樣的結果,而在以前,是很少能夠看到這樣完整的例子的。

       AppFuse的另一個啟示是:我們可以依靠開源軟件的功能降低開發成本,而且可以閱讀開源軟件的代碼提高所在團隊的整體實力。

      

       但是通過2個月的實際學習和使用,我也遇到一系列的問題,因為AppFuse是將其他的一些類庫或者框架集成在一起的,集成的技術眾多,而且有一些技術在國內甚至很少有人知道,資料也比較少,所以雖然作者經過了一些測試,但都是基于英文編碼的,而對于中文編碼來說,還潛在的存在著一些問題,雖然不是AppFuse的問題,但卻降低了開發速度,下面是我在開發過程中遇到過的問題,有些解決了,有些還沒有解決:

一.Struts

1.  AppFuse中默認的MVC框架是Struts,而且使用的是LookupDispatchAction,并且使用的是按鈕(button),在XP下用IE瀏覽效果還可以,但如果在2000或者98下,就使外觀很難看,而且當時我還遇到一個問題:如果按鈕顯示中文,則在DisplayTag中翻頁失靈,而且報錯,后來我把BaseAction的相關方法改變了,才可以使用,因為國內的客戶都比較重視界面,所以后來我將那些按鈕都改成圖片了,當然也要添加一些方法了,有點麻煩!

2.  Struts中的標簽如今推薦使用的只有html部分的標簽了,其他的標簽或者可以使用JSTL替代,或者已經不推薦使用了,而且AppFuse中推薦使用JSTL,而JSTLstruts的標簽的聯合使用時,需要的不是標簽<html:標簽>,而是標簽<html-el:標簽>,這個問題曾經困擾了我整整2天。

3.  StrutsValidation的校驗規則并不完善,比如如果使用客戶端的javascript校驗,則在郵箱中輸入漢字根本校驗不出來,到了服務器端報錯。

4.  最嚴重的問題是AppFuse生成的Strutsvalidation.xml文件中有許多多余的".",如果你去掉了,常常在執行antdeploy任務時又恢復原樣。這樣是提交表單的時候經常會報javascript的腳本錯誤或者缺少對象或者缺少value,所以我會手工的修改這個文件,然后把修改后的文件備份,當重新生成有錯誤的文件時,我會用備份的沒有錯誤的文件去覆蓋。

5.  Strutsvalidatioin對于使用同一個FormBeanAction的校驗方式比較復雜。(待解決)。

二.Hibernate

1.  Hibernate是現在受到越來越多的人推崇的一個ORM工具(框架、類庫),它將我們從繁瑣的使用JDBC的開發過程中解放出來,但同時也帶來了新的問題,如學習曲線,執行效率,數據庫設計優化,還有最重要的靈活性。Hibernate不是一個很容易上手的東西,要完全駕馭它還需要讀很多資料,但好的資料卻很少。

2.  使用Xdoclet可以很方便的生成Hibernate中的持久類的配置文件(*.hbm.xml,但對一些特殊的映射卻無能為力,如使用序列的id生成規則,序列的名字沒有地方寫,所以也只好先利用它生成主要的內容,然后手工修改。

3.  同樣還是id的生成策略問題,如果使用序列、hilo等需要一些數據庫機制支持的策略時,schemaExport并不能自動生成序列或者保存當前id的表,這項工作仍然要手工解決。

4.  Hibernate中提供了幾種關聯,一對一、一對多、多對多,但對于怎樣調整效率卻沒有一個很明確的提示,還要根據情況判定,這就帶來和一些彈性的設計。

5.  Hibernate中可以選擇的操作數據庫的方式有3種,其中HQL功能最強大,但有些功能使用標準查詢可能會更方便,但會有一些限制,所以雖然它很靈活,但易用性不如JDBC好。

三.Spring

       AppFuse的過程中,Spring完全隱藏在幕后,除了一些配置外,幾乎感覺不到它的存在,所以我在使用它的過程中并沒有遇到什么麻煩,這里只是簡單的介紹一下它在AppFuse中起到的作用。

1.  SpringAppFuse中起到的主要作用是對HibernateSession和事務的管理,利用Spring封裝的Hibernate模板類,我們大大地減少了實現DAO的代碼行數。

2.  Spring還起到了連接映射文件和類之間的關聯,及接口和實現類之間的關聯,這些都依賴于SpringIoC的機制的實現。

3.  對于字符進行編碼和解碼部分用到了Spring自帶的Filter,只需要在配置文件中配置就好了。

 

四.SiteMesh

SiteMesh是一個基于Decorator模式的技術,它可以修飾返回的網頁文件,它的工作方式受到越來越多的人的推崇,這點從Manning出版的一些技術書籍中可以看出來。

我在使用SiteMesh的過程中并不順利,我參考了《Java Open Source Programming》,這本書中說SiteMesh在默認的情況下不對下載文件進行裝飾,但我在下載文件時發現,我的文件內容被丟棄了,取而代之的是SiteMesh的模板的內容,后來我通過修改SiteMesh的配置文件解決了這個問題,但感覺還有一些不太清楚的地方需要學習。

 

五.DisplayTag

       DisplayTag是一個優秀的顯示內容的標簽,從SourceForge的訪問量來看,它是很活躍的項目,僅次于AntHibernateXdoclet等幾個著名的項目,我總結,它的主要功能有4項:顯示、分頁、排序、將顯示的數據寫入指定類型的文件中,然后下載。

1.  據我使用的情況看,我只使用了分頁和顯示的功能,因為當時我沒有很好的解決中文編碼的問題,所以排序會有問題,直到昨天,我在朋友的幫助下解決了這個問題,至此我可以放心使用的功能又增加了排序(我昨天簡單的測試了一下是可以的)

 

2.  但對于將顯示的內容生成到一個指定格式的文件中的功能卻有著很多缺陷,如:

(1)       生成的文件中只有顯示的數據,那些沒有顯示在界面上的的數據,則不會被寫到文件中。

(2)       如果修改了DisplayTag的顯示的內容,比如添加一列,在這列中的內容不是字符,而是HTML的標簽,則生成的文件只有這些HTML標簽,而沒有數據。

(3)       即使DisplayTag中沒有我們定制的HTML腳本,生成的文件偶爾也有問題,比如:它會把"007"生成為"7",把字符串自動的轉換為整型值。有時候還生成空白內容的文件。

(4)       DisplayTag生成的Excel文件兼容性不好,有時在Excel2003中不能正常打開,或者在XP下打開報錯。

      后來,我看了作者寫的《Spring Live》,書中說如果想實現穩定的Excel,推薦使用POI,于是我使用POI生成Excel,穩定性和兼容性都不錯。

六.DBUnit

       DBUnit是一個可以被Ant集成的向數據庫中添加數據和備份數據的一個類庫,配置很方便,因為AppFuse已經集成好了,所以使用也很容易。

       但是如果你使用EditPlus之類的工具手工修改了AppFuse生成的內容,則執行Antsetupsetup-db或者deploy的任務時,常常報錯,說無效的格式,這是因為這個被手工修改的文件再次被AppFuse執行后,它的第一行的文件聲明的前幾個字母是無效的,是因為本地的字符集編碼的原因而引起了亂碼,如果把這幾個無效的字母去掉,問題就解決了。

 

七.Struts Menu

       Struts Menu也是AppFuse的作者開發的一個開源軟件,它可以根據配置文件讀取當前用戶可以使用的功能菜單,這個功能是我一直以來都想要的,我也找到了一些代碼,但實現的都不如這個完善,沒什么好說的,使用簡單,配置容易,很好的解決了我的問題。

       問題是我只使用了AppFuse提供的2個角色,對于多個角色的實驗我還沒有做。

 

八.XDoclet

       AppFuse中,使用Xdoclet生成了幾乎一切的配置文件:Struts-config.xmlweb.xmlvalidation.xml*.hbm.xml等文件,如果使用AppGen的話,還會生成更多的文件,這一切都是使用Xdoclet實現的。

       問題是我在Struts部分提到的,生成的Validation.xml文件中會多生成一個".",另外在生成資源文件時也會多生成一個".",目前我沒有很好的閱讀這段代碼,不知道是不是Xdoclet的問題。

 

九.Ant

       Ant并沒有什么問題,但在執行作者寫的Ant任務的時候,有一些任務不能正常執行,比如,運行模擬對象測試的任務,作者也在1.7版本的修復列表中提到以前版本有些ant任務不能執行,在1.7中修改了一些ant任務,使他們能夠正常的執行了。

       實際上,我們如果使用AppGen進行開發的話,使用的任務一般不超過8個。

 

十.JSTL

       JSTL是個好東西,我常用的有部分的標簽,但是如果使用JSTL進行邏輯判斷,我并沒有感覺比使用JSP的代碼塊優雅多少。另外,熟悉JSTL也需要一段時間,我就經歷了面對著JSP頁面不知道該怎么寫JSTL語法的困境。當然,AppFuse中使用的基本都是JSTL,包括向DisplayTag傳遞顯示的數據,使用的都是JSTL語法,這方面的資料挺多,我參考的是電子工業出版社出的《JSP2.0技術》,說的很詳細。

 

十一.Tomcat

       你也許會說:"Tomcat就不用說了吧?",是的,Tomcat一般都會使用,但是―――――――――――――Tomcat5Tomcat4.X對于中文編碼使用了不同的機制,這個問題困擾了我好久,我解決了頁面上寫入漢字顯示亂碼的問題,我也曾經以為DisplayTag對漢字不能排序,也不能正常分頁是因為DisplayTag的開發者都是老外,是因為他們沒有考慮中文的關系的原因。

      直到昨天,我才知道這一切都是因為Tomcat5對漢字編碼的實現的方式和Tomcat4不一樣的原因,如果感興趣,可以看看這個帖子:http://www.javaworld.com.tw/jute/post/view?bid=9&id=44042&sty=1&tpg=1&age=0

      再次感謝倦兔!:D

 

十二.JavaScript

       JavaScript簡單易學,但想運用自如就不太容易了。AppFuse中嵌入了幾個js文件,里面包含了許多函數,值得我們好好的研究一下,比如,如果有一個必填字段沒有填寫,AppFuse會自動的聚焦在那個input上,類似的小技巧有很多,你可以自己去翻看。

       AppFuse自帶的JavaScript腳本有一個Bug,就是當DisplatyTag中沒有可以顯示的數據時,你用鼠標單擊,它會報JavaScript錯誤,你仔細研究一下function highlightTableRows(tableId) 就知道了:我的解決辦法是在location.href = link.getAttribute("href");前面添加一行判斷:if (link != null)。
 

十三.資源文件國際化

       對于StrutsDisplayTag都涉及到資源文件國際化AppFuse1.6.1很好的解決了Struts資源映射文件國際化的問題,你只需要在對應本國語言的資源文件中寫入漢字,Ant中有一項執行native2ascii的任務,AppFuse自動的為你進行了資源文件的編碼轉換,而對于DisplayTag的資源文件問題,還要自己執行native2ascii命令,為了避免每次都輸入一串命令,我用Delphi寫了個小工具,可視化的選擇資源文件,點擊按鈕自動執行該命令,底層依賴于JDK

 
 

經過2個多月的學習,我感覺這個框架非常不錯,它為我以后的項目開發指出了一個新的方向,但如果想很熟練的使用這個框架進行開發,至少要對以下幾種技術比較熟練:Struts(或者WebWorkSpring及其他的已經整合進來的MVC框架)Hibernate(或者ibatis)、JSTL,當然其他的技術至少也要知道一點,否則遇到問題都不知道出在哪里。

 
 

       目前我還沒有解決的問題有:

1.  如何在翻頁的時候才讀取下面的數據?

2.  怎樣對使用同一個FormBean的多個Form進行客戶端校驗?

3.  怎樣優化Hibernate的效率?《Hibernate In Action》中提供了多種策略,有些時候應該使用lazy,有些時候應該使用outer-join

4.  在什么時機生成導出文件?目前我是在查詢的Action中同時生成了導出文件,否則,到了下一頁,我就不知道查詢條件了,當然,如果把拼裝后的HQL存儲在Session或者Hidden中也可以解決這個問題,但是這樣就破壞了DAO的封裝,要把DAO封裝后的HQL發送給Action,然后發送的到Web界面層,所以目前我還在猶豫生成導出文件的時機選擇在哪里?

5.  什么時候應該自己獲取數據庫連接,執行native SQL?具體需要注意些什么?

6.  SiteMesh的模板優化?

7.  DisplayTag的底層實現?

 
 

每個問題都比較棘手,要一個一個解決!   

 

       這個框架的優點是:如果熟悉了開發流程,可以大幅度的提高開發速度,如果業務不是很復雜,使用AppGen可以生成60%左右的代碼,而且程序可維護性好,因為作者使用了多個設計模式對各個層面進行了封裝,所以不同的模塊代碼風格出奇的一致,有利于開發人員快速上手,有利于接收其他開發人員遺留的代碼。

 

兔八哥





native2ascii在Ant中有任務,可以寫        
<target name="makeresource">
          <delete file="${resource.dir}/ApplicationResources_zh_CN.properties"/>
          <native2ascii src="${resource.dir}" dest="${resource.dir}" includes="ApplicationResources_cn.properties" encoding="GBK">
             <mapper refid="resourcemapper"/>
<mapper id="resourcemapper" type="glob" from="*_cn.properties" to="*_zh_CN.properties"/>
          </native2ascii>
       </target>

                                                        



笨笨 2005-03-08 23:53 發表評論
]]>
從AppFuse開始 http://www.tkk7.com/kapok/archive/2005/03/08/1851.html笨笨笨笨Tue, 08 Mar 2005 15:46:00 GMThttp://www.tkk7.com/kapok/archive/2005/03/08/1851.htmlhttp://www.tkk7.com/kapok/comments/1851.htmlhttp://www.tkk7.com/kapok/archive/2005/03/08/1851.html#Feedback0http://www.tkk7.com/kapok/comments/commentRss/1851.htmlhttp://www.tkk7.com/kapok/services/trackbacks/1851.htmlhttp://blog.csdn.net/flydreamgy/archive/2004/12/13/214931.aspx

從AppFuse開始

很早以前接觸過AppFuse,一直沒有什么興趣,今天在csdn上看到了新聞,就花了時間到官方網站出看了一下.呵呵,版本改進很快.包涵的東西越來越多了,很好的把眾多的OpenSource結合在了一起,從明天開始花時間詳細全面的學習一下.不停的學習才是進步.哈哈
這是官方的介紹.
AppFuse is an application for "kickstarting" webapp development. Download, extract and execute ant new -Dapp.name=yourApp -Ddb.name=database to instantly be up and running with a Tomcat/MySQL app. Uses Ant, XDoclet, Spring, Hibernate (or iBATIS), JUnit, Cactus, StrutsTestCase, Canoo's WebTest, Struts Menu, Display Tag Library, OSCache, JSTL and Struts (or Spring MVC). The Spring Framework has greatly enhanced AppFuse since February 2004. It's used throughout for its Hibernate/iBATIS support, declarative transactions, dependency binding and layer decoupling. This clean and simple framework has greatly reduced the complexity of AppFuse, and also eliminated many lines of code. In short, for J2EE - it's the best thing since sliced bread.

Features include Container Managed Authentication (CMA), Remember Me, Self Registration, Password Hint and GZip Compression. The fuse to start your apps.

作者的介紹:
http://today.java.net/pub/a/today/2004/07/15/thefuse.html
官方網站:
http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse
http://appfuse.dev.java.net/
http://jroller.com/page/raible



笨笨 2005-03-08 23:46 發表評論
]]>
主站蜘蛛池模板: 久久久久国色av免费看| 免费一级全黄少妇性色生活片 | 国色精品va在线观看免费视频| a毛片免费在线观看| 亚洲高清不卡视频| 亚洲www在线观看| 国产亚洲情侣久久精品| 中文字幕不卡高清免费| 1a级毛片免费观看| 在线免费观看国产视频| 亚洲婷婷五月综合狠狠爱| 亚洲成aⅴ人片在线观| 欧美亚洲精品一区二区| 国内精品免费久久影院| 思思re热免费精品视频66| 免费国产a国产片高清| 久久精品国产亚洲| 亚洲欧洲av综合色无码| 久久精品国产亚洲αv忘忧草| WWW亚洲色大成网络.COM| 成人电影在线免费观看| 猫咪社区免费资源在线观看| 国产精品亚洲二区在线观看| 亚洲理论精品午夜电影| 日韩电影免费在线观看网址| 美丽的姑娘免费观看在线播放| 亚洲成AV人网址| 亚洲国产精品日韩在线| 九九免费久久这里有精品23| 国产精品视频免费| 2048亚洲精品国产| 最新国产成人亚洲精品影院| 国产一二三四区乱码免费| 免费国产黄线在线观看| 亚洲成AV人片在线观看| 九九精品国产亚洲AV日韩| 99久9在线|免费| 亚洲日韩涩涩成人午夜私人影院| 亚洲一级毛片中文字幕| 特级做A爰片毛片免费看无码 | 一个人看的www视频免费在线观看 一个人看的免费观看日本视频www |