小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

struts2學(xué)習(xí)筆記(7)——validate校驗(yàn)框架

 levinLee 2010-07-23

前面講到了一種驗(yàn)證方法,是在Action的 validate方法中通過(guò)代碼的方式來(lái)完成的。而struts2提供了另外一種 方式來(lái)實(shí)現(xiàn)輸入驗(yàn)證。

這種方式就是使用validate框架來(lái)實(shí)現(xiàn)輸入校驗(yàn),這種方式是基于XML的驗(yàn)證。

文件名為XXXAction-validation.xml。

那么校驗(yàn)xml文件格式該如何寫(xiě)呢?

可以使用firefox查看此xml的DTD定義,地址為 http://www./xwork/xwork-validator-1.0.2.dtd

在此列出此DTD的內(nèi)容

<?xml version="1.0" encoding="UTF-8"?>

<!--
  XWork Validators DTD.
  Used the following DOCTYPE.
  <!DOCTYPE validators PUBLIC
          "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
          "
http://www./xwork/xwork-validator-1.0.2.dtd">
-->

<!ELEMENT validators (field|validator)+>

<!ELEMENT field (field-validator+)>
<!ATTLIST field
    name CDATA #REQUIRED
>

<!ELEMENT field-validator (param*, message)>
<!ATTLIST field-validator
    type CDATA #REQUIRED
    short-circuit (true|false) "false"
>

<!ELEMENT validator (param*, message)>
<!ATTLIST validator
    type CDATA #REQUIRED
    short-circuit (true|false) "false"
>

<!ELEMENT param (#PCDATA)>
<!ATTLIST param
    name CDATA #REQUIRED
>

<!ELEMENT message (#PCDATA)>
<!ATTLIST message
    key CDATA #IMPLIED
>

由此DTD的定義可知,此XML文件的根元素為validators。

在根元素下可以有若干個(gè)field或validator子元素,即分別代表著字段校驗(yàn)和非字段校驗(yàn),它們的區(qū)別將在后面介紹。


字段校驗(yàn)

字段校驗(yàn)代表著field,標(biāo)簽有個(gè)name屬性石必填的,它和表單中的name屬性值是一樣的。
這里我填入username。

<validators>
    <field name="username">
    </field>
</validators>

field下面有個(gè)子元素叫field-validator,代表著要用什么方式來(lái)進(jìn)行校驗(yàn),其有個(gè)屬性叫 type,也是必填的。


<validators>
    <field name="username">
        <field-validator type="">
        </field-validator>
    </field>
</validators>

type應(yīng)該填入什么內(nèi)容呢?

可以查看xwork的源文件,在包 com.opensymphony.xwork2.validator.validators下有個(gè)文件default.xml,在這個(gè)文件中定義了 type屬性值。

    <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>

還有很多定義好的type值,這里不一一列舉

在validator元素中,name屬性表示可以定義的type值,class 表示用哪個(gè)類(lèi)來(lái)進(jìn)行校驗(yàn),這是struts2默認(rèn)設(shè)置好的校驗(yàn)器,我們可以直接使用。

在這個(gè)例子中,我們將type設(shè)置為requiredstring

<validators>
    <field name="username">
        <field-validator type="requiredstring">
        </field-validator>
    </field>
</validators>

在field-validator下面有兩個(gè)子元素,param和message
param可以任意個(gè),可有可無(wú),但是message有且只有一個(gè)。

param表示傳入的參數(shù),message表示出錯(cuò)時(shí)顯示的信息。也就是說(shuō)message可以是任意的字符串,但是param卻是特定的。

在繼續(xù)之前還是看看 com.opensymphony.xwork2.validator.validators.RequiredStringValidator這個(gè)類(lèi)的源代碼。首先確定已經(jīng)下載了源代碼,并且在MyEclipse中關(guān)聯(lián)了源代碼,這是一個(gè)好習(xí)慣。

在這個(gè)類(lèi)中有一個(gè)成員變量

private boolean doTrim = true;

因此,我們?cè)趐aram中要做的就是,將param元素的name屬性設(shè)置為doTrim,值為true。

<validators>
    <field name="username">
        <field-validator type="requiredstring">
            <param name="trim"<true>/param>
            <message<username should not be blank!</message>
        </field-validator>
    </field>
</validators>

trim表示是否忽略空格,默認(rèn)是true,因此在此也可以省略掉param元素。

其實(shí)在 field-validator元素中還有一個(gè)屬性short-circuit,其默認(rèn)值是false,表示的意思是短路,即前面驗(yàn)證失敗,后面就不做驗(yàn)證了。

然而這僅僅只是一個(gè)校驗(yàn)條件,還是以 username為例,在上次的例子中,還要求username的長(zhǎng)度要在6到10之間,因此,繼續(xù)看default.xml文件

在其中找到這樣一個(gè)元素
<validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>

從字面上可以看出是限制字符串長(zhǎng)度的,因此查看這個(gè)實(shí)現(xiàn)類(lèi)

它有3個(gè)成員變量:

    private boolean doTrim = true;
    private int maxLength = -1;
    private int minLength = -1;

其中最主要的是maxLength和minLength分別代表最大長(zhǎng)度和最小長(zhǎng)度

因此在這個(gè)校驗(yàn)器中內(nèi)容應(yīng)該如下:

    <field name="username">
        <field-validator type="stringlength">
            <param name="minLength">6</param>
            <param name="maxLength">10&lr;/param>
            <message>username should be between ${minLength} and ${maxLength}</message>
        </field-validator>
    </field>

有個(gè)問(wèn)題就是
    <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>

required和requiredstring有什么區(qū)別嗎?

requiredstring是指這個(gè)字符串是必須的,而required表示這個(gè)字段是必須的,而沒(méi)有指明這個(gè)字段是否必須是字符串。

因此對(duì)于字符串,可以使用requiredstring,而對(duì)于非字符串類(lèi)型就必須使用required了。如在這個(gè)示例中的age,birthday。注意birthday是Date類(lèi)型的,不是String。

還是回顧一下register2.jsp的頁(yè)面內(nèi)容。

body中的內(nèi)容為:
<s:actionerror />
    <s:form action="register2"  theme="simple">
                    ……
                    ……
    </s:form>
但是輸入數(shù)據(jù)提交后,仍然顯示的是以前的出錯(cuò)信息,并不是今天所設(shè)置的信息。

這就涉及到一些知識(shí)點(diǎn)了,因?yàn)樾r?yàn)框架產(chǎn)生的錯(cuò)誤是fielderror,不會(huì)在actionerror中顯示。

