struts2請求引數處理
今天總結一下struts2中有關action處理請求引數的兩部分核心內容,第一:請求引數的封裝,第二:請求引數的校驗。
Action處理請求引數
struts2 和 MVC 定義關係
StrutsPrepareAndExecuteFilter: 控制器
JSP : 檢視
Action : 可以作為模型,也可以是控制器
struts2 Action 接受請求引數 :屬性驅動 和 模型驅動
Action處理請求引數三種方式
第一種:Action 本身作為model物件,通過成員setter封裝 (屬性驅動 )
頁面:
使用者名稱 <input type="text" name="username" /><br/>
Action:
publicclass RegistAction1 extends ActionSupport {
privateString username;
publicvoid setUsername(String username) {
this.username= username;
}
}
問題一: Action封裝資料,會不會有執行緒問題 ?
*struts2 Action 是多例項 ,為了在Action封裝資料 (struts1 Action 是單例的 )
問題二: 在使用第一種資料封裝方式,資料封裝到Action屬性中,不可能將Action物件傳遞給 業務層
* 需要再定義單獨JavaBean ,將Action屬性封裝到 JavaBean
第二種:建立獨立model物件,頁面通過ognl表示式封裝 (屬性驅動)
頁面:
使用者名稱 <input type="text" name="user.username" /><br/> ----- 基於OGNL表示式的寫法
Action:
publicclass RegistAction2 extends ActionSupport {
private User user;
publicvoid setUser(User user) {
this.user= user;
}
publicUser getUser() {
returnuser;
}
}
問題: 誰來完成的引數封裝
<interceptor
name="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
第三種 :使用ModelDriven介面,對請求資料進行封裝 (模型驅動 ) ----- 主流
頁面:
使用者名稱 <input type="text" name="username" /><br/>
Action:
publicclass RegistAction3 extends ActionSupport implements ModelDriven<User> {
privateUser user = new User(); // 必須手動例項化
publicUser getModel() {
returnuser;
}
}
* struts2 有很多圍繞模型驅動的特性
* <interceptorname="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>為模型驅動提供了更多特性
對比第二種、第三種 : 第三種只能在Action中指定一個model物件,第二種可以在Action中定義多個model物件
<inputtype="text" name="user.username" />
<inputtype="text" name="product.info" />
封裝資料到Collection和Map
1)封裝資料到Collection物件
頁面:
產品名稱 <input type="text"name="products[0].name" /><br/>
Action:
publicclass ProductAction extends ActionSupport {
privateList<Product> products;
publicList<Product> getProducts() {
returnproducts;
}
publicvoid setProducts(List<Product> products) {
this.products= products;
}
}
2)封裝資料到Map物件
頁面:
產品名稱
<inputtype="text" name="map['one'].name" />
<br/> ======= one是map的鍵值
Action:
publicclass ProductAction2 extends ActionSupport {
private Map<String,Product> map;
publicMap<String, Product> getMap() {
returnmap;
}
publicvoid setMap(Map<String, Product> map) {
this.map= map;
}
}
Struts2型別轉換(瞭解)
1、 struts2 內部提供大量型別轉換器,用來完成資料型別轉換問題
boolean 和 Boolean
char和 Character
int 和 Integer
long 和 Long
float 和 Float
double 和 Double
Date 可以接收 yyyy-MM-dd格式字串
陣列 可以將多個同名引數,轉換到陣列中
集合 支援將資料儲存到 List 或者 Map 集合
案例: 輸入合法年齡和生日可以自動轉換
當輸入abc 轉換為 int型別 age時
Causedby: java.lang.NoSuchMethodException:
cn.xxxx.struts2.demo3.CustomerAction.setAge([Ljava.lang.String;
分析: 輸入20 ,轉換 int型別20 --- setAge(int)
輸入abc,轉換int 出錯 ---- setAge(String) ----- 報錯方法不存在異常
Jsp中接受異常資訊
<%@ taglib uri="/struts-tags"prefix="s"%>
<s:fielderror/>
請求引數校驗
校驗的分類 :客戶端資料校驗 和 伺服器端資料校驗
客戶端資料校驗 ,通過JavaScript 完成校驗 (改善使用者體驗,使使用者減少出錯 )
伺服器資料校驗 ,使用框架內建校驗功能(struts2 內建校驗功能 ) ----- 必須的
struts2 支援校驗方式
程式碼校驗 :在伺服器端通過編寫java程式碼,完成資料校驗
配置校驗 :XML配置校驗(主流) 和 註解配置校驗
手工程式碼校驗請求引數
步驟一: 封裝資料
步驟二: 實現校驗Action ,必須繼承ActionSupport 類
步驟三: 覆蓋validate方法,完成對Action的業務方法資料校驗
通過程式碼邏輯判斷引數是否有效,如果引數非法 , this.addFieldError (ActionSupport提供)
workflow攔截器 跳轉回 input頁面
步驟四: 在jsp中 通過 <s:fieldError/> 顯示錯誤資訊
* validate方法會對Action中所有業務方法進行校驗,如果只想校驗某一個方法: validate方法名()
比如執行action裡面的名稱是add的方法,只想對add方法進行校驗
validateAdd()
Xml配置方式資料校驗
XML配置方式資料校驗 (企業主流校驗)
程式碼校驗 不適用於 大型專案, 流程資料複雜時,開發量和維護量都會很大
xml配置校驗原理: 將很多校驗規則程式碼已經寫好,只需要在xml中定義資料所使用校驗規則就可以了
步驟一 :編寫jsp
步驟二 :編寫Action 繼承ActionSupport 或者 實現 Validateable 介面
步驟三 :封裝請求引數
*使用xml校驗 必須提供get方法
步驟四 :編寫校驗規則xml檔案
在Action所在包編寫 Action類名-validation.xml對Action所有業務方法進行校驗
引入DTD
------xwork-core-2.3.7.jar 中 xwork-validator-1.0.3.dtd
<!DOCTYPEvalidators PUBLIC
"-//Apache Struts//XWorkValidator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
內建校驗器定義檔案
xwork-core-2.3.7.jar中/com/opensymphony/xwork2/validator/validators/default.xml
<validators>
<!-- name:要校驗的欄位名 -->
<fieldname="username">
<field-validatortype="requiredstring">
<message>使用者名稱不能為空!(XML)</message>
</field-validator>
</field>
內建校驗器
* required (必填校驗器,要求被校驗的屬性值不能為null)
* requiredstring (必填字串校驗器,要求被校驗的屬性值不能為null,並且長度大於0,預設情況下會對字串去前後空格)
* stringlength (字串長度校驗器,要求被校驗的屬性值必須在指定的範圍內,否則校驗失敗,minLength引數指定最小長度,maxLength引數指定最大長度,trim引數指定校驗field之前是否去除字串前後的空格)
* regex (正則表示式校驗器,檢查被校驗的屬性值是否匹配一個正則表示式,expression引數指定正則表示式,caseSensitive引數指定進行正則表示式匹配時,是否區分大小寫,預設值為true)
* int(整數校驗器,要求field的整數值必須在指定範圍內,min指定最小值,max指定最大值)
* double(雙精度浮點數校驗器,要求field的雙精度浮點數必須在指定範圍內,min指定最小值,max指定最大值)
* fieldexpression (欄位OGNL表示式校驗器,要求field滿足一個ognl表示式,expression引數指定ognl表示式,該邏輯表示式基於ValueStack進行求值,返回true時校驗通過,否則不通過)
* email(郵件地址校驗器,要求如果被校驗的屬性值非空,則必須是合法的郵件地址)
* url(網址校驗器,要求如果被校驗的屬性值非空,則必須是合法的url地址)
* date(日期校驗器,要求field的日期值必須在指定範圍內,min指定最小值,max指定最大值)
案例
required 必填校驗器
<field-validatortype="required">
<message>性別不能為空!</message>
</field-validator>
requiredstring 必填字串校驗器
<field-validatortype="requiredstring">
<param name="trim">true</param>
<message>使用者名稱不能為空!</message>
</field-validator>
stringlength:字串長度校驗器
<field-validatortype="stringlength">
<paramname="maxLength">10</param>
<paramname="minLength">2</param>
<paramname="trim">true</param>
<message><![CDATA[產品名稱應在2-10個字元之間]]></message>
</field-validator>
int:整數校驗器
<field-validatortype="int">
<paramname="min">1</param>
<paramname="max">150</param>
<message>年齡必須在1-150之間</message>
</field-validator>
date: 日期校驗器
<field-validatortype="date">
<paramname="min">1900-01-01</param>
<paramname="max">2050-02-21</param>
<message>生日必須在${min}到${max}之間</message>
</field-validator>
url: 網路路徑校驗器
<field-validatortype="url">
<message>xxxx播客的主頁地址必須是一個有效網址</message>
</field-validator>
email:郵件地址校驗器
<field-validatortype="email">
<message>電子郵件地址無效</message>
</field-validator>
regex:正則表示式校驗器
<field-validator type="regex">
<paramname="expression"><![CDATA[^13\d{9}$]]></param>
<message>手機號格式不正確!</message>
</field-validator>
fieldexpression : 欄位表示式校驗
<field-validatortype="fieldexpression">
<param name="expression"><![CDATA[(password==repassword)]]></param>
<message>兩次密碼輸入不一致</message>
</field-validator>
=============================
如何對指定的方法校驗?
格式 Action類名-ActionName(<action>元素name屬性)-validation.xml
例如 : 校驗AddCustomerAction中execute方法 配置 <action
name="addcustomer".../> 校驗檔名字:
AddCusotmerAction-addcustomer-validation.xml
自定義校驗規則(瞭解)
步驟一: 自定義校驗器必須實現 Validator 介面
通常自定義校驗器 繼承 ValidatorSupport 和 FieldValidatorSupport
*ValidatorSupport 針對不是一個輸入欄位 (兩個密碼一致)
*FieldValidatorSupport 針對是一個輸入欄位 (使用者名稱非空)
步驟二: 註冊校驗器
在工程的src下新建validators.xml檔案
引入 xwork-core-2.3.7.jar中xwork-validator-config-1.0.dtd
步驟三 :使用校驗器
在Action所在包 建立Action類名-validation.xml
編寫一個類繼承FieldValidatorSupport :
public class MyAgeValidator extends FieldValidatorSupport {
public void validate(Objectobj) throws ValidationException {
// 獲得欄位名稱:
String name =this.getFieldName();
// 獲得欄位的值:
Object value = this.getFieldValue(name, obj);
if(value instanceofInteger){
int age = (Integer)value;
if(age < 0){
this.addFieldError(name,obj);
}
}
}
}
*註冊校驗規則:
* 在src下建立一個validators.xml
* 引入一個DTD:
* xwork-core-2.3.7.jar下的xwork-validator-config-1.0.dtd
* 配置:
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWorkValidator Config 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">
<validators>
<validator name="aaa" class="cn.xxxx.action.demo6.MyAgeValidator"></validator>
</validators>
* 使用校驗規則:
<validators>
<fieldname="age">
<field-validatortype="aaa">
<message>年齡不能為負數!</message>
</field-validator>
</field>
</validators>
**** 實際開發中很少用到自定義校驗器