欧美一区电影,日韩精品亚洲视频,精品视频一区二区三区http://www2.blogjava.net/kapok/category/696.html垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!zh-cnWed, 28 Feb 2007 03:21:05 GMTWed, 28 Feb 2007 03:21:05 GMT60為大型項(xiàng)目提供的 Ant 1.6 新特性http://www.aygfsteel.com/kapok/archive/2005/06/14/6106.html笨笨笨笨Tue, 14 Jun 2005 04:22:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/06/14/6106.htmlhttp://www.aygfsteel.com/kapok/comments/6106.htmlhttp://www.aygfsteel.com/kapok/archive/2005/06/14/6106.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/6106.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/6106.htmlhttp://www.oracle.com/technology/global/cn/pub/articles/bodewig_ant1.6.html

為大型項(xiàng)目提供的 Ant 1.6 新特性

作者:Stefan Bodewig

了解 Ant 1.6 的新特性以及它們?nèi)绾斡绊懩M織編譯過(guò)程的方式。

雖然 Ant 版本的 1.5.x 系列在任務(wù)級(jí)方面有很大的改善,但它沒(méi)有改變?nèi)藗兪褂?Ant 的方式。而 Ant 1.6 卻有所不同。它增加了幾個(gè)新特性,以支持大型或非常復(fù)雜的編譯情況。但是,要充分利用它們的功能,用戶可能需要稍微調(diào)整它們的編譯過(guò)程。

本文重點(diǎn)介紹了其中的三種新特性 — <macrodef>、<import>、<subant> 任務(wù),表明使用它們可以有什么收獲,以及它們?nèi)绾斡绊懩M織編譯設(shè)置的方式。

大多數(shù)編譯工程師遲早會(huì)面臨必須執(zhí)行相同的任務(wù)組合但在幾個(gè)地方配置稍微有點(diǎn)不同的情況。一個(gè)常見的例子是創(chuàng)建一個(gè)web 應(yīng)用程序存檔,對(duì)于開發(fā)系統(tǒng)、測(cè)試系統(tǒng)和生產(chǎn)系統(tǒng)有著不同的配置。

讓我們假設(shè) web 應(yīng)用程序擁有依賴于目標(biāo)系統(tǒng)的不同的 web 部署描述符,并為開發(fā)環(huán)境使用了一個(gè)不同的 JSP 集合以及一個(gè)不同的資料庫(kù)集合。配置信息將放在屬性中,創(chuàng)建 web 存檔的任務(wù)看起來(lái)將類似于

  <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 是引用一個(gè)在其它位置定義的 <fileset> ,該引用指向您的應(yīng)用程序所需的附加資料庫(kù)的一個(gè)公共集合。

如果您只想一次創(chuàng)建一個(gè) web 存檔,那么您只需要正確地設(shè)置屬性。比如說(shuō),您可以從一個(gè)您的目標(biāo)專有的屬性文件中加載它們。

利用 Ant 1.5 創(chuàng)建存檔

現(xiàn)在,假定您想為測(cè)試系統(tǒng)和生產(chǎn)系統(tǒng)同時(shí)創(chuàng)建存檔,以確保您真正為兩個(gè)系統(tǒng)打包了相同的應(yīng)用程序。利用 Ant 1.5,您可能使用 <antcall> 來(lái)調(diào)用擁有不同屬性設(shè)置的 "war" 目標(biāo),類似:

  <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>

當(dāng)然,這假定兩個(gè)目標(biāo)系統(tǒng)都將使用相同的 jar 和 JSP。

但這種方法有一個(gè)主要缺點(diǎn) — 就是速度慢。<antcall> 重新分析編譯文件,并為每一次調(diào)用重新運(yùn)行調(diào)用的目標(biāo)所依賴的所有目標(biāo)。在上面的例子中,"jar" 目標(biāo)將被運(yùn)行兩次。我們希望這對(duì)第二次調(diào)用沒(méi)有影響,因?yàn)?"war" 目標(biāo)依賴于它。

利用 Ant 1.6 創(chuàng)建存檔

使用 Ant 1.6,您可以忘掉用 <antcall> 來(lái)實(shí)現(xiàn)宏的方法,相反您可以通過(guò)參數(shù)化現(xiàn)有的任務(wù)來(lái)創(chuàng)建一個(gè)新的任務(wù)。因而上面的例子將變?yōu)椋?/SPAN>

  <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>

這定義了一個(gè)名稱為 makewar 的任務(wù),該任務(wù)可以和任何其它的任務(wù)一樣使用。該任務(wù)有兩個(gè)必需的屬性,webxml 和 destfile。要使屬性可選,我們必需在任務(wù)定義中提供一個(gè)默認(rèn)值。這個(gè)示例假定 ${jar.name}${jsps} 在編譯期間為常量,從而它們?nèi)匀蛔鳛閷傩灾付āW⒁猓瑢傩栽谑褂萌蝿?wù)時(shí)展開而不是在定義宏的地方展開。

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

于是新的 production-wars 目標(biāo)將類似于:

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

這個(gè)新的代碼段不僅執(zhí)行得快一些,而且也更易讀,因?yàn)閷傩悦Q提供了更多的信息。

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

  <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>

調(diào)用將類似于:

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

這就像 <morefiles> 的嵌套元素直接在 <war> 任務(wù)內(nèi)部使用的效果一樣。

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

下面的宏不僅將創(chuàng)建 web 存檔,還將確保包含最終存檔的目錄在試圖寫入之前存在。在一個(gè)實(shí)際的編譯文件中,您可能在調(diào)用任務(wù)之前使用一個(gè)設(shè)置目標(biāo)來(lái)完成這個(gè)操作。

  <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>

這里注意兩件事情:

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

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

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

相反將不會(huì)在 "production-wars" 目標(biāo)中的第二次 <makewar> 調(diào)用產(chǎn)生期望的結(jié)果。第一次調(diào)用將定義一個(gè)新的名稱為 parent 的屬性,該屬性指向父目錄 ${staging.war.name}。第二次調(diào)用將查看這個(gè)屬性但不會(huì)修改它的值。

預(yù)期 Ant 未來(lái)的版本將支持某些類型的限定范圍的屬性,這種屬性只在宏執(zhí)行期間定義。在此之前,使用特性的名稱來(lái)構(gòu)建屬性名稱是一種變通辦法,潛在的副作用是要?jiǎng)?chuàng)建大量的屬性。

提示:如果您查看您的編譯文件時(shí)發(fā)現(xiàn)使用了 <antcall> 代替宏,那么強(qiáng)烈建議您考慮使用 macrodef 將其轉(zhuǎn)換成真正的宏。性能影響可能非常顯著,并且還可能產(chǎn)生更易讀和更易于維護(hù)的編譯文件。
導(dǎo)入

將一個(gè)編譯文件分成多個(gè)文件有幾個(gè)原因。

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

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

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

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

摘自 Ant 常見問(wèn)題解答。

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

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

Ant 1.6 自帶了一個(gè)名稱為 import 的新任務(wù),您現(xiàn)在可以使用它。上面的示例將變?yōu)?/SPAN>

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

因?yàn)樗且粋€(gè)任務(wù),因此您可以使用 Ant 所有的特性來(lái)指定文件位置。主要的差異是被導(dǎo)入的文件本身必須是一個(gè)有效的 Ant 編譯文件,因而必須有一個(gè)名稱為 project 的根元素。如果您想從實(shí)體包含轉(zhuǎn)換到導(dǎo)入,那么您必須在導(dǎo)入的文件的內(nèi)容首尾放上 <project> 標(biāo)記;然后 Ant 將在讀取文件時(shí)再次劃分它們。

注意文件名稱由 Ant 任務(wù)根據(jù)編譯文件的位置(而不是指定的基本目錄)確定。如果您沒(méi)有設(shè)置項(xiàng)目的 basedir 屬性或?qū)⑵湓O(shè)為 ".",那么您將不會(huì)注意到任何差異。如果您需要根據(jù)基本目錄解析一個(gè)文件,那么您可以使用一個(gè)屬性作為變通辦法,類似于:

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

屬性 common.location 將包含文件 common.xml 的絕對(duì)路徑,并已根據(jù)導(dǎo)入項(xiàng)目的基本目錄解析。

使用 Ant 1.6,所有的任務(wù)都可能放在目標(biāo)之外或之內(nèi),除了兩個(gè)例外。<import> 一定不能嵌入到目標(biāo)中,<antcall> 一定不能在目標(biāo)外使用(否則它將創(chuàng)建一個(gè)無(wú)限循環(huán))。

而 <import> 可做的不僅僅是導(dǎo)入另一個(gè)文件。

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

這意味著 <project> 的名稱屬性在 <import> 任務(wù)環(huán)境中變得更加重要。它還用來(lái)為在被導(dǎo)入的編譯文件中定義的目標(biāo)提供別名。如果導(dǎo)入了以下文件

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

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

讓我們假定有一個(gè)包含了多個(gè)獨(dú)立的組件(每個(gè)組件擁有它自己的編譯文件)的編譯系統(tǒng)。這些編譯文件幾乎相同,因此我們決定將公用功能轉(zhuǎn)移到一個(gè)共享和已導(dǎo)入的文件中。為了簡(jiǎn)單起見,我們只介紹 Java 文件的編譯和創(chuàng)建結(jié)果的一個(gè) 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>

這個(gè)文件不會(huì)作為一個(gè)獨(dú)立的 Ant 編譯文件進(jìn)行工作,因?yàn)樗鼪](méi)有定義 "setup" 所依賴的 "set-properties" 目標(biāo)。