因此,需要將 theme="simple"去掉,并把那些表格標(biāo)簽頁(yè)去掉,然后執(zhí)行時(shí)會(huì)看到在username上方的錯(cuò)誤信息。

還有一個(gè)問(wèn)題就是validate校驗(yàn)框架和Action中validate方法是否沖突。

實(shí)際上雖然會(huì)使用框架驗(yàn)證,但是也會(huì)調(diào)用Action的validate方法,通過(guò)上面的顯示結(jié)果應(yīng)該可以清楚的看到,在表單上面集中的顯示了actionerror。

但是如果把Action中的validate方法的出錯(cuò)信息add到field中會(huì)有什么效果呢??

修改RegisterAction中validate方法,將 addActionError改為addFieldError。

當(dāng)沒(méi)有輸入用戶(hù)名時(shí),會(huì)顯示如下錯(cuò)誤信息:

username should not be blank!
username invalid

為什么會(huì)顯示這樣的結(jié)果呢???

首先肯定的是在validate中增加的fielderror,和xml中不會(huì)沖突

即錯(cuò)誤信息不會(huì)被覆蓋,而是兩者都有,而且先顯示xml中定義的錯(cuò)誤信息,然后才是validate中定義的錯(cuò)誤信息。實(shí)際上是所有的xml執(zhí)行完畢后,在執(zhí)行validate。

為什么會(huì)產(chǎn)生這樣的效果呢???那么你就必須知道fielderror到底是什么!繼續(xù)查看源代碼。

因?yàn)镽egisterAction是繼承的 ActionSupport,addFieldError是繼承自ActionSupport,所以先看看ActionSupport中 addFieldError的實(shí)現(xiàn)方法。

在 ActionSupport中addFieldError是這么實(shí)現(xiàn)的,

    public void addActionError(String anErrorMessage) {
        validationAware.addActionError(anErrorMessage);
    }
即通過(guò)調(diào)用validationAware對(duì)象的addActionError,而validationAware是 ValidationAwareSupport的一個(gè)實(shí)例,在ValidationAwareSupport中定義了fielderror是什么。

    private Map>String, List<String>> fieldErrors;

    public synchronized void addFieldError(String fieldName, String errorMessage) {
        final Map<String, List<String>> errors = internalGetFieldErrors();
        List<String> thisFieldErrors = errors.get(fieldName);

        if (thisFieldErrors == null) {
            thisFieldErrors = new ArrayList<String>();
            errors.put(fieldName, thisFieldErrors);
        }

        thisFieldErrors.add(errorMessage);
    }

通過(guò)源代碼,可以看到fieldErrors實(shí)際上是一個(gè)Map>String, List<String>>。key是String類(lèi)型的,而value是List<String>

而實(shí)際上這個(gè)List是通過(guò)ArrayList<String>來(lái)實(shí)現(xiàn)的,也就是說(shuō),key是String類(lèi)型的,而value是ArrayList<String>。

