天天看點

struts2學習筆記2

1、類型轉換:

struts2的類型轉換器實際上是基于OGNL實作的,自定義類型轉換需要實作TypeConverter或者DefaultTypeConverter或者StrutsTypeConverter

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

繼承DefaultTypeConverter需要重寫convertValue()

public Object convertValue(Map context, Object value, Class toType) {//value是原始字元串數組
	        if (toType == Locale.class ) {//轉換成Locale類
	        	System.out.println( " Converting String to Locale " );
	           String locale = ((String[]) value)[0];
	            return new Locale(locale.substring( 0 , 2 ), locale.substring( 3 ));
	       } else if (toType == String.class ) {//轉換成String
	    	   System.out.println( " Converting Locale to String " );
	           Locale locale = (Locale) value;
	            return locale.toString();
	       } 
	        return null ;
	   } 
           

   局部類型轉換器:需建立ActionName-conversion.properties,ActionName是需要轉化器生效的Action的類名,應該和Action是相同的路徑下

propertyName=類型轉換器類(需要包名)
           

 全局類型轉換器:需要建立的是xwork-conversion.properties

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

基于struts2的類型轉換器:StrutsTypeConverter,将DefaultTypeConverter中的雙向轉換變成了兩個方法,其他的和其一樣

數組屬性轉換和集合類型轉換實作方法類似

------******************-----

另一種實作轉換的原理是根據OGNL在表單域中寫成Action屬性名.屬性名或者當屬性為MAP類型時:Action屬性名['Key'].屬性名

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

struts2 的colletion和Map支援

在Collection中:1)使用泛型來限制集合裡面元素的類型,若不使用,類型轉換就無法自動起作用了

                         2)使用struts2的配置檔案:需要在局部類型轉換檔案中增加如下的Key-value對:

Element_xxx=複合類型
           

 Element是固定的,xxx是action中的集合屬性名,複合類型是集合元素類型的權限定類名(包括包)

如果是Map類型的,則是

key_xxx=複合類型     ###map中的key類型
Element_xxx=複合類型  ##map中value的類型
           

 然後在jsp頁面中輸出

<s:property value="集合屬性名[索引].集合元素屬性名"/>
           

 但是set,map是無序的,是以不能用上面的索引,是以在沒有泛型時,需要在局部轉換檔案中增加:

Element_xxx=複合類型
           
keyProperty_集合屬性名=集合元素的索引屬性名  ##
           

 2、類型轉換錯誤的處理

當類型轉換出現異常時,conversionError攔截器會處理該異常,然後轉入名為input的邏輯視圖

#改變預設的類型轉換失敗後的提示資訊
xwork.default.invalid.fieldvalue={0}字段類型轉換失敗!
           
invalid.fieldvalue.屬性名=提示資訊
           

3、檔案下載下傳與上傳

enctype="multipart/form-data"表示送出表單時不再以字元串方式送出而是以二進制編碼的方式送出請求  

Java檔案代碼是:

private File image;   //上傳檔案
    private String title;  //設定上傳檔案的标題
    private String imageFileName;  //設定上傳檔案名,必須應上傳檔案屬性的名字開頭,然後後面是FileName,即若private File image 改成upload,則相應改成uploadFileName
    private String imageContentType; //上傳檔案類型,同imageFileName
    private String savePath;  //上傳檔案的儲存路徑,在struts.xml中定義
           

 其中image和title是出現在jsp中的:

<form action="/fileUpload.action" enctype="multipart/form-data" method="post">
        <s:textfield name="title"></s:textfield>
        <s:file name="image"></s:file>
        <s:submit/>
    </form>
           

 savePath在struts.xml中定義即可:

<package name="fileupload" extends="struts-default">
            <global-results>
                <result name="input">/jsp/fileupload/uploadError.jsp</result>                
            </global-results>
            <action name="fileUpload" class="com.leo.fileupload.FileUploadAction">
                <interceptor-ref name="fileUpload">
                    <param name="allowedTypes">image/bmp,image/x-png,image/gif,image/pjpeg</param>
                    <param name="maximumSize">2048000</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack" />
                 <result>/jsp/fileupload/uploadSucc.jsp</result>
                 <param name="savePath">/uploadFile</param>
            </action>
        </package> 
           

