什麼是靜態參數?
靜態參數就是硬編碼的,不可隨意改變。javascript
例子:java
咱們首先建立一個Action類,裏面有兩個參數,用來封裝請求參數 public class User extends ActionSupport { private String username; //用戶名 private int age; //年齡 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String adduser(){ System.out.println(username+":"+age); return null; } }
咱們在struts.xml中配置靜態參數 <package name="p1" extends="struts-default"> <action name="action1" class="com.cad.struts2.User" method="adduser"> <!--經過注入的方式封裝靜態參數--> <param name="username">張三</param> <param name="age">18</param> </action> </package>
咱們訪問action1動做時,會輸出 張三:18
咱們配置的靜態參數怎麼就被傳遞到動做類裏呢?程序員
咱們在struts2的運行流程中提到過,咱們動做類的動做方法執行以前,會有一系列的攔截器幫咱們執行一些操做。 在struts-default.xml中,有不少攔截器,攔截器又分爲不少攔截器棧,咱們默認是使用defaultStack的攔截器棧。 這個攔截器棧中有一個叫作staticParams的攔截器幫咱們完成靜態參數的封裝,將配置的靜態方法經過action類中的set方法設置進去。
什麼是動態參數?web
像咱們用表單提交的數據,就是動態數據。數據是可變的。
例子:正則表達式
第一步:咱們先建立一個添加用戶的表單 <form action="${pageContext.request.contextPath }/action1" method="post"> 用戶名:<input type="text" name="username"><br> 年 齡:<input type="text" name="age"><br> <input type="submit" value="提交"> </form>
第一種方式:數據參數和動做類寫在一塊兒 要求是表單中的name必須和咱們類中的set方法後面的名稱一致,例如表單中的username對應類中的setUsername,和參數並無太大關係,和set方法有關係。 public class User extends ActionSupport { private String username; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String adduser(){ System.out.println(username+":"+age); return null; } }
配置struts.xml文件 <package name="p1" extends="struts-default"> <action name="action1" class="com.cad.struts2.User" method="adduser"> </action> </package>
咱們訪問添加用戶頁面,添加數據,會輸出咱們添加的數據。sql
這一系列操做是由攔截器棧中的名爲params的攔截器幫咱們完成的數據庫
上面這種方式將參數和動做類寫在一塊兒,看起來太過混亂,咱們能不能用一個JavaBean將參數給封裝起來。 答案是能。express
第二種方式,將參數數據和動做類分開寫 第一步,咱們建立一個javaBean,User類,用來封裝請求參數 public class User implements Serializable{ private String username; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
第二步:建立一個添加用戶的動做類,裏面有一個user對象 public class AdduserAction extends ActionSupport { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String adduser(){ System.out.println(user.getUsername()+":"+user.getAge()); return null; } }
第三步:咱們得改變一些咱們的jsp頁面的寫法,由於表單的name要和類中的數據相對應,但類中只有一個user ,username去找動做類中的setUsername,確定找不到。 咱們這樣寫,他就會先找類中的user對象,而後去找user對象的username和age <body> <form action="${pageContext.request.contextPath }/action1" method="post"> 用戶名:<input type="text" name="user.username"><br> 年 齡:<input type="text" name="user.age"><br> <input type="submit" value="提交"> </form> </body>
原理:apache
這一系列操做仍是攔截器params幫咱們完成。咱們在getUser和setUser裏打印兩句話來看看他究竟是怎麼執行的 public User getUser() { System.out.println("getuser"); return user; } public void setUser(User user) { System.out.println("setuser"); this.user = user; } 輸出 getuser :先判斷對象是否存在 setuser :若是判斷不存在,調用set方法,經過反射建立一個對象,而且設置給該類 getuser :而後再獲取該對象,調用該對象的get和set方法對參數賦值
出於結構清晰的考慮,應該採用單獨的Model實例來封裝請求參數和處理結果,這就是所謂的模型驅動, 所謂模型驅動,就是使用單獨的JavaBean來貫穿整個MVC流程。 所謂屬性驅動,就是使用屬性來做爲貫穿MVC流程的信息攜帶者,固然屬性必須依附於對象,這個對象就是Action實例。 簡單說,模型驅動就是使用單獨的javaBean封裝請求參數。 屬性驅動就是把屬性寫在Action類中。
咱們發現上面的jsp中的name必須前面得加 user.username。。太過麻煩。咱們使用模型驅動來解決這個問題。實際開發中使用這種方式數組
模型驅動的要求: 1.動做類實現ModelDriven接口 2.實現接口中的getModel方法,返回咱們的數據對象 3.數據模型對象必須由咱們實例化。 咱們改進動做類 public class AdduserAction extends ActionSupport implements ModelDriven<User>{ //數據模型對象由咱們實例化 private User user=new User(); public User getUser() { System.out.println("getuser"); return user; } public void setUser(User user) { System.out.println("setuser"); this.user = user; } public String adduser(){ System.out.println(user.getUsername()+":"+user.getAge()); return null; } //實現接口方法,返回咱們的數據模型對象 public User getModel() { // TODO Auto-generated method stub return user; } }
咱們在jsp上就能像之前那樣 ,name只用咱們的參數相同便可 <body> <form action="${pageContext.request.contextPath }/action1" method="post"> 用戶名:<input type="text" name="username"><br> 年 齡:<input type="text" name="age"><br> <input type="submit" value="提交"> </form> </body>
原理:
其實這時候表單的name已經不只僅是一個簡單的字符串了。 這一系列的操做是由ModelDriven和params攔截器幫咱們作的 。 params攔截器負責提取請求參數,若是是屬性驅動模式,則還負責將請求參數傳給Action類的屬性 模型驅動的話就只提取請求參數。 ModelDriven攔截器會先判斷咱們的動做類是否屬於ModelDriven類型 屬於的話,就調用咱們實現的getModel方法,獲取咱們傳入的對象 而後將咱們的對象給壓入棧中
第一步:咱們先建立數據庫表 create database demo; use demo; create table user( username varchar(100) primary key, password varchar(100), birthday date, hobby varchar(255), married boolean );
第二步:在domain包建立咱們的user實體類 public class User { private String username;//用戶名 private String password;//密碼 private Date birthday; //生日 private String hobby; //愛好 private boolean married; //是否結婚 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } public boolean isMarried() { return married; } public void setMarried(boolean married) { this.married = married; } }
第三步:完成數據層,咱們在Dao層處理數據 public class UserDao { QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource()); //根據名字查找用戶 public User findUserByUsername(String username){ try { String sql="select * from user where username=?"; return qr.query(sql, new BeanHandler<User>(User.class),username); } catch (Exception e) { throw new RuntimeException(e); } } //添加用戶 public int addUser(User user){ String sql="insert into user values(?,?,?,?,?)"; Object []params={user.getUsername(),user.getPassword(),user.getBirthday(),user.getHobby(),user.isMarried()}; try { return qr.update(sql,params); } catch (SQLException e) { throw new RuntimeException(e); } } }
第四步:完成業務邏輯層的編寫,service層 public class UserService { private UserDao userdao=new UserDao(); //註冊 public int regist(User user){ return userdao.addUser(user); } //經過用戶名查找用戶 public User findByUsername(String username){ return userdao.findUserByUsername(username); } }
第五步:建立web層,咱們建立web層動做類 public class UserAction extends ActionSupport implements ModelDriven{ private User user=new User(); private UserService userservice=new UserService(); //註冊方法 public String regist(){ User _user=userservice.findByUsername(user.getUsername()); //判斷用戶是否存在,存在返回exists字符串 if(_user!=null){ return "exists"; } //獲取註冊成功更新的行數 int count=userservice.regist(user); //若是>0,返回success if(count>0){ return SUCCESS; } return null; } public Object getModel() { // TODO Auto-generated method stub return user; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
第六步:咱們編寫註冊的jsp頁面 <body> <form action="${pageContext.request.contextPath }/regist.action" method="post"> 用戶名:<input type="text" name="username"><br> 密 碼:<input type="password" name="password"><br> 生 日:<input type="text" name="birthday"><br> 愛好:<input type="checkbox" name="hobby" value="籃球">籃球 <input type="checkbox" name="hobby" value="足球">足球 <input type="checkbox" name="hobby" value="寫代碼">寫代碼<br> 已婚:<input type="checkbox" name="married" value="true"><br> <input type="submit" name="註冊"><br> </form> </body>
第七步:配置 struts.xml <package name="p1" extends="struts-default"> <action name="regist" class="com.cad.web.action.UserAction" method="regist"> <result name="success">/success.jsp</result> <result name="exists">/msg.jsp</result> </action> </package>
成熟的MVC框架應該提供成熟的異常處理機制。固然能夠在方法中手動捕捉異常,當捕捉到特定異常時,返回特定邏輯視圖名。
這種方式很是繁瑣,須要在方法中寫大量try catch塊,最大的缺點仍是一旦須要改變異常處理方法時,須要修改代碼。
最好的方式是經過聲明式的方式管理異常處理。struts2提供了一種聲明式的異常處理方式。
咱們看Action接口中的execute方法聲明。 public String execute() throws Exception 這就意味着咱們重寫該方法時,無需進行任何異常處理,而是把異常拋給struts2框架處理. struts2框架接收到Action拋出的異常後,根據struts.xml文件配置的異常映射,轉入指定的視圖資源。 異常映射功能是由 exception的攔截器幫咱們作的。 struts2的異常處理機制是經過在struts.xml中配置<exception-mapping..../>元素完成。 屬性: exception:異常類型 result:出現該異常時,系統轉入result指定的結果
全局異常映射對全部的Action都有效,但局部異常映射只對該異常映射所在的Action有效。
若是全局異常映射和局部異常映射配置了同一個異常類型,在該Action內,局部覆蓋全局。
局部異常映射:將<exception-mapping..../>元素做爲<action.../>的子元素配置 全局異常映射:將<exception-mapping..../>元素做爲<global-exception-mappings>元素的子元素配置
咱們作一個簡單的登錄應用 第一步:咱們編寫咱們的Action類 public class LoginAction implements Action{ private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute()throws Exception{ //當用戶名爲monster時,拋出咱們的自定義異常 if(getUsername().equals("monster")){ throw new MyException("自定義異常"); } //當用戶名爲sql時,拋出sql異常 if(getUsername().equalsIgnoreCase("sql")){ throw new SQLException("用戶名不能爲sql"); } if(getUsername().equals("cad")&&getPassword().equals("123456")){ return "success"; }else { return "error"; } } }
第二步:咱們編寫咱們的登錄jsp頁面 <body> <form action="${pageContext.request.contextPath }/login" method="post"> 用戶名:<input type="text" name="username"><br> 密 碼:<input type="password" name="password"><br> <input type="submit" value="提交"> </form> </body>
第三步:咱們編寫咱們的配置文件struts.xml <package name="p2" extends="struts-default"> //全局結果視圖定義 <global-results> <result name="sql">/exception.jsp</result> </global-results> //全局異常定義 <global-exception-mappings> //出現sql異常,就轉入到視圖名爲sql的視圖結果 <exception-mapping result="sql" exception="java.sql.Exception"></exception-mapping> </global-exception-mappings> <action name="login" class="com.cad.struts2.LoginAction" > //局部異常定義 <exception-mapping result="my" exception="conm.cad.struts2.MyException"></exception-mapping> <result name="my">/exception.jsp</result> <result name="success">/welcome.jsp</result> <result name="error">/error.jsp</result> </action> </package>
從struts2.1開始,struts2增長了未知處理器。 當用戶請求未知Action,或指定Action裏的未知方法,或Action處理結束後返回一個未知的result。struts2容許使用未知處理器來處理這些狀況。 未知處理器須要實現UnknownHandler接口,該接口包含三個方法 -handleUnknownAction:用戶請求未知Action時,該方法會被回調 -handleUnknownActionMethod:用戶請求指定Action的未知方法時,該方法會被回調 -handleUnknownResult:Action處理結束後返回一個未知Result時,該方法會被回調 一旦實現了自定義的未知處理器,就能夠在struts.xml中經過<bean../>元素來配置未知處理器 例如 <bean name="myHandler" class="com.cad.struts2.MyUnknownHandler" type="com.opensymphony.xwork2.UnknownHandler"></bean>
第一步:咱們實現咱們簡單的未知處理器 public class MyUnknownHandler implements UnknownHandler { public ActionConfig handleUnknownAction(String namespace, String actionName) throws XWorkException { System.out.println(actionName+"不存在"); return null; } public Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode) throws XWorkException { System.out.println(resultCode+"不存在"); return null; } public Object handleUnknownActionMethod(Object action, String methodName) throws NoSuchMethodException { System.out.println(methodName+"不存在"); return null; } }
第二步:在struts.xml中配置未知處理器 //定義咱們的未知處理器 <bean name="myHandler" class="com.cad.struts2.MyUnknownHandler" type="com.opensymphony.xwork2.UnknownHandler"></bean> <package name="p3" extends="struts-default"> <action name="myAction"></action> </package> //定義未知處理器棧 <unknown-handler-stack> <unknown-handler-ref name="myHandler"></unknown-handler-ref> </unknown-handler-stack>
而後咱們訪問myAction,會輸出success不存在。 是由於不指定action的class屬性時,默認使用ActioSupport 通常未知處理器主要處理Action返回未知result時有用。 瞭解便可。
全部的MVC框架,都屬於表現層的解決方案,都須要負責收集用戶請求參數,並將請求參數傳給應用的控制器組件。
這時問題出現了,全部的請求參數都是字符串類型數據,所以MVC框架必須具有將這些字符串請求參數轉換成相應的數據類型。
struts2提供了很是強大的類型轉換機制,struts2的類型轉換是基於OGNL表達式。
struts2提供了很好的擴展性,開發者能夠開發出本身的類型轉換器。完成字符串到自定義類型之間的轉換。
若是類型轉換中出現未知異常,開發者無須關心異常處理,struts2的conversionError攔截器會自動處理該異常,而且在頁面上生成提示信息。
表單中提交的全部數據都是字符串類型
例如咱們有一個User類,name爲String類型,age爲int類型,birthday爲Date類型,咱們必須在servlet中獲取表單傳入的參數,而後將其進行類型轉換,而後封裝到User對象中。
上述須要程序員本身進行類型轉換操做,比較繁瑣。
對於一個MVC框架而言,同樣須要將請求參數封裝成對象,也必須將請求參數轉換成對象屬性的數據類型,這就是類型轉換的意義。
struts內建的類型轉換器能自動將咱們的表單數據(字符串)轉換成對應的數據類型。
完成字符串和日期類型之間的轉換時,日期格式必須使用請求用戶本地的格式。通常是yyyy-MM-dd,若是輸入的日期格式不是本地的日期格式,例如咱們輸入1996/01/31,就會出現錯誤,類型轉換失敗。
需求:
當咱們在表單中輸入的日期格式不是本地的格式時,就會出現類型轉換錯誤,咱們也常常須要將字符串轉換成其餘的格式,例如字符串轉換成對象之類的操做,這時咱們就須要自定義類型轉換器。 struts2的類型轉換器其實是基於OGNL實現的。xwork集成了OGNL。 實現類型轉換器必須實現TypeConverter接口。這個接口的方法太過複雜,因此還提供了一個該接口的實現類DefaultTypeConverter。 咱們重寫DefaultTypeConverter類的convertValue方法便可。 咱們基於DefaultTypeConverter類實現類型轉換器時,將字符串轉換成咱們須要的類型經過convertValue方法實現,將咱們的類型轉換成字符串也是經過convertValue方法實現,所以咱們必須判斷轉換的類型來實現不一樣的邏輯。 爲了簡化類型轉換器的實現,struts2提供了一個StrutsTypeConverter抽象類,這個類是DefaultTypeConverter類的子類。 咱們看下這個類的源碼 :
繼承DefaultTypeConverter public abstract class StrutsTypeConverter extends DefaultTypeConverter { //重寫DefaultTypeConverter類的convertValue方法 public Object convertValue(Map context, Object o, Class toClass) { //若是要轉換的類型是字符串類型,也就是把咱們的類型轉換成字符串,調用convertToString方法 if (toClass.equals(String.class)) { return convertToString(context, o); } //若是參數是字符串數組,也就是將字符串轉換成咱們須要的類型,調用convertFromString方法 else if (o instanceof String[]) { return convertFromString(context, (String[]) o, toClass); } //若是參數是字符串,也就是將字符串轉換成咱們須要的類型,調用convertFromString方法 else if (o instanceof String) { return convertFromString(context, new String[]{(String) o}, toClass); } else { return performFallbackConversion(context, o, toClass); } } protected Object performFallbackConversion(Map context, Object o, Class toClass) { return super.convertValue(context, o, toClass); } //將字符串轉換成咱們須要的類型的方法 public abstract Object convertFromString(Map context, String[] values, Class toClass); //將咱們的類型轉換成字符串的方法 public abstract String convertToString(Map context, Object o); } 三個參數 : Map context:OGNL的上下文。暫時還沒學,後面會學到,暫時不用管。 value:須要轉換的參數。 toClass:轉換後的類型
需求:咱們將咱們前面的註冊案例中的生日改爲 yyyy/MM/dd類型 第一步:建立自定義類型轉換器 public class MyConverter extends StrutsTypeConverter { //日期轉換器,轉換成指定的類型 private DateFormat format=new SimpleDateFormat("yyyy/MM/dd"); //將字符串轉換成日期類型 public Object convertFromString(Map context, String[] values, Class toClass) { //判斷參數是否爲空 if(values==null||values.length==0){ return null; } //咱們只有一個參數,就是表單的birthday String date=values[0]; //判斷目標類型是不是Date if(toClass==java.util.Date.class){ try { //進行轉換 return format.parse(date); } catch (ParseException e) { e.printStackTrace(); } } return null; } //將日期類型轉換成字符串 public String convertToString(Map context, Object o) { //判斷當前參數是不是日期類型 if(o instanceof java.util.Date){ return format.format(o); } return null; } }
第二步:註冊類型轉換器 局部類型轉換器 按照屬性來註冊 若是屬性都在action中,那麼應該建立一個文件 Action名字-conversion.properties ,例如LoginAction-conversion.properties 若是屬性放到了javaBean中,那麼建立一個文件 javaBean名稱-conversion.properties 例如 User-conversion.properties 文件由鍵值對組成。 鍵爲須要轉換的屬性名字,值爲本身實現的類型轉換器全類名。 咱們建立 User-conversion.properties 內容 birthday=com.cad.web.convert.MyConverter 這時咱們註冊時使用 1996/01/24這種格式進行註冊就不會出現類型轉換錯誤。 用戶提交請求時,請求中的birthday參數會先被該類型轉換器處理。 全局類型轉換器 全部的Action都能用。咱們須要在src目錄下建立一個 xwork-conversion.properties 的文件 由於是全局的,就不存在只對birthday這個屬性進行轉換。 這裏的鍵是要轉換的類型,值仍是類型轉換器類。 咱們建立 xwork-conversion.properties 內容 java.util.Date=com.cad.web.convert.MyConverter 這樣當咱們輸入日期的表單時,就可使用咱們自定義的日期格式。
struts2提供了一個名爲conversionError的攔截器,這個攔截器被註冊在默認攔截器棧中。
當類型轉換器執行類型轉換出現錯誤時,該攔截器負責將對應錯誤封裝成表單域錯誤(fieldError),並將錯誤信息放入ActionContext中。
當攔截器對轉換異常進行處理後,系統會跳轉到名爲input的邏輯視圖。
咱們在struts.xml中配置 <result name="input">/regist.jsp</result> 當類型轉換失敗後,再跳轉到註冊頁面 跳轉到input視圖之後,咱們發現沒有任何錯誤提示信息。咱們前面講過conversionError攔截器會將轉換錯誤封裝成fieldError,並放在ActionContext中。 爲了在頁面中輸出錯誤信息,咱們須要使用struts的標籤。咱們先使用一些,後面會詳細介紹。 咱們在頁面添加<s:fielderror></s:fielderror>標籤 當咱們類型轉換失敗後,就會輸出錯誤信息。 咱們發現輸出的錯誤信息是英文的,咱們但願能變爲中文的提示信息。 咱們只須要在建立一個properties文件 文件名爲 javabean名稱.properties 鍵爲invalid.fieldvalue.屬性名稱 例如 :invalid.fieldvalue.birthday 值爲要輸出的內容 例如 invalid.fieldvalue.birthday=生日格式不正確
輸入校驗是web應用必須處理的問題,要防止用戶的誤輸入和惡意非法輸入。struts2給咱們提供了很是強大的輸入校驗體系。 輸入校驗分爲客戶端校驗和服務器端校驗。通常開發中二者都用,可是服務端校驗必須使用。 客戶端校驗是經過javascript在表單頁面進行初步過濾。客戶端校驗並不安全,攻擊者有不少方法能夠繞過客戶端校驗,因此服務端校驗是必不可少的。 可是客戶端校驗必不可少,由於大多數瀏覽者都是正經常使用戶,能夠阻止一些誤操做,下降了服務器的負載。 服務端校驗: 咱們之前在servlet中增長校驗。是經過獲取參數,而後判斷參數是否爲空和長度等等來進行校驗。 在servlet中使用硬編碼進行輸入校驗乏味而又繁瑣,struts2提供了基於校驗框架的輸入校驗,只須要指定簡單的配置文件便可。
聲明式驗證:經過xml配置文件進行驗證
-校驗規則文件與Action類放在同一目錄下 -校驗配置文件名稱爲 ActionClassName-validation.xml 例如 :UserAction-validation.xml 增長校驗文件後,系統會自動加載該文件。當用戶提交請求時,struts2會根據該文件對用戶數據進行校驗
基於表單字段的配置風格
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> //校驗文件的根元素 <validators> //被校驗表單項名稱 <field name="username"> //指定校驗器,struts2有不少內建校驗器,requiredstring是校驗數據是否爲空並去除兩端空格 <field-validator type="requiredstring"> //校驗失敗後的提示信息 <message>用戶名不能爲空</message> </field-validator> </field> </validators>
校驗失敗後,struts2會返回名爲input的邏輯視圖名,所以咱們還須要添加一個<result> 這個配置文件是全局驗證。也就是這個Action中的全部動做都會被驗證,咱們Action有的方法並不須要驗證,加入驗證甚至會出錯。 咱們有兩種方式可讓不須要驗證的方法跳過驗證: 第一種:在不須要驗證的方法前面添加註解@SkipValidation 第二種:針對動做類中的某個方法進行驗證,建立的XML文件名爲 ActionClassName-ActionName-validation.xml ,這裏的ActionName不是方法名,而是配置的action名字 ,例如 :UserAction-regist-validation.xml
非字段配置風格(基於驗證器的配置風格)
<validators> //驗證器類型 <validator type="requiredstring"> //要校驗的參數名字 <param name="fieldName">password</param> //校驗失敗後返回的信息 <message>密碼不能爲空</message> </validator> </validators>
校驗配置文件的<field-validator>和<validator>元素能夠指定一個可選的short-circuit屬性,指定該校驗器是不是短路校驗器,默認是false。 短路校驗器的做用是若是一個字段內有多個校驗器,若是一個校驗器校驗失敗,其餘校驗器根本不會繼續校驗。 校驗器的執行順序 -全部基於驗證器的配置風格的校驗器優先於字段風格的校驗器 -全部的基於驗證器風格的校驗器,排在前面的先執行 -全部的基於字段風格的校驗器,排在前面的先執行。 校驗器的短路原則 -全部的非字段校驗器最早執行,若是某個非字段校驗器校驗失敗,則該字段上的全部字段校驗器都不會執行 -非字段校驗器校驗失敗,不會阻止其餘非字段校驗器的執行 -若是某個字段校驗器校驗失敗,則該字段下的後面的字段校驗器都不會執行 -字段校驗器永遠都不會阻止非字段校驗器的執行
required:必填驗證器,要求指定的字段必須有值。使用非字段風格的配置時,能夠配置fieldName屬性來設置要校驗的表單項名稱。 requiredstring:必填字符串驗證器。 int、long、short:整數校驗器。要求字段的整數值必須在指定範圍內。參數:min指定該屬性最小值,不指定不檢查最小值。max指定該屬性最大值,不指定不檢查最大值。 date:日期校驗器。要求字段的日期值必須在指定範圍內。參數:min最小日期 ,max最大日期 expression:表達式校驗器,它只能被非字段風格配置。參數:expression指定一個邏輯表達式。 fieldexpression:字段表達式校驗器。要求字段知足一個邏輯表達式。 email:郵件校驗器。要求被檢查字段非空,而且必須是合法的郵箱地址,底層是正則表達式。 url:網址校驗器。要求被檢查字段非空而且是個發的url地址,底層是正則表達式。 stringlength:字符串長度校驗器。要求字段長度必須在指定的範圍內。參數:manLength 最大長度 minLength最小長度 regex:正則表達式校驗器。 等等。
struts2內建的校驗器能夠完成大部分輸入校驗。可是有時候沒法知足一些特殊的要求,struts2容許經過手動方式完成自定義校驗。 繼承ActionSupport,重寫validate方法 public void validate() { if(user.getUsername()==null||user.getUsername().isEmpty()){ addFieldError("username", "用戶名不能爲空!!!"); } } 重寫validate方法會檢驗action類裏的全部方法,咱們不須要校驗某些方法,有兩種方法。 第一種:在不須要校驗的方法前加上註解@SkipValidation 第二種:重寫validateXxx方法,Xxx即爲要驗證的方法名 public void validateRegist() { if(user.getUsername()==null||user.getUsername().isEmpty()){ addFieldError("username", "用戶名不能爲空!!!"); } }
1.對字符串類型的請求參數進行類型轉換,而且設置給JavaBean的屬性 2.類型轉換中可能出現異常,若是出現異常,將異常信息保存並封裝 3.調用struts2的輸入校驗規則進行輸入校驗(根據各類vatidate.xml文件裏定義的校驗規則) 4.經過反射調用validateXxx方法進行校驗 5.調用validate方法校驗 6.上面的校驗出現錯誤,轉到input對應的視圖資源。沒錯誤,調用action中的處理方法。