組件 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>

它僅設(shè)置適當(dāng)?shù)沫h(huán)境,然后將全部的編譯邏輯交給被導(dǎo)入的文件負(fù)責(zé)。注意該編譯文件創(chuàng)建了一個(gè)空的路徑作為編譯 CLASSPATH,因?yàn)樗亲园摹DK 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 的編譯文件幾乎一樣,因此似乎有可能將大多數(shù)的 set-properties 目標(biāo)也推送到 shared.xml 中。實(shí)際上,我們可以假定有一個(gè)對(duì) dest 和 src 目標(biāo)一致的命名慣例,以實(shí)現(xiàn)這一目的。

  <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 是一個(gè)內(nèi)置的屬性,它包含了最外面的 <project> 標(biāo)記的名稱屬性的值。因此,如果模塊 A 的編譯文件導(dǎo)入了 share.xml,那么它將擁有值 A。

注意,所有的文件都與導(dǎo)入編譯文件的基本目錄相關(guān),因此 scr 屬性的實(shí)際值依賴于導(dǎo)入文件。

為此,A 的編譯文件將簡(jiǎn)單地變?yōu)?/SPAN>

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

B 的編譯文件將變?yōu)?/SPAN>

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

現(xiàn)在假定 B 增加了一些 RMI 接口,需要在編譯類之后但在創(chuàng)建 jar 之前運(yùn)行 <rmic>。這就是目標(biāo)覆蓋能派上用場(chǎng)的地方。如果我們?cè)趯?dǎo)入編譯文件中定義了一個(gè)目標(biāo),該目標(biāo)與被導(dǎo)入的編譯文件中的一個(gè)目標(biāo)名稱相同,那么將使用導(dǎo)入編譯文件中的目標(biāo)。例如,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" 目標(biāo),而不是 share.xml 中的目標(biāo);然而,不幸的是,這只是從共享那里復(fù)制 <javac> 任務(wù)。一種更好的解決方案是:

  <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" 在原來(lái)的 "compile" 目標(biāo)使用之后運(yùn)行 <rmic>。

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

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

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

因此您可以完全覆蓋一個(gè)目標(biāo)或通過(guò)在原始目標(biāo)之前或之后運(yùn)行任務(wù)來(lái)增強(qiáng)它。

這里要注意一個(gè)危險(xiǎn)。目標(biāo)覆蓋機(jī)制使導(dǎo)入編譯文件依賴于在導(dǎo)入文件中使用的名稱屬性。如果任何人修改了導(dǎo)入文件的名稱屬性,那么導(dǎo)入編譯文件將被破壞。Ant 開發(fā)社區(qū)目前正在討論在 Ant 的一個(gè)未來(lái)的版本中為此提供一個(gè)解決方案。

提示:如果您在編譯文件中發(fā)現(xiàn)了非常常見的結(jié)構(gòu),那么值得嘗試將文件重構(gòu)為一個(gè)(一些)共享文件,并在必要時(shí)使用目標(biāo)覆蓋。這可以使您的編譯系統(tǒng)更加一致,并讓您能夠重用編譯邏輯。
Subant

在某種意義上,subant 是兩種任務(wù)合二為一,因?yàn)樗私獠僮鞯膬煞N模式。

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

第二種模式不使用 genericantfile 屬性,而獲取一個(gè)編譯文件的列表和集合進(jìn)行迭代,以在每一個(gè)編譯文件中調(diào)用目標(biāo)。這種工作方式類似于在一個(gè)循環(huán)中使用 <ant> 任務(wù)。

第二種形式的典型情景是幾個(gè)能夠獨(dú)立編譯的模塊的一個(gè)編譯系統(tǒng),但是該系統(tǒng)需要一個(gè)主編譯文件來(lái)一次性編譯所有的模塊。

接下來(lái)的步驟

使用以下資源了解關(guān)于 Ant 的更多信息,并開始編譯和部署 Java 項(xiàng)目。

Ant 業(yè)界趨勢(shì)
對(duì)這個(gè)跨平臺(tái)編譯工具的形成進(jìn)行幕后觀察

閱讀關(guān)于 JDeveloper 中的 Ant 集成的更多信息
Oracle JDeveloper 中的 Ant 集成是通過(guò)在 JDeveloper 項(xiàng)目中添加一個(gè) Ant 編譯文件或通過(guò)從一個(gè)現(xiàn)有的 JDeveloper 項(xiàng)目中創(chuàng)建一個(gè)新的 Ant 編譯文件來(lái)實(shí)現(xiàn)的。

下載 Oracle JDeveloper 10g
Oracle JDeveloper 10g 是一個(gè)集成開發(fā)環(huán)境,它提供了對(duì)建模、開發(fā)、調(diào)試、優(yōu)化和部署 Java 應(yīng)用程序及 Web 服務(wù)的端到端支持。

測(cè)試驅(qū)動(dòng):將 Ant 用于編譯
這個(gè) viewlet 演示了已擁有 Ant 項(xiàng)目的用戶如何能夠在 JDeveloper 內(nèi)部使用這些項(xiàng)目。

Ant 入門第 1 部分
這里開始將這個(gè)非常有用的工具用于構(gòu)建和部署 Java 項(xiàng)目。本文介紹了您可能在 Java 開發(fā)過(guò)程期間執(zhí)行的一些基本的 Ant 任務(wù)。

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

在 Linux 上創(chuàng)建 Java 應(yīng)用程序的命令行方法
本文可用作使用 Ant 在 Linux 上開發(fā)和部署 Java 客戶端應(yīng)用程序的一個(gè)不錯(cuò)的上機(jī)操作指南。

閱讀關(guān)于 Ant 的更多信息
訪問(wèn)官方 Apache Ant 站點(diǎn),獲取更多的項(xiàng)目詳細(xì)信息。

相關(guān)文章與下載

Blog:到 OC4J 的 Ant 部署

Blog: 如何從一個(gè) JDeveloper 項(xiàng)目文件中將屬性動(dòng)態(tài)檢索到一個(gè) ant 編譯文件中?

Viewlet:將 CVS 用于軟件配置

在 Ant 1.6 之前構(gòu)建主編譯文件

在導(dǎo)入部分中討論的例子使用了這樣一個(gè)主編譯文件。

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

在 Ant 1.6 之前的 Ant 中。

使用 Ant 1.6 構(gòu)建主編譯文件

在 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>

這看起來(lái)并沒(méi)有很大的改善,因?yàn)槟匀槐仨殕为?dú)指定每一個(gè)子編譯文件。相反如果您轉(zhuǎn)用 <fileset>,那么情況將有所改觀。

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

這將自動(dòng)發(fā)現(xiàn)所有模塊的編譯文件。如果您增加了一個(gè)模塊 C,主編譯文件中的目標(biāo)不需要修改。

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

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

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

  <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>

這個(gè)假想的 buildlist 任務(wù)已經(jīng)在 Ant 用戶郵件列表和 bug 跟蹤系統(tǒng)中進(jìn)行了討論。很有可能 Ant 的一個(gè)將來(lái)的版本中將包含這樣的一個(gè)任務(wù)。

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



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

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

  將會(huì)使用 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 并且解壓
   需要啟動(dòng)Mysql服務(wù)器
   建立自己的應(yīng)用程序數(shù)據(jù)庫(kù)默認(rèn)字符集是UTF8,這個(gè)問(wèn)題很關(guān)鍵,因?yàn)锳ppfuse支持多語(yǔ)言否則程序無(wú)法正常運(yùn)行。所以Mysql服務(wù)器的默認(rèn)的字符集也應(yīng)該是UTF8,大家使用mysql怎么更改到UTF8字符集我不知道,我是通過(guò)命名行參數(shù)啟動(dòng)的:
   mysqld --default-character-set=utf8

  此時(shí)可以用ant建立自己的應(yīng)用了:
ant new -Dapp.name=myApp -Ddb.name=mydb

如果需要改變數(shù)據(jù)庫(kù)可以修改build.properties文件中這部分的參數(shù):
代碼
#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}


建立數(shù)據(jù)庫(kù)database, 在tomcat上發(fā)布應(yīng)用

運(yùn)行
ant setup

出錯(cuò)了,無(wú)法自動(dòng)建立數(shù)據(jù)庫(kù)mydb。出錯(cuò)信息如下:
BUILD FAILED: D:\myfile\myApp\build.xml:830: org.dbunit.dataset.NoSuchTableException: app_user

檢查執(zhí)行過(guò)程,把自動(dòng)執(zhí)行的創(chuàng)建app_user的sql語(yǔ)句放到mysql control center中執(zhí)行
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)
);
執(zhí)行失敗,錯(cuò)誤提示:
[root@localhost:3306] 錯(cuò)誤 1071: Specified key was too long. Max key length is 500
作如下修改,成功了,
email varchar(255) not null unique改成
email varchar(100) not null unique,

經(jīng)過(guò)測(cè)試,長(zhǎng)度超過(guò)166(包括)就出錯(cuò)了!
不知道是不是UTF8字符集造成的原因,一個(gè)UTF8字符被認(rèn)為占用了三個(gè)字節(jié)(500/3<167)??
就是說(shuō)聲明為 not null unique的字段長(zhǎng)度不能超過(guò)166。


由于sql語(yǔ)句根據(jù)POJO的tag自動(dòng)創(chuàng)建:

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

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

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

運(yùn)行
ant setup-db

成功了!ok!



啟動(dòng)tomcat 5.0.25
運(yùn)行
ant setup