struts2可以配置上傳解析器,在struts.properties,

#指定使用COS的檔案上傳解析器
#struts.multipart.parser=cos
#指定使用Pell的檔案上傳解析器
#struts.multipart.parser=pell
#預設使用jakarta的common-fileupload
struts.multipart.parser=jakarta
           

 同時上傳多個檔案 

<tr>
                <td> <s:textfield name="title" label="标題"></s:textfield></td>
                <td><s:file name="filelist" label="檔案"></s:file></td>
                </tr>
            <tr>
                <td> <s:textfield name="title" label="标題2"></s:textfield></td>
                 <td><s:file name="filelist" label="檔案2"></s:file></td>
            </tr>
           

 name保持一緻,這樣就可以直接處理,可以用數組:

private List<String> title =new ArrayList<String>();
    private List<File> filelist =new ArrayList<File>();
    private List<String> filelistFileName=new ArrayList<String>();
    private List<String> filelistContentType=new ArrayList<String>();
           

下載下傳

<action name="fileDown" class="com.leo.filedown.FileDownAction">
                <param name="inputPath">/uploadFile</param>
                <result type="stream" name="success">
                    <!--下載下傳的檔案類型-->
                     <param name="contentType">application/octet-stream;text/plain;image/gif</param>
                      <param name="inputName">targetFile</param>   <!--此處name="inputName" 容易寫成name="inputStream"注意注意-->
                    <!--
                        檔案下載下傳的處理方式,包括内聯(inline)和附件(attachment)兩種方式,
                        而附件方式會彈出檔案儲存對話框,否則浏覽器會嘗試直接顯示檔案,預設為inline
                    -->
                    <param name="contentDisposition">attachment;filename="${fileName}"</param>
                    <param name="bufferSize">4096</param>
                </result>
           

 在action中需要傳回InputStream,如果報異常

java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [imageStream] in the invocation stack. Check the <param name="inputName"> tag specified for this action.
           

  則是inputStream傳回的執行個體為null造成的,應該注意路徑是不是對的。檔案存在不存在

4、struts攔截器    

 定義攔截器: 

<interceptor name="攔截器名" class="">
    <param name="參數名">值</param>
</interceptor>
           

 定義攔截器棧:

<interceptor-stack name="攔截器棧名">
   <interceptor-ref name="攔截器一"/>
   <interceptor-ref name="攔截器二"/>
   ...
</interceptor-stack>
           

 預設攔截器:

<interceptors>
   <default-interceptor-ref name="">
      <param 。。。/>
   </default-interceptor-ref>
</interceptors>
           

 實作攔截器需要繼承Interceptor接口,提供了三個方法,init(),destroy(),interceptor(ActionInvocation actionInvocation);

而如果我們的攔截器不需要申請資源,可則可以繼承AbstractInterceptor類,它的init和desttory是空實作的;

而如果我們不是攔截該action的所有方法,則是繼承MethodFilterInterceptor類,它是AbstractInterceptor的子類,我們重寫doInterceptor方法

MethodFilterInterceptor裡面有兩個方法,

          setExcludeMethods(String excludeMethods):所有excludeMethods字元串中列出的方法都不會被攔截

          setIncludeMethods(String includeMethods):這裡面的方法都會被攔截,

          如果兩個方法裡面都有的方法,則也會被攔截。

<param name="excludeMethods">execute,hh,method2</param>
           

 攔截結果的監聽器:

     這個監聽器是通過手動注冊在攔截内部的,必須實作PreResultListener接口的beforeResult方法,同時在攔截器裡面增加監聽就可以了

public String intercept(ActionInvocation actionInvocation) throws Exception {
        //增加監聽器
        actionInvocation.addPreResultListener(new MyPreResultListener());
        ActionContext ctx=actionInvocation.getInvocationContext();
           

覆寫攔截器裡面的特定的方法,可以直接在引用棧的時候直接修改

<interceptor-ref name="my-stack"><!--my-stack是攔截器棧-->
    <param name="second.name">xiugai</param>
</interceptor-ref>