雖然一個(gè)key只能對(duì)應(yīng)一個(gè)value,但是在這里value并不是一個(gè)字符串,而是一個(gè)數(shù)組。所以錯(cuò)誤信息不會(huì)被覆蓋掉。

在ActionSupport類(lèi)中存在一個(gè)方法getFieldErrors,按照方法名可以猜的出該方法返回的是fieldError這個(gè)數(shù)組,既然如此那么是否可以通過(guò) getFieldErrors直接添加呢??

    List<String> list = new ArrayList<String>();
    list.add("username should be between 6 and 10");
    this.getFieldErrors().put("username",list);

雖然編譯器沒(méi)有報(bào)錯(cuò),但是實(shí)際上是不行的。查看API文檔:

getFieldErrors,其解釋如下:

public Map<String,List<String>> getFieldErrors()

Description copied from interface: ValidationAware

Get the field specific errors associated with this action. Error messages should not be added directly here, as implementations are free to return a new Collection or an

Unmodifiable Collection.

注釋?zhuān)?

這個(gè)方法返回與這個(gè)action相關(guān)的具體的fielderrors,錯(cuò)誤信息不能直接從這里添加,執(zhí)行結(jié)果返回一個(gè)新的集合或一個(gè)不可修改的集合

這是什么意思呢?看源代碼,這個(gè)方法同樣是在 ValidationAwareSupport中實(shí)現(xiàn)的。

    public synchronized Map<String, List<String>> getFieldErrors() {
        return new LinkedHashMap<String, List<String>>(internalGetFieldErrors());
    }
由此可以看到該方法返回的是一個(gè)新的LinkedHashMap,只是一個(gè)拷貝,而不是原集合,所以這樣直接添加是無(wú)法顯示出來(lái)的。

那么何時(shí)使用validate驗(yàn)證框架,什么時(shí)候使用action中的 validate方法呢?

一般來(lái)說(shuō),簡(jiǎn)單驗(yàn)證可以使用 xml,復(fù)雜時(shí)用validate

前面講到了 struts2的數(shù)據(jù)校驗(yàn),那么為什么要有服務(wù)器校驗(yàn)??擁有了客戶(hù)端校驗(yàn)不是也行嗎??

服務(wù)端校驗(yàn)是必須的,即使有客戶(hù)端校驗(yàn)。因?yàn)榭梢圆煌ㄟ^(guò)browser訪問(wèn)web服務(wù)器??!強(qiáng)健的web應(yīng)用要有客戶(hù)端和服務(wù)器端的驗(yàn)證。

當(dāng)然,struts2同樣支持客戶(hù)端驗(yàn)證。

要使用struts2的客戶(hù)端校驗(yàn),必須滿(mǎn)足一下條件:

1.form的主題(theme)一定不能設(shè)置為simple

2.將struts2 form標(biāo)簽中validate屬性設(shè)置為true

但是看到小時(shí)效果后就會(huì)發(fā)現(xiàn),struts2生成的也是js代碼,但是效果卻很差,所以一般來(lái)說(shuō),使用struts2的服務(wù)器端校驗(yàn),而客戶(hù)端校驗(yàn)自己寫(xiě)。

struts2標(biāo)簽支持事件,可以像使用html標(biāo)簽一樣使用。

同樣用validate校驗(yàn)框架也應(yīng)該可以使用局部校驗(yàn):

當(dāng)action中有多個(gè)方法時(shí),需要在和action同目錄下新建文件 XXXAction-XXX(方法名)-validation.xml

在實(shí)例化子類(lèi)對(duì)象時(shí),會(huì)先執(zhí)行父類(lèi)的全局校驗(yàn),然后是局部校驗(yàn),接著是子類(lèi)的全局校驗(yàn),然后是子類(lèi)的局部校驗(yàn),因此不要提供全局校驗(yàn)。

字段校驗(yàn)和非字段校驗(yàn)的區(qū)別

通俗點(diǎn)講:

字段校驗(yàn):校驗(yàn)誰(shuí),用什么方法

非字段校驗(yàn):用什么校驗(yàn),校驗(yàn)誰(shuí)

非字段校驗(yàn)示例:

<validator type="requiredstring">
    <param name="fieldName">username</param>
    <message></message>
</validator>

其中tyoe="fieldName"是不變的。至于其他細(xì)節(jié)不在這里詳細(xì)敘述。

但還是建議使用字段校驗(yàn)器。

通過(guò)今天的學(xué)習(xí),了解到了另外一種通過(guò)配置文件進(jìn)行數(shù)據(jù)校驗(yàn)的方法。而這種方法顯得更加簡(jiǎn)單,易懂。

下次課將談到struts2的攔截器。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多