出錯(cuò)了

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

沒(méi)有反應(yīng)??怎么回事??

命令行下面啟動(dòng)tomcat,看看有什么錯(cuò)誤提示:

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"/ -->


重新啟動(dòng)tomcat

還是不對(duì)

更換版本tomcat 5.0.5.28
錯(cuò)誤信息變了
Application 沒(méi)有啟動(dòng)??

運(yùn)行任務(wù)

ant install


沒(méi)有成功!出錯(cuò)信息如下:

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

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

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

增加兩個(gè)角色

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


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


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

運(yùn)行

ant install

成功了!!



但是tomcat報(bào)錯(cuò):
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
嚴(yán)重: Skipped installing application listeners due to previous error(s)
2004-11-14 20:00:04 org.apache.catalina.core.StandardContext start
嚴(yán)重: Error listenerStart
2004-11-14 20:00:04 org.apache.catalina.core.StandardContext start
嚴(yán)重: 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版本不對(duì)??

運(yùn)行struts安裝程序,正常運(yùn)行

重新運(yùn)行ant install-webwork

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

嗯~~

更改extras\viewgen目錄名稱為webwork

重新運(yùn)行ant install-webwork

再運(yùn)行ant install

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



輸入用戶名mraible
密碼tomcat

OK!!進(jìn)入主界面(界面沒(méi)有上傳,不好意思了^_^)


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

 

你可以在兩種情況下使用本文:學(xué)習(xí)過(guò)濾器的功用,或者作為你寫過(guò)濾器時(shí)的輔助。我將從幾個(gè)簡(jiǎn)單的例子開始然后繼續(xù)更多高級(jí)的過(guò)濾器。最后,我將向你介紹我為了支持多路請(qǐng)求而寫的一個(gè)文件上傳過(guò)濾器。

 

Servlet 過(guò)濾器

也許你還不熟悉情況,一個(gè)過(guò)濾器是一個(gè)可以傳送請(qǐng)求或修改響應(yīng)的對(duì)象。過(guò)濾器并不是servlet,他們并不實(shí)際創(chuàng)建一個(gè)請(qǐng)求。他們是請(qǐng)求到達(dá)一個(gè)servlet前的預(yù)處理程序,和/或響應(yīng)離開servlet后的后處理程序。就像你將在后面的例子中看到的,一個(gè)過(guò)濾器能夠:

·在一個(gè)servlet被調(diào)用前截獲該調(diào)用

·在一個(gè)servlet被調(diào)用前檢查請(qǐng)求

·修改在實(shí)際請(qǐng)求中提供了可定制請(qǐng)求對(duì)象的請(qǐng)求頭和請(qǐng)求數(shù)據(jù)

·修改在實(shí)際響應(yīng)中提供了可定制響應(yīng)對(duì)象的響應(yīng)頭和響應(yīng)數(shù)據(jù)

·在一個(gè)servlet被調(diào)用之后截獲該調(diào)用

 

    你可以一個(gè)過(guò)濾器以作用于一個(gè)或一組servlet,零個(gè)或多個(gè)過(guò)濾器能過(guò)濾一個(gè)或多個(gè)servlet。一個(gè)過(guò)濾器實(shí)現(xiàn)java.servlet.Filter接口并定義它的三個(gè)方法:

1.              void init(FilterConfig config) throws ServletException:在過(guò)濾器執(zhí)行service前被調(diào)用,以設(shè)置過(guò)濾器的配置對(duì)象。

2.              void destroy();在過(guò)濾器執(zhí)行service后被調(diào)用。

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

 

服務(wù)器調(diào)用一次init(FilterConfig)以為服務(wù)準(zhǔn)備過(guò)濾器,然后在請(qǐng)求需要使用過(guò)濾器的任何時(shí)候調(diào)用doFilter()。FilterConfig接口檢索過(guò)濾器名、初始化參數(shù)以及活動(dòng)的servlet上下文。服務(wù)器調(diào)用destory()以指出過(guò)濾器已結(jié)束服務(wù)。過(guò)濾器的生命周期和servelt的生命周期非常相似 ——在Servlet API 2.3 最終發(fā)布稿2號(hào) 中最近改變的。先前得用setFilterConfig(FilterConfig)方法來(lái)設(shè)置生命周期。

 

在doFilter()方法中,每個(gè)過(guò)濾器都接受當(dāng)前的請(qǐng)求和響應(yīng),而FilterChain包含的過(guò)濾器則仍然必須被處理。doFilter()方法中,過(guò)濾器可以對(duì)請(qǐng)求和響應(yīng)做它想做的一切。(就如我將在后面討論的那樣,通過(guò)調(diào)用他們的方法收集數(shù)據(jù),或者給對(duì)象添加新的行為。)過(guò)濾器調(diào)用

chain.doFilter()將控制權(quán)傳送給下一個(gè)過(guò)濾器。當(dāng)這個(gè)調(diào)用返回后,過(guò)濾器可以在它的doFilter()方法的最后對(duì)響應(yīng)做些其他的工作;例如,它能記錄響應(yīng)的信息。如果過(guò)濾器想要終止請(qǐng)求的處理或或得對(duì)響應(yīng)的完全控制,則他可以不調(diào)用下一個(gè)過(guò)濾器。

 

循序漸進(jìn)

如果想要真正理解過(guò)濾器,則應(yīng)該看它們?cè)趯?shí)際中的應(yīng)用。我們將看到的第一個(gè)過(guò)濾器是簡(jiǎn)單而有用的,它記錄了所有請(qǐng)求的持續(xù)時(shí)間。在Tomcat 4.0發(fā)布中被命名為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");

  }

}

 

當(dāng)服務(wù)器調(diào)用init()時(shí),過(guò)濾器用config變量來(lái)保存配置類的引用,這將在后面的doFilter()方法中被使用以更改ServletContext。當(dāng)調(diào)用doFilter()時(shí),過(guò)濾器計(jì)算請(qǐng)求發(fā)生到該請(qǐng)求執(zhí)行完畢之間的時(shí)間。該過(guò)濾器很好的演示了請(qǐng)求之前和之后的處理。注意doFilter()方法的參數(shù)并不是HTTP對(duì)象,因此要調(diào)用HTTP專用的getRequestURI()方法時(shí)必須將request轉(zhuǎn)化為HttpServletRequest類型。

 

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

   
 <filter>

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

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

</filter>


 

這將通知服務(wù)器一個(gè)叫timerFiter的過(guò)濾器是從TimerFiter類實(shí)現(xiàn)的。你可以使用確定的URL模式或使用<filter-mapping>標(biāo)簽命名的servelt 來(lái)注冊(cè)一個(gè)過(guò)濾器,如:

<filter-mapping>

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

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

</filter-mapping>


 

這種配置使過(guò)濾器操作所有對(duì)服務(wù)器的請(qǐng)求(靜態(tài)或動(dòng)態(tài)),正是我們需要的計(jì)時(shí)過(guò)濾器。如果你連接一個(gè)簡(jiǎn)單的頁(yè)面,記錄輸出可能如下:

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

 

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

 

此過(guò)濾器的WAR文件從此下載:

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

 

誰(shuí)在你的網(wǎng)站上?他們?cè)谧鍪裁矗?BR>
我們下一個(gè)過(guò)濾器是由OpenSymphony成員寫的clickstream過(guò)濾器。這個(gè)過(guò)濾器跟蹤用戶請(qǐng)求(比如:點(diǎn)擊)和請(qǐng)求隊(duì)列(比如:點(diǎn)擊流)以向網(wǎng)絡(luò)管理員顯示誰(shuí)在她的網(wǎng)站上以及每個(gè)用戶正在訪問(wèn)那個(gè)頁(yè)面。這是個(gè)使用LGPL的開源庫(kù)。

 

在clickstream包中你將發(fā)現(xiàn)一個(gè)捕獲請(qǐng)求信息的ClickstreamFilter類,一個(gè)像操作結(jié)構(gòu)一樣的Clickstream類以保存數(shù)據(jù),以及一個(gè)保存會(huì)話和上下文事件的ClickstreamLogger類以將所有東西組合在一起。還有個(gè)BotChecker類用來(lái)確定客戶端是否是一個(gè)機(jī)器人(簡(jiǎn)單的邏輯,像“他們是否是從robots.txt來(lái)的請(qǐng)求?”)。該包中提供了一個(gè)clickstreams.jsp摘要頁(yè)面和一個(gè)viewstream.jsp詳細(xì)頁(yè)面來(lái)查看數(shù)據(jù)。

 

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

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 {

    // 確保該過(guò)濾器在每次請(qǐng)求中只被使用一次

    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));

    }

 

    // 傳遞請(qǐng)求

    chain.doFilter(request, response);

  }

 

  public void destroy() { }

}


 

doFilter()方法取得用戶的session,從中獲取Clickstream,并將當(dāng)前請(qǐng)求數(shù)據(jù)加到Clickstream中。其中使用了一個(gè)特殊的FILTER_APPLIED標(biāo)記屬性來(lái)標(biāo)注此過(guò)濾器是否已經(jīng)被當(dāng)前請(qǐng)求使用(可能會(huì)在請(qǐng)求調(diào)度中發(fā)生)并且忽略所有其他的過(guò)濾器行為。你可能疑惑過(guò)濾器是怎么知道當(dāng)前session中有clickstream屬性。那是因?yàn)镃lickstreamLogger在會(huì)話一開始時(shí)就已經(jīng)設(shè)置了它。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(記錄器)獲取應(yīng)用事件并將使用他們將所有東西幫定在一起。當(dāng)context創(chuàng)建中,logger在context中放置了一個(gè)共享的流map。這使得clickstream.jsp頁(yè)面知道當(dāng)前活動(dòng)的是哪個(gè)流。而在context銷毀中,logger則移除此map。當(dāng)一個(gè)新訪問(wèn)者創(chuàng)建一個(gè)新的會(huì)話時(shí),logger將一個(gè)新的Clickstream實(shí)例放入此會(huì)話中并將此Clickstream加入到中心流map中。在會(huì)話銷毀時(shí),由logger從中心map中移除這個(gè)流。

 

