176142998

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            116 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

          #

          (1)模板 + 數據模型 = 輸出

          FreeMarker基于設計者和程序員是具有不同專業技能的不同個體的觀念他們是分工勞動的:
          設計者專注于表示——創建HTML文件、圖片、Web頁面的其它可視化方面;
          程序員創建系統,生成設計頁面要顯示的數據。
          經常會遇到的問題是:在Web頁面(或其它類型的文檔)中顯示的信息在設計頁面時是無效的,是基于動態數據的。在這里,你可以在HTML(或其它要輸出的文本)中加入一些特定指令,FreeMarker會在輸出頁面給最終用戶時,用適當的數據替代這些代碼。

          下面是一個例子:

          <html>
          <head>
          <title>Welcome!</title>
          </head>
          <body>
          <h1>Welcome ${user}!</h1>
          <p>Our latest product:
          <a href="${latestProduct.url}">${latestProduct.name}</a>!
          </body>
          </html>
          
          這個例子是在簡單的HTML中加入了一些由${…}包圍的特定代碼,這些特定代碼是FreeMarker的指令,而包含FreeMarker的指令的文件就稱為模板(Template)。
          至于user、latestProduct.url和latestProduct.name來自于數據模型(data model)。
          數據模型由程序員編程來創建,向模板提供變化的信息,這些信息來自于數據庫、文件,甚至于在程序中直接生成。
          模板設計者不關心數據從那兒來,只知道使用已經建立的數據模型。

          下面是一個可能的數據模型:

          (root)
          |
          +- user = "Big Joe"
          |
          +- latestProduct
          |
          +- url = "products/greenmouse.html"
          |
          +- name = "green mouse"
          
          數據模型類似于計算機的文件系統,latestProduct可以看作是目錄。

          2、數據模型

          (1)基礎

          在快速入門中介紹了在模板中使用的三種基本對象類型:scalars、hashes 和sequences,其實還可以有其它更多的能力:

          • scalars:存儲單值
          • hashes:充當其它對象的容器,每個都關聯一個唯一的查詢名字
          • sequences:充當其它對象的容器,按次序訪問
          • 方法:通過傳遞的參數進行計算,以新對象返回結果
          • 用戶自定義FTL標記:宏和變換器

          通常每個變量只具有上述的一種能力,但一個變量可以具有多個上述能力,如下面的例子:

          (root)
          |
          +- mouse = "Yerri"
          |
          +- age = 12
          |
          +- color = "brown">
          
          mouse既是scalars又是hashes,將上面的數據模型合并到下面的模板:
          ${mouse}       <#-- use mouse as scalar -->
          ${mouse.age}   <#-- use mouse as hash -->
          ${mouse.color} <#-- use mouse as hash -->
          
          輸出結果是:
          Yerri
          12
          brown
          

          (2)Scalar變量

          Scalar變量存儲單值,可以是:

          • 字符串:簡單文本,在模板中使用引號(單引號或雙引號)括起
          • 數字:在模板中直接使用數字值
          • 日期:存儲日期/時間相關的數據,可以是日期、時間或日期-時間(Timestamp);通常情況,日期值由程序員加到數據模型中,設計者只需要顯示它們
          • 布爾值:true或false,通常在<#if …>標記中使用

          (3)hashes 、sequences和集合

          有些變量不包含任何可顯示的內容,而是作為容器包含其它變量,者有兩種類型:

          • hashes:具有一個唯一的查詢名字和它包含的每個變量相關聯
          • sequences:使用數字和它包含的每個變量相關聯,索引值從0開始

          集合變量通常類似sequences,除非無法訪問它的大小和不能使用索引來獲得它的子變量;集合可以看作只能由<#list …>指令使用的受限sequences

          (4)方法

          方法變量通常是基于給出的參數計算值。

          下面的例子假設程序員已經將方法變量avg放到數據模型中,用來計算數字平均值:

          The average of 3 and 5 is: ${avg(3, 5)}
          The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
          The average of the price of python and elephant is:
          ${avg(animals.python.price, animals.elephant.price)}
          

          (5)宏和變換器

          宏和變換器變量是用戶自定義指令(自定義FTL標記),會在后面講述這些高級特性

          (6)節點

          節點變量表示為樹型結構中的一個節點,通常在XML處理中使用,會在后面的專門章節中講

          3、模板

          (1)整體結構

          模板使用FTL(FreeMarker模板語言)編寫,是下面各部分的一個組合:

          • 文本:直接輸出
          • Interpolation:由${和},或#{和}來限定,計算值替代輸出
          • FTL標記:FreeMarker指令,和HTML標記類似,名字前加#予以區分,不會輸出
          • 注釋:由<#--和-->限定,不會輸出

          下面是以一個具體模板例子:

          <html>
          <head>
          <title>Welcome!</title>
          </head>
          <body>
          <#-- Greet the user with his/her name -->
          <h1>Welcome ${user}!</h1>
          <p>We have these animals:
          <ul>
          <#list animals as being>
          <li>${being.name} for ${being.price} Euros
          </#list>
          </ul>
          </body>
          </html>
          

          注意事項:

          • FTL區分大小寫,所以list是正確的FTL指令,而List不是;${name}和${NAME}是不同的
          • Interpolation只能在文本中使用
          • FTL標記不能位于另一個FTL標記內部,例如:
          <#if <#include 'foo'>='bar'>...</if>
          
          • 注釋可以位于FTL標記和Interpolation內部,如下面的例子:
          <h1>Welcome ${user <#-- The name of user -->}!</h1>
          <p>We have these animals:
          <ul>
          <#list <#-- some comment... --> animals as <#-- again... --> being>
          ...
          
          • 余的空白字符會在模板輸出時移除

          (2)指令

          在FreeMarker中,使用FTL標記引用指令。有三種FTL標記,這和HTML標記是類似的:

          • 開始標記:<#directivename parameters>
          • 結束標記:</#directivename>
          • 空內容指令標記:<#directivename parameters/>

          有兩種類型的指令:預定義指令和用戶定義指令。

          用戶定義指令要使用@替換#,如<@mydirective>...</@mydirective>(會在后面講述)。

          FTL標記不能夠交叉,而應該正確的嵌套,如下面的代碼是錯誤的:

          <ul>
          <#list animals as being>
          <li>${being.name} for ${being.price} Euros
          <#if use = "Big Joe">
          (except for you)
          </#list>
          </#if> <#-- WRONG! -->
          </ul>
          
          如果使用不存在的指令,FreeMarker不會使用模板輸出,而是產生一個錯誤消息。

          FreeMarker會忽略FTL標記中的空白字符,如下面的例子:

          <#list
          animals       as
          being
          >
          ${being.name} for ${being.price} Euros
          </#list    >
          
          但是,<、</和指令之間不允許有空白字符。

          (3)表達式

          直接指定值

          • 字符串
          使用單引號或雙引號限定

          如果包含特殊字符需要轉義,如下面的例子:

          ${"It's \"quoted\" and
          this is a backslash: \\"}
          ${'It\'s "quoted" and
          this is a backslash: \\'}
          
          輸出結果是:
          It's "quoted" and
          this is a backslash: \
          It's "quoted" and
          this is a backslash: \
          
          下面是支持的轉義序列:

          轉義序列 含義
          \" 雙引號(u0022)
          \' 單引號(u0027)

          反斜杠(u005C)
          \n 換行(u000A)
          \r Return (u000D)
          \t Tab (u0009)
          \b Backspace (u0008)
          \f Form feed (u000C)
          \l <
          \g >
          \a &
          \{ {
          \xCode 4位16進制Unicode代碼

          有一類特殊的字符串稱為raw字符串,被認為是純文本,其中的\和{等不具有特殊含義,該類字符串在引號前面加r,下面是一個例子:

          ${r"${foo}"}
          ${r"C:\foo\bar"}
          
          輸出的結果是:
          ${foo}
          C:\foo\bar
          
          • 數字

          直接輸入,不需要引號

          精度數字使用“.”分隔,不能使用分組符號

          目前版本不支持科學計數法,所以“1E3”是錯誤的

          不能省略小數點前面的0,所以“.5”是錯誤的

          數字8、+8、08和8.00都是相同的

          • 布爾值

          true和false,不使用引號

          • 序列

          由逗號分隔的子變量列表,由方括號限定,下面是一個例子:

          <#list ["winter", "spring", "summer", "autumn"] as x>
          ${x}
          </#list>
          
          輸出的結果是:
          winter
          spring
          summer
          autumn
          
          列表的項目是表達式,所以可以有下面的例子:
          [2 + 2, [1, 2, 3, 4], "whatnot"]
          
          可以使用數字范圍定義數字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意數字范圍沒有方括號

          可以定義反遞增的數字范圍,如5..2

          • 散列(hash)
          由逗號分隔的鍵/值列表,由大括號限定,鍵和值之間用冒號分隔,下面是一個例子:
          {"name":"green mouse", "price":150}
          
          鍵和值都是表達式,但是鍵必須是字符串

          獲取變量

          • 頂層變量: ${variable},變量名只能是字母、數字、下劃線、$、@和#的組合,且不能以數字開頭
          • 從散列中獲取數據

          可以使用點語法或方括號語法,假設有下面的數據模型:

          (root)
          |
          +- book
          |   |
          |   +- title = "Breeding green mouses"
          |   |
          |   +- author
          |       |
          |       +- name = "Julia Smith"
          |       |
          |       +- info = "Biologist, 1923-1985, Canada"
          |
          +- test = "title"
          
          下面都是等價的:
          book.author.name
          book["author"].name
          book.author.["name"]
          book["author"]["name"]
          
          使用點語法,變量名字有頂層變量一樣的限制,但方括號語法沒有該限制,因為名字是任意表達式的結果
          • 從序列獲得數據:和散列的方括號語法語法一樣,只是方括號中的表達式值必須是數字;注意:第一個項目的索引是0

          序列片斷:使用[startIndex..endIndex]語法,從序列中獲得序列片斷(也是序列);startIndex和endIndex是結果為數字的表達式

          • 特殊變量:FreeMarker內定義變量,使用.variablename語法訪問

          字符串操作

          • Interpolation(或連接操作)

          可以使用${..}(或#{..})在文本部分插入表達式的值,例如:

          ${"Hello ${user}!"}
          ${"${user}${user}${user}${user}"}
          
          可以使用+操作符獲得同樣的結果
          ${"Hello " + user + "!"}
          ${user + user + user + user}
          
          ${..}只能用于文本部分,下面的代碼是錯誤的:
          <#if ${isBig}>Wow!</#if>
          <#if "${isBig}">Wow!</#if>
          
          應該寫成:
          <#if isBig>Wow!</#if>
          
          • 子串

          例子(假設user的值為“Big Joe”):

          ${user[0]}${user[4]}
          ${user[1..4]}
          
          結果是(注意第一個字符的索引是0):
          BJ
          ig J
          
          序列操作
          • 連接操作:和字符串一樣,使用+,下面是一個例子:
          <#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
          - ${user}
          </#list>
          
          輸出結果是:
          - Joe
          - Fred
          - Julia
          - Kate
          
          散列操作
          • 連接操作:和字符串一樣,使用+,如果具有相同的key,右邊的值替代左邊的值,例如:
          <#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
          - Joe is ${ages.Joe}
          - Fred is ${ages.Fred}
          - Julia is ${ages.Julia}
          
          輸出結果是:
          - Joe is 30
          - Fred is 25
          - Julia is 18
          
          算術運算
          • +、-、×、/、%,下面是一個例子:
          ${x * x - 100}
          ${x / 2}
          ${12 % 10}
          
          輸出結果是(假設x為5):
          -75
          2.5
          2
          
          操作符兩邊必須是數字,因此下面的代碼是錯誤的:
          ${3 * "5"} <#-- WRONG! -->
          
          使用+操作符時,如果一邊是數字,一邊是字符串,就會自動將數字轉換為字符串,例如:
          ${3 + "5"}
          
          輸出結果是:
          35
          
          使用內建的int(后面講述)獲得整數部分,例如:
          ${(x/2)?int}
          ${1.1?int}
          ${1.999?int}
          ${-1.1?int}
          ${-1.999?int}
          
          輸出結果是(假設x為5):
          2
          1
          1
          -1
          -1
          
          • 比較操作符

          使用=(或==,完全相等)測試兩個值是否相等,使用!= 測試兩個值是否不相等

          =和!=兩邊必須是相同類型的值,否則會產生錯誤,例如<#if 1 = "1">會引起錯誤

          Freemarker是精確比較,所以對"x"、"x "和"X"是不相等的

          對數字和日期可以使用<、<=、>和>=,但不能用于字符串

          由于Freemarker會將>解釋成FTL標記的結束字符,所以對于>和>=可以使用括號來避免這種情況,例如<#if (x > y)>

          另一種替代的方法是,使用lt、lte、gt和gte來替代<、<=、>和>=

          • 邏輯操作符

          &&(and)、||(or)、!(not),只能用于布爾值,否則會產生錯誤

          例子:

          <#if x < 12 && color = "green">
          We have less than 12 things, and they are green.
          </#if>
          <#if !hot> <#-- here hot must be a boolean -->
          It's not hot.
          </#if>
          
          • 內建函數

          內建函數的用法類似訪問散列的子變量,只是使用“?”替代“.”,下面列出常用的一些函數

            • 字符串使用的:

          html:對字符串進行HTML編碼

          cap_first:使字符串第一個字母大寫

          lower_case:將字符串轉換成小寫

          upper_case:將字符串轉換成大寫

          trim:去掉字符串前后的空白字符

            • 序列使用的:

          size:獲得序列中元素的數目

            • 數字使用的:

          int:取得數字的整數部分(如-1.9?int的結果是-1)

          例子(假設test保存字符串"Tom & Jerry"):

          ${test?html}
          ${test?upper_case?html}
          
          輸出結果是:
          Tom &amp; Jerry
          TOM &amp; JERRY
          
          • 操作符優先順序

          操作符組 操作符
          后綴 [subvarName] [subStringRange] . (methodParams)
          一元 +expr、-expr、!
          內建 ?
          乘法 *、 / 、%
          加法 +、-
          關系 <、>、<=、>=(lt、lte、gt、gte)
          相等 ==(=)、!=
          邏輯and &&
          邏輯or 雙豎線
          數字范圍 ..

          (4)Interpolation

          Interpolation有兩種類型:

          1. 通用Interpolation:${expr}
          1. 數字Interpolation:#{expr}或#{expr; format}

          注意:Interpolation只能用于文本部分

          • 通用Interpolation

          插入字符串值:直接輸出表達式結果

          插入數字值:根據缺省格式(由#setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string格式化單個Interpolation,下面是一個例子:

          <#setting number_format="currency"/>
          <#assign answer=42/>
          ${answer}
          ${answer?string}  <#-- the same as ${answer} -->
          ${answer?string.number}
          ${answer?string.currency}
          ${answer?string.percent}
          
          輸出結果是:
          $42.00
          $42.00
          42
          $42.00
          4,200%
          
          插入日期值:根據缺省格式(由#setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string格式化單個Interpolation,下面是一個使用格式模式的例子:
          ${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}
          ${lastUpdated?string("EEE, MMM d, ''yy")}
          ${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}
          
          輸出的結果類似下面的格式:
          2003-04-08 21:24:44 Pacific Daylight Time
          Tue, Apr 8, '03
          Tuesday, April 08, 2003, 09:24:44 PM (PDT)
          
          插入布爾值:根據缺省格式(由#setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string格式化單個Interpolation,下面是一個例子:
          <#assign foo=true/>
          ${foo?string("yes", "no")}
          
          輸出結果是:
          yes
          
          • 數字Interpolation的#{expr; format}形式可以用來格式化數字,format可以是:

          mX:小數部分最小X位

          MX:小數部分最大X位

          例子:

          <#-- If the language is US English the output is: -->
          <#assign x=2.582/>
          <#assign y=4/>
          #{x; M2}   <#-- 2.58 -->
          #{y; M2}   <#-- 4    -->
          #{x; m1}   <#-- 2.6 -->
          #{y; m1}   <#-- 4.0 -->
          #{x; m1M2} <#-- 2.58 -->
          #{y; m1M2} <#-- 4.0  -->
          

          4、雜項

          (1)用戶定義指令

          宏和變換器變量是兩種不同類型的用戶定義指令,它們之間的區別是宏是在模板中使用macro指令定義,而變換器是在模板外由程序定義,這里只介紹宏

          • 基本用法

          宏是和某個變量關聯的模板片斷,以便在模板中通過用戶定義指令使用該變量,下面是一個例子:

          <#macro greet>
          <font size="+2">Hello Joe!</font>
          </#macro>
          
          作為用戶定義指令使用宏變量時,使用@替代FTL標記中的#
          <@greet></@greet>
          
          如果沒有體內容,也可以使用:
          <@greet/>
          
          • 參數

          在macro指令中可以在宏變量之后定義參數,如:

          <#macro greet person>
          <font size="+2">Hello ${person}!</font>
          </#macro>
          
          可以這樣使用這個宏變量:
          <@greet person="Fred"/> and <@greet person="Batman"/>
          
          輸出結果是:
            <font size="+2">Hello Fred!</font>
          and   <font size="+2">Hello Batman!</font>
          

          宏的參數是FTL表達式,所以下面的代碼具有不同的意思:

          <@greet person=Fred/>
          
          這意味著將Fred變量的值傳給person參數,該值不僅是字符串,還可以是其它類型,甚至是復雜的表達式

          可以有多參數,下面是一個例子:

          <#macro greet person color>
          <font size="+2" color="${color}">Hello ${person}!</font>
          </#macro>
          
          可以這樣使用該宏變量:
          <@greet person="Fred" color="black"/>
          
          其中參數的次序是無關的,因此下面是等價的:
          <@greet color="black" person="Fred"/>
          
          只能使用在macro指令中定義的參數,并且對所有參數賦值,所以下面的代碼是錯誤的:
          <@greet person="Fred" color="black" background="green"/>
          <@greet person="Fred"/>
          
          可以在定義參數時指定缺省值,如:
          <#macro greet person color="black">
          <font size="+2" color="${color}">Hello ${person}!</font>
          </#macro>
          
          這樣<@greet person="Fred"/>就正確了

          宏的參數是局部變量,只能在宏定義中有效

          • 嵌套內容

          用戶定義指令可以有嵌套內容,使用<#nested>指令執行指令開始和結束標記之間的模板片斷

          例子:

          <#macro border>
          <table border=4 cellspacing=0 cellpadding=4><tr><td>
          <#nested>
          </tr></td></table>
          </#macro>
          
          這樣使用該宏變量:
          <@border>The bordered text</@border>
          
          輸出結果:
            <table border=4 cellspacing=0 cellpadding=4><tr><td>
          The bordered text
          </tr></td></table>
          

          <#nested>指令可以被多次調用,例如:

          <#macro do_thrice>
          <#nested>
          <#nested>
          <#nested>
          </#macro>
          <@do_thrice>
          Anything.
          </@do_thrice>
          
          輸出結果:
            Anything.
          Anything.
          Anything.
          
          嵌套內容可以是有效的FTL,下面是一個有些復雜的例子: <@border> <ul> <@do_thrice> <li><@greet person="Joe"/> </@do_thrice> </ul> </@border> }}} 輸出結果:
            <table border=4 cellspacing=0 cellpadding=4><tr><td>
          <ul>
          <li><font size="+2">Hello Joe!</font>
          <li><font size="+2">Hello Joe!</font>
          <li><font size="+2">Hello Joe!</font>
          </ul>
          </tr></td></table>
          
          宏定義中的局部變量對嵌套內容是不可見的,例如:
          <#macro repeat count>
          <#local y = "test">
          <#list 1..count as x>
          ${y} ${count}/${x}: <#nested>
          </#list>
          </#macro>
          <@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>
          
          輸出結果:
              test 3/1: ? ? ?
          test 3/2: ? ? ?
          test 3/3: ? ? ?
          
          • 在宏定義中使用循環變量

          用戶定義指令可以有循環變量,通常用于重復嵌套內容,基本用法是:作為nested指令的參數傳遞循環變量的實際值,而在調用用戶定義指令時,在<@…>開始標記的參數后面指定循環變量的名字

          例子:

          <#macro repeat count>
          <#list 1..count as x>
          <#nested x, x/2, x==count>
          </#list>
          </#macro>
          <@repeat count=4 ; c, halfc, last>
          ${c}. ${halfc}<#if last> Last!</#if>
          </@repeat>
          
          輸出結果:
            1. 0.5
          2. 1
          3. 1.5
          4. 2 Last!
          

          指定的循環變量的數目和用戶定義指令開始標記指定的不同不會有問題

          調用時少指定循環變量,則多指定的值不可見

          調用時多指定循環變量,多余的循環變量不會被創建

          (2)在模板中定義變量

          在模板中定義的變量有三種類型:

          • plain變量:可以在模板的任何地方訪問,包括使用include指令插入的模板,使用assign指令創建和替換
          • 局部變量:在宏定義體中有效,使用local指令創建和替換
          • 循環變量:只能存在于指令的嵌套內容,由指令(如list)自動創建

          宏的參數是局部變量,而不是循環變量;局部變量隱藏(而不是覆蓋)同名的plain變量;循環變量隱藏同名的局部變量和plain變量,下面是一個例子:

          <#assign x = "plain">
          1. ${x}  <#-- we see the plain var. here -->
          <@test/>
          6. ${x}  <#-- the value of plain var. was not changed -->
          <#list ["loop"] as x>
          7. ${x}  <#-- now the loop var. hides the plain var. -->
          <#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
          8. ${x}  <#-- it still hides the plain var. -->
          </#list>
          9. ${x}  <#-- the new value of plain var. -->
          <#macro test>
          2. ${x}  <#-- we still see the plain var. here -->
          <#local x = "local">
          3. ${x}  <#-- now the local var. hides it -->
          <#list ["loop"] as x>
          4. ${x}  <#-- now the loop var. hides the local var. -->
          </#list>
          5. ${x}  <#-- now we see the local var. again -->
          </#macro>
          
          輸出結果:
          1. plain
          2. plain
          3. local
          4. loop
          5. local
          6. plain
          7. loop
          8. loop
          9. plain2
          

          內部循環變量隱藏同名的外部循環變量,如:

          <#list ["loop 1"] as x>
          ${x}
          <#list ["loop 2"] as x>
          ${x}
          <#list ["loop 3"] as x>
          ${x}
          </#list>
          ${x}
          </#list>
          ${x}
          </#list>
          
          輸出結果:
            loop 1
          loop 2
          loop 3
          loop 2
          loop 1
          
          模板中的變量會隱藏(而不是覆蓋)數據模型中同名變量,如果需要訪問數據模型中的同名變量,使用特殊變量global,下面的例子假設數據模型中的user的值是Big Joe:
          <#assign user = "Joe Hider">
          ${user}          <#-- prints: Joe Hider -->
          ${.globals.user} <#-- prints: Big Joe -->
          

          (3)名字空間

          通常情況,只使用一個名字空間,稱為主名字空間

          為了創建可重用的宏、變換器或其它變量的集合(通常稱庫),必須使用多名字空間,其目的是防止同名沖突

          • 創建庫

          下面是一個創建庫的例子(假設保存在lib/my_test.ftl中):

          <#macro copyright date>
          <p>Copyright (C) ${date} Julia Smith. All rights reserved.
          <br>Email: ${mail}</p>
          </#macro>
          <#assign mail = "jsmith@acme.com">
          
          使用import指令導入庫到模板中,Freemarker會為導入的庫創建新的名字空間,并可以通過import指令中指定的散列變量訪問庫中的變量:
          <#import "/lib/my_test.ftl" as my>
          <#assign mail="fred@acme.com">
          <@my.copyright date="1999-2002"/>
          ${my.mail}
          ${mail}
          
          輸出結果:
            <p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
          <br>Email: jsmith@acme.com</p>
          jsmith@acme.com
          fred@acme.com
          
          可以看到例子中使用的兩個同名變量并沒有沖突,因為它們位于不同的名字空間

          可以使用assign指令在導入的名字空間中創建或替代變量,下面是一個例子:

          <#import "/lib/my_test.ftl" as my>
          ${my.mail}
          <#assign mail="jsmith@other.com" in my>
          ${my.mail}
          
          輸出結果:
          jsmith@acme.com
          jsmith@other.com
          
          數據模型中的變量任何地方都可見,也包括不同的名字空間,下面是修改的庫:
          <#macro copyright date>
          <p>Copyright (C) ${date} ${user}. All rights reserved.</p>
          </#macro>
          <#assign mail = "${user}@acme.com">
          
          假設數據模型中的user變量的值是Fred,則下面的代碼:
          <#import "/lib/my_test.ftl" as my>
          <@my.copyright date="1999-2002"/>
          ${my.mail}
          
          輸出結果:
            <p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>
          Fred@acme.com
          
          posted @ 2008-08-12 14:14 飛飛 閱讀(236) | 評論 (0)編輯 收藏

          <a href="javascript:void(window.open('1.htm','_blank','toolbar=no,scrollbar=no,top=50,left=50,width=100,height=100'));" >Open 1.htm</a>

          <a href="javascript: var win=window.open
          ('1.htm','_blank','toolbar=no,scrollbar=no,top=50,left=50,width=100,height=100')" >Open
          1.htm</a>
          最好。
          <a href="#" onclick="window.open('1.htm','_blank','toolbar=no,scrollbar=no,top=50,left=50,width=100,height=100')" >Open 1.htm</a>
          點擊后,原窗口的聯接地址會發生變化,加上了#,感覺不太好:)雖然也能實現功能
          posted @ 2008-08-11 18:44 飛飛 閱讀(983) | 評論 (2)編輯 收藏

          視圖解析器的一些屬性

          <bean id="viewResolver"

                class="org.springframework.web.servlet.view.InternalResourceViewResolver">

              <property name="exposeSpringMacroHelpers" value="true"/>

              <property name="requestContextAttribute" value="rc"/>

              <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>

              <property name="prefix" value="/"/>

              <property name="suffix" value=".jsp"/>

          </bean>

          在視圖解析器的定義中,“exposeSpringMacroHelpers”設置是否通過Spring的宏庫暴露一個RequestContext(名為springBindRequestContext)供外部使用,默認值為false。它暴露了處理表單和驗證錯誤信息的宏操作;

          requestContextAttribute”把SpringRequestContext對象暴露為變量rc。利用${rc.contextPath}來獲取應用程序的contextPath(也就是/MyUsers);利用${rc.getMessage("user.name")}讀取/WEB-INF/classes/messages.properties本地化信息。此對象對于那些不訪問serlvet請求的View技術(也就是VelocityFreeMarker模板)來說是必不可少的。

          還有一些屬性:

          exposeRequestAttributes:默認值false,設置是否所有的request屬性在與模板進行合并之前添加到model中。(可以理解為request范圍內包含的所有對象,而不是一個真正的Request對象。)

          exposeSessionAttributes:默認值false,設置是否所有的session屬性在與模板進行合并之前添加到model中。(理解同上)

          posted @ 2008-08-11 17:20 飛飛 閱讀(482) | 評論 (0)編輯 收藏

          Step 1:配置web.xml
          <?xml version="1.0" encoding="UTF-8"?>
          <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
              xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation
          ="http://java.sun.com/xml/ns/j2ee 
              http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
          >


              
          <display-name>springapp</display-name>
                  
              
          <servlet>
                  
          <servlet-name>springMVC</servlet-name>
                  
          <servlet-class>
                      org.springframework.web.servlet.DispatcherServlet
                  
          </servlet-class>
                  
          <load-on-startup>1</load-on-startup>
              
          </servlet>

              
          <servlet-mapping>
                  
          <servlet-name>springMVC</servlet-name>
                  
          <url-pattern>/page/*</url-pattern>
              
          </servlet-mapping>

          </web-app>
          servlet-mapping定義所有以/page/開頭的url請求都會被spring 的DispatcherServlet處理轉發。默認情況下DispatcherServlet會讀取<servlet-name>-servlet.xml文件的配置信息初始化,該文件中urlMapping的定義決定當前請求轉發給哪個controller來處理。

          Step2:
          定義/WEB-INF/springMVC-servlet.xml
           
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

          <beans>
              
          <!-- 方法名解析器 -->
              
          <bean id="InternalPathMethodNameResolver"
                  class
          ="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />
                  
              
          <!-- 視圖解析器 -->
              
          <bean id="viewResolver"
                  class
          ="org.springframework.web.servlet.view.InternalResourceViewResolver">
                  
          <property name="viewClass">
                      
          <value>org.springframework.web.servlet.view.JstlView</value>
                  
          </property>
              
          </bean>
              
              
          <bean id="controller" class="com.controller.IndexController">
                  
          <property name="methodNameResolver">
                      
          <ref bean="InternalPathMethodNameResolver" />
                  
          </property>
              
          </bean>

              
          <bean id="urlMapping"
                  class
          ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                  
          <property name="mappings">
                      
          <props>
                          
          <prop key="/controller/*">controller</prop>
                      
          </props>
                  
          </property>
              
          </bean>
          </beans>
          urlMapping定義/controller/開頭的url請求由名字為controller的控制器來處理,因為是多動作處理器,所以要定義MethodNameResolver來告訴springMVC應該調用controller的哪個方法,這里用的是InternalPathMethodNameResolver,該方法名解釋器會把整個URL中最后一個"/"和最后一個"."之間的部分作為要調用的方法名。

          Step3:定義controller類并繼承MultiActionController 
          package com.controller;

          import
           java.io.IOException;
          import
           java.util.HashMap;
          import
           java.util.Map;

          import
           javax.servlet.ServletException;
          import
           javax.servlet.http.HttpServletRequest;
          import
           javax.servlet.http.HttpServletResponse;

          import
           org.springframework.web.servlet.ModelAndView;
          import
           org.springframework.web.servlet.mvc.multiaction.MultiActionController;

          public class IndexController extends MultiActionController 
          {
              
              
          public
           ModelAndView method1(HttpServletRequest request,
                      HttpServletResponse respnose) 
          throws ServletException, IOException 
          {
                  Map model 
          = new
           HashMap();
                  model.put(
          "message""你調用的是方法1"
          );
                  
          return new ModelAndView("/index.jsp""model"
          , model);
              }

              
              
          public ModelAndView method2(HttpServletRequest request,
                      HttpServletResponse respnose) 
          throws ServletException, IOException 
          {
                  Map model 
          = new
           HashMap();
                  model.put(
          "message""你調用的是方法2"
          );
                  
          return new ModelAndView("/index.jsp""model"
          , model);
              }

          }


          通過配置文件,訪問上面這個controller中某個方法的url即為:localhost:8080/page/controller/方法名


          Step4:/index.jsp
          <%@ page language="java" pageEncoding="UTF-8"%>
          <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
          <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt"%> 


          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

          <html>
          <head></head>  
          <body>

              
          <c:out value="${model.message}"/>
          </body>
          </html>
          因為InternalPathMethodNameResolver方法名解釋器會把整個URL中最后一個"/"和最后一個"."之間的部分作為要調用的方法名,所以你可以在這個URL后面加任意文件格式的后綴,比如:
          localhost:8080/page/controller/method1.jsp

          localhost:8080/page/controller/method2.html
          很爽吧,和真實的URL地址一樣。


          另:開發環境:MyEclipse5.0M2+tomcat5.5
            需要用到spring.jar和jstl.jar兩個包。
          posted @ 2008-08-11 16:02 飛飛 閱讀(217) | 評論 (0)編輯 收藏

          servlet 2.5的寫法
              <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"
          version="2.5">

          別以為看到這里就結束了,很可惜地告訴你,這段代碼是錯誤的。不信你嘗試打開一下這個鏈接http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd,你會發現是no page found。

          那為什么tomcat6的范例程序能夠工作呢,那是因為在tomcat6的lib里面,已經存在這個文件,所以也不需要從網絡上面抓取。其實你按照這個web.xml寫了servlet 2.5的程序,在tomcat6里面也是可以運行的。

          可是當我使用eclipse+xmlbuddy的時候,問題就出來了,因為web-app_2_5.xsd一直不能下載,xmlbuddy一直報錯,并且沒有語法提示功能。通過搜索,我發現了web-app_2_5.xsd的真實地址其實是http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd,而它的namespace是http://java.sun.com/xml/ns/javaee,于是代碼應該改成:

              <web-app xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          version="2.5">

          留意一下不同的部分,其實是因為sun把j2ee改名為javaee。

          ps,另外附上servlet 2.4的寫法

              <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
          version="2.4">
          posted @ 2008-08-11 10:13 飛飛 閱讀(539) | 評論 (0)編輯 收藏

          1. 實體(表)的命名
            1) 表以名詞或名詞短語命名,確定表名是采用復數還是單數形式,此外給表的別名定義簡單規則(比方說,如果表名是一個單詞,別名就取單詞的前4 個字母;如果表名是兩個單詞,就各取兩個單詞的前兩個字母組成4 個字母長的別名;如果表的名字由3 個單詞組成,從頭兩個單詞中各取一個然后從最后一個單詞中再取出兩個字母,結果還是組成4 字母長的別名,其余依次類推)
            對工作用表來說,表名可以加上前綴WORK_ 后面附上采用該表的應用程序的名字。在命名過程當中,根據語義拼湊縮寫即可。注意,由于ORCLE會將字段名稱統一成大寫或者小寫中的一種,所以要求加上下劃線。
            舉例:
            定義的縮寫 Sales: Sal 銷售;
            Order: Ord 訂單;
            Detail: Dtl 明細;
            則銷售訂單明細表命名為:Sal_Ord_Dtl;
            2) 如果表或者是字段的名稱僅有一個單詞,那么建議不使用縮寫,而是用完整的單詞。
            舉例:
            定義的縮寫 Material Ma 物品;
            物品表名為:Material, 而不是 Ma.
            但是字段物品編碼則是:Ma_ID;而不是Material_ID
            3) 所有的存儲值列表的表前面加上前綴Z
            目的是將這些值列表類排序在數據庫最后。
            4) 所有的冗余類的命名(主要是累計表)前面加上前綴X
            冗余類是為了提高數據庫效率,非規范化數據庫的時候加入的字段或者表
            5) 關聯類通過用下劃線連接兩個基本類之后,再加前綴R的方式命名,后面按照字母順序羅列兩個表名或者表名的縮寫。
            關聯表用于保存多對多關系。
            如果被關聯的表名大于10個字母,必須將原來的表名的進行縮寫。如果沒有其他原因,建議都使用縮寫。
            舉例:表Object與自身存在多對多的關系,則保存多對多關系的表命名為:R_Object;
            表 Depart和Employee;存在多對多的關系;則關聯表命名為R_Dept_Emp
            2. 屬性(列)的命名
            1) 采用有意義的列名,表內的列要針對鍵采用一整套設計規則。每一個表都將有一個自動ID作為主健,邏輯上的主健作為第一組候選主健來定義,如果是數據庫自動生成的編碼,統一命名為:ID;如果是自定義的邏輯上的編碼則用縮寫加“ID”的方法命名。如果鍵是數字類型,你可以用_NO 作為后綴;如果是字符類型則可以采用_CODE 后綴。對列名應該采用標準的前綴和后綴。
            舉例:銷售訂單的編號字段命名:Sal_Ord_ID;如果還存在一個數據庫生成的自動編號,則命名為:ID。
            2) 所有的屬性加上有關類型的后綴,注意,如果還需要其它的后綴,都放在類型后綴之前。
            注: 數據類型是文本的字段,類型后綴TX可以不寫。有些類型比較明顯的字段,可以不寫類型后綴。
            3) 采用前綴命名
            給每個表的列名都采用統一的前綴,那么在編寫SQL表達式的時候會得到大大的簡化。這樣做也確實有缺點,比如破壞了自動表連接工具的作用,后者把公共列名同某些數據庫聯系起來。
            3. 視圖的命名
            1) 視圖以V作為前綴,其他命名規則和表的命名類似;
            2) 命名應盡量體現各視圖的功能。
            4. 觸發器的命名
            觸發器以TR作為前綴,觸發器名為相應的表名加上后綴,Insert觸發器加"_I",Delete觸發器加"_D",Update觸發器加"_U",如:

            TR_Customer_I,TR_Customer_D,TR_Customer_U。
            5. 存儲過程名
            存儲過程應以"UP_"開頭,和系統的存儲過程區分,后續部分主要以動賓形式構成,并用下劃線分割各個組成部分。如增加代理商的帳戶的存儲過程為"UP_Ins_Agent_Account"。
            6. 變量名
            變量名采用小寫,若屬于詞組形式,用下劃線分隔每個單詞,如@my_err_no。
            7. 命名中其他注意事項
            1)  以上命名都不得超過30個字符的系統限制。變量名的長度限制為29(不包括標識字符@)。
            2)  數據對象、變量的命名都采用英文字符,禁止使用中文命名。絕對不要在對象名的字符之間留空格。
            3) 小心保留詞,要保證你的字段名沒有和保留詞、數據庫系統或者常用訪問方法沖突
            5) 保持字段名和類型的一致性,在命名字段并為其指定數據類型的時候一定要保證一致性。假如數據類型在一個表里是整數,那在另一個表里可就別變成字符型了。

          posted @ 2008-08-08 10:00 飛飛 閱讀(456) | 評論 (0)編輯 收藏

          如果底層數據庫(如Oracle)支持存儲過程,也可以通過存儲過程來執行批量更新。存儲過程直接在數據庫中運行,速度更加快。在Oracle數據庫中可以定義一個名為batchUpdateStudent()的存儲過程,代碼如下:

          create or replace procedure batchUpdateStudent(p_age in number) as
          begin
          update STUDENT set AGE=AGE+1 where AGE>p_age;
          end;

          以上存儲過程有一個參數p_age,代表學生的年齡,應用程序可按照以下方式調用存儲過程:

          tx = session.beginTransaction();
          Connection con=session.connection();

          String procedure = "{call batchUpdateStudent(?) }";
          CallableStatement cstmt = con.prepareCall(procedure);
          cstmt.setInt(1,0); //把年齡參數設為0
          cstmt.executeUpdate();
          tx.commit();

          在以上代碼中,用的是Hibernate的 Transaction接口來聲明事務,而不是采用JDBC API來聲明事務。

          posted @ 2008-08-08 09:53 飛飛 閱讀(345) | 評論 (0)編輯 收藏

          BUG1
          2008-08-07 11:25:01,015 DEBUG (FacesSetupInterceptor.java:136) - Unable to initialize faces
           java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
           at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:256)
           at org.apache.struts2.jsf.FacesSetupInterceptor.init(FacesSetupInterceptor.java:133)
           at com.opensymphony.xwork2.ObjectFactory.buildInterceptor(ObjectFactory.java:186)
           at com.opensymphony.xwork2.config.providers.InterceptorBuilder.constructInterceptorReference(InterceptorBuilder.java:57)
           at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.lookupInterceptorReference(XmlConfigurationProvider.java:905)
           at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStack(XmlConfigurationProvider.java:743)
           at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStacks(XmlConfigurationProvider.java:756)
           at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptors(XmlConfigurationProvider.java:777)
           at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:410)
           at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:239)
           at org.apache.struts2.config.StrutsXmlConfigurationProvider.loadPackages(StrutsXmlConfigurationProvider.java:111)
           at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reload(DefaultConfiguration.java:152)
           at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:52)
           at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:395)
           at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:452)
           at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:201)
           at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
           at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
           at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
           at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3693)
           at org.apache.catalina.core.StandardContext.start(StandardContext.java:4340)
           at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
           at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
           at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
           at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
           at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
           at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
           at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
           at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
           at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
           at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
           at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
           at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
           at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
           at org.apache.catalina.core.StandardService.start(StandardService.java:516)
           at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
           at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
           at java.lang.reflect.Method.invoke(Unknown Source)
           at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
           at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

          這個錯誤是由配置文件引起。在session-factory段加入:
          <property name="current_session_context_class">thread</property>
          posted @ 2008-08-07 11:31 飛飛 閱讀(428) | 評論 (0)編輯 收藏

               摘要: 一. 簡介 1. 簡介 目前的版本是:4.0 正式版 發布于2008-05-30 2. 注意事項 My97DatePicker目錄是一個整體,不可破壞里面的目錄結構,也不可對里面的文件改名,可以改目錄名 My97DatePicker.htm是必須文件,不可刪除 各目錄及文件的用途: WdatePicker.js 配置文件,在調用的地方僅需使用該文...  閱讀全文
          posted @ 2008-08-06 09:09 飛飛 閱讀(3013) | 評論 (0)編輯 收藏

          1、MyEclipse下建立新的Web Porject

          2、Copy Struts2的lib文件到工程的WEB-INF/lib下非*-plugin-2.0.6.jar的所有的包加上struts2-spring- plugin-2.0.6.jar,最小的包可以在struts-2.0.6\apps\struts2-blank-2.0.6\WEB-INF\ lib下找到,不過因為使用Spring、Hiberate那點包是不夠用的

          3.1、工程名上右鍵->MyEclipse->Add Spring Capabilities點擊出現對話框

          3.2、由于我用的MyEclipse中Spring的插件是1.2的,所以沒使用MyEclipse下的包,不選擇MyEclipse Libraries

          3.3、選中Copy checked library contents to project folder (TLDs always copied)

          3.4、使用默認的Library Folder:/WebRoot/WEB-INF/lib,Next

          3.5、Folder點周Brower選中項目的WebRoot/WEB-INF/

          3.6、點擊Finish

          4、配置MyEclipse數據庫設置

          4.1、菜單Windows->Preferences->MyEclipse->Database Explorer->Drivers

          4.2、點擊New設置數據庫連接,例:
          Driver template : Oracle (Thin driver)
          Driver name : Oracle (Thin driver)
          Connection URL : jdbc:oracle:thin:@<server>[:<1521>]:<database_name>
          Driver JARs: ojdbc14.jar
          Dirver classname : oracle.jdbc.driver.OracleDriver

          4.3、點擊OK、OK

          5、忘了Copy Spring 2的jar包到工程中了,不過沒關系,現在Copy也一樣,Copy spring-framework-2.0.3\dist\spring.jar 到/WebRoot/WEB-INF/lib下就可以了,如果想Copy專用的包可以Copy spring-framework-2.0.3\dist\modules下的

          5.1、菜單Windows->Open perspective->MyEclipse Database Explorer

          5.2、在DB Brower點右鍵->New

          5.3、配置例子如下:
          Profile name: test
          Driver: Oracle (Thin driver)
          URL: jdbc:oracle:thin:@127.0.0.1:1521:test
          User name: test
          Password: test
          選中Save password

          5.4、點擊Finish

          6.1、配置Hibernate

          6.2 工程名上右鍵->MyEclipse->Add Hiberate Capabilities點擊出現對話框

          6.3、選中Copy checked Library Jars to project forlder and add to build-path 點擊Next

          6.4、選中Spring configuration file (applicationContext.xml)點擊Next

          6.5、選中Existing Spring configuration file,MyEclipse會幫你自動找到Spring Config文件的

          6.6、SessionFactory ID填寫sessionFactory點擊Next

          6.7、Bean Id填寫dataSource,選中DB Profile下剛才建好的test,點擊Next

          6.8、不選擇Create SessionFactory class?點擊Finish

          7、這時候會提示你某些類沒發現,Copy commons-dbcp-1.2.1.jar到lib下就OK了


          8 配置struts.properties文件,指定spring作為struts的IoC容器
          struts.objectFactory = spring
          (1)默認的autowiring模式是:by name
          即如果applicationContext.xml文件中的bean id與struts.xml文件中的action name相同,就
          (2)如果要改為其他模式:
          struts.objectFactory.spring.autoWire = name|type|auto|constructor

          例:

          struts.i18n.encoding=ISO-8859-1
          struts.locale=de_DE
          struts.objectFactory=spring
          ### Load custom default resource bundles
          struts.custom.i18n.resources=testmessages
          ### XSLT Cache
          struts.xslt.nocache = true


          9配置web.xml文件,啟動Spring偵聽器
          <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          </listener>

          10 在WEB-INF目錄下的applicationContext.xml文件
          例:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" " <beans default-autowire="autodetect">
          <bean id="personManager" class="com.acme.PersonManager"/>
          </beans >

          11 設置由Spring來初始化action
          11.1  在Spring的applicationContext.xml文件中配置bean(即action類)
          11.2  將struts.xml中的action的class屬性,由class名改為Spring中定義的bean名
          例如:
          (1)applicationContext.xml中,定義bean id是bar
          <beans default-autowire="autodetect">
          <bean id="bar" class="com.my.BarClass" singleton="false"/>
          ...
          </beans>
          (2)struts.xml中,action的class="bar",而不是通常的類名
          <package name="secure" namespace="/secure" extends="default">
          <action name="bar" class="bar">
          <result>bar.ftl</result>
          </action>
          </package >

          啟動運行:
          報錯
          log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
          log4j:WARN Please initialize the log4j system properly.
          2008-8-6 9:29:16 org.apache.catalina.core.ApplicationContext log
          信息: Initializing Spring root WebApplicationContext
          2008-8-6 9:29:18 org.apache.catalina.core.StandardContext listenerStart
          嚴重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
          org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:883)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:839)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
           at java.security.AccessController.doPrivileged(Native Method)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
           at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
           at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
           at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
           at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
           at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
           at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
           at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
           at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
           at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
           at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
           at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
           at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3827)
           at org.apache.catalina.core.StandardContext.start(StandardContext.java:4334)
           at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
           at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
           at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
           at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
           at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
           at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
           at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
           at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
           at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
           at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
           at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
           at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
           at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
           at org.apache.catalina.core.StandardService.start(StandardService.java:516)
           at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
           at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
           at java.lang.reflect.Method.invoke(Unknown Source)
           at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
           at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
          Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
           at java.lang.Class.getDeclaredConstructors0(Native Method)
           at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
           at java.lang.Class.getConstructor0(Unknown Source)
           at java.lang.Class.getDeclaredConstructor(Unknown Source)
           at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:54)
           at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:877)
           ... 40 more
          2008-8-6 9:29:18 org.apache.catalina.core.StandardContext start
          嚴重: Error listenerStart
          2008-8-6 9:29:18 org.apache.catalina.core.StandardContext start
          嚴重: Context [/ssh] startup failed due to previous errors

          原因:
          找不到 Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
          就Apache所提供的基本對象池。

          解決:
          到這里
          http://commons.apache.org/downloads/download_pool.cgi下載包,然后,把里面的commons-pool-x.jar復制到項目的lib文件夾下

          錯誤:
          log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
          log4j:WARN Please initialize the log4j system properly.

          解決:
          在WEB-INF/class 目錄下建立一個log4j.properties文件,內容如下:
          log4j.rootLogger=DEBUG,stdout
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
          log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n

          警告:

          信息: Starting Servlet Engine: Apache Tomcat/6.0.13
          log4j:WARN No appenders could be found for logger (org.apache.struts.util.PropertyMessageResources).
          log4j:WARN Please initialize the log4j system properly.
          2008-8-6 9:40:09 org.apache.catalina.core.ApplicationContext log
          信息: Initializing WebApplicationContext for Struts ActionServlet 'action', module ''
          2008-08-06 09:40:29,859 DEBUG (CollectionFactory.java:195) - Creating [java.util.concurrent.ConcurrentHashMap]
           2008-8-6 9:40:29 org.apache.catalina.core.ApplicationContext log
          信息: Initializing Spring root WebApplicationContext
          2008-08-06 09:40:29,906  INFO (ContextLoader.java:189) - Root WebApplicationContext: initialization started
           2008-08-06 09:40:30,203  INFO (AbstractApplicationContext.java:412) - Refreshing org.springframework.web.context.support.XmlWebApplicationContext@1df59bd: display name [Root WebApplicationContext]; startup date [Wed Aug 06 09:40:30 CST 2008]; root of context hierarchy
           2008-08-06 09:40:30,406 DEBUG (CollectionFactory.java:195) - Creating [java.util.concurrent.ConcurrentHashMap]


          index.jsp

          <%@ page language="java" pageEncoding="GBK"%>
          <%@ taglib prefix="s" uri="/struts-tags"%>
          <html>
           <head>
            <title>登錄</title>
            <style type="text/css">
          .label {
           font-style: italic;
          }

          .errorLabel {
           font-style: italic;
           color: red;
          }

          .errorMessage {
           font-weight: bold;
           color: red;
          }
          </style>
           </head>
           <s:head theme="ajax" />
           <body>
           <s:debug>
            <s:form action="First">
             <s:textfield name="username" label="用戶名" />
             <s:textfield name="password" label="密碼" />
             <s:submit value="登錄" />
             <s:a href="First.action">登錄</s:a>
            </s:form>
          </s:debug>
           </body>
          </html>



          BUG:
          2008-8-6 10:58:02 org.apache.catalina.core.StandardWrapperValve invoke
          嚴重: Servlet.service() for servlet jsp threw exception
          The Struts dispatcher cannot be found.  This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the request has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag. - [unknown location]
           at org.apache.struts2.views.jsp.TagUtils.getStack(TagUtils.java:60)
           at org.apache.struts2.views.jsp.StrutsBodyTagSupport.getStack(StrutsBodyTagSupport.java:52)
           at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:49)
           at org.apache.jsp.index_jsp._jspx_meth_s_005fhead_005f0(index_jsp.java:126)
           at org.apache.jsp.index_jsp._jspService(index_jsp.java:94)
           at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
           at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
           at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
           at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
           at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
           at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
           at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
           at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
           at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
           at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
           at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
           at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
           at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
           at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
           at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
           at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
           at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
           at java.lang.Thread.run(Unknown Source)

          解決:web.xml添加
          <filter>
            <filter-name>struts2</filter-name>
            <filter-class>
             org.apache.struts2.dispatcher.FilterDispatcher
            </filter-class>
           </filter>
           <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
           </filter-mapping>


          posted @ 2008-08-06 09:07 飛飛 閱讀(2002) | 評論 (0)編輯 收藏

          僅列出標題
          共12頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
          主站蜘蛛池模板: 牙克石市| 宽城| 哈尔滨市| 杭州市| 临猗县| 东海县| 赤水市| 岐山县| 安龙县| 奉节县| 河源市| 营山县| 盐边县| 禹州市| 外汇| 沿河| 台江县| 辽阳县| 东兰县| 关岭| 福州市| 右玉县| 万安县| 阿尔山市| 新安县| 苗栗市| 兰西县| 微山县| 新乡县| 台山市| 铜梁县| 金沙县| 佛坪县| 鹤庆县| 杂多县| 咸丰县| 苏尼特左旗| 兰溪市| 神池县| 灵台县| 夏邑县|