1. 類型轉換:
* 從頁面中獲取對應的內容
* 在動作類action中,聲明與頁面中表單name屬性的值同名的屬性
* 提供get和set方法
* struts2框架就會通過反射機制,從頁面中獲取對應的內容
* struts2框架不能把頁面中獲取到的字符串類型轉換成任何類型
* 當struts2框架不能把頁面中獲取到的字符串類型進行轉換時,就需要自定義類型轉換器
* 自定義類型轉換器:
* 要麼實現TypeConverter接口或者繼承TypeConverter接口的某個實現類,我們繼承DefaultTypeConverter類
* 重寫convertValue(Object value, Class toType){}方法
* 參數"value":要轉換的值
* 參數"toType":要轉換的類型
* 具體代碼實現:
if(value==null){
return false;
}
if(toType==null){
return false;
}
if(toType!=java.util.Date.class){
return false;
}
if(value instanceof java.lang.String[]){
String [] str = (String[])value;
if(str[0]!=null&&str[0].length()>0){
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
return sdf.parse(str[0]);
} catch (ParseException e) {
/*
* 在struts2框架裏,自定義的類型轉換器,
* 如果我們不手動拋出異常,struts2框架只捕獲異常,但是並不拋出。
* 所以框架就會認爲類型轉換器轉換成功,轉向成功頁面。
*/
throw new RuntimeException(e);
}
}
}
* 兩種註冊方式:
* 基於字段的(局部)
* 在動作類action同目錄下,創建一個名爲"UserAction-conversion.properties"的資源文件
* UserAction爲動作類action的名稱
* "-conversion.properties"是固定寫法
* 其內容配置如下:
createTime=cn.itcast.converter.DateConverter
* 基於類的(全局)
* 在src目錄下,創建一個名爲"xwork-conversion.properties"的資源文件
* 該資源文件的名稱是固定的
* 其內容配置如下:
java.util.Date=cn.itcast.converter.DateConverter
* 如果在頁面中輸入一個不正確的值的時候,不手動拋出異常,頁面依然轉向成功頁面
/*
* 在struts2框架裏,自定義的類型轉換器,
* 如果我們不手動拋出異常,struts2框架只捕獲異常,但是並不拋出。
* 所以框架就會認爲類型轉換器轉換成功,轉向成功頁面。
*/
* 配置修改錯誤提示信息爲中文
* 在動作類action同目錄下,創建一個名爲"converter.properties"的資源文件
* 該資源文件配置如下:
* 針對所有字段:
xwork.default.invalid.fieldvalue=類型轉換失敗 "{0}".
* 針對某個字段:
invalid.fieldvalue.createTime=出生日期轉換失敗
* 在struts.xml文件進行配置:
<constant name="struts.custom.i18n.resources"
value="cn.itcast.converter.converter">
</constant>
2. struts2框架的文件上傳:
* 單文件上傳:
* 在動作類action中聲明相關屬性:
* 在動作類action中,要聲明與頁面中表單name屬性同名的屬性,同名的屬性的類型時File類型;
* 在動作類action中,要聲明[同名的屬性]ContentType,類型時String類型;
* 在動作類action中,要聲明[同名的屬性]FileName,類型時String類型
* 給所有屬性提供get和set方法
* 在業務方法中,處理文件上傳:
* 獲取要上傳文件的路徑,保存的位置
* 在目標文件夾內,創建一個與上傳文件同名的文件
* 通過FileUtils工具類提供copyFile()方法,將臨時文件內容拷貝到目標文件夾下的那個同名的文件
* 設置上傳文件的總大小
* 在struts.xml文件中,<constant name="struts.multipart.maxSize" value="2097152000"></constant>
* 設置上傳文件的大小、類型和擴展名:
* 在自定義的配置文件中,在action標籤下:
<!-- 配置攔截器的參數,這裏是文件上傳攔截器 -->
<interceptor-ref name="defaultStack">
<!--
配置文件上傳攔截器的參數
* 與定義參數的順序無關
* 允許的類型(allowedTypes)和允許的擴展名(allowedExtensions)必須保持一致
-->
<!--
* 配置上傳文件的大小
* struts.xml文件中配置的是上傳文件的總大小
* 這裏配置的是上傳文件的單個大小
-->
<param name="fileUpload.maximumSize">20971520</param>
<!-- 配置上傳文件允許的類型,如果配置多個值的話,用","隔開 -->
<param name="fileUpload.allowedTypes">text/plain,application/msword</param>
<!-- 配置上傳文件的擴展名,如果配置多個值的話,用","隔開 -->
<param name="fileUpload.allowedExtensions">.txt</param>
</interceptor-ref>
* 自定義上傳文件的錯誤提示信息:
* 在動作類action同目錄下,創建一個名爲fileuploadmessage.properties資源文件(名爲自定義)
* 改資源文件配置如下:
struts.messages.error.uploading=Error uploading: {0}
struts.messages.error.file.too.large=File too large: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
* 多文件上傳:
* 所有流程於配置都與單文件上傳一致。
* 需要注意的是:
* 在頁面中,雖然是多文件上傳,但是頁面中表單的name屬性的值必須保持一致;
* 在動作類action中聲明的相關屬性,類型改成數組;
* 在業務方法中,相關處理流程改成單文件上傳的循環。
3. struts2手動驗證:
* 首先要從頁面中獲取對應的標籤name屬性的值,在動作類action中聲明同名的屬性,提供get和set方法
* 要繼承ActionSupport類或者實現Validateable接口
* 重寫Validateable接口的validate()方法
* 前提是:要保證setUsername()、validate()、login()方法要按照這個先後順序執行
* 如果登錄失敗,如何處理:
* this.addFieldError( key, value);
* key:錯誤提示字段
* value:錯誤提示信息
* 什麼時候纔是驗證通過?
* 驗證通過:1、map集合不存在;2、map集合存在併爲空
* 驗證不通過:map集合存在並且不爲空
* 分析需求:
* 用戶名不能爲null ,""
* 密碼不能爲null, "" ,並且密碼的長度6-12之間
* 針對所有業務方法進行驗證還是針對某個指定業務方法進行驗證?
* 重寫的validate()方法,針對所有業務方法進行驗證
* 重寫的validate()方法加上要驗證的指定的業務方法名(業務方法名的首字母大寫),實現針對某個指定的業務方法進行驗證
* 爲什麼要這樣進行拼接?因爲struts2框架底層拼接,如果不這樣寫,底層就找不到對應方法名
struts2框架驗證(xml方式):
* 首先要從頁面中獲取對應的標籤name屬性的值,在動作類action中聲明同名的屬性,提供get和set方法
* 創建一個xml格式驗證文件:
* 命名方式:ActionClassName-validation.xml,ActionClassName指的是動作類action的名稱
* <validators>標籤:根元素
* field:指定action中要校驗的屬性,實際上就是頁面中表單的name屬性的值
* name:指定頁面中表單的name屬性的值
* field-validator:指定驗證規則
* type:指定驗證規則名稱,
struts2框架提供的驗證規則放在xwork-core-xxx.jar
下的com\opensymphony\xwork2\validator\validators
的default.xml配置文件。
* param:向底層的驗證規則傳遞的參數
* message:驗證失敗時,提供的錯誤提示信息
* 如果要對指定方法進行驗證的話:
* xml驗證文件的命名方式:ActionClassName-ActionName-validation.xml,
ActionName對應的是struts.xml文件對應的action標籤的name屬性的值
4. 如何自定義攔截器:
* 所有的攔截器都需要實現Interceptor接口或者繼承Interceptor接口的擴展實現類
* 要重寫init()、intercept()、destroy()方法
* init()是在struts2框架運行時執行,在攔截器的生命週期中只執行一次,可以做必要的內容的初始化工作
* intercept(),是每一次請求就執行一次,做相關處理工作。
* intercept()方法接收一個ActionInvocation接口的實例
* 通過這個接口的實例,可以獲取以下內容
:
//cn.itcast.aop.UserAction@15b5783,動作類的對象
System.out.println("invocation.getAction() : "+invocation.getAction());
//cn.itcast.aop.UserAction@15b5783,與invocation.getAction()方法獲取的是同一的對象
System.out.println("invocation.getProxy().getAction() : "+invocation.getProxy().getAction());
//userAction_save,自定義配置文件中的action標籤的name屬性的值
System.out.println("invocation.getProxy().getActionName() : "+invocation.getProxy().getActionName());
//save,對應動作類指定要執行的方法名
System.out.println("invocation.getProxy().getMethod() : "+invocation.getProxy().getMethod());
// /aop,自定義配置文件中的package標籤的namespace屬性的值
System.out.println("invocation.getProxy().getNamespace() : "+invocation.getProxy().getNamespace());
* destroy()是在攔截器銷燬前執行,在攔截器的聲明週期中只執行一次。
* 在struts.xml配置文件中,進行註冊
* 在配置文件中的package標籤下,進行相關配置:
<interceptors>
<!-- 聲明自定義的攔截器 -->
<interceptor name="expessionInterceptor" class="cn.itcast.aop.ExpessionInterceptor" />
<!-- 聲明自定義攔截器棧 -->
<interceptor-stack name="expessionStack">
<interceptor-ref name="defaultStack"/>
<!-- 配置使用自定義攔截器 -->
<interceptor-ref name="expessionInterceptor"/>
</interceptor-stack>
</interceptors>
<!-- 配置修改struts2框架運行時,默認執行的是自定義攔截器棧 -->
<default-interceptor-ref name="expessionStack" />
5. 模型驅動:
* 要從頁面中獲取表單元素的值,需要在動作類中聲明與頁面元素同名的屬性。導致動作類中既有javabean又有業務方法。
* 將javabean和業務方法進行分離:
* 將重新創建一個javabean,將javabean的內容放置其中。
* 動作類action中只留業務方法
* 在動作類中聲明的javabean無法從頁面中獲取同名的屬性
* 需要使用struts2框架提供"ModelDriven(模型驅動)"
* 實現ModelDriven這個接口
* 重寫getModel()方法,返回該javabean的實例
* 代碼如下:
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
public User getModel() {
return user;
}
public String add(){
System.out.println("UserAction ************* add()");
return "add";
}
public String save(){
System.out.println("UserAction ************* save()");
return "success";
}
}
* 模型驅動的原理:
* 在不使用模型驅動的時候,之所以在動作類中獲取不到對應的屬性的原因:
* 在ValueStack中沒有對應javabean的所有屬性
* 模型驅動的作用,就是將javabean的實例壓入對象棧的棧頂,從而可以獲取到對應的屬性的值
6. 頁面回顯技術:
* 通過模型驅動,在動作類action中,可以獲取到頁面中元素的值
//方法一
* 通過javabean實例的set()方法,將新的內容set到javabean中,從而放置在頁面對應元素中
user.setUsername(newUser.getUsername());
user.setTel(newUser.getTel());
user.setDes(newUser.getDes());
//方法二
* 首先將值棧中,舊的javabean的內容,刪除掉
* 然後將新的內容壓入到值棧中的棧頂
ValueStack valueStack = ServletActionContext.getContext().getValueStack();
valueStack.pop();
valueStack.push(newUser);
7. 處理表單重複提交:
* 在頁面中增加一個隱藏域:<s:token></s:token>
* 創建一個struts.xml的配置文件,具體配置如下:
<!-- 配置默認執行的攔截器棧,增加令牌攔截器 -->
<interceptors>
<interceptor-stack name="tokenStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="token" >
<!-- 配置令牌攔截器,攔截的方法名,如果配置多個方法時,用","隔開 -->
<param name="includeMethods">save,update</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="tokenStack" />
* 在struts.xml配置文件中,增加一個result結果類型:
<!-- 配置表單重複提交後,要轉向到的頁面 -->
<result name="invalid.token">/model/error.jsp</result>
* 在表單重複提交後,要轉向到的頁面中通過<s:actionerror>獲取struts2框架底層提供錯誤提示信息
* 將struts2框架底層提供錯誤提示信息改成中文:
* 在與動作類action同級目錄下,創建名爲"token.properties"的資源文件,文件內容如下:
struts.messages.invalid.token=表單重複提交,請刷新後重試!
struts2學習筆記
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.