|
||||||||
|
<html:radio idName=" idName "? value="value"? name=" name" property=" property " /> 表示在輸出時,html:radio輸出為input type="radio";name輸出為name="name";對 于value的輸出,當不指定idName時,value="value",當指定idName時,輸出是由bean 名為" idName ",屬性名為"value"的屬性值;當bean名為" name ",屬性名為" property "的屬性值等于上述value的輸出值時,輸出checked="checked"。 我的例子: <logic:iterate id = "answer" name = "answerList" scope = "page"> <html:radio idName = "answer" value = "answerItem" name = "question" property = "rightAnswer" ></html:radio> </logic:iterate> 如果從bean answer的answerItem屬性中取出的值等于從bean question的rightAnswer 屬性中取出的值相等,那么該radio將被選中 |
|
1. 一個表如果建有大量索引會影響 INSERT、UPDATE 和 DELETE 語句的性能,因為在表中的數據更改時,所有索引都須進行適當的調整。另一方面,對于不需要修改數據的查詢(SELECT 語句),大量索引有助于提高性能,因為數據庫有更多的索引可供選擇,以便確定以最快速度訪問數據的最佳方法。 2. 組合索引:組合索引即多列索引,指一個索引含有多個列。一個組合索引相當于多個單列索引,如索引(ColA, ColB, ColC)至少相當于(ColA)、(ColA, ColB)、(ColA, ColB, ColC)三個索引。 2. 覆蓋的查詢可以提高性能。覆蓋的查詢是指查詢中所有指定的列都包含在同一個索引(組合索引)中。例如,如果在一個表的 a、b 和 c 列上創建了組合索引,則從該表中檢索 a 和 b 列的查詢被視為覆蓋的查詢。創建覆蓋一個查詢的索引可以提高性能,因為該查詢的所有數據都包含在索引自身當中;檢索數據時只需引用表的索引頁,不必引用數據頁,因而減少了 I/O 總量。盡管給索引添加列以覆蓋查詢可以提高性能,但在索引中額外維護更多的列會產生更新和存儲成本。 3. 對小型表進行索引可能不會產生優化效果,因為數據庫在遍歷索引以搜索數據時,花費的時間可能會比簡單的表掃描還長。 4. 應使用 SQL 事件探查器和索引優化向導幫助分析查詢,確定要創建的索引。為數據庫及其工作負荷選擇正確的索引是非常復雜的,需要在查詢速度和更新成本之間取得平衡。窄索引(搜索關鍵字中只有很少的列的索引)需要的磁盤空間和維護開銷都更少。而另一方面,寬索引可以覆蓋更多的查詢。確定正確的索引集沒有簡便的規則。經驗豐富的數據庫管理員常常能夠設計出很好的索引集,但是,即使對于不特別復雜的數據庫和工作負荷來說,這項任務也十分復雜、費時和易于出錯。可以使用索引優化向導使這項任務自動化。有關更多信息,請參見索引優化向導。 5. 可以在視圖上指定索引。 6. 可以在計算列上指定索引。 7. 避免在索引列上使用IS NULL和IS NOT NULL。避免在索引中使用任何可以為空的列,數據庫將無法使用該索引。對于單列索引,如果列包含空值,索引中將不存在此記錄;對于復合索引,如果每個列都為空,索引中同樣不存在此記錄. 如果至少有一個列不為空,則記錄存在于索引中。 8. 如果經常檢索包含大量數據的表中的少于15%的行則需要創建索引。 9. 衡量索引效率的 95/5 規則:如果查詢的結果返回的行數少于表中所有行的5%,則索引是檢索數據的最快方法,如果查詢的結果超過5%,那么通常使用索引就不是最快的方式。 10.主關鍵字和唯一關鍵字所在的列自動具有索引,但外部關鍵字沒有自動索引。
●聚集還是非聚集 |
|
基礎
sysibm.sysdummy1表是一個特殊的內存中的表,用它可以發現如上面演示的 db2 寄存器的值。您也可以使用關鍵字 values 來對寄存器或表達式求值。例如,在 db2 命令行處理器(command line processor,clp)上,以下 sql 語句揭示了類似信息:
在余下的示例中,我將只提供函數或表達式,而不再重復 要使當前時間或當前時間戳記調整到 gmt/cut,則把當前的時間或時間戳記減去當前時區寄存器:
給定了日期、時間或時間戳記,則使用適當的函數可以單獨抽取出(如果適用的話)年、月、日、時、分、秒及微秒各部分:
從時間戳記單獨抽取出日期和時間也非常簡單:
因為沒有更好的術語,所以您還可以使用英語來執行日期和時間計算:
要計算兩個日期之間的天數,您可以對日期作減法,如下所示:
而以下示例描述了如何獲得微秒部分歸零的當前時間戳記:
如果想將日期或時間值與其它文本相銜接,那么需要先將該值轉換成字符串。為此,只要使用 char() 函數:
要將字符串轉換成日期或時間值,可以使用:
timestamp()、date() 和 time() 函數接受更多種格式。上面幾種格式只是示例,我將把它作為一個練習,讓讀者自己去發現其它格式。
日期函數
對于 <n>,可以使用以下各值來替代,以指出結果的時間單位:
當日期很接近時使用 timestampdiff() 比日期相差很大時精確。如果需要進行更精確的計算,可以使用以下方法來確定時差(按秒計):
為方便起見,還可以對上面的方法創建 sql 用戶定義的函數:
如果需要確定給定年份是否是閏年,以下是一個很有用的 sql 函數,您可以創建它來確定給定年份的天數:
最后,以下是一張用于日期操作的內置函數表。它旨在幫助您快速確定可能滿足您要求的函數,但未提供完整的參考。有關這些函數的更多信息,請參考 sql 參考大全。
改變日期格式
也就是說,日期的格式是 mm/dd/yyyy. 如果想要改變這種格式,你可以通過綁定特定的 db2 工具包來實現. 其他被支持的日期格式包括:
在 windows 環境下,要將缺省的日期和時間格式轉化成 iso 格式(yyyy-mm-dd),執行下列操作:
現在,你可以看到你的數據庫已經使用 iso 作為日期格式了:
定制日期/時間格式
下面是這個 udf 的代碼:
乍一看,函數的代碼可能顯得很復雜,但是在仔細研究之后,你會發現這段代碼其實非常簡單而且很優雅。最開始,我們使用了一個公共表表達式(cte)來將一個時間戳記(第一個輸入參數)分別剝離為單獨的時間元素。然后,我們檢查提供的定制格式(第二個輸入參數)并將前面剝離出的元素按照該定制格式的要求加以組合。 這個函數還非常靈活。如果要增加另外一種模式,可以很容易地再添加一個 when 子句來處理。在使用過程中,如果用戶提供的格式不符合任何在 when 子句中定義的任何一種模式時,函數會返回一個錯誤信息。 使用方法示例:
? |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||
|
JSP視窗組件所使用的struts標記庫由四類標記組成: 2. Bean標記:用來在JSP頁中管理bean 3. 邏輯標記:用來在JSP頁中控制流程 4. HTML標記:用來生成HTML標記,在表單中顯示數據,使用會話ID對URL進行編程 5. 模板標記:使用動態模板構造普通格式的頁 2.1 Bean標記 這個標記庫中包含用于定義新bean、訪問bean及其屬性的標記。Struts框架提供了多種自定義標記用來在JSP頁中處理JavaBean。這些標記被封裝在一個普通的標記庫中,在文件struts-bean.tld中定義了它的標記庫描述器。Bean標記庫將標記定義在四個子類別中: 創建和復制bean的標記 腳本變量定義標記 bean翻譯標記 消息國際化標記 2.1.1 Bean復制標記 可定義新bean,可復制現有bean,還可從現有bean復制屬性。 <bean:define>標記用來: 定義新字符串常數 將現有的bean復制到新定義的bean對象 復制現有bean的屬性來創建新的bean <bean:define>標記屬性: 屬性描述Id 新定義的bean腳本變量名稱,必須設置Type 定義引入腳本變量的類Value 為id屬性定義的腳本變量分配一個新的對象Name 目標bean的名稱。若value屬性沒有設置,這個屬性就必須設置property Name屬性定義的bean的屬性名稱,用來定義新的bean 13 Scope 源bean的作用域。若沒有設置,搜索范圍是從頁作用域到應用程序作用域toScope 目標bean的作用域。若沒有設置,默認值是頁作用域 例如:定義一個bean: <bean:define id=”test” value=”this is a test”/> 源bean在頁作用域中被拷貝大哦請求作用域中的另一個bean: <bean:define id=”targetBean” name=”sourceBean” scope=”page” toScope=”request”/> 2.1.2 定義腳本變量的標記 從多種資源中定義和生成腳本變量,這些資源包括cookie,請求參數,HTTP標頭等等。屬性如下: 屬性描述Id 腳本變量和要定義的頁作用域屬性的名稱Name cookie/標頭/參數的名稱multiple 如果這個屬性設置了任意一個數值,所有匹配的cookie都會被積累并存儲到一個Cookie[](一個數組)類型的bean里。若無設置,指定cookie的第一個值將作為Cookie類型的值Value 如果沒有匹配的cookie或數值,就返回這個屬性指定的默認值 例如: <bean:cookie id=”myCookie” name=”userName”/> 腳本變量名稱是myCookie,用來創建這個屬性的cookie的名稱是userName。 <bean:header id=”myHeader” name=”Accept-Language”/> 腳本變量名稱是myHeader,請求標頭的名稱是Accept-Language. <bean:parameter id=”myParameter” name=”myParameter”> 腳本變量名稱是myPatameter,它保存的請求參數的名稱也是myParameter. <bean:include>標記將對一個資源的響應進行檢索,并引入一個腳本變量和字符串類型的頁作用域屬性。這個資源可以是一個頁,一個ActionForward或一個外部URL。與<jsp:include>的不同是資源的響應被存儲到一個頁作用域的bean中,而不是寫入到輸出流。屬性如下: 屬性描述Id 腳本變量和要定義的頁作用域屬性的名稱Page 一個內部資源forward 一個ActionForward Href 要包含的資源的完整URL 例如: <bean:include id=”myInclude” page=”MyJsp?x=1”/> 腳本變量的名稱是myInclude,要檢索的響應來自資源MyJsp?x=1。 <bean:resource>標記將檢索web應用中的資源,并引入一個腳本變量和InputStream或字符串類型的頁作用域屬性。如果在檢索資源時發生問題,就會產生一個請求時間異常。屬性如下: 屬性描述 14 Id 腳本變量和要定義的頁作用域屬性的名稱Name 資源的相對路徑Input 如果這個屬性不存在,資源的類型就是字符串 例如: <bean:resource id=”myResource” name=”/WEB-INF/images/myResource.xml”/> 腳本變量的名稱是myResource,要檢索的資源的名稱是myResource.xml。 2.1.3 顯示Bean屬性 標記庫中定義了<bean:write>標記,用來將bean的屬性輸送到封裝的JSP頁寫入器。這個標記與<jsp:getProperty>類似,屬性如下: 屬性描述Name 要進行屬性顯示的bean的名稱property 要顯示的屬性的名稱。如果這個屬性類有java.beans.PropertyEditor,getAsText()或toString 方法會被調用Scope Bean的作用域,若沒有設置,搜索范圍是從頁到應用程序作用域Filter 如果設置true,屬性中的所有特殊HTML字符都將被轉化為相應的實體引用Ignore 如果設置false,當發現屬性時會產生一個請求時間異常,否則返回null 例如: <bean:write name=”myBean” property=”myProperty” scope=”request” filter=”true”/> myBean的屬性myProperty將會被顯示,作用域為請求,如果發現任何HTML特殊字符都將被轉化為相應的實體引用。 2.1.4 消息標記和國際化 strtus框架支持國際化和本地化。用戶在他們的計算機中定義自己所在的區域,當web應用程序需要輸出一條消息時,它將引用一個資源文件,在這個文件中所有的消息都使用了適當的語言。一個應用程序可能提供了很多資源文件,每個文件提供了用不同語言編寫的消息。如果沒有找到所選語言的資源文件,就將使用默認的資源文件。 struts框架對國際化的支持是使用<bean:message>標記,以及使用java.util數據包中定義的Locale和ResourceBundle類來實現Java2平臺對這些任務的支持。Java.text.MessageFormat類定義的技術可以支持消息的格式。利用此功能,開發人員不需了解這些類的細節就可進行國際化和設置消息的格式。 用strtus實現國際化和本地化: 第一步要定義資源文件的名稱,這個文件會包含用默認語言編寫的在程序中會出現的所有消息。這些消息以“關鍵字-值”的形式存儲,如下: error.validation.location = The entered location is invalid 這個文件需要存儲在類的路徑下,而且它的路徑要作為初始化參數傳送給ActionServlet作為參數進行傳遞時,路徑的格式要符合完整Java類的標準命名規范。比如,如果資源文件存儲在WEB-INFclasses目錄中,文件名是 15 ApplicationResources.properties,那么需要傳遞的參數值是ApplicationResources。如果文件在WEB-INFclassescomtest中,那么參數值就應該是com.test. ApplicationResources. 為了實現國際化,所有的資源文件必須都存儲在基本資源文件所在的目錄中?;举Y源文件包含的是用默認地區語言-本地語言編寫的消息。如果基本資源文件的名稱是ApplicationResources.properties,那么用其他特定語言編寫的資源文件的名稱就應該是ApplicationResources_xx.properties(xx為ISO編碼,如英語是en)。因此這些文件應包含相同的關鍵字,但關鍵字的值是用特定語言編寫的。 ActionServlet的區域初始化參數必須與一個true值一起傳送,這樣ActionServlet就會在用戶會話中的Action.LOCALE_KEY關鍵字下存儲一個特定用戶計算機的區域對象?,F在可以運行一個國際化的web站點,它可以根據用戶計算機上的設置的區域自動以相應的語言顯示。 我們還可以使用特定的字符串來替換部分消息,就象用java.text.MessageFormat的方法一樣: error.invalid.number = The number {0} is valid 我們可以把字符串{0}替換成任何我們需要的數字。<bean:message>標簽屬性如下: 屬性描述Key 資源文件中定義消息關鍵字Locale 用戶會話中存儲的區域對象的屬性名稱。若沒有設置,默認值是Action.LOCALE_KEY Bundle 在應用程序上下文中,存儲資源對象的屬性的名稱。如果沒有設置這個屬性,默認值是Action.MESSAGE_KEY arg0 第一個替換參數值arg1 第二個替換參數值arg2 第三個替換參數值arg3 第四個替換參數值 例如:資源文件中定義了一個消息: info.myKey = The numbers entered are {0},{1},{2},{3} 我們可使用下面的消息標記: <bean:message key=”info.myKey” arg0=”5” arg1=”6” arg2=”7” arg3=”8”/> 這個信息標記輸出到JSP頁會顯示為:The numbers entered are 5,6,7,8 2.2 邏輯標記 邏輯庫的標記能夠用來處理外觀邏輯而不需要使用scriptlet。Struts邏輯標簽庫包含的標記能夠有條件地產生輸出文本,在對象集合中循環從而重復地產生輸出文本,以及應用程序流程控制。它也提供了一組在JSP頁中處理流程控制的標記。這些標記封裝在文件名為struts-logic.tld的標記包中。邏輯標記庫定義的標記能夠執行下列三個功能: 條件邏輯 重復 轉發/重定向響應 16 2.2.1 條件邏輯 struts有三類條件邏輯。第一類可以比較下列實體與一個常數的大?。? cookie 請求參數 bean或bean的參數 請求標頭 以下列出了這一類標記: 標記功能<equal> 如果常數與被定義的實體相等,返回true <notEqual> 如果常數與被定義的實體不相等,返回true <greaterEqual> 如果常數大于等于被定義的實體,返回true <lessEqual> 如果常數小于等于被定義的實體,返回true <lessThan> 如果常數小于被定義的實體,返回true <greaterThan> 如果常數大于被定義的實體,返回true 這一類的所有標記有相同的屬性 屬性描述Value 要進行比較的常數值Cookie 要進行比較的HTTP cookie的名稱Header 要進行比較的HTTP請求標頭的名稱parameter 要進行比較的HTTP請求參數的名稱Name 如果要進行比較的是bean或bean的屬性,則這個屬性代表bean的名稱property 要進行比較的bean屬性的名稱Scope Bean的作用域,如果沒有指定作用域,則它的搜索范圍是從頁到應用程序 例如: <logic:equal parameter=”name” value=”SomeName”> The entered name is SomeName </logic:equal> 判斷名為”name”的請求參數的值是否是”SomeName”。 <logic:greaterThan name=”bean” property=”prop” scope=”page” value=”7”> The value of bean.Prop is greater than 7 </logic:greaterThan> 判斷在頁的作用域中是否有一個名為”bean”的bean,它有一個prop屬性,這個屬性的值是否大于7。如果這個屬性能夠轉化為數值,就進行數值比較,否則就進行字符串比較。 第二類條件標記定義了兩個標記: <logic:present> <logic:notPresent> 它們的功能是在計算標記體之前判斷特定的項目是否存在。標記的屬性和屬性值決定了要進行檢查的項目。 屬性描述 17 Cookie 由這個屬性指定的cookie將被檢查是否存在Header 由這個屬性指定的請求標頭將被檢查是否存在parameter 由這個屬性指定的請求參數將被檢查是否存在Name 如果沒有設置property屬性,那么有這個屬性指定的bean將被檢查是否存在。如果設置了,那么bean和bean屬性都將被檢查是否存在。property 檢查有name屬性指定的bean中是否存在指定的屬性Scope 如果指定了bean的名稱,這就是bean的作用域。如果沒有指定作用域,搜索的范圍從頁到應用程序作用域。Role 檢查當前已經確認的用戶是否屬于特殊的角色User 檢查當前已經確認的用戶是否有特定的名稱 例如: <logic:notPresent name=”bean” property=”prop” scope=”page”> The bean property bean.prop is present </logic:notPresent> 標記判斷在頁作用域中是否存在一個名為”bean”的bean,這個bean有一個prop屬性。 第三類條件標記比較復雜,這些標記根據模板匹配的結果檢查標記體的內容。換句話說,這些標記判斷一個指定項目的值是否是一個特定常數的子字符串: <logic:match> <logic:notMatch> 這些標記允許JSP引擎在發現了匹配或是沒有發現時計算標記主體。屬性如下: 屬性描述Cookie 要進行比較的HTTP cookie的名稱Header 要進行比較的的HTTP標頭的名稱parameter 要進行比較的的HTTP請求參數的名稱Name 若要對bean或bean的屬性進行比較,這個屬性是用戶指定bean的名稱location 如果設置了這個屬性的值,將會在這個指定的位置(索引值)進行匹配scope 如果對bean進行比較,這個屬性指定了bean的作用域。如果沒有設置這個參數,搜索范圍是從頁到應用程序作用域property 要進行比較的bean的屬性名稱value 要進行比較的常數值 例如: <logic:match parameter=”name” value=”xyz” location=”1”> The parameter name is a sub-string of the string xyz from index 1 </logic:match> 標記檢查名為”name”的請求參數是否是”xyz”的子字符串,但是子字符串必須從”xyz”的索引位置1開始(也就是說子字符串必須是”y”或”yz”)。 2.2.2 重復標記 在邏輯標記庫中定義了<logic:iterate>標記,它能夠根據特定集合中元素的數目對標記體的內容進行重復的檢查。集合的類型可以是java.util.Iterator,java.util.Collection 18 ,java.util.Map或是一個數組。有三種方法可以定義這個集合: 使用運行時間表達式來返回一個屬性集合的集合 將集合定義為bean,并且使用name屬性指定存儲屬性的名稱。 使用name屬性定義一個bean,并且使用property屬性定義一個返回集合的bean屬性。 當前元素的集合會被定義為一個頁作用域的bean。屬性如下,所有這些屬性都能使用運行時表達式。 屬性描述collection 如果沒有設置name屬性,它就指定了要進行重復的集合Id 頁作用域bean和腳本變量的名稱,它保存著集合中當前元素的句柄indexed 頁作用域JSP bean的名稱,它包含著每次重復完成后集合的當前索引Length 重復的最大次數Name 作為集合的bean的名稱,或是一個bean名稱,它由property屬性定義的屬性,是個集合Offset 重復開始位置的索引property 作為集合的Bean屬性的名稱Scope 如果指定了bean名稱,這個屬性設置bean的作用域。若沒有設置,搜索范圍從頁到應用程序作用域Type 為當前定義的頁作用域bean的類型 例如: <logic:iterate id=”currentInt” collection=”<% =myList %>” type=”java.lang.Integer” offset=”1” length=”2”> <% =currentint %> </logic:iterate> 代碼將從列表中的第一個元素開始重復兩個元素并且能夠讓當前元素作為頁作用域和java.lang.Integer類型的腳本變量來使用。也就是說,如果myList包含元素1,2,3,4等,代碼將會打印1和2。 2.2.3 轉發和重定向標記 轉發標記 <logic:forward>標記能夠將響應轉發給重定向到特定的全局ActionForward上。ActionForward的類型決定了是使用PageContext轉發響應,還是使用sendRedirect將響應進行重定向。此標記只有一個”name”屬性,用來指定全局ActionForward的名稱,例如: <logic:forward name=”myGlobalForward”/> 重定向標記 <logic:redirect>標記是一個能夠執行HTTP重定向的強大工具。根據指定的不同屬性,它能夠通過不同的方式實現重定向。它還允許開發人員指定重定向URL的查詢參數。屬性如下: 19 屬性描述Forward 映射了資源相對路徑的ActionForward Href 資源的完整URL Page 資源的相對路徑Name Map類型的頁名稱,請求,會話或程序屬性的名稱,其中包含要附加大哦重定向URL(如果沒有設置property屬性)上的“名稱-值”參數?;蚴蔷哂蠱ap類型屬性的bean名稱,其中包含相同的信息(沒有設置property屬性) Property Map類型的bean屬性的名稱。Bean的名稱由name屬性指定。Scope 如果指定了bean的名稱,這個屬性指定搜索bean的范圍。如果沒有設置,搜索范圍從頁到應用程序作用域ParamID 定義特定查詢參數的名稱ParamName 字符串類型的bean的名稱,其中包含查詢參數的值(如果沒有設置paramProperty屬性);或是一個bean的名稱,它的屬性(在paramProperty屬性中指定)包含了查詢參數值paramProperty 字符串bean屬性的名稱,其中包含著查詢參數的值ParamScope ParamName定義的bean的搜索范圍 使用這個標記時至少要指定forward,href或page中的一個屬性,以便標明將響應重定向到哪個資源。 2.3 HTML標記 Struts HTML標記可以大致地分為以下幾個功能: 顯示表單元素和輸入控件 顯示錯誤信息 顯示其他HTML元素 2.3.1 顯示表單元素和輸入控件 struts將HTML表單與為表單操作而定義的ActionForm bean緊密聯系在一起。表單輸入字段的名稱與ActionForm bean里定義的屬性名稱是對應的。當第一次顯示表單時,表單的輸入字段是從ActionForm bean中移植過來的,當表單被提交時,請求參數將移植到ActionForm bean實例。 所有可以在<form>標記中使用的用來顯示HTML輸入控件的內嵌標記都使用下列屬性來定義JavaScript事件處理器。 屬性描述Onblur 字段失去了焦點Onchange 字段失去了焦點并且數值被更改了Onclick 字段被鼠標點擊Ondblclick 字段被鼠標雙擊Onfocus 字段接收到輸入焦點Onkeydown 字段擁有焦點并且有鍵按下 20 onkeypress 字段擁有焦點并且有鍵按下并釋放Onkeyup 字段擁有焦點并且有鍵被釋放onmousedown 鼠標指針指向字段并且點擊onmousemove 鼠標指針指向字段并且在字段內移動onmouseout 鼠標指針指向控件,但是指針在元素外圍移動onmouseover 鼠標指針沒有指向字段,但是指針在元素內部移動Onmouseup 鼠標指針指向字段,并且釋放了鼠標按鍵 <form>元素中能夠被定義的其他一般屬性有: 屬性描述Accesskey 定義訪問輸入字段的快捷鍵Style 定義輸入字段的樣式styleClass 定義輸入字段的樣式表類Tabindex 輸入字段的tab順序 a) 表單標記 <html:form>標記用來顯示HTML標記,可以指定AcitonForm bean的名稱和它的類名。如果沒有設置這些屬性,就需要有配置文件來指定ActionMapping以表明當前輸入的是哪個JSP頁,以及從映射中檢索的bean名和類。如果在ActionMapping指定的作用域中沒有找到指定的名稱,就會創建并存儲一個新的bean,否則將使用找到的bean。 <form>標記能夠包含與各種HTML輸入字段相對應的子標記。 <html:form>標記屬性如下: 屬性描述Action 與表單相關的操作。在配置中,這個操作也用來標識與表單相關的ActionForm bean Enctype 表單HTTP方法的編碼類型Focus 表單中需要初始化焦點的字段Method 表單使用的HTTP方法Name 與表單相關的ActionForm bean的名稱。如果沒有設置這個屬性,bean的名稱將會從配置信息中獲得Onreset 表單復位時的JavaScript事件句柄Onsubmit 表單提交時的JavaScript事件句柄Scope 搜索ActionForm bean的范圍。如果沒有設置,將從配置文件中獲取Style 使用的格式styleClass 這個元素的格式表類Type ActionForm bean的完整名稱。如果沒有設置,將從配置文件獲得 例如: <html:form action=”validateEmploee.do” method=”post”> </html:form> 與表單相關的操作路徑是validateEmployee,而表單數據是通過POST傳遞的。對于這個表單來說,ActionForm bean的其他信息,如bean名稱類型,作用域,都是從表單指定操作的ActionMapping中檢索得到的: 21 <form-beans> <form-bean name=”empForm” type=”com.example.EmployeeForm”/> </form-beans> <action-mappings> <action path=”/validateEmployee” type=”com.example.ValidateExampleAction” name=”empForm” scope=”request” input=”/employeeInput.jsp”> <forward name=”success” path=”/employeeOutput.jsp”> </action> </action-mapping> 如果配置文件中包含上述信息,并且請求URI的*.do被映射到ActionServlet,與表單相關的ActionForm bean的名稱,類型和作用域分別是empForm,com.example.EmployeeForm和request.這些屬性也可以使用<html:form>標記屬性進行顯示的定義。 以下標記必須嵌套在<html:form>標記里 b) 按鈕和取消標記 <html:button>標記顯示一個按鈕控件;<html:cancel>標記顯示一個取消按鈕。屬性如下: 屬性描述Property 定義在表單被提交時返回到服務器的請求參數的名稱Value 按鈕上的標記 c) 復位和提交標記 <html:reset>和<html:submit>標記分別能夠顯示HTML復位按鈕和提交按鈕。 d) 文本和文本區標記 <html:text>和<html:textarea>標記分別HTML文本框和文本區,屬性如下: 屬性描述Property 定義當表單被提交時送回到服務器的請求參數的名稱,或用來確定文本元素當前值的bean的屬性名稱Name 屬性被查詢的bean的名稱,它決定了文本框和文本區的值。如果沒有設置,將使用與這個內嵌表單相關的ActionForm的名稱 <html:text>標記還有以下屬性: 屬性描述Maxlength 能夠輸入的最大字符數 22 Size 文本框的大?。ㄗ址麛担? <html:textarea>標記特有的屬性如下: 屬性描述Rows 文本區的行數Cols 文本區的列數 e) 檢查框和復選框標記 <html:checkbox>標記能夠顯示檢查框控件。<html:multibox>標記能夠顯示HTML復選框控件,請求對象在傳遞檢查框名稱時使用的getParameterValues()調用將返回一個字符串數組。屬性如下: 屬性描述Name Bean的名稱,其屬性會被用來確定檢查是否以選中的狀態顯示。如果沒有設置,將使用與這個內嵌表單相關的ActionFrom bean的名稱。Property 檢查框的名稱,也是決定檢查框是否以選中的狀態顯示的bean屬性名稱。在復選框的情況下,這個屬性必須是一個數組。Value 當檢查框被選中時返回到服務器的請求參數的值 例如: <html:checkbox property=”married” value=”Y”/> 一個名為married的檢查框,在表單提交時會返回一個”Y”. f) 文件標記 <html:file>標記可以顯示HTML文件控件。屬性如下: 屬性描述Name Bean的名稱,它的屬性將確定文件控件中顯示的內容。如果沒設置,將使用與內嵌表單相關的ActionForm bean的名稱property 這個屬性定義了當表單被提交時送回到服務器的請求參數的名稱,以及用來確定文件控件中顯示內容的bean屬性名稱Accept 服務器能夠處理的內容類型集。它也將對客戶瀏覽器對話框中的可選文件類型進行過濾Value 按鈕上的標記,這個按鈕能夠在本地文件系統中瀏覽文件 g) 單選鈕標記 <html:radio>標記用來顯示HTML單選鈕控件,屬性如下: 屬性描述Name Bean的名稱,其屬性會被用來確定單選鈕是否以選中的狀態顯示。如果沒有設置,將使用與這個內嵌表單相關的ActionFrom bean的名稱。property 當表單被提交時送回到服務器的請求參數的名稱,以及用來確定單選鈕是否以被選中狀態進行顯示的bean屬性的名稱 23 Value 當單選鈕被選中時返回到服務器的值 h) 隱藏標記 <html:hidden>標記能夠顯示HTML隱藏輸入元素,屬性如下: 屬性描述Name Bean的名稱,其屬性會被用來確定隱藏元素的當前值。如果沒有設置,將使用與這個內嵌表單相關的ActionFrom bean的名稱。property 定義了當表單被提交時送回到服務器的請求參數的名稱,以及用來確定隱藏元素當前值的bean屬性的名稱Value 用來初始化隱藏輸入元素的值 i) 密碼標記 <html:password>標記能夠顯示HTML密碼控件,屬性如下: 屬性描述maxlength 能夠輸入的最大字符數Name Bean的名稱,它的屬性將用來確定密碼元素的當前值。如果沒有設置,將使用與這個內嵌表單相關的ActionFrom bean的名稱。property 定義了當表單被提交時送回到服務器的請求參數的名稱,以及用來確定密碼元素當前值的bean屬性的名稱redisplay 在顯示這個字段時,如果相應的bean屬性已經被設置了數據,這個屬性決定了是否顯示密碼的內容Size 字段的大小 j) 選擇標記 <html:select>標記能夠顯示HTML選擇控件,屬性如下: 屬性描述multiple 表明這個選擇控件是否允許進行多選Name Bean的名稱,它的屬性確定了哪個。如果沒有設置,將使用與這個內嵌表單相關的ActionFrom bean的名稱。property 定義了當表單被提交時送回到服務器的請求參數的名稱,以及用來確定哪個選項需要被選中的bean屬性的名稱Size 能夠同時顯示的選項數目Value 用來表明需要被選中的選項 k) 選項標記(這個元素需要嵌套在<html:select>標記里) <html:option>標記用來顯示HTML選項元素集合,屬性如下: 24 屬性描述collection Bean集合的名稱,這個集合存儲在某個作用域的屬性中。選項的數目與集合中元素的數目相同。Property屬性能夠定義選項值所使用的bean屬性,而labelProperty屬性定義選項標記所使用的bean的屬性labelName 用來指定存儲于某個作用域的bean,這個bean是一個字符串的集合,能夠定義<html:option>元素的標記(如果標志與值不相同) labelProperty 與collection屬性共同使用時,用來定義了存儲于某個作用域的bean,這個bean將返回一個字符串集合,能夠用來寫入<html:option>元素的value屬性Name 如果這是唯一被指定的屬性,它就定義了存儲于某個作用域的bean,這個bean將返回一個字符串集合,能夠用來寫入<html:option>元素的value屬性property 這個屬性在與collection屬性共同使用時,定義了每個要顯示選項值的獨立bean的name屬性。如果不是與collection屬性共同使用,這個屬性定義了由name屬性指定的bean的屬性名稱(如果有name屬性),或是定義了一個ActionForm bean,這個bean將返回一個集合來寫入選項的值 我們看一下這個標記的一些例子: <html:option collection=”optionCollection” property=”optionValue” labelProperty=”optionLabel”/> 標記假設在某個作用域中有一個名為optionCollection的集合,它包含了一些具有optionValue屬性的獨立的bean,每個屬性將作為一個選項的值。每個選項的標志由bean的optionLabel屬性屬性進行定義。 <html:option name=”optionValues” labelName=”optionLabels”/> 標記中optionValues代表一個存儲在某個作用域中的bean,它是一個字符串集合,能夠用來寫入選項的值,而optionLabels代表一個存儲在某個作用域中的bean,它也是一個字符串集合,能夠用來寫入選項的標志。 2.3.2.顯示錯誤信息的標記 <html:errors>標記能夠與ActionErrors結合在一起來顯示錯誤信息。這個標記首先要從當前區域的資源文件中讀取消息關鍵字errors.header,然后顯示消息的文本。接下去它會在ActionErrors對象(通常作為請求參數而存儲在Action.ERROR_KEY關鍵字下)中循環,讀取單個ActionError對象的消息關鍵字,從當前區域的資源文件中讀取并格式化相應的消息,并且顯示它們。然后它讀取與errors.footer關鍵字相對應的消息并且顯示出來。 通過定義property屬性能夠過濾要顯示的消息,這個屬性的值應該與ActionErrors對象中存儲ActionError對象的關鍵字對應。屬性如下: 屬性描述Bundle 表示應用程序作用域屬性的名稱,它包含著消息資源,其默認值Acion.MESSAGE_KEY Locale 表示會話作用域屬性的名稱,它存儲著用戶當前登錄的區域信息。其默認值是Action.ERROR_KEY 25 Name 表示請求屬性的名稱,它存儲著ActionErrors對象。其默認值是Action.ERROR_KEY property 這個屬性指定了ActionErrors對象中存儲每個獨立ActionError對象的關鍵字,它可以過濾消息 例子: <html:errors/> 顯示集合中所有的錯誤。 <html:errors property=”missing.name”/> 顯示存儲在missing.name關鍵字的錯誤。 2.3.3.其他HTML標記 struts HTML標記還定義了下列標記來顯示其他HTML元素: <html:html> : 顯示HTML元素 <html:img> : 顯示圖象標記 <html:link> : 顯示HTML鏈接或錨點 <html:rewrite> : 創建沒有錨點標記的URI 這些標記的詳細內容請參照struts文檔。 2.4. 模板標記 動態模板是模塊化WEB頁布局設計的強大手段。Struts模板標記庫定義了自定義標記來實現動態模板。 2.4.1.插入標記 <template:insert>標記能夠在應用程序的JSP頁中插入動態模板。這個標記只有一個template屬性,用來定義模板JSP頁。要插入到模板的頁是有多個<template:put>標記來指定的,而這些標記被定義為<template:insert>標記的主體內容。 2.4.2.放置標記 <template:put>標記是<template:insert>標記內部使用的,用來指定插入到模板的資源。屬性如下: 屬性描述content 定義要插入的內容,比如一個JSP文件或一個HTML文件direct 如果這個設置為true,由content屬性指定的內容將直接顯示在JSP上而不是作為包含文件Name 要插入的內容的名稱Role 如果設置了這個屬性,只有在當前合法用戶具有特定角色時才能進行內容的插入。 26 2.4.3.獲得標記 在模板JSP頁中使用<template:get>標記能夠檢索由<template:put>標記插入到JSP頁的資源。屬性如下: 屬性描述Name 由<template:put>標記插入的內容的名稱Role 如果設置了這個屬性,只有在當前合法用戶具有特定角色時才能進行內容的檢索 2.4.4.使用模板標記 首先編寫一個模板JSP頁,它將被所有的web頁使用: <html> <%@ taglib uri=”/template” prefix=”template” %> <head> <title></title> </head> <body> <table width=”100%” height=”100%” > <tr height=”10%”> <td> <template:get name=”header”/> </td> </tr> <tr height=”80%”> <td> <template:get name=”content”/> </td> </tr> <tr height=”10%”> <td> <template:get name=”footer”/> </td> </tr> </table> </body> </html> 我們將這個文件命名為template.jsp。這個文件使用<template:get>標記來獲得由JSP頁使用<template:put>標記提供的內容,并且將內容在一個HTML表格中顯示出來。這三個內容是標題,內容和頁腳。典型的內容JSP會是這樣: <%@ taglib uri=”/template” prefix=”/template” %> <template:insert template=”template.jsp”> <template:put name=”header” content=”header.html”/> 27 <template:put name=”content” content=”employeeList.jsp”/> <template:put name=”footer” content=”footer.html”/> </template:insert> 這個應用程序JSP頁使用<template:insert標記來定義模板,然后使用<template:put>標記將特定內容名稱指定的資源放到模板JSP頁中。如果我們有上百個布局相同的頁,但突然想改變這個模板,我們只需要改變template.jsp文件。 |
|
指令名稱:sudo
使用權限:在 /etc/sudoers 中有出現的使用者 |
|
Struts的Token(令牌)機制能夠很好的解決表單重復提交的問題,基本原理是:服務器端在處理到達的請求之前,會將請求中包含的令牌值與保存在當前用戶會話中的令牌值進行比較,看是否匹配。在處理完該請求后,且在答復發送給客戶端之前,將會產生一個新的令牌,該令牌除傳給客戶端以外,也會將用戶會話中保存的舊的令牌進行替換。這樣如果用戶回退到剛才的提交頁面并再次提交的話,客戶端傳過來的令牌就和服務器端的令牌不一致,從而有效地防止了重復提交的發生。
這時其實也就是兩點,第一:你需要在請求中有這個令牌值,請求中的令牌值如何保存,其實就和我們平時在頁面中保存一些信息是一樣的,通過隱藏字段來保存,保存的形式如: 〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,這個value是TokenProcessor類中的generateToken()獲得的,是根據當前用戶的session id和當前時間的long值來計算的。第二:在客戶端提交后,我們要根據判斷在請求中包含的值是否和服務器的令牌一致,因為服務器每次提交都會生成新的Token,所以,如果是重復提交,客戶端的Token值和服務器端的Token值就會不一致。下面就以在數據庫中插入一條數據來說明如何防止重復提交。
在Action中的add方法中,我們需要將Token值明確的要求保存在頁面中,只需增加一條語句:saveToken(request);,如下所示:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
//前面的處理省略
saveToken(request);
return mapping.findForward("add");
}在Action的insert方法中,我們根據表單中的Token值與服務器端的Token值比較,如下所示:
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
if (isTokenValid(request, true)) {
// 表單不是重復提交
//這里是保存數據的代碼
} else {
//表單重復提交
saveToken(request);
//其它的處理代碼
}
}
222222222222222222222222222222222222222222222222222222222222222222222
1。重復提交、重復刷新的場景
重復提交、重復刷新都是來解決系統重復記錄的問題。也就是說某個人在多次的提交某條記錄(為什么?也許是閑了沒有事情干的;最有可能是用戶根本就不知道自己的提交結果是否已經執行了??。?。
但出現了這樣的問題并不見得就必須處理,要看你所開發的系統的類別而定。比如你接手的是某個資源管理系統,系統本身從需求的角度根本就不允許出現"重復"的記錄,在這樣需求的約束條件下,去執行重復的提交動作只會引發“業務級異常”的產生,根本就不可能執行成功也就無所謂避免不避免的問題了。
?
2。防止后退的場景
了解了重復刷新、重復提交的場景,我們來了解一下"防止后退"操作的原因是什么?比如你在開發某個投票系統,它有很多的步驟,并且這些步驟之間是有聯系的,比如第一步會將某些信息發送給第二步,第二步緩存了這些信息,同時將自身的信息發送給了第三步。。。。。等等,如果此時用戶處在第三步驟下,我們想象一下某個淘氣用戶的用戶點擊了后退按鈕,此時屏幕出現了第二步驟的頁面,他再次的修改或者再次的提交,進入到下一個步驟(也就是第三步驟),錯誤就會在此產生?!什么錯誤呢?最為典型的就是這樣的操作直接導致了對于第一個步驟信息的丟失?。ㄈ绻@樣的信息是依靠Request存放的話,當然你可以存放在Session或者更大的上下文環境中,但這不是個好主意!關于信息存放的問題,下次在就這個問題詳細的討論)
三。如何處理的問題
當然很多的系統(比如訂票系統從需求上本身是允許個人重復訂票的)是必須要避免重復刷新、重復提交、以及防止后退的問題的,但即使是這樣的問題,也要區分如何處理以及在哪里處理的(網上只是告訴你如何處理,但很少去區分在哪里處理的),顯然處理的方式無非是客戶端或者服務器端兩種,而面對不同的位置處理的方式也是不同的,但有一點要事先聲明:任何客戶端(尤其是B/S端)的處理都是不可信任的,最好的也是最應該的是服務器端的處理方法。
客戶端處理:
面對客戶端我們可以使用Javascript腳本來解決,如下
1。重復刷新、重復提交
Ways One:設置一個變量,只允許提交一次。
<script language="javascript">
??? var checkSubmit*** = false;
??? function checkSubmit() {
????? if (checkSubmit*** == true) {
???????? return false;
????? }
????? checkSubmit*** = true;
????? return true;
?? }
?? document.ondblclick = function docondblclick() {
??? window.event.returnValue = false;
?? }
?? document.onclick = function doconclick() {
?????? if (checkSubmit***) {
???????? window.event.returnValue = false;
?????? }
?? }
</script>
<html:form action="myAction.do" method="post" onsubmit="return checkSubmit();">
Way Two : 將提交按鈕或者image置為disable
? <html:form action="myAction.do" method="post"?
??? onsubmit="getElById('submitInput').disabled = true; return true;">??
? <html:image styleId="submitInput" src="images/ok_b.gif" border="0" />
? </html:form>?
2。防止用戶后退
這里的方法是千姿百態,有的是更改瀏覽器的歷史紀錄的,比如使用window.history.forward()方法;有的是“用新頁面的URL替換當前的歷史紀錄,這樣瀏覽歷史記錄中就只有一個頁面,后退按鈕永遠不會變為可用。”比如使用javascript:location.replace(this.href); event.returnValue=false;
2.服務器端的處理(這里只說Struts框架的處理)
利用同步令牌(Token)機制來解決Web應用中重復提交的問題,Struts也給出了一個參考實現。
基本原理:
服務器端在處理到達的請求之前,會將請求中包含的令牌值與保存在當前用戶會話中的令牌值進行比較,
看是否匹配。在處理完該請求后,且在答復發送給客戶端之前,將會產生一個新的令牌,該令牌除傳給
客戶端以外,也會將用戶會話中保存的舊的令牌進行替換。這樣如果用戶回退到剛才的提交頁面并再次
提交的話,客戶端傳過來的令牌就和服務器端的令牌不一致,從而有效地防止了重復提交的發生。
if (isTokenValid(request, true)) {
??? // your code here
??? return mapping.findForward("success");
} else {
??? saveToken(request);
??? return mapping.findForward("submitagain");
}
Struts根據用戶會話ID和當前系統時間來生成一個唯一(對于每個會話)令牌的,具體實現可以參考
TokenProcessor類中的generateToken()方法。
1. //驗證事務控制令牌,<html:form >會自動根據session中標識生成一個隱含input代表令牌,防止兩次提交
2. 在action中:
?????? //<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"?
?????? //? value="6aa35341f25184fd996c4c918255c3ae">
?????? if (!isTokenValid(request))
?????????? errors.add(ActionErrors.GLOBAL_ERROR,
????????????????????? new ActionError("error.transaction.token"));
?????? resetToken(request); //刪除session中的令牌
3. action有這樣的一個方法生成令牌
?? protected String generateToken(HttpServletRequest request) {
?????? HttpSession session = request.getSession();
?????? try {
?????????? byte id[] = session.getId().getBytes();
?????????? byte now[] =
?????????????? new Long(System.currentTimeMillis()).toString().getBytes();
?????????? MessageDigest md = MessageDigest.getInstance("MD5");
?????????? md.update(id);
?????????? md.update(now);
?????????? return (toHex(md.digest()));
?????? } catch (IllegalStateException e) {
?????????? return (null);
?????? } catch (NoSuchAlgorithmException e) {
?????????? return (null);
?????? }
?? }?
總結
對于重復提交、重復刷新、防止后退等等都是屬于系統為避免重復記錄而需要解決的問題,在客戶端去處理需要針對每一種的可能提出相應的解決方案,然而在服務器端看來只不過是對于數據真實性的檢驗問題,基于令牌的處理就是一勞永逸的方法。
同時我們也看到,從不同的角度去看待問題,其解決的方法也是不同的。客戶端更追求的是用戶的操作,而服務端則將注意力放在了數據的處理上,所以在某個對于服務器端看似容易的問題上,用客戶端來解決卻麻煩了很多!反之依然。所以在某些問題的處理上我們需要綜合考慮和平衡,是用客戶端來解決?還是用服務器端來處理