Struts2中的多個驗證方法的共存細節一
在Struts2中默認的,使用validateAbc()作爲abc()的驗證方法
所以,如果還存在xyz()方法的話,那麼它的驗證方法就是validateXyz()方法
執行時,首先執行validateAbc()方法
而無論validateAbc()方法執行後的結果如何,都會去執行validate()方法
也就是說,如果一個Action中提供validate()方法的話,那麼它是一定會被執行的
執行完validate()之後,如果沒有發現存在Field或者Action級別的ERROR的話
那麼纔會執行相應的業務邏輯的方法,如abc()方法
Struts2中的多個驗證方法的共存細節二
很顯然這種機制不是很合理。因爲不同的業務邏輯存在着不同的驗證方式
如果不同的驗證方式驗證完之後,還要去驗證一下validate()的話,顯然這是不合理的
這種情況下有兩種解決的策略
1..不再複寫validate()方法,由於父類的validate()方法的方法體是空的
儘管它也會被調用,但是它什麼也不會做,不會對我們的程序造成任何影響
2..重命名validate()方法,即命名爲validateExecute()
所以本例若需執行execute()的話,則可通過validateExecute()驗證表單
提示Struts2的默認錯誤信息
如果int或long發生類型轉換錯誤的話,Struts2會將該屬性值自動設爲零
如果String發生類型轉換錯誤的話,它會將該屬性值自動設爲null
但若前臺頁面輸入的age是字符串的話,那麼它是無法轉換成int型的
這時在前臺頁面就會提示Invalid field value for field "age".信息
在這個錯誤提示信息中的age對應的是前臺頁面中<input name="">爲age的值
這是因爲Struts2在遇到類型轉換錯誤的時候,也就是說無法進行類型轉換的時候
struts2框架會自動生成一條錯誤信息,並將該錯誤信息放到addFieldError()中
然後就可以通過全局或局部的國際化資源轉換文件來自定義更爲人性化的錯誤提示信息
然後就可以在前臺使用<s:fielderror/>標籤輸出資源文件中自定義的錯誤提示信息
另外,在Struts1.x中若想在頁面中提示關於表單填寫的信息,則要增加<html:errors/>標籤
全局的國際化資源轉換文件自定義Struts2提示的錯誤信息
類型轉換出現錯誤時Struts2中的conversionError攔截器負責將錯誤封裝成表單錯誤中的Fielderror
在xwork-2.0.4.jar中的com.opensymphony.xwork2包裏面有一個xwork-messages.properties文件
將它裏面的xwork.default.invalid.fieldvalue屬性在資源文件中覆蓋就可以輸出人性化的信息了
在struts.xml中配置了message.properties之後,就可以建立該文件了
建好後輸入xwork.default.invalid.fieldvalue = {0} error
由於是進行資源轉換,所以xwork.default.invalid.fieldvalue寫法是固定的
而{0}則對應前臺頁面中<input name="">裏面的name值
比如在age輸入域中輸入字符串之後,就會提示age error
如果在birthday輸入域中輸入字符串的話,同樣會提示birthday error
局部的國際化資源轉換文件
全局的資源文件有些時候並不是特別好用,因爲它顯示的效果過於單一枯板
而Struts2也已經認識到了這一點,因此它又給我們提供了使用局部的資源文件的方式
局部的國際化資源轉換文件也是在項目開發中使用的最多的
雖然它顯得比較麻煩,但是它能夠爲用戶提供一種更友好的視圖表現方式
局部的資源文件必須與它所要驗證的類在同一個目錄下,並且要與類同名
比如驗證RegisterAction的某些屬性,那麼它必須與RegisterAction位於同一目錄下
並且的它名字也必須是RegisterAction.properties,然後編輯它的內容
比如相對於age屬性來說invalid.fieldvalue.age = age conversion error
其中invalid.fieldvalue.是固定的,後面跟RegisterAction類中的屬性
所以這句話的意思就是:當age發生類型轉換錯誤時,則顯示age conversion error信息
並且局部的先級要高於全局的國際化資源轉換文件,所以將優先顯示局部資源文件中的提示信息
下面是示例工程,這是一個Struts2.0.11應用
首先是web.xml文件
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <welcome-file-list>
- <welcome-file>validateInput.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
然後是用於提供表單輸入的validateInput.jsp頁面
- <%@ page language="java" pageEncoding="UTF-8"%>
- <%@ taglib prefix="s" uri="/struts-tags"%>
- <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold"/>
- <s:form action="validateInput" theme="simple">
- <table border="9">
- <tr>
- <td>姓名</td>
- <td><s:textfield name="username"/></td>
- </tr>
- <tr>
- <td>密碼</td>
- <td><s:password name="password"/></td>
- </tr>
- <tr>
- <td>重複密碼</td>
- <td><s:password name="repassword"/></td>
- </tr>
- <tr>
- <td>年齡</td>
- <td><s:textfield name="age"/></td>
- </tr>
- <tr>
- <td>出日</td>
- <td><s:textfield name="birthday"/></td>
- </tr>
- <tr>
- <td>畢業時間</td>
- <td><s:textfield name="graduation"/></td>
- </tr>
- <tr>
- <td> </td>
- <td><s:submit value="輸入校驗"/></td>
- </tr>
- </table>
- </s:form>
- <!--
- ================================================================================================
- 也可以使用普通<form/>替代<s:form/>來編寫上面的第6--37行的表單內容,一樣可以實現相同的功能
- ================================================================================================
- 【類型轉換與輸入校驗的流程】
- 1. 首先Struts2對客戶端傳來的數據進行類型轉換
- 2. 類型轉換完畢後再進行輸入校驗
- 3. 如果類型轉換和輸入校驗都沒有錯誤發生,那麼進入execute方法,調用商業邏輯
- 注意:如果類型轉換不成功,也同樣要進行輸入校驗
- ================================================================================================
- 幾乎Struts2的每一個標籤都有它的theme屬性
- 如果未設置該屬性的話,在運行時Struts2會自動生成表格,這樣不便於排版
- 我們可以通過設置標籤的theme="simple"屬性使得它不自動生成表格
- 這是很重要的一個屬性,有了它就可以很方便的佈局了
- ================================================================================================
- 【theme="simple"】
- 當將<s:form/>設置爲theme="simple"時,它的子標籤也就不會自動生成表格了
- 而且此時<s:form/>中的自動輸出FieldError信息的功能就會失效
- 這時我們可以在頁面中添加<s:fielderror/>或者<s:actionerror/>標籤來統一顯示錯誤信息
- 並且這個時候所顯示的錯誤提示信息中,總會在前面出現一個黑色圓點
- 如果想把這個圓點去掉的話,是一件比較困難的事情
- 可以查看struts2-core-2.0.11.jar中的template.simple中的fielderror.ftl
- 打開這個模板之後可以發現,我們頁面顯示的信息都是由這個模板定義的
- 我們也可以手工寫這個模板,但這將會是一件相當困難的事情
- 如果想把這個黑色圓點去掉的話,就只能修改這個模板,不過挺困難的,很不好改
- 一般情況下都不會去手動的寫這個模板,我們多數都是參考已有模板,然後對其稍稍加工
- ================================================================================================
- -->
當表單輸入域均正確時顯示的validateSuccess.jsp頁面
- <%@ page language="java" pageEncoding="UTF-8"%>
- <%@ taglib prefix="s" uri="/struts-tags"%>
- 姓名:<s:property value="username"/><br/>
- 密碼:<s:property value="password"/><br/>
- 年齡:<s:property value="age"/><br/>
- 生日:<s:property value="birthday"/><br/>
- 畢業:<s:property value="graduation"/>
然後是struts.xml文件
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <constant name="struts.custom.i18n.resources" value="message"/>
- <package name="struts2" extends="struts-default">
- <action name="validateInput" class="com.jadyer.action.ValidateInputAction" method="abc">
- <result>/validateSuccess.jsp</result>
- <result name="input">/validateInput.jsp</result>
- </action>
- </package>
- </struts>
用到的核心驗證邏輯的ValidateInputAction.java
- package com.jadyer.action;
- import java.util.Calendar;
- import java.util.Date;
- import com.opensymphony.xwork2.ActionSupport;
- @SuppressWarnings({"serial", "unused"})
- public class ValidateInputAction extends ActionSupport {
- private String username;
- private String password;
- private String repassword;
- private int age;
- private Date birthday;
- private Date graduation;
- /* 以上六個屬性對應的setter和getter略 */
- // /**
- // * INPUT頁面中需要添加<s:actionerror/>標籤方可顯示此處的錯誤消息
- // */
- // public String abc() throws Exception {
- // if(null==username || username.trim().equals("")){
- // this.addActionError("用戶名不能爲空");
- // }else if(!Pattern.matches("^[a-zA-Z][a-zA-Z0-9_]{3,14}$", username)){
- // this.addActionError("用戶名必須以字母開始,後面跟字母、數字或下劃線,且長度必須爲4--15位");
- // }
- // if(null==password || password.equals("")){
- // this.addActionError("密碼不能爲空");
- // }else if(!Pattern.matches("^[a-zA-Z0-9@#]{4,15}$", password)){
- // this.addActionError("密碼可以由 字母、數字、@、# 組成,且長度必須爲4--15位");
- // }
- // if(this.hasActionErrors()){
- // return INPUT; //如果在驗證的過程中,發現用戶輸入的內容不合理,則返回輸入頁面
- // }
- // return SUCCESS;
- // }
- public String abc() throws Exception {
- return SUCCESS;
- }
- /**
- * public void addFieldError(String fieldName, String errorMessage)
- * 第一個參數是頁面中表單裏的輸入域的name值,如<input/>或<s:textfield/>等等
- * 第二個參數是提示信息。這個提示信息顯示在第一個參數所對應的字段的正上方居中位置
- * 若頁面中提供了<s:fielderror/>標籤,那麼在<s:fielderror/>的位置就會顯示相應的提示信息
- */
- public void validateAbc() {
- if (null == username || username.length() < 6 || username.length() > 10) {
- this.addFieldError("username", "用戶名不能爲空,且長度必須爲6--10位");
- }
- if (null == password || password.length() < 6 || password.length() > 10) {
- this.addFieldError("password", "密碼不能爲空,且長度必須爲6--10位");
- } else if (null == repassword || repassword.length() < 6 || repassword.length() > 10) {
- this.addFieldError("repassword", "重複密碼不能爲空,且長度必須爲6--10位");
- } else if (!password.equals(repassword)) {
- this.addFieldError("password", "輸入的重複密碼與設定密碼不一致");
- }
- if (null != birthday && null != graduation) {
- Calendar c1 = Calendar.getInstance();
- c1.setTime(birthday);
- Calendar c2 = Calendar.getInstance();
- c2.setTime(graduation);
- if (!c1.before(c2)) {
- this.addFieldError("birthday","出生日期應該在畢業時間的前面");
- }
- }
- }
- }
用到的局部的國際化資源轉換文件ValidateInputAction.properties
- invalid.fieldvalue.age = /u5E74/u9F84/u5E94/u8BE5/u662F/u4ECB/u4E8E 1 /u5230 100 /u4E4B/u95F4/u7684/u6B63/u6574/u6570
- invalid.fieldvalue.birthday = /u51FA/u751F/u65E5/u671F/u8F93/u5165/u6709/u8BEF
- invalid.fieldvalue.graduation = /u6BD5/u4E1A/u65F6/u95F4/u8F93/u5165/u6709/u8BEF
用到的全局的國際化資源轉換文件message.properties
- xwork.default.invalid.fieldvalue = {0} /u8F93/u5165/u6709/u8BEF