下面的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>

 

    這注冊(cè)了ClickstreamFilter并設(shè)置其處理*.jsp和*.html來(lái)的請(qǐng)求。這也將ClickstreamLogger注冊(cè)為一個(gè)監(jiān)聽器以在應(yīng)用事件發(fā)生時(shí)接受他們。

 

   兩個(gè)JSP頁(yè)面從會(huì)話中取clickstream數(shù)據(jù)和context對(duì)象并使用HTML界面來(lái)顯示當(dāng)前狀態(tài)。下面的clickstream.jsp文件顯示了個(gè)大概:

<%@ 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>

<%

  }

}

%>



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

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

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

 

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

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

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

·我不得不將web.xml中的映射由/*.html和/*.jsp改成正確的*.html和*.jsp。一些服務(wù)器會(huì)忽略開頭的/,但Tomcat強(qiáng)硬的規(guī)定開頭不能有/。

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

 

可下載的WAR文件已經(jīng)包含了這些修改并能通過(guò)服務(wù)器在包外運(yùn)行,雖然我并沒(méi)有廣泛的進(jìn)行測(cè)試。

 

壓縮響應(yīng)

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

 

CompressionFilter類的策略是檢查請(qǐng)求頭以判定客戶端是否支持壓縮,如果支持,則將響應(yīng)對(duì)象用自定義的響應(yīng)來(lái)打包,它的getOutputStream()和getWriter()方法已經(jīng)被定義為可以利用壓縮過(guò)的輸出流。使用過(guò)濾器允許如此簡(jiǎn)單而有效的解決問(wèn)題。

 

我們將從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;

      }

    }

  }

 

注意在檢索請(qǐng)求頭前必須把request轉(zhuǎn)化為HttpServletRequest,就想在第一個(gè)例子里那樣。過(guò)濾器使用wrapper類CompressResponseWrapper,一個(gè)從

HttpServletResponseWrapper類繼承下來(lái)的自定義類。這個(gè)wrapper的代碼相對(duì)比較簡(jiǎn)單:

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;

  }

}


 

所有調(diào)用getOutputStream() 或者getWriter()都返回一個(gè)使用

CompressResponseStream類的對(duì)象。CompressionResponseStrteam類沒(méi)有顯示在這個(gè)例子中,因?yàn)樗^承于ServletOutputStream并使用java.util.zip.GZIPOutputStream類來(lái)壓縮流。

 

Tomcat的”examples”Web程序中已經(jīng)預(yù)先配置了這個(gè)壓縮過(guò)濾器并加載了一個(gè)示例servlet。示例servlet響應(yīng)/CompressionTestURL(確定先前的路徑是/examples)。使用我制作的有用的WAR文件,你可以用/servlet/compressionTest(再次提醒,別忘了適當(dāng)?shù)那皩?dǎo)路徑)訪問(wèn)此測(cè)試servlet。你可以使用如下的web.xml片段來(lái)配置這個(gè)測(cè)試:

<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(這里沒(méi)有顯示)輸出壓縮是否可用,如果可用,則輸出壓縮響應(yīng)成功! 
 

 

//~~~~~~~~~~CSDN這里到底有多少字?jǐn)?shù)限制?

請(qǐng)各位斧正了:)

來(lái)自:csdn

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

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

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

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

2.

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

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

這樣就是調(diào)用hello這個(gè)action指定類的noHello方法了.
如果要帶參數(shù)的話,還沒(méi)找到如何配置.呵呵.

3.
明確指定調(diào)用那個(gè)方法的配置文件寫法:

<!-- action指定了調(diào)用action哪個(gè)方法-->
  <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文件夾里面,在頁(yè)面上面寫
<ww:i18n name="'resources.ApplicationResources'">
 <ww:text name="'delete'">
 </ww:text>
</ww:i18n>
可以正確的找到中文字符集. 如果寫成<ww:i18n name="ApplicationResources'">,則會(huì)提示:  Could not find the bundle 'ApplicationResources'.以上操作并沒(méi)有設(shè)置webwork.custom.i18n.resources屬性.如果指定webwork.custom.i18n.resources=resources.ApplicationResources而不指定i18n標(biāo)簽的name是不允許的.i18n標(biāo)簽的name屬性是必須的選項(xiàng),并且要寫全路徑.

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

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

5.
上面的試驗(yàn)表示多語(yǔ)言的第一步是成功的,接下來(lái)的問(wèn)題是中文顯示成?.以及手工控制多語(yǔ)言的問(wèn)題.

webwork.i18n.encoding=UTF-8
測(cè)試頁(yè)面中的文字如下:

中國(guó)
<p></p>
<ww:text name="'add'"/>

在這個(gè)頁(yè)面里面沒(méi)有指定頁(yè)面的編碼方式,只是頁(yè)面本身的編碼方式在IDE中指定,當(dāng)在ie中選擇UTF-8編碼時(shí),中文"中國(guó)"顯示正常.
(原來(lái)把頁(yè)面設(shè)置成IDE里面的UFT-8,結(jié)果如果用myeclipse的jsp編輯器打開,默認(rèn)時(shí)ISO編碼).

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

中文問(wèn)題解決,沒(méi)有使用filter. 注意: 我的webwork版本為2.1.7.有些老版本的估計(jì)還是得用filter來(lái)處理.以后有空可以試一下.

6.
繼續(xù)上面的試驗(yàn), 所有條件不變,在helloworld.HelloWorldAction所在包中新建與該action名字想同的資源文件,本例中叫做HelloWorldAction_en.properties和HelloWorld_zh_CN.properties,然后在里面加兩個(gè)跟全局resource相同key的資源文件,頁(yè)面上會(huì)優(yōu)先從這里來(lái)取國(guó)際化文字,也就是說(shuō)即使指定了全局resource文件,如果在action執(zhí)行的包內(nèi)存在同名的key也會(huì)覆蓋同名全局資源文件中的key定義.
同樣,如果雖然action包中存在資源文件,但是沒(méi)有定義請(qǐng)求的key的國(guó)際化文字,則會(huì)到全局資源文件里面進(jìn)行查找.

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

原文
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

測(cè)試通過(guò),自定義語(yǔ)種問(wèn)題解決.


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



8.
今天發(fā)現(xiàn)5.8.4版本的myeclipse的tag屬性面板挺好用的.good.


9.
有關(guān)webwork的javascript驗(yàn)證能力參看以下帖子:
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 發(fā)表評(píng)論
]]>
AppFuse中集成ValueList的問(wèn)題http://www.aygfsteel.com/kapok/archive/2005/03/18/2211.html笨笨笨笨Fri, 18 Mar 2005 15:40:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/18/2211.htmlhttp://www.aygfsteel.com/kapok/comments/2211.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/18/2211.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/2211.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/2211.htmlhttp://rabbit8.blogchina.com/blog/article_144619.1140620.html

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

在執(zhí)行 ant setup的時(shí)候,在compile-module的時(shí)候,總是說(shuō)找不到valuelist的類,后來(lái)發(fā)現(xiàn)AppFuse的jar都添加到了builde.xml中,于是我也把valuelist.jar添加過(guò)去了,發(fā)現(xiàn)問(wèn)題解決了,方法如下:

AppFuse執(zhí)行Setup后自動(dòng)將valuelist.jar復(fù)制到Tomcat下:

在appfuse\lib\lib.properties中添加如下內(nèi)容:

#
# 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}"/>                             //這是我添加的內(nèi)容
            <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 發(fā)表評(píng)論
]]>
Aceqihttp://www.aygfsteel.com/kapok/archive/2005/03/18/2190.html笨笨笨笨Fri, 18 Mar 2005 05:41:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/18/2190.htmlhttp://www.aygfsteel.com/kapok/comments/2190.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/18/2190.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/2190.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/2190.htmlhttp://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseSecurity

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

關(guān)于URLEncoder的解析問(wèn)題     

      http://rabbit8.blogchina.com/blog/article_144619.789425.html后,有個(gè)朋友留言,說(shuō)在百度試驗(yàn)的結(jié)果和我文章中說(shuō)的不一致,我做了個(gè)實(shí)驗(yàn),證實(shí)JDK的幫助沒(méi)錯(cuò),原因如下:


我的試驗(yàn)代碼如下:
public static void main(String[] args) {
        URLEncoder urle = null;
       
        //得到默認(rèn):%A8%B9
        System.out.println("默認(rèn):" +   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來(lái)查看"ü"的ASCII的話,得到的結(jié)果如圖:
 
      可見,UltraEdit使用的是操作系統(tǒng)默認(rèn)的編碼方式(實(shí)際上,MS采用的也不是GBK,而是另一種編碼,但效果和GBK差不多),所以它顯示的ASCII的編碼為A8 B9,就是第一和第二種情況的結(jié)果。而第三種情況才是JDK幫助中所聲明的情況。
 
      我查看了百度,提交了一下,結(jié)果和我預(yù)期的是一樣的!

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



笨笨 2005-03-09 00:44 發(fā)表評(píng)論
]]>
DisplayTag、Tomcat中編碼的問(wèn)題http://www.aygfsteel.com/kapok/archive/2005/03/09/1863.html笨笨笨笨Tue, 08 Mar 2005 16:41:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1863.htmlhttp://www.aygfsteel.com/kapok/comments/1863.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1863.html#Feedback2http://www.aygfsteel.com/kapok/comments/commentRss/1863.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1863.html DisplayTag、Tomcat中編碼的問(wèn)題 2005年 02月04日 對(duì)DisplayTag、Tomcat中編碼問(wèn)題的總結(jié)

關(guān)于AppFuse中使用中文編碼的問(wèn)題

 

      這2個(gè)月一直被DisplayTag折騰,如果DisplayTag的鏈接或者排序的列中有漢字,那么排序或者翻頁(yè)都會(huì)查詢不到結(jié)果或報(bào)錯(cuò)(如果你處理的好,可能會(huì)顯示沒(méi)有可以顯示的數(shù)據(jù))。

      我一直以為這個(gè)問(wèn)題是因?yàn)?FONT size=+0>DisplayTag的開發(fā)者們沒(méi)有考慮到中文的問(wèn)題,因?yàn)轫?xiàng)目進(jìn)度很緊,所以就把排序的功能給屏蔽了,雖然經(jīng)過(guò)了大量的測(cè)試,但都沒(méi)有發(fā)現(xiàn)翻頁(yè)時(shí)候也存在這個(gè)問(wèn)題(AppFuse自動(dòng)生成的頁(yè)面的默認(rèn)顯示25行,如果超過(guò)25行會(huì)自動(dòng)分頁(yè)),直到前天,測(cè)試人員才發(fā)現(xiàn)這個(gè)問(wèn)題,按照我的理解要修改DisplayTag的源碼,后來(lái)又想通過(guò)自己寫過(guò)濾器試試,幸運(yùn)的是在我動(dòng)手干之前,先和倦兔聊了幾句,結(jié)果倦兔說(shuō)他也遇到過(guò)這個(gè)問(wèn)題,指出如果在server.xml中添加URIEncoding="GBK"就可以解決問(wèn)題,我試了一下,果然可以,但這是為什么呢?

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

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

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

      不是!!!!它采用的是Get方法進(jìn)行提交的,這就是問(wèn)題的答案了!
      Post和Get提交有什么區(qū)別嗎?

      簡(jiǎn)單的說(shuō):Post是將地址傳送一次,將form的數(shù)據(jù)單獨(dú)提交,而Get則是將地址和參數(shù)一起傳送,傳送的不止是form的數(shù)據(jù),但傳送的數(shù)據(jù)的長(zhǎng)度有字節(jié)限制,另外還有安全問(wèn)題。如果感興趣,你可以用google搜一下,會(huì)找到很多資料。

      當(dāng)我想到這個(gè)區(qū)別時(shí),我又檢查了一下我的顯示列表的頁(yè)面,發(fā)現(xiàn)這個(gè)頁(yè)面沒(méi)有form,只有,這說(shuō)明我的提交的確是Get的,于是,Tomcat5對(duì)我的Get請(qǐng)求執(zhí)行的是另外的處理方式,和Post的處理方式不再一樣了!
      Tomcat5對(duì)Get請(qǐng)求是怎么處理的?
      默認(rèn)情況下,Tomcat對(duì)請(qǐng)求采用的默認(rèn)編碼是ISO-8859-1,我們的JSP頁(yè)面上聲明的


     <meta http-equiv="Content-Type" content="text/html; charset=GBK"/>
只在顯示漢字時(shí)有用,而且這2種寫法的作用在理論上應(yīng)該時(shí)一致的,但是由于各個(gè)軟件廠商對(duì)Web標(biāo)準(zhǔn)都按照自己的理解進(jìn)行了修改,所以,常常這2種寫法作用就不一致了,使我們?cè)陂_發(fā)Web程序時(shí)備感混亂。如果你想了解詳情,請(qǐng)查看《網(wǎng)站重構(gòu)》一書。

 

這樣我們提交的漢字被認(rèn)為是ISO-8859-1的編碼,所以在程序中接收時(shí)顯示亂碼,如果使用過(guò)濾器,在過(guò)濾器中調(diào)用request.setCharacterEncoding("GBK")的話,那么Post上來(lái)的漢字將被認(rèn)為是GBK編碼,而Tomcat5對(duì)于Get請(qǐng)求上來(lái)的編碼并不根據(jù)過(guò)濾器的設(shè)定辨認(rèn)編碼方式,默認(rèn)的依然是ISO-8859-1Tomcat5中處理Get請(qǐng)求的源代碼如下:

 tomcat5中處理Get請(qǐng)求的函數(shù)

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

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

 

 

      這個(gè)問(wèn)題我參考了這篇文章:

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

      另外,對(duì)于編碼解碼的問(wèn)題,我還有一句要說(shuō),理論上,如果編碼的charset和解碼的charset是一致的話,那么就應(yīng)該沒(méi)有亂碼的問(wèn)題,但是,對(duì)于某些特殊的字符來(lái)說(shuō),如果采用的charset不對(duì),則可能在解碼的時(shí)候不能顯示,所以要選擇好字符集,我推薦在處理簡(jiǎn)體漢字的時(shí)候使用GBK。網(wǎng)上也有推薦UTF-8的,具體使用哪種依情況而定。

 

       以上是我的總結(jié),若有錯(cuò)誤,請(qǐng)指正,謝謝!

 

      明天,我就放假了,祝我的朋友們春節(jié)快樂(lè),萬(wàn)事勝意!

 

                                                                                   兔八哥

                                                           20052414:04

 
 

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



笨笨 2005-03-09 00:41 發(fā)表評(píng)論
]]>
在AppFuse中集成ValueList的方法http://www.aygfsteel.com/kapok/archive/2005/03/09/1860.html笨笨笨笨Tue, 08 Mar 2005 16:29:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1860.htmlhttp://www.aygfsteel.com/kapok/comments/1860.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1860.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1860.htmlhttp://www.aygfsteel.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文件復(fù)制到/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"為原來(lái)配置好的。
  "defaultNumberPerPage"為每頁(yè)顯示的記錄行數(shù)。
  "defaultSortColumn"排序列。
  "org.appfuse.model.User"為POJO的名字。
 
6.將相關(guān)的樣式表的內(nèi)容合并到原有的樣式表中。
7.將valuelist.jar添加到類路徑下。

 


8:如果為行添加onclick事件,注意要對(duì)"&"進(jìn)行轉(zhuǎn)義-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后的內(nèi)容如下:

  <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函數(shù),添加完函數(shù)后的內(nèi)容如下:
<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 發(fā)表評(píng)論
]]>
DT編譯成功了!!!http://www.aygfsteel.com/kapok/archive/2005/03/09/1858.html笨笨笨笨Tue, 08 Mar 2005 16:28:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1858.htmlhttp://www.aygfsteel.com/kapok/comments/1858.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1858.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1858.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1858.html DT編譯成功了!!! 2005年 03月01日

DT編譯成功了,Struts Menu從數(shù)據(jù)庫(kù)取數(shù)據(jù)組建菜單的試驗(yàn)成功了......

這幾天又開始做技術(shù)實(shí)驗(yàn)了,被折磨的有點(diǎn)情緒化,不過(guò)一切還算順利,多虧朋友們的幫忙!

昨晚在家讀DisplayTag的源代碼,發(fā)現(xiàn)DisplatyTag(以下簡(jiǎn)稱DT)翻頁(yè)時(shí)候不是從緩存中讀取的數(shù)據(jù),它又重新向數(shù)據(jù)庫(kù)發(fā)出請(qǐng)求,和我調(diào)試程序時(shí)發(fā)現(xiàn)的一樣,它的動(dòng)作大致是這樣的:

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

      今天試了一下從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)來(lái)生成Struts Menu的菜單,結(jié)果發(fā)現(xiàn)如果一頁(yè)中放入2個(gè)Struts Menu的菜單,則會(huì)有一個(gè)有問(wèn)題,我看了一下源碼,發(fā)現(xiàn)是在一個(gè)js文件中的函數(shù)引起的,Struts Menu首先初始化菜單,然后擴(kuò)展,在擴(kuò)展的時(shí)候,把點(diǎn)擊的菜單寫到Cookies中,如果同一個(gè)頁(yè)面有2個(gè)的聲明,則第二個(gè)菜單的折疊的部分不能展開,我的一個(gè)同事折騰了將近一周,就是因?yàn)檫@個(gè)問(wèn)題。

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

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

      Matt Raible關(guān)于DT、ValueList、DataGrid的簡(jiǎn)短介紹:http://raibledesigns.com/comments/rd/sunsets/there_s_a_new_sorting

                                                                                                               兔八哥

                                                                                                       2005-3-1 18:21

 



笨笨 2005-03-09 00:28 發(fā)表評(píng)論
]]>
ValueList的實(shí)驗(yàn)做完了,但是……http://www.aygfsteel.com/kapok/archive/2005/03/09/1859.html笨笨笨笨Tue, 08 Mar 2005 16:28:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1859.htmlhttp://www.aygfsteel.com/kapok/comments/1859.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1859.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1859.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1859.html ValueList的實(shí)驗(yàn)做完了,但是…… 2005年 03月07日

今天,同事終于把ValueList的實(shí)驗(yàn)做完了,ValueList0.1.7新添了許多新功能,但是,今天看到"王者之劍"的留言,又讀了一下源碼,發(fā)現(xiàn)ValueList也是取回?cái)?shù)據(jù)庫(kù)的全部數(shù)據(jù),只是把需要返回頁(yè)面的數(shù)據(jù)返回了,并不是我想的使用Hibernate的分頁(yè)方法進(jìn)行查詢數(shù)據(jù)庫(kù)的

    今天,同事終于把ValueList的實(shí)驗(yàn)做完了,ValueList0.1.7新添了許多新功能,但是,今天看到"王者之劍"在我的Blog上的留言,有點(diǎn)不太相信ValueList也是取回所有的數(shù)據(jù)。
   
    剛才,我抽空看了一下ValueList的Hibernate20Adapter的源碼,結(jié)果發(fā)現(xiàn)果然是把所有的數(shù)據(jù)都取回來(lái)了,但比DT稍強(qiáng)一些的是,它沒(méi)有把所有的Object都放入request中,只是把當(dāng)前頁(yè)要顯示的Object放入了,但這樣也同樣耗費(fèi)數(shù)據(jù)庫(kù)資源,同樣需要循環(huán),不同的是,耗費(fèi)的網(wǎng)絡(luò)資源少些,因?yàn)椋鼈骰氐膶?duì)象只有一頁(yè)的對(duì)象。

    但結(jié)果并不是我想像的,我以為,它會(huì)自己像Hibernate那樣,根據(jù)不同的數(shù)據(jù)庫(kù)采用分頁(yè)算法,使用Criteria Query設(shè)定返回在指定范圍的數(shù)據(jù)。
實(shí)驗(yàn)結(jié)果有點(diǎn)讓我失望,但畢竟比DT要強(qiáng)一些,不知道DT的1.1是不是也是這樣解決的,如果是的話,那不用等它的正式版本了,在JIRA上已經(jīng)有參考實(shí)現(xiàn)了。

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

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

    昨天,和朋友開車去天津,在濱江路上轉(zhuǎn)了一天,我在94年取過(guò)一次,發(fā)現(xiàn)十年后再看天津已經(jīng)不是以前的那個(gè)城市了,看來(lái)是我的看法變了!不過(guò)昨天天津的氣溫有15度,很是舒服,好久沒(méi)有這樣放松了,希望每隔2個(gè)月,能出去轉(zhuǎn)轉(zhuǎn)!

 

                                                                                                                                   兔八哥

                                                                                                                             2005-3-7 19:38



笨笨 2005-03-09 00:28 發(fā)表評(píng)論
]]>
AppFuse最新版本的幫助http://www.aygfsteel.com/kapok/archive/2005/03/09/1857.html笨笨笨笨Tue, 08 Mar 2005 16:27:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1857.htmlhttp://www.aygfsteel.com/kapok/comments/1857.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1857.html#Feedback1http://www.aygfsteel.com/kapok/comments/commentRss/1857.htmlhttp://www.aygfsteel.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 發(fā)表評(píng)論
]]>
URLEncode的問(wèn)題解決了http://www.aygfsteel.com/kapok/archive/2005/03/09/1856.html笨笨笨笨Tue, 08 Mar 2005 16:19:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1856.htmlhttp://www.aygfsteel.com/kapok/comments/1856.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1856.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1856.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1856.html http://rabbit8.blogchina.com/blog/article_144619.790247.html
URLEncode的問(wèn)題解決了
2005年 02月02日 URLEncode的問(wèn)題解決了,倦兔的解決方法竟然如此簡(jiǎn)單!!!

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

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

 

不用讀DisplayTag的源碼了,也可以安心過(guò)個(gè)年了,謝謝倦兔!!!



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

以下內(nèi)容是我翻譯的JDK的幫助。

URLEncoder類:

用于HTML的form中數(shù)據(jù)編碼的類。

這個(gè)類包含將字符串轉(zhuǎn)換為application/x-www-form-urlencoded MIME 格式的靜態(tài)方法.

如果想了解HTML的編碼細(xì)則,請(qǐng)參考HTML規(guī)范。

編碼規(guī)則如下:

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

空格" "被轉(zhuǎn)換為加號(hào)"+"。

所有其他的字符都被認(rèn)為是不安全的,首先都根據(jù)指定的編碼scheme被轉(zhuǎn)換為1個(gè)或者多個(gè)字節(jié)。[憑什么認(rèn)為其他的字符都是不安全的?看來(lái)這些規(guī)范的制訂者中沒(méi)有中國(guó)人呀!]

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

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

"The string ü@foo-bar"將被轉(zhuǎn)換為"The+string+%C3%BC%40foo-bar" 。

因?yàn)檩dUTF-8中字符ü被編碼成2個(gè)字節(jié)C3 (十六進(jìn)制) 和BC (十六進(jìn)制), 字符@被編碼成一個(gè)字節(jié)40 (十六進(jìn)制)。

起始于:JDK1.0

 

這個(gè)類共有2個(gè)重載方法:

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

和即將被廢棄的方法:public static String encode(String s)。(因?yàn)檫@個(gè)方法的編碼的字符集依賴于程序運(yùn)行的系統(tǒng)的默認(rèn)的字符集)。

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

注意: W3C推薦UTF-8。

參數(shù):

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

enc - 編碼用的character。

 返回:翻譯后的字符串。

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

起始于:1.4

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

 

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

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

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

 

                                                                                                           兔八哥

                                                                                                   2005-2-2下午16:30

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

在百度提交:The string ü@foo-bar
并不是您說(shuō)的結(jié)果.

    匿名網(wǎng)友 | 2005年 02月05日 16 : 58


     回復(fù) [回復(fù)]
   

請(qǐng)看:http://rabbit8.blogchina.com/blog/article_144619.859489.html

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


     [回復(fù)]
   

不錯(cuò)不錯(cuò),附上實(shí)現(xiàn)代碼
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 發(fā)表評(píng)論
]]>
關(guān)于DisplayTag:新的郁悶開始了……http://www.aygfsteel.com/kapok/archive/2005/03/09/1854.html笨笨笨笨Tue, 08 Mar 2005 16:17:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/09/1854.htmlhttp://www.aygfsteel.com/kapok/comments/1854.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/09/1854.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1854.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1854.html http://rabbit8.blogchina.com/blog/article_144619.789350.html
關(guān)于DisplayTag:新的郁悶開始了……
2005年 02月02日 DisplayTag的默認(rèn)的URL為上一次的URL,而上一次的URL中包含被編碼后的漢字,所以,將編碼后的漢字再次進(jìn)行編碼,肯定查不到結(jié)果,所以也不能翻頁(yè),看來(lái)要修改DisplayTag了,本來(lái)想年后再弄的......

DisplayTag的默認(rèn)的URL默認(rèn)為上一次的URL,如果上一次的URL包含中文的話,則會(huì)被進(jìn)行URLEncode,所以在翻頁(yè)的時(shí)候,又會(huì)把進(jìn)行了URLEncode后的數(shù)據(jù)再次進(jìn)行URLEncode,所以翻頁(yè)就沒(méi)有數(shù)據(jù),因?yàn)檫@部分功能被封裝在DisplayTag中,于是,我又開始郁悶了......

如漢字"專業(yè)"被編碼后為"%D7%A8%D2%B5",于是DisplayTag就將這個(gè)編碼作為連接的關(guān)鍵字,如果再次提交,則這個(gè)編碼還會(huì)被編碼,所以查詢結(jié)果一定就不對(duì)了!!!

下面的內(nèi)容是我分析這個(gè)問(wèn)題的由來(lái):

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

剛才到網(wǎng)上查找了些資料,找到HTML4.0.1的規(guī)范中關(guān)于URLEncode的部分,我把我關(guān)心的內(nèi)容翻譯了一下:

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

其中相關(guān)內(nèi)容如下在17.13.3 Processing form data

提交時(shí),HTML的規(guī)范處理如下:

1.標(biāo)識(shí)successful controls (概念可以在上文中查找)。

2.構(gòu)建form的數(shù)據(jù)集。

3.根據(jù)form的enctype的設(shè)置,對(duì)form的數(shù)據(jù)集進(jìn)行Encode。

4.提交已經(jīng)Encode的數(shù)據(jù)集。

 

HTML規(guī)范中指出Content type和Languange code是不區(qū)分大小寫的。

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

"&" 表示"&"。關(guān)于charset的詳細(xì)內(nèi)容見:http://www.w3.org/TR/html401/charset.html#entities

 

有一個(gè)小發(fā)現(xiàn):Frame中的target的值的列表原來(lái)是在HTML的規(guī)范中制定的,呵呵:

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

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

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

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

_parent  在當(dāng)前窗口的父窗口中打開,如果當(dāng)前窗口沒(méi)有父窗口,那么就等同于_self

_top  在最開始的窗口中轉(zhuǎn)載,如果當(dāng)前框架沒(méi)有parent,那就等于_self

 

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

form的默認(rèn)的content type是:application/x-www-form-urlencoded

form提交content type的數(shù)據(jù)必須用下列規(guī)則進(jìn)行編碼(encode):

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

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

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

控件的名字和數(shù)值之間使用"="分隔,多個(gè)控件之間用"&"分隔。

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

                                                                                                    兔八哥

                                                                                                2005-2-2下午

 



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

使用正則表達(dá)式,將原代碼
            <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,''))"
 />
就解決了問(wèn)題,用戶如果輸入漢字,則自動(dòng)刪除漢字,而且如果使用向左的箭頭向前移動(dòng)使光標(biāo)前移,則根本移動(dòng)不了,光標(biāo)始終在行尾,只能刪除后面的字符,再重新寫,其實(shí)最好是在EMail的自動(dòng)生成的腳本中提示,目前先這樣實(shí)現(xiàn)吧,將來(lái)再說(shuō)!

笨笨 2005-03-09 00:16 發(fā)表評(píng)論
]]>
使用AppFuse進(jìn)行開發(fā)的總結(jié)http://www.aygfsteel.com/kapok/archive/2005/03/08/1852.html笨笨笨笨Tue, 08 Mar 2005 15:53:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/08/1852.htmlhttp://www.aygfsteel.com/kapok/comments/1852.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/08/1852.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1852.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1852.html使用AppFuse進(jìn)行開發(fā)的總結(jié)
http://rabbit8.blogchina.com/blog/article_144619.796348.html

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

      它最大的價(jià)值就是為我們提供了一個(gè)Web開發(fā)的新的方式和思路,盡管這些技術(shù)在國(guó)外都已進(jìn)很流行了,但在國(guó)內(nèi)能夠?qū)?FONT size=+0>Hibernate、StrutsSpringDBUnitAntLog4JStruts MenuXdocletSiteMeshVelocityJUnitJSTLWebWork這些技術(shù)集成到一個(gè)框架中的還不多見,所以即使不使用它的全部功能,它也給我們提供了一個(gè)很好的借鑒、學(xué)習(xí)的機(jī)會(huì)。

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

 

       通過(guò)關(guān)注AppFuse,我們可以看到目前國(guó)外的主流開發(fā)都使用了哪些技術(shù),開發(fā)方式是什么樣的,可能達(dá)到什么樣的結(jié)果,而在以前,是很少能夠看到這樣完整的例子的。

       AppFuse的另一個(gè)啟示是:我們可以依靠開源軟件的功能降低開發(fā)成本,而且可以閱讀開源軟件的代碼提高所在團(tuán)隊(duì)的整體實(shí)力。

      

       但是通過(guò)2個(gè)月的實(shí)際學(xué)習(xí)和使用,我也遇到一系列的問(wèn)題,因?yàn)?FONT size=+0>AppFuse是將其他的一些類庫(kù)或者框架集成在一起的,集成的技術(shù)眾多,而且有一些技術(shù)在國(guó)內(nèi)甚至很少有人知道,資料也比較少,所以雖然作者經(jīng)過(guò)了一些測(cè)試,但都是基于英文編碼的,而對(duì)于中文編碼來(lái)說(shuō),還潛在的存在著一些問(wèn)題,雖然不是AppFuse的問(wèn)題,但卻降低了開發(fā)速度,下面是我在開發(fā)過(guò)程中遇到過(guò)的問(wèn)題,有些解決了,有些還沒(méi)有解決:

一.Struts

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

2.  Struts中的標(biāo)簽如今推薦使用的只有html部分的標(biāo)簽了,其他的標(biāo)簽或者可以使用JSTL替代,或者已經(jīng)不推薦使用了,而且AppFuse中推薦使用JSTL,而JSTLstruts的標(biāo)簽的聯(lián)合使用時(shí),需要的不是標(biāo)簽<html:標(biāo)簽>,而是標(biāo)簽<html-el:標(biāo)簽>,這個(gè)問(wèn)題曾經(jīng)困擾了我整整2天。

3.  StrutsValidation的校驗(yàn)規(guī)則并不完善,比如如果使用客戶端的javascript校驗(yàn),則在郵箱中輸入漢字根本校驗(yàn)不出來(lái),到了服務(wù)器端報(bào)錯(cuò)。

4.  最嚴(yán)重的問(wèn)題是AppFuse生成的Strutsvalidation.xml文件中有許多多余的".",如果你去掉了,常常在執(zhí)行antdeploy任務(wù)時(shí)又恢復(fù)原樣。這樣是提交表單的時(shí)候經(jīng)常會(huì)報(bào)javascript的腳本錯(cuò)誤或者缺少對(duì)象或者缺少value,所以我會(huì)手工的修改這個(gè)文件,然后把修改后的文件備份,當(dāng)重新生成有錯(cuò)誤的文件時(shí),我會(huì)用備份的沒(méi)有錯(cuò)誤的文件去覆蓋。

5.  Strutsvalidatioin對(duì)于使用同一個(gè)FormBeanAction的校驗(yàn)方式比較復(fù)雜。(待解決)。

二.Hibernate

1.  Hibernate是現(xiàn)在受到越來(lái)越多的人推崇的一個(gè)ORM工具(框架、類庫(kù)),它將我們從繁瑣的使用JDBC的開發(fā)過(guò)程中解放出來(lái),但同時(shí)也帶來(lái)了新的問(wèn)題,如學(xué)習(xí)曲線,執(zhí)行效率,數(shù)據(jù)庫(kù)設(shè)計(jì)優(yōu)化,還有最重要的靈活性。Hibernate不是一個(gè)很容易上手的東西,要完全駕馭它還需要讀很多資料,但好的資料卻很少。

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

3.  同樣還是id的生成策略問(wèn)題,如果使用序列、hilo等需要一些數(shù)據(jù)庫(kù)機(jī)制支持的策略時(shí),schemaExport并不能自動(dòng)生成序列或者保存當(dāng)前id的表,這項(xiàng)工作仍然要手工解決。

4.  Hibernate中提供了幾種關(guān)聯(lián),一對(duì)一、一對(duì)多、多對(duì)多,但對(duì)于怎樣調(diào)整效率卻沒(méi)有一個(gè)很明確的提示,還要根據(jù)情況判定,這就帶來(lái)和一些彈性的設(shè)計(jì)。

5.  Hibernate中可以選擇的操作數(shù)據(jù)庫(kù)的方式有3種,其中HQL功能最強(qiáng)大,但有些功能使用標(biāo)準(zhǔn)查詢可能會(huì)更方便,但會(huì)有一些限制,所以雖然它很靈活,但易用性不如JDBC好。

三.Spring

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

1.  SpringAppFuse中起到的主要作用是對(duì)HibernateSession和事務(wù)的管理,利用Spring封裝的Hibernate模板類,我們大大地減少了實(shí)現(xiàn)DAO的代碼行數(shù)。

2.  Spring還起到了連接映射文件和類之間的關(guān)聯(lián),及接口和實(shí)現(xiàn)類之間的關(guān)聯(lián),這些都依賴于SpringIoC的機(jī)制的實(shí)現(xiàn)。

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

 

四.SiteMesh

SiteMesh是一個(gè)基于Decorator模式的技術(shù),它可以修飾返回的網(wǎng)頁(yè)文件,它的工作方式受到越來(lái)越多的人的推崇,這點(diǎn)從Manning出版的一些技術(shù)書籍中可以看出來(lái)。

我在使用SiteMesh的過(guò)程中并不順利,我參考了《Java Open Source Programming》,這本書中說(shuō)SiteMesh在默認(rèn)的情況下不對(duì)下載文件進(jìn)行裝飾,但我在下載文件時(shí)發(fā)現(xiàn),我的文件內(nèi)容被丟棄了,取而代之的是SiteMesh的模板的內(nèi)容,后來(lái)我通過(guò)修改SiteMesh的配置文件解決了這個(gè)問(wèn)題,但感覺(jué)還有一些不太清楚的地方需要學(xué)習(xí)。

 

五.DisplayTag

       DisplayTag是一個(gè)優(yōu)秀的顯示內(nèi)容的標(biāo)簽,從SourceForge的訪問(wèn)量來(lái)看,它是很活躍的項(xiàng)目,僅次于AntHibernateXdoclet等幾個(gè)著名的項(xiàng)目,我總結(jié),它的主要功能有4項(xiàng):顯示、分頁(yè)、排序、將顯示的數(shù)據(jù)寫入指定類型的文件中,然后下載。

1.  據(jù)我使用的情況看,我只使用了分頁(yè)和顯示的功能,因?yàn)楫?dāng)時(shí)我沒(méi)有很好的解決中文編碼的問(wèn)題,所以排序會(huì)有問(wèn)題,直到昨天,我在朋友的幫助下解決了這個(gè)問(wèn)題,至此我可以放心使用的功能又增加了排序(我昨天簡(jiǎn)單的測(cè)試了一下是可以的)

 

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

(1)       生成的文件中只有顯示的數(shù)據(jù),那些沒(méi)有顯示在界面上的的數(shù)據(jù),則不會(huì)被寫到文件中。

(2)       如果修改了DisplayTag的顯示的內(nèi)容,比如添加一列,在這列中的內(nèi)容不是字符,而是HTML的標(biāo)簽,則生成的文件只有這些HTML標(biāo)簽,而沒(méi)有數(shù)據(jù)。

(3)       即使DisplayTag中沒(méi)有我們定制的HTML腳本,生成的文件偶爾也有問(wèn)題,比如:它會(huì)把"007"生成為"7",把字符串自動(dòng)的轉(zhuǎn)換為整型值。有時(shí)候還生成空白內(nèi)容的文件。

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

      后來(lái),我看了作者寫的《Spring Live》,書中說(shuō)如果想實(shí)現(xiàn)穩(wěn)定的Excel,推薦使用POI,于是我使用POI生成Excel,穩(wěn)定性和兼容性都不錯(cuò)。

六.DBUnit

       DBUnit是一個(gè)可以被Ant集成的向數(shù)據(jù)庫(kù)中添加數(shù)據(jù)和備份數(shù)據(jù)的一個(gè)類庫(kù),配置很方便,因?yàn)?FONT size=+0>AppFuse已經(jīng)集成好了,所以使用也很容易。

       但是如果你使用EditPlus之類的工具手工修改了AppFuse生成的內(nèi)容,則執(zhí)行Antsetupsetup-db或者deploy的任務(wù)時(shí),常常報(bào)錯(cuò),說(shuō)無(wú)效的格式,這是因?yàn)檫@個(gè)被手工修改的文件再次被AppFuse執(zhí)行后,它的第一行的文件聲明的前幾個(gè)字母是無(wú)效的,是因?yàn)楸镜氐淖址幋a的原因而引起了亂碼,如果把這幾個(gè)無(wú)效的字母去掉,問(wèn)題就解決了。

 

七.Struts Menu

       Struts Menu也是AppFuse的作者開發(fā)的一個(gè)開源軟件,它可以根據(jù)配置文件讀取當(dāng)前用戶可以使用的功能菜單,這個(gè)功能是我一直以來(lái)都想要的,我也找到了一些代碼,但實(shí)現(xiàn)的都不如這個(gè)完善,沒(méi)什么好說(shuō)的,使用簡(jiǎn)單,配置容易,很好的解決了我的問(wèn)題。

       問(wèn)題是我只使用了AppFuse提供的2個(gè)角色,對(duì)于多個(gè)角色的實(shí)驗(yàn)我還沒(méi)有做。

 

八.XDoclet

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

       問(wèn)題是我在Struts部分提到的,生成的Validation.xml文件中會(huì)多生成一個(gè)".",另外在生成資源文件時(shí)也會(huì)多生成一個(gè)".",目前我沒(méi)有很好的閱讀這段代碼,不知道是不是Xdoclet的問(wèn)題。

 

九.Ant

       Ant并沒(méi)有什么問(wèn)題,但在執(zhí)行作者寫的Ant任務(wù)的時(shí)候,有一些任務(wù)不能正常執(zhí)行,比如,運(yùn)行模擬對(duì)象測(cè)試的任務(wù),作者也在1.7版本的修復(fù)列表中提到以前版本有些ant任務(wù)不能執(zhí)行,在1.7中修改了一些ant任務(wù),使他們能夠正常的執(zhí)行了。

       實(shí)際上,我們?nèi)绻褂?FONT size=+0>AppGen進(jìn)行開發(fā)的話,使用的任務(wù)一般不超過(guò)8個(gè)。

 

十.JSTL

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

 

十一.Tomcat

       你也許會(huì)說(shuō):"Tomcat就不用說(shuō)了吧?",是的,Tomcat一般都會(huì)使用,但是―――――――――――――Tomcat5Tomcat4.X對(duì)于中文編碼使用了不同的機(jī)制,這個(gè)問(wèn)題困擾了我好久,我解決了頁(yè)面上寫入漢字顯示亂碼的問(wèn)題,我也曾經(jīng)以為DisplayTag對(duì)漢字不能排序,也不能正常分頁(yè)是因?yàn)?FONT size=+0>DisplayTag的開發(fā)者都是老外,是因?yàn)樗麄儧](méi)有考慮中文的關(guān)系的原因。

      直到昨天,我才知道這一切都是因?yàn)?FONT size=+0>Tomcat5對(duì)漢字編碼的實(shí)現(xiàn)的方式和Tomcat4不一樣的原因,如果感興趣,可以看看這個(gè)帖子:http://www.javaworld.com.tw/jute/post/view?bid=9&id=44042&sty=1&tpg=1&age=0

      再次感謝倦兔!:D

 

十二.JavaScript

       JavaScript簡(jiǎn)單易學(xué),但想運(yùn)用自如就不太容易了。AppFuse中嵌入了幾個(gè)js文件,里面包含了許多函數(shù),值得我們好好的研究一下,比如,如果有一個(gè)必填字段沒(méi)有填寫,AppFuse會(huì)自動(dòng)的聚焦在那個(gè)input上,類似的小技巧有很多,你可以自己去翻看。

       AppFuse自帶的JavaScript腳本有一個(gè)Bug,就是當(dāng)DisplatyTag中沒(méi)有可以顯示的數(shù)據(jù)時(shí),你用鼠標(biāo)單擊,它會(huì)報(bào)JavaScript錯(cuò)誤,你仔細(xì)研究一下function highlightTableRows(tableId) 就知道了:我的解決辦法是在location.href = link.getAttribute("href");前面添加一行判斷:if (link != null)。
 

十三.資源文件國(guó)際化

       對(duì)于StrutsDisplayTag都涉及到資源文件國(guó)際化AppFuse1.6.1很好的解決了Struts資源映射文件國(guó)際化的問(wèn)題,你只需要在對(duì)應(yīng)本國(guó)語(yǔ)言的資源文件中寫入漢字,Ant中有一項(xiàng)執(zhí)行native2ascii的任務(wù),AppFuse自動(dòng)的為你進(jìn)行了資源文件的編碼轉(zhuǎn)換,而對(duì)于DisplayTag的資源文件問(wèn)題,還要自己執(zhí)行native2ascii命令,為了避免每次都輸入一串命令,我用Delphi寫了個(gè)小工具,可視化的選擇資源文件,點(diǎn)擊按鈕自動(dòng)執(zhí)行該命令,底層依賴于JDK

 
 

經(jīng)過(guò)2個(gè)多月的學(xué)習(xí),我感覺(jué)這個(gè)框架非常不錯(cuò),它為我以后的項(xiàng)目開發(fā)指出了一個(gè)新的方向,但如果想很熟練的使用這個(gè)框架進(jìn)行開發(fā),至少要對(duì)以下幾種技術(shù)比較熟練:Struts(或者WebWorkSpring及其他的已經(jīng)整合進(jìn)來(lái)的MVC框架)Hibernate(或者ibatis)、JSTL,當(dāng)然其他的技術(shù)至少也要知道一點(diǎn),否則遇到問(wèn)題都不知道出在哪里。

 
 

       目前我還沒(méi)有解決的問(wèn)題有:

1.  如何在翻頁(yè)的時(shí)候才讀取下面的數(shù)據(jù)?

2.  怎樣對(duì)使用同一個(gè)FormBean的多個(gè)Form進(jìn)行客戶端校驗(yàn)?

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

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

5.  什么時(shí)候應(yīng)該自己獲取數(shù)據(jù)庫(kù)連接,執(zhí)行native SQL?具體需要注意些什么?

6.  SiteMesh的模板優(yōu)化?

7.  DisplayTag的底層實(shí)現(xiàn)?

 
 

每個(gè)問(wèn)題都比較棘手,要一個(gè)一個(gè)解決!   

 

       這個(gè)框架的優(yōu)點(diǎn)是:如果熟悉了開發(fā)流程,可以大幅度的提高開發(fā)速度,如果業(yè)務(wù)不是很復(fù)雜,使用AppGen可以生成60%左右的代碼,而且程序可維護(hù)性好,因?yàn)樽髡呤褂昧硕鄠€(gè)設(shè)計(jì)模式對(duì)各個(gè)層面進(jìn)行了封裝,所以不同的模塊代碼風(fēng)格出奇的一致,有利于開發(fā)人員快速上手,有利于接收其他開發(fā)人員遺留的代碼。

 

兔八哥





native2ascii在Ant中有任務(wù),可以寫        
<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 發(fā)表評(píng)論
]]>
從AppFuse開始 http://www.aygfsteel.com/kapok/archive/2005/03/08/1851.html笨笨笨笨Tue, 08 Mar 2005 15:46:00 GMThttp://www.aygfsteel.com/kapok/archive/2005/03/08/1851.htmlhttp://www.aygfsteel.com/kapok/comments/1851.htmlhttp://www.aygfsteel.com/kapok/archive/2005/03/08/1851.html#Feedback0http://www.aygfsteel.com/kapok/comments/commentRss/1851.htmlhttp://www.aygfsteel.com/kapok/services/trackbacks/1851.htmlhttp://blog.csdn.net/flydreamgy/archive/2004/12/13/214931.aspx

從AppFuse開始

很早以前接觸過(guò)AppFuse,一直沒(méi)有什么興趣,今天在csdn上看到了新聞,就花了時(shí)間到官方網(wǎng)站出看了一下.呵呵,版本改進(jìn)很快.包涵的東西越來(lái)越多了,很好的把眾多的OpenSource結(jié)合在了一起,從明天開始花時(shí)間詳細(xì)全面的學(xué)習(xí)一下.不停的學(xué)習(xí)才是進(jìn)步.哈哈
這是官方的介紹.
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
官方網(wǎng)站:
http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuse
http://appfuse.dev.java.net/
http://jroller.com/page/raible



笨笨 2005-03-08 23:46 發(fā)表評(píng)論
]]>
主站蜘蛛池模板: 聂荣县| 慈溪市| 武功县| 漳浦县| 巴林右旗| 望都县| 福贡县| 延寿县| 遵义市| 略阳县| 龙井市| 晴隆县| 葵青区| 朝阳县| 闵行区| 杨浦区| 镇宁| 竹北市| 彭阳县| 辽阳县| 永靖县| 新营市| 特克斯县| 边坝县| 桃源县| 余姚市| 莎车县| 休宁县| 五寨县| 青川县| 平潭县| 那坡县| 溧阳市| 钟祥市| 扎鲁特旗| 南城县| 白玉县| 天水市| 太谷县| 佛山市| 读书|