隨筆:45 文章:5 評論:25 引用:0
          BlogJava 首頁 發新隨筆
          發新文章 聯系 聚合管理

               摘要: 原因:首先,JFreeChart和中文驗證碼的亂碼問題和jsp的編碼無關,是由于Java虛擬機找不到字體文件造成的,所以同類的Swing或者AWT的中文亂碼問題也適用

            閱讀全文
          posted @ 2009-01-12 17:18 Hill 閱讀(4050) | 評論 (0)編輯 收藏
           
               摘要: JFreeChart真是個好東西,今天剛剛學習了一下,以后要是用時,可以深入,大家要是不知道怎么在Web中畫出圖表,請參考,謝謝  閱讀全文
          posted @ 2009-01-12 16:41 Hill 閱讀(135) | 評論 (0)編輯 收藏
           

          Struts Validator驗證器使用指南


          驗證器:

          從0.5版,驗證器在一些form中就已經實現了,他最初包含在開發人員包中,后來核心代碼挪到Jakarta Commons包中和Struts特別擴展中作為 Struts 1.1的一部分。許多開發者為方便一直使用struts驗證器,這篇文檔首先概述驗證器的核心功能性,然后大概介紹在 struts1.1中的變化和新增功能。

          如果你配置好驗證器插件,你應該擴展ValidatorForm而不是ActionForm,以便它能加載你的Validator資源。他根據struts-config.xml文件中的action的name屬性為當前form的調用相應的驗證器,因此在validator-rules.xml中的form元素的名稱屬性應該與action的name屬性值相匹配。

          另外一種選擇是擴展ValidatorActionForm 而不是ValidatorForm,ValidatorActionForm使用struts-config.xml中action的path屬性,所以path屬性的值相應的應該與validator-rules.xml中的Form的name屬性匹配。

          一個分離的action可以定義給多頁form的每個頁面,而且驗證規則可以與action關聯而不是與頁碼,就像驗證范例中的多頁form范例那樣。
          國際化

          在validator-rules.xml 文件中form的驗證規則可以組織為FormSet。FormSet 有與java.util.Locale 類相應的屬性:如語言, 國家以及變量型屬性,如果他們未定義,FormSet 將把它設置為默認值。一個FormSet 也可以有關聯的常量。另外還可以定義與FormSet 同一級別的全局global元素,他與FormSet同樣也有常量。

          注意:你必須在國際化的FormSet前聲明一個沒有國際化的默認FormSet。這樣如果Validator沒有找到locale時可以有一個默認版本。

                  可插入驗證器的默認錯誤信息值可以被msg元素覆蓋。所以為mask驗證器生成錯誤信息的替代方法就是使用msg屬性,如果字段的name屬性與驗證器的name屬性匹配,那末將使用字段的msg屬性。

                  error messages的可以設置arg0-arg3 等參數元素。如果沒有設置arg0-arg3的name屬性, error messages將使用他們作為默認的構建參數值。如果設置了name屬性,你就可以把參數指定給一特定的可插入驗證器,然后這些參數將在構造錯誤信息時被使用。

          <field

          property="lastName"

          depends="required,mask">

          <msg

          name="mask"

          key="registrationForm.lastname.maskmsg"/>

          <arg0 key="registrationForm.lastname.displayname"/>

          <var>

          <var-name>mask</var-name>

          <var-value>^[a-zA-Z]*$</var-value>

          </var>

          </field>

          默認的arg0-arg3元素將在消息資源中查找相應的key,如果資源屬性設為false,她將把值直接傳進去,而不從消息資源中查找。注意1.1版本中,你必須為每個模塊中明確地定義在驗證中用到的消息資源,否則將使用top-level資源。

          <field

          property="integer"

          depends="required,integer,intRange">

          <arg0 key="typeForm.integer.displayname"/>

          <arg1

          name="range"

          key="${var:min}"

          resource="false"/>

          <arg2

          name="range"

          key="${var:max}"

          resource="false"/>

          <var>

          <var-name>min</var-name>

          <var-value>10</var-value>

          </var>

          <var>

          <var-name>max</var-name>

          <var-value>20</var-value>

          </var>

          </field>
          常量/變量

          全局的常量可以在全局標簽中定義,FormSet/本地常量能在formset 標簽中創建。常量當前僅僅是代替字段的property屬性,字段的var 元素的 value屬性,字段的msg 元素的 key屬性,字段的arg0-arg3 元素的 key屬性。字段的變量也可以在arg0-arg3 元素中被代替(例如:${var:min}))。替換的順序是FormSet/Locale常量第一,全局的常量第二,

          arg elements 變量最后。

          <global>

          <constant>

          <constant-name>zip</constant-name>

          <constant-value>^\d{5}(-\d{4})?$</constant-value>

          </constant>

          </global>

           

          <field

          property="zip"

          depends="required,mask">

          <arg0 key="registrationForm.zippostal.displayname"/>

          <var>

          <var-name>mask</var-name>

          <var-value>${zip}</var-value>

          </var>

          </field>

          驗證器可以使用字段下面的變量部分來存儲變量,這些變量通過字段的getVar((String key)方法取得。

          <field

          property="integer"

          depends="required,integer,intRange">

          <arg0 key="typeForm.integer.displayname"/>

          <arg1

          name="range"

          key="${var:min}" resource="false"/>

          <arg2

          name="range"

          key="${var:max}" resource="false"/>

          <var>

          <var-name>min</var-name>

          <var-value>10</var-value>

          </var>

          <var>

          <var-name>max</var-name>

          <var-value>20</var-value>

          </var>

          </field>
          使用validwhen設計復雜的驗證

          使用validwhen來設計復雜驗證的一個經常的要求就是根據一個字段驗證另外一個字段(比如, 如果你要用戶兩次輸入口令來確認值口令一致),另外一個就是表單中的一個字段只有另外一個字段有確定值的時候才是必須輸入的。新的validwhen驗證規則將很快被包含在1.1后的STRUTS版本中,她就是用來處理這種情況的。

                  validwhen 規則處理單個的變量字段,叫測試。這變量的值是一個布爾的表達式,如果驗證有效則它必須為真。可以包含這種變量的表達式有:

          u        單引號或雙引號字符串literals,

          u        十進制、十六進制、八進制的Integer literals,

          u        null與null和空字符串匹配,

          u        其它可以用屬性名引用的form字段,例如customerAge,

          u        可以在外部因用得索引字段, 例如childLastName[2],

          u        可以默認implicit因用得索引字段, 例如childLastName[], 她將作為被索引的字段使用同樣的索引到數組中,

          The literal *這里指它包含當前測試字段的值,

          作為例子,考慮一個包含通訊地址和郵箱字段的form。如果通訊地址不為空則郵箱字段是必須的required。你能這樣定義validwhen 規則:

          <field property="emailAddress" depends="validwhen">

          <arg0 key="userinfo.emailAddress.label"/>

          <var>

          <var-name>test</var-name>

          <var-value>((sendNewsletter == null) or (*this* != null))</var-value>

          </var>

          </field>

          上面定義的意思是:如果通訊地址是空或不空時這個字段時有效的。

          這里有個稍微復雜的例子,它使用了索引字段。假定有一個表單,允許用戶輸入他們希望定購的部件號和數量。類orderLine 的bean的一數組被用來在稱為orderLines 的一屬性保持輸入項。

          If you wished to verify that every line with part number also had a quantity entered, you could do it with:

          如果你希望校驗訂單中有數量輸入得每一行,你可以這樣:

          <field

          property="quantity"

          indexedListProperty="orderLines"

          depends="validwhen">

          <arg0 key="orderform.quantity.label"/>

          <var>

          <var-name>test</var-name>

          <var-value>((orderLines[].partNumber == null) or (*this* != null))</var-value>

          </var>

          </field>

          這里的意思是:如果相應的partNumber 字段是空, 或這字段是不空的,則這字段是有效的。

          最后一個例子,想象一表單,用戶必須輸入他們的以英寸為單位的高度,如果他們在高度在60英寸以下,則出一錯誤。(it is an error to have checked off nbaPointGuard as a career.)

          <field property="nbaPointGuard" depends="validwhen">

          <arg0 key="careers.nbaPointGuard.label"/>

          <var>

          <var-name>test</var-name>

          <var-value>((heightInInches >= 60) or (*this* == null))</var-value>

          </var>

          </field>

           

          給程序員的簡單說明:

          所有的比較關系必須在parens 封裝。All comparisons must be enclosed in parens.

          只有兩個itme時可以and或or鏈接。

          如果比較的兩item都可以轉為整數,則使用numeric比較,否則使用字符串比較。
          可插入驗證器

          驗證是從validation.xml 文件中加載的,默認的驗證規則定義在validation.xml 文件中,默認定義了required, mask ,byte, short, int, long, float, double, date (沒有本地支持), and a numeric range。

          " mask "方式依賴于默認值安裝要求,那意味著"required "可以完成,在"'mask "將運行以前"required "和" mask "方式被默認包含進框架中了。任何字段如果不是"required "而且是空或有零長度將跳過其他驗證。

          如果使用了Javascript 標簽,客戶端javascript在validator's javascript 屬性中查找值而且產生一個有驗證form方法的對象,要得到更多的關于Javascript Validator 標簽工作細節的詳細的解釋,參閱html標簽API參考。

          "'mask' "方式讓你用一正則表達式掩碼驗證字段,它使用jakarta的正規表達式包,所有的有效性規則存儲在validator-rules.xml 文件,使用的主類是org.apache.regexp.RE。

          validation.xml文件中的驗證器配置范例:

          <validator name="required"

          classname="org.apache.struts.validator.FieldChecks"

          method="validateRequired"

          methodParams="java.lang.Object,

          org.apache.commons.validator.ValidatorAction,

          org.apache.commons.validator.Field,

          org.apache.struts.action.ActionErrors,

          javax.servlet.http.HttpServletRequest"

          msg="errors.required">

          <validator name="mask"

          classname="org.apache.struts.validator.FieldChecks"

          method="validateMask"

          methodParams="java.lang.Object,

          org.apache.commons.validator.ValidatorAction,

          org.apache.commons.validator.Field,

          org.apache.struts.action.ActionErrors,

          javax.servlet.http.HttpServletRequest"

          msg="errors.invalid">


          定義可插入驗證器

          方法的參數是用逗號分隔的一些類名稱列表,方法屬性需要有一個符合上面的列表的簽名。列表由以下組合而成:

          java.lang.Object – 要驗證的Bean。

          org.apache.commons.validator.ValidatorAction – 當前ValidatorAction。

          org.apache.commons.validator.Field – 要驗證的字段

          org.apache.struts.action.ActionErrors – 如果驗證錯誤將加入ActionError的錯誤對象javax.servlet.http.HttpServletRequest –當前request 對象。

          javax.servlet.ServletContext – 應用的ServletContext。

          org.apache.commons.validator.Validator–當前的org.apache.commons.validator.Validator實例。

          java.util.Locale – 當前用戶的Locale。
          多頁面form

          字段部分有一可選的頁面屬性,它可以被設為整數,頁上字段的所有驗證小于或等于服務器端驗證的當前頁,頁上字段的所有驗證小于或等于客戶端頁上所有字段的驗證小于或等于服務器端驗證的當前頁驗證的當前頁。一個mutli-part表單需要定義頁面屬性:

          <html:hidden property="page" value="1"/>。
          比較兩個字段

          這是一個展示你怎樣才能比較兩個字段是否有一樣的值的例子。比如“用戶改變他們的口令“一般會有口令字段和一確認字段。

          <validator name="twofields"

          classname="com.mysite.StrutsValidator"

          method="validateTwoFields"

          msg="errors.twofields"/>

          <field property="password" depends="required,twofields">

          <arg0 key="typeForm.password.displayname"/>

          <var>

          <var-name>secondProperty</var-name>

          <var-value>password2</var-value>

          </var>

          </field>

           

          public static boolean validateTwoFields(

          Object bean, ValidatorAction va,  

          Field field, ActionErrors errors, HttpServletRequest request,  

          ServletContext application) {

          String value = ValidatorUtils.getValueAsString( bean,   field.getProperty());

          String sProperty2 = field.getVarValue("secondProperty");

          String value2 = ValidatorUtils.getValueAsString( bean,   sProperty2);

           

                  if (!GenericValidator.isBlankOrNull(value)) {

          try {

          if (!value.equals(value2)) {

          errors.add(field.getKey(),

          Resources.getActionError( application, request, va, field));

                                       return false;

          }

          } catch (Exception e) {

          errors.add(field.getKey(), Resources.getActionError( application, request, va, field));

          return false;

          }

          }

          }
          已知的bug

          Struts Validator依賴于Commons Validator包,所以問題報告和增強需求可能在兩個產品中列出。

          ·    Struts Validator Bugzilla Reports

          ·    Commons Validator Bugzilla Reports
          變更和deprecations

          新建的標記屬性。

          <html:javascript>標記有新的屬性定義.

          使用commons-validator.jar中的DTD驗證。

          當前使用的驗證XML文件是根據commons-validator.jar中的DTD。Struts不在為validator-rules.xml and validator.xml.單獨維護一個分離的DTD,另外,commons-validator 現在維護一個統一的validator.dtd。修改所有validator.xml文件的DTD引用為

          <!DOCTYPE form-validation PUBLIC

          "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"

          "

          空字段。

          當前默認在所有得基礎驗證類型中忽略空白的字段,如果你要求一個字段必須輸入,那末在你的應用的validator.xml 文件相應的字段定義的depends屬性中添加 " required "。

          新建的范圍RANGE方法.

          JavaScript 和JAVA中都添加了intRange & floatRange 方法。

          有條件地REQUIRED字段.

          最大的修改是添加了基于其她字段的值的有條件地require驗證的能力。它允許你定義邏輯如:“只有X字段非空的時候Y字段為’male’才有效”,這是實現上述邏輯的推薦方法,這種方法在1.1版后的第一版將實現。在1.1版中添加的Requiredif驗證規則,將在新版中去掉。不過,如果你正準備使用requiredif,這里有一個簡短的教程。

                  讓我們假定你有一個有3個字段的醫藥的信息表單,性別sex,懷孕測試pregnancyTest,測試結果testResult,如果性別為'f' or 'F',則懷孕測試pregnancyTest是required,如果pregnancyTest不是空,測試結果testResult是required。

          你的validation.xml 文件的輸入項應該是這樣的:

          <form name="medicalStatusForm">

          <field property="pregnancyTest" depends="requiredif">

          <arg0 key="medicalStatusForm.pregnancyTest.label"/>

          <var>

          <var-name>field[0]</var-name>

          <var-value>sex</var-value>

          </var>

          <var>

          <var-name>fieldTest[0]</var-name>

          <var-value>EQUAL</var-value>

          </var>

          <var>

          <var-name>fieldValue[0]</var-name>

          <var-value>F</var-value>

          </var>

          <var>

          <var-name>field[1]</var-name>

          <var-value>sex</var-value>

          </var>

          <var>

          <var-name>fieldTest[1]</var-name>

          <var-value>EQUAL</var-value>

          </var>

          <var>

          <var-name>fieldValue[1]</var-name>

          <var-value>f</var-value>

          </var>

          <var>

          <var-name>fieldJoin</var-name>

          <var-value>OR</var-value>

          </var>

          </field>

          <field property="testResult" depends="requiredif">

          <arg0 key="medicalStatusForm.testResult.label"/>

          <var>

          <var-name>field[0]</var-name>

          <var-value>pregnancyTest</var-value>

          </var>

          <var>

          <var-name>fieldTest[0]</var-name>

          <var-value>NOTNULL</var-value>

          </var>

          </field>

          </form>

           

          這里有一個使用索引的屬性更復雜的例子,如果你的struts-config.xml 有這下面:

          <form-bean name="dependentlistForm"

          type="org.apache.struts.webapp.validator.forms.ValidatorForm">

          <form-property

          name="dependents"

          type="org.apache.struts.webapp.validator.Dependent[]" size="10"/>

          <form-property name="insureDependents" type="java.lang.Boolean" initial="false"/>

          </form-bean>

          這里dependentlistForm bean有lastName,firstName,dob,coverageType四個屬性,你可以這樣定義一驗證規則:

          <form name="dependentlistForm">

          <field

          property="firstName" indexedListProperty="dependents" depends="requiredif">

          <arg0 key="dependentlistForm.firstName.label"/>

          <var>

          <var-name>field[0]</var-name>

          <var-value>lastName</var-value>

          </var>

          <var>

          <var-name>fieldIndexed[0]</var-name>

          <var-value>true</var-value>

          </var>

          <var>

          <var-name>fieldTest[0]</var-name>

          <var-value>NOTNULL</var-value>

          </var>

          </field>

           

          <field

          property="dob" indexedListProperty="dependents" depends="requiredif,date">

          <arg0 key="dependentlistForm.dob.label"/>

          <var>

          <var-name>field[0]</var-name>

          <var-value>lastName</var-value>

          </var>

          <var>

          <var-name>fieldIndexed[0]</var-name>

          <var-value>true</var-value>

          </var>

          <var>

          <var-name>fieldTest[0]</var-name>

          <var-value>NOTNULL</var-value>

          </var>

          </field>

           

          <field

          property="coverageType" indexedListProperty="dependents" depends="requiredif">

          <arg0 key="dependentlistForm.coverageType.label"/>

          <var>

          <var-name>field[0]</var-name>

          <var-value>lastName</var-value>

          </var>

          <var>

          <var-name>fieldIndexed[0]</var-name>

          <var-value>true</var-value>

          </var>

          <var>

          <var-name>fieldTest[0]</var-name>

          <var-value>NOTNULL</var-value>

          </var>

          <var>

          <var-name>field[1]</var-name>

          <var-value>insureDependents</var-value>

          </var>

          <var>

          <var-name>fieldTest[1]</var-name>

          <var-value>EQUAL</var-value>

          </var>

          <var>

          <var-name>fieldValue[1]</var-name>

          <var-value>true</var-value>

          </var>

          <var>

          <var-name>fieldJoin</var-name>

          <var-value>AND</var-value>

          </var>

          </field>

          </form>

          這里的意思是:

          如果lastName 字段是非空的,firstName 字段required。因為字段Indexed 為真,這它意味著lastName的indexed 必須與firstName 的索引的一樣,dob同理,除非date不為空。

          如果lastName 用樣索引時的值不空, 而且非索引字段insureDependents為真,則coverageType 是only require。

          你可以對字段在[n]中使用任意數字,唯一的限制是他們必須都是AND或OR,你無法混合使用。

          Deprecation:

          u        JavaScript 和Java的range方法.

          u        StrutsValidator &StrutsValidatorUtil 類中的Deprecation方法
          驗證器api指南

          一個簡明的Struts驗證器API指南 可以幫助你開始。
          驗證器資源

          Struts Validator: Validating Two Fields Match 作者Matt Raible。(兩個字段匹配驗證)關于使用方法的文章。(范例部分為翻譯此文內容)

          DynaForms and the Validator 作者James Turner and Kevin Bedell。Struts Kickstart的其中一章(動態form和驗證器),可以自由下載PDF).

          Validating user input 作者 David Winterfeldt and Ted Husted。Struts in Action的其中一章,可以自由下載(PDF)。

          posted @ 2009-01-07 09:52 Hill 閱讀(204) | 評論 (0)編輯 收藏
           

          首先,我先大概介紹一下jpetstore的整體架構,spring的這個版本主要使用了struts+spring+ibatis的框架組合,
          而在MVC層的框架,這個版本又同時提供了兩個實現版本,一個是struts,一個是spring 自帶的web框架,

          而數據庫持久層使用的是ibatis框架,這個框架是一個SQL映射框架,輕量級而且使用非常容易,基本上會

          使用JDBC的朋友看一兩個小時就會使用了。
          下圖是該應用的一個簡略架構圖,沒有什么好的工具,就大概畫了一個,雖然比較簡單,不過也基本可以

          概括應用的整體框架了,首先是JSP請求,通過struts-config.xml(這里只是根據struts來畫的,spring其實也差不多),

          請求轉到相應的Action中,可以看到,這里有一個BaseAction,是所有Action實現的父類,這個類的作用稍后再講,

          然后就是每個Action通過PetStoreFacade的對象調用后臺DAO對象,從而通過ibatis進行數據的持久操作,

          這里使用了門面(Facade)模式,隔離了前臺與后臺耦合度,而PetStoreFacade就是這個門面。結合下圖,

          相信大家對整個jpetstore會有個大概的了解。

           

           

          好了,大概的結構講了下,接下來我們就從代碼入手,在這里考慮到struts大家比較熟悉,因此,

          本文是以struts版本來講,同時聲明,本文并不會一段段代碼詳細講述,而只是提供一個學習的參考,

          大概講解一下流程,讓大家不再茫然不知從哪開始,好了,廢話也不多說了。

          既然是WEB應用,那當然首先從配置文件看起,那就非web.xml莫屬了,打開WEB-INF目錄下的web.xml,

          我們挑出目前我們應該關注的配置代碼:
          代碼  
          <servlet>    
             <servlet-name>petstore</servlet-name>    
             <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
             <load-on-startup>2</load-on-startup>    
          </servlet>    
             
          <servlet>    
             <servlet-name>action</servlet-name>    
             <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>    
             <load-on-startup>3</load-on-startup>    
          </servlet>    
             
          <servlet-mapping>    
             <servlet-name>petstore</servlet-name>    
             <!--   
             <servlet-name>action</servlet-name>   
             -->    
             <url-pattern>*.do</url-pattern>    
          </servlet-mapping>
          在這里可看到兩個servlet設置,以及一個servlet mapping,第一個petstore的servlet是用于spring web框架的,

          而第二個action的servlet就是用于struts的,而這個版本的mapping默認的是使用spring web,可以看到,<servlet-name>action</servlet-name>這一行是被注釋掉了,我們要使用struts的話,那就把這個注釋去掉,

          改為注釋掉<servlet-name>petstore</servlet-name>,好了,如此注釋以后,整個應用就會以struts的框架運行。

          (這些配置是什么意思?如果你還搞不懂的話,建議你先去學學基礎再來研究應用吧)

          接下來我們可以打開strutc-config.xml文件,這里就是struts的默認配置文件,在這里可以看到struts的相關配置信息。

          好了,接下來我們就以一個請求來講述基本的請求流程,以search為例,生成項目,再啟動,

          成功之后進入應用的首頁,我們終于可以看到久違的鸚鵡界面了,激動吧,呵呵,在界面的右上角,

          有一個Search文本框,我們就以這個Search為例子來講解,輸入一個關鍵字cat,然后點search,

          結果出來了,這個過程的內部是如何運作的呢?

          我們用鼠標右鍵點擊頁面,然后選擇屬性,我們看到顯示的地址可能是:
          http://localhost:8080/shop/searchProducts.do;jsessionid=E2D01E327B82D068FEE9D073CA33A2A3

          這個地址就是我們剛才點擊查詢時提交的地址了,我們看到searchProducts.do這個字符串,

          我們之前在web.xml里面的設置大家還記得嗎?
          <servlet-mapping>
             <!--
             <servlet-name>petstore</servlet-name>
             -->
             <servlet-name>action</servlet-name>
             <url-pattern>*.do</url-pattern>
          </servlet-mapping>
          代表著所有以.do為結尾的請求,都將被名叫action的servlet處理,也就是通過struts-config配置進行處理,那我們就去struts-config.xml里面看看,打開struts-config.xml文件,ctrl+F彈出查詢界面,輸入searchProducts,我們就可查到
          <action path="/shop/searchProducts" type="org.springframework.samples.jpetstore.web.
          struts.SearchProductsAction" name="emptyForm" scope="session" validate="false">    
          <forward name="success" path="/WEB-INF/jsp/struts/SearchProducts.jsp"/>    
          </action>
          根據以上配置,我們可以得知,剛才我們的提交將會被SearchProductsAction處理,而該action的form是emptyForm,查找emptyForm這個別名,我們可以找到它指向一個BaseActionForm,打開這個form我們可以看到,里面只有兩個validate方法和一個addErrorIfStringEmpty方法,沒有任何的屬性,那就是說search這個提交并沒有把我們輸入的關鍵字保存在form里面,打開SearchProductsAction,我們看到execute方法里的第一句就是

          String keyword = request.getParameter("keyword");
          也就是說我們輸入的關鍵字是以參數的形式傳入到request里面,參數名字為“keyword”,我們打開IncludeTop.jsp,這個文件在WEB-INF/jsp/struts目錄下。

          注意了,jsp目錄下分別有spring以及struts兩個目錄,這兩個目錄就是分別對應兩個web框架的,我們使用的是struts所以jsp代碼就到struts目錄里面,為什么打開IncludeTop.jsp呢,我們可以看到,無論我們進入哪個頁面,search那個文本框都存在,也就是說,這個文本框是被當作一個模板插入到所有頁面當中去的,我們隨便打開一個頁面,就可以看到頁面開頭都是:

          <%@ include file="IncludeTop.jsp" %>
          這句就是把IncludeTop.jsp當作頁面頭部包含進來,所以凡是包含這個頭頁面的頁面,他們的頭部都是一樣的,這也是我們在開發中常用的一種方式,統一界面的一種方式,我們也可以看到在這些文件尾部也有類似的代碼,如:

          <%@ include file="IncludeBottom.jsp" %>

          其作用也是一樣。打開IncludeTop.jsp后,我們看到其中有一段代碼:

          <form action="<c:url value="/shop/searchProducts.do"/>" method="post">
          <input type="hidden" name="search" value="true"/>
          <input name="keyword" size="14"/> <input border="0" src="../images/search.gif"

          type="image" name="search"/>
          </form>
          這段代碼就是我們search文本框以及提交鏈接的代碼,在這里就不做詳細介紹了。

          好了,接下來我們再看看這個action的后續代碼

          if (keyword != null) {  
          if (!StringUtils.hasLength(keyword)) {  
             request.setAttribute("message", "Please enter a keyword to search for,

          then press the search button.");  
             return mapping.findForward("failure");  
             }  
          PagedListHolder productList = new PagedListHolder(getPetStore().

          searchProductList(keyword.toLowerCase()));  
          productList.setPageSize(4);  
          request.getSession().setAttribute("SearchProductsAction_productList", productList);  
          request.setAttribute("productList", productList);  
          return mapping.findForward("success");  
          }

          這里第一句就是判斷keyword是否為空,不為空就執行其中的代碼,我們search的時候這個keyword肯定是不為空的,

          那就是說這段if包含的代碼就是我們search的處理代碼了,有的人也許會說,如果我不輸入關鍵字而直接點search呢,

          這keyword不就是為空了嗎?我想這個你在此處加個斷點,再運行一下就知道了,雖然你沒有輸入,

          但是keyword一樣不是null,它將是一個空字符串,而不是空對象。我們看到if里面還包含有一個if,

          這里就是判斷keyword是否為空字符串了,StringUtils.hasLength()方式是一個工具類,

          用來判斷keyword是否為空字符串,如果是空字符串就返回false,而這句判斷當返回false時,

          因為前面有個感嘆號,所以值為false就執行被if所包含的語句,里面的代碼就是保存一個錯誤信息,然后return mapping.findForward("failure");,這句的意思就不再解釋了。

          現在假設我們正確輸入keyword,那么程序將不會執行if語句中的代碼,直接向下執行,我們看到


          PagedListHolder productList = new PagedListHolder(getPetStore().

          searchProductList(keyword.toLowerCase()));

          這句代碼,PagedListHolder是spring提供的一個用來保存查詢結構類,通常用來進行分頁處理,

          因此我們可以知道

          getPetStore().searchProductList(keyword.toLowerCase())
          這一句就是用來查詢,并返回查詢結果的。getPetStore()這個方法是繼承自BaseAction的,它將獲得一個PetStoreFacade的實現,我們打開BaseAction的代碼,可以看到如下代碼

          public void setServlet(ActionServlet actionServlet) {  
                 super.setServlet(actionServlet);  
                 if (actionServlet != null) {  
                     ServletContext servletContext = actionServlet.getServletContext();  
                 WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);  
                 this.petStore = (PetStoreFacade) wac.getBean("petStore");  
                 }  
          }

          這句代碼里面最重要的一句就是

          WebApplicationContext wac = WebApplicationContextUtils.

          getRequiredWebApplicationContext(servletContext);
          這句代碼的作用就是獲取一個WebApplicationContext對象wac,在這里我們只需要知道這個對象的作用,而不對其進行深入研究,通過這個對象,我們可以根據spring的配置文件,獲得相應的Bean,下面這句就是用來獲取相應bean的語句:


          this.petStore = (PetStoreFacade) wac.getBean("petStore");
          petStore這個就是bean的id,這個petStore的bean具體是哪個類呢?我們打開applicationContext.xml,可以找到以下配置代碼


          <bean id="petStore" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
             <property name="accountDao" ref="accountDao"/>
             <property name="categoryDao" ref="categoryDao"/>
             <property name="productDao" ref="productDao"/>
             <property name="itemDao" ref="itemDao"/>
             <property name="orderDao" ref="orderDao"/>
          </bean>
          從這里可以看到,petStoreFacade的具體類就是PetStoreImpl,而這個類當中,分別通過spring IOC注入了幾個DAO的bean,這幾個DAO的配置可以在dataAccessContext-local.xml文件里面找到,我們打開PetStoreImpl這個實現類,我們看到類里有一個searchProductList方法,這個方法就是我們在Action當中調用的方法

          return this.productDao.searchProductList(keywords);
          從這句代碼可以看出,這個方法是通過調用productDao的searchProductList方法來獲得結果的,

          productDao這個DAO從上面的配置文件可以看出,是通過IOC容器進行注入的,我們打開dataAccessContext-local.xml文件,可以看到

          <bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis

          .SqlMapProductDao">
             <property name="sqlMapClient" ref="sqlMapClient"/>
          </bean>
          這句配置代表了productDao的實現類就是SqlMapProductDao,同時這個類包含有一個sqlMapClient的屬性對象,這個對象也是通過ioc注入的,再在這個配置文件里,我們可以找到如下一段代碼

          <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
             <property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
             <property name="dataSource" ref="dataSource"/>
          </bean>
          這段代碼就是sqlMapClient這個bean的配置,這里的實現是SqlMapClientFactoryBean,它是spring專門為ibatis框架提供的一個支持,通過這個對象就可以很好的集成ibatis框架,具體的介紹可以通過spring官方文檔或者是其他一些教程獲得,在這里就不多做介紹。

          好了,接下來我們知道了,實際查詢數據是通過DAO的實現類SqlMapProductDao進行的,而SqlMapProductDao當中就是通過了ibatis進行數據的查詢,從而返回結果,這里也就不多做介紹了,大家可以通過ibatis的教程獲得ibatis的使用方法,非常的簡單,search操作從前臺到后臺的大概流程就介紹到這里了。

          在這個參考文章中,我并沒有對具體技術做過多的講解,那是因為本文只是作為一個研究jpetstore的參考,提供一個可供參考的研究流程,主要是為了那些想開始研究jpetstore但是又不知道從哪開始或者是不知道如何進行研究的新人朋友們而準備的,如果具體的講解每一部分,那我想將不僅僅是一篇文章就可以完成的事情,因為這里涉及到struts,spring,ibatis等具體的框架技術,每一個框架基本都可以寫成一本書,用一篇文章來講就不太實際了,而且我個人更傾向于遇到不理解的地方的時候,多使用google來搜索,這樣能夠進一步加深自己對問題的理解。

          好了,關于jpetstore源碼研究入門的文章就寫到這里結束了,由于本人技術和文筆有限,有錯漏或者表達不當的地方請不要介意,歡迎各位朋友來指正。

          posted @ 2009-01-06 15:50 Hill 閱讀(3780) | 評論 (0)編輯 收藏
           
          本人剛轉到Java技術方向,希望能在這里與大家一起學習,進步。
          posted @ 2009-01-05 17:24 Hill 閱讀(383) | 評論 (0)編輯 收藏
          僅列出標題
          共5頁: 上一頁 1 2 3 4 5 
          CALENDER
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(3)

          隨筆檔案

          文章檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜


          Powered By: 博客園
          模板提供滬江博客

          主站蜘蛛池模板: 壤塘县| 平利县| 伊吾县| 武宁县| 临夏市| 门源| 灵武市| 松江区| 陵川县| 探索| 马公市| 灵山县| 百色市| 宿松县| 阿拉尔市| 九龙坡区| 任丘市| 山丹县| 瑞金市| 永仁县| 赞皇县| 定远县| 万山特区| 明星| 将乐县| 同心县| 绥芬河市| 大冶市| 洛扎县| 定兴县| 法库县| 兰溪市| 无为县| 奉节县| 宜城市| 石城县| 陵川县| 万全县| 正安县| 南雄市| 扎兰屯市|