Struts 学习笔记2(输入校验、国际化、异常处理)

项目文件结构

 

项目源文件下载地址:http://dl.dbank.com/c05qyg3yir

 

Struts2的输入校验

Struts2输入校验、执行流程:

1)首先进行类型转换

2)然后进行输入校验(执行validate方法)

3)如果在上述过程中出现了任何错误,都不会再去执行 execute方法,会转向 struts.xml 中该 action 的名为 input 的 result 所对应的页面。

要点:

1. ActionSupport 类的 addActionError()方法的实现:首先创建一个ArrayList对象,然后将错误消息添加到该 ArrayList对象中。

2. 当调用 getActionErrors()方法返回 Action 级别的错误信息列表时,返回的实际上是集合的一个副本而不是集合本身,因此对集合副本调用 clear()方法清除的依旧是副本中的元素而非原集合中的元素,此时原集合中的内容没有收到任何的影响。换句话说,Action级别的错误信息列表对开发者来说是只读的。

3. Field Error 级别的错误信息底层是用 LinkedHashMap 实现的,该Map 的 key 是 String 类型,value 是 List<String>类型,这就表示一个 Field Name 可以对应多条错误信息,这些错误信息都放置在List<String>集合当中。

 

register.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags" %>

………………………………

<body>

<h2><font color="blue">用户注册</font></h2>

<s:actionerror cssStyle="color:red"/>

----------------------------------------

<s:fielderror cssStyle="color:blue"></s:fielderror>

 

<!--

<form action="register.action">

 

username: <input type="text" name="username" size="20"><br>

password: <input type="password" name="password" size="20"><br>

repassword: <input type="password" name="repassword" size="20"><br>

age: <input type="text" name="age" size="20"><br>

birthday: <input type="text" name="birthday" size="20"><br>

graduation: <input type="text" name="graduation" size="20"><br>

 

<input type="submit" value="submit"/>

 

</form>

-->

<s:form action="register.action" theme="simple"><!—-theme="simple修饰以简单表单呈现-->

username: <s:textfield name="username" label="username"></s:textfield><br>

password: <s:password name="password" label="password"></s:password><br>

repassword: <s:password name="repassword" label="repassword"></s:password><br>

age: <s:textfield name="age" label="age"></s:textfield><br>

birthday: <s:textfield name="birthday" label="birthday"></s:textfield><br>

graduation: <s:textfield name="graduation" label="graduation"></s:textfield><br>

<s:submit value="submit"></s:submit>

</s:form>

</body>

</html>

 

RegisterAction.java

package com.shengsiyuan.struts2;

 

import java.util.Calendar;

import java.util.Date;

 

import com.opensymphony.xwork2.ActionSupport;

 

public class RegisterAction extends ActionSupport

{

    private String username;

    private String password;

    private String repassword;

    private int age;

    private Date birthday;

    private Date graduation;

    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 getRepassword()

    {

        return repassword;

    }

    public void setRepassword(String repassword)

    {

        this.repassword = repassword;

    }

    public int getAge()

    {

        return age;

    }

    public void setAge(int age)

    {

        this.age = age;

    }

    public Date getBirthday()

    {

        return birthday;

    }

    public void setBirthday(Date birthday)

    {

        this.birthday = birthday;

    }

    public Date getGraduation()

    {

        return graduation;

    }

    public void setGraduation(Date graduation)

    {

        this.graduation = graduation;

    }

    @Override

    public String execute() throws Exception

    {

        return SUCCESS;

    }

    @Override

    public void validate()

    {

        if(null == username || username.length() < 4 || username.length() > 6)

        {

            this.addActionError("username invalid");    //Action级别的错误

            this.addFieldError("username", "username invalid in field");//field级别的错误

        }

        if(null == password || password.length() < 4 || password.length() > 6)

        {

            this.addActionError("password invalid");

        }

        else if(null == repassword || repassword.length() < 4 || repassword.length() > 6)

        {

            this.addActionError("repassword invalid");

        }

        else if(!password.equals(repassword))

        {

            this.addActionError("the passwords not the same");

        }

        if(age < 10 || age > 50)

        {

            this.addActionError("age invalid");

        }

        if(null == birthday)

        {

            this.addActionError("birthday invalid");

        }

        if(null == graduation)

        {

            this.addActionError("graduation invalid");

        }

        if(null != birthday && null != graduation)

        {

            Calendar c1 = Calendar.getInstance();    //获取日期

            c1.setTime(birthday);

            

            Calendar c2 = Calendar.getInstance();

            c2.setTime(graduation);

            

            if(!c1.before(c2)) //如果c1不在c2

            {

                this.addActionError("birthday should be before graduation");

            }

        }

        //this.getFieldErrors().clear();    //clear()方法清空的只是副本

        //this.getActionErrors().clear();

        //this.clearActionErrors();    //清除Action级别的错误消息

        //this.clearFieldErrors();    //清除field级别的错误消息

        System.out.println("invoked!!!");

    }

}

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>

    <package name="struts2" extends="struts-default">

      

        <action name="login" class="com.shengsiyuan.struts2.LoginAction" method="myExecute">    <!-- 指定执行myExecute方法 -->

            <result name="success">/result.jsp</result><!-- 结果为success时,跳转到result.jsp -->

        </action>

        

        <action name="userAction" class="com.shengsiyuan.struts2.UserAction">

            <result name="success">/output.jsp</result>

        </action>

        

        <action name="userAction2" class="com.shengsiyuan.struts2.UserAction2">

            <result name="success">/output.jsp</result>

        </action>

        

        <action name="register" class="com.shengsiyuan.struts2.RegisterAction">

            <result name="success">/registerResult.jsp</result>

            <result name="input">/register.jsp</result>

        </action>

    </package>

</struts>

 

截图

提交之前截图

html标签提交之后的截图

struts标签,且未加theme="simple"属性提交的结果

若使用<s:form action="register.action" theme="simple">则呈现的结果同以html提交一样。不管是Action级别的,还是field级别的,在执行excute方法时,只要对应的错误容器中有错误消息,则转到input对应的页面,如果容器中没有错误消息,则继续往下执行。

 

----------------------------------------------------------

在tomcat中手动添加web项目:

    …………

<Context path="/myWebSite" docBase="D:/Workspace/servlet/myWebSite" reloadable="true"/>

</Host>

</Engine>

</Service>

</Server>

 

java.lang.ClassNotFoundException: javax.el.ELResolver错误解决方法:Remove of classpath server-api.jar and jsp-api.jar

-------------------------------------------------------------

 

Action级别的自定义方法的输入校验

要点:

1. Action中自定义方法的输入校验。对于通过action的method属性所指定的自定义方法,其对应的自定义输入校验方法名为validateMyExecute(假设自定义的方法名为 myExecute) 。底层是通过反射来调用的。

2. 当在Action中指定了自定义的 execute方法时,首先会执行自定义的 execute 方法所对应的输入校验方法,然后再去执行标准的 validate 方法,执行完毕后如果出现了任何错误都不会再去执行自定义的execute方法,流程转向了 input这个名字所对应的页面上。

 

Login.jsp

…………

<body>

<form action="login.action">

username: <input type="text" name="username"><br>

password: <input type="password" name="password"><br>

age: <input type="text" name="age"><br>

date: <input type="text" name="date"><br>

<input type="submit" value="submit">

</form>

</body>

</html>

 

LoginAction

package com.shengsiyuan.struts2;

 

import java.util.Date;

 

import com.opensymphony.xwork2.ActionSupport;

import com.shengsiyuan.exception.PasswordException;

import com.shengsiyuan.exception.UsernameException;

 

public class LoginAction extends ActionSupport

{

    private String username;

    private String password;

    private int age;

    private Date date;

    

    public Date getDate()

    {

        return date;

    }

 

    public void setDate(Date date)

    {

        this.date = date;

    }

 

    public int getAge()

    {

        return age;

    }

 

    public void setAge(int age)

    {

        this.age = age;

    }

 

    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

    {

        if(!"hello".equals(username))

        {

            throw new UsernameException("username invalid");

        }

        if(!"world".equals(password))

        {

            throw new PasswordException("password invalid");

        }

        return SUCCESS;

    }

    

    //自定的execute方法,在struts.xml中指定了LoginAction中的method方法为myExecute

    public String myExecute() throws Exception

    {

        System.out.println("myExecute invoked!!");

        return SUCCESS;

    }

    

    //Action自定义方法的输入校验

    public void validateMyExecute()    //此验证方法规定为将myExecute()方法名首字母大写后,再加前缀validate构成

    {

        System.out.println("validateMyExecute invoked!!");

        this.addActionError("action error");

    }

    

    @Override

    public void validate()

    {

        //System.out.println("validate invoked!");

        //this.addActionError("action error");

    }

}

注:如果去除了struts.xml文件中的method="myExecute",则对应的自定义的校验方法将无效。

<action name="login" class="com.shengsiyuan.struts2.LoginAction " method="myExecute">

    <result name="success">/result.jsp</result>

</action>

 

自定义Field级别的错误提示消息

要点:

1) 新建一个以 Action 名命名的 properties 文件 , 如RegisterAction.properties。 属性文件名要求为对应的Action文件名字。

2) 然后在该属性文件中指定每一个出错字段的错误消息 invalid.fieldvalue.birthday=birthday invalid !!

 

Tip: jdk提供的一款中文转换为unicode编码的工具,在jdk的bin目录下,native2ascii。在命令行下使用,使用方法如下:

 

struts2校验框架

要点:

  1. 1) 首先执行校验框架(xml文件)

    2) 执行自定义方法的校验方法(validateMyExecute)

    3) 执行validate方法

 

xwork-validator.xml

<?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.opensymphony.com/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

>

 

RegisterAcion-validation.xml

字段优先校验

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

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

<validators>

    <field name="username"><!-- username设置校验规则 -->

        <field-validator type="requiredstring"><!-- 字符串必填规则设置 -->

            <param name="trim">false</param><!-- 不清除空格 -->

            <message>username can't be blank!</message><!-- 当校验失败提示的错误消息 -->

        </field-validator>

        <field-validator type="stringlength"><!-- 字符串长度规则设置 -->

            <param name="minLength">4</param><!-- 最小长度 -->

            <param name="maxLength">6</param><!-- 最大长度 -->

            <param name="trim">false</param>

            <!—读取属性文件,使用国际化,当校验失败提示的错误消息 --

            <message key="username.invalid"></message>>

        </field-validator>

    </field>

    

    <field name="password">

        <field-validator type="requiredstring">

            <message>password can't be blank!</message>

        </field-validator>

        <field-validator type="stringlength">

            <param name="minLength">4</param>

            <param name="maxLength">6</param>

            <message>length of password should be between ${minLength} and ${maxLength}</message>

        </field-validator>

    </field>

    

    <field name="age">

        <field-validator type="required">

            <message>age can't be blank!</message>

        </field-validator>

        <field-validator type="int">

            <param name="min">10</param>

            <param name="max">40</param>

            <!—在这里可以用${元素名} 引用上面的子元素-->

            <message>age should be between ${min} and ${max}</message>

        </field-validator>

    </field>

    

    <field name="birthday">

        <field-validator type="required">

            <message>birthday can't be blank!</message>

        </field-validator>

        <field-validator type="date">

            <param name="min">2005-1-1</param>

            <param name="max">2007-12-31</param>

            <message>birthday should be between ${min} and ${max}</message>

        </field-validator>

    </field>

</validators>

 

 

校验器优先校验(混合)

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

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

    <validator type="requiredstring">

        <param name="fieldName">username</param>

        <message>username can't be blank!</message>

    </validator>

    

    <validator type="stringlength">

        <param name="fieldName">username</param>

        <param name="minLength">4</param>

        <param name="maxLength">6</param>

        <!—在这里可以用${元素名} 引用上面的子元素-->

        <message>length of username should be between ${minLength} and ${maxLength}</message>

    </validator>

    

    <field name="birthday">

        <field-validator type="required">

            <message>birthday can't be blank!</message>

        </field-validator>

        <field-validator type="date">

            <param name="min">2005-1-1</param>

            <param name="max">2007-12-31</param>

            <message>birthday should be between ${min} and ${max}</message>

        </field-validator>

    </field>

</validators>

 

打开com.opensymphony.xwork2.validator.validators可以发现一个default.xml文件,打开可以发现其中定义了各种校验器,内容如下:

default.xml

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

<!DOCTYPE validators PUBLIC

"-//OpenSymphony Group//XWork Validator Config 1.0//EN"

"http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">

 

<!-- START SNIPPET: validators-default -->

<validators>

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

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

<validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>

<validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>

<validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>

<validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>

<validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>

<validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>

<validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>

<validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>

<validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>

<validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>

<validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>

<validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>

<validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>

<validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>

</validators>

<!-- END SNIPPET: validators-default -->

错误消息国际化

在Action所在的包下建立两个属性文件,名字分别叫:

package_en_US.properties

username.invalid=username invalid

 

package_zh_CN.properties

username.invalid=\u7528\u6237\u540D\u4E0D\u5408\u6CD5\uFF01

#用户名不合法

 

运行结果截图

 

Struts2国际化

对于国际化的资源文件,其命名规则是: package_语言名_国家名,比如package_zh_CN,package_en_US 。

 

I18NTest1.java

package com.shengsiyuan.i18n;

import java.util.Locale;

public class I18NTest1

{

    public static void main(String[] args)

    {

        Locale[] locales = Locale.getAvailableLocales();

 

        for (Locale locale : locales)

        {

            System.out.println(locale.getDisplayCountry() + " : "

                    + locale.getCountry());        //显示国家及国家代码

//            System.out.println(locale.getDisplayLanguage() + " : " + locale.getLanguage());

        }

    }

}

 

I18Ntest2.java

在src目录(classpath)下,建立三个资源文件,分别如下(注 i18n即为资源文件的base name):

i18n_en_US.properties

hello=hello\:{0}

 

i18n_zh_CN.properties

hello=\u4F60\u597D\uFF1A{0}

 

i18n.properties

hello=hello world

 

I18Ntest2.java代码如下 :

package com.shengsiyuan.i18n;

import java.util.Locale;

import java.util.ResourceBundle;

public class I18NTest2

{

    public static void main(String[] args)

    {

        System.out.println(Locale.getDefault());

        //绑定一个base name i18n的资源文件,Locale使用FRANCE(法国)

        ResourceBundle bundle = ResourceBundle.getBundle("i18n", Locale.FRANCE);

        //获取hello字符串的值

        String value = bundle.getString("hello");

        System.out.println(value);

    }

}

 

I18Ntest3.java(传入参数)

package com.shengsiyuan.i18n;

import java.text.MessageFormat;

import java.util.Locale;

import java.util.ResourceBundle;

public class I18NTest3

{

    public static void main(String[] args)

    {

        Locale locale = Locale.CHINA;    //locale定义为CHINA

        //绑定到资源文件

        ResourceBundle bundle = ResourceBundle.getBundle("i18n", locale);

        //获取资源文件中的字符串对象

        String value = bundle.getString("hello");

        //格式化字符串对象,并传入参数,后边的Object数组对象表示要插入到占位符上的具体的对象

        String result = MessageFormat.format(value, new Object[]{"维唯为为"});

        System.out.println(result);

    }

}

 

注意:调整浏览器的语言和字符编码选项后,要注意,程序中输入的日期格式,也要做相应的改变,不然会出现日期类型转换错误。字符串国际化的同时,也要注意,日期的国际化。

 

Struts2异常处理及全局异常与结果

要点:

 

struts2异常处理实例

在第三层建一个包,取名exception ,并在包中建两个类,分别取名为:

PasswordException.java

package com.shengsiyuan.exception;

public class UsernameException extends Exception

{

    private String message;

    public UsernameException(String message)

    {

        super(message);

        this.message = message;

    }

    public String getMessage()

    {

        return message;

    }

    public void setMessage(String message)

    {

        this.message = message;

    }

}

 

UsernameException.java

package com.shengsiyuan.exception;

public class PasswordException extends Exception

{

    private String message;

    public PasswordException(String message)

    {

        super(message);

        this.message = message;

    }

    public String getMessage()

    {

        return message;

    }

    public void setMessage(String message)

    {

        this.message = message;

    }

}

 

编辑loginAction的execute方法

    public String execute() throws Exception

    {

        if(!"hello".equals(username))

        {

            throw new UsernameException("username invalid");

        }

        if(!"world".equals(password))

        {

            throw new PasswordException("password invalid");

        }

        return SUCCESS;

    }

 

编辑struts.xml文件

…………

<struts>

    <package name="struts2" extends="struts-default">

        <action name="login" class="com.shengsiyuan.struts2.LoginAction">

            <exception-mapping result="usernameInvalid" exception="com.shengsiyuan.exception.UsernameException"></exception-mapping>

            <exception-mapping result="passwordInvalid" exception="com.shengsiyuan.exception.PasswordException"></exception-mapping>

            

            <result name="usernameInvalid">/usernameInvalid.jsp</result>

            <result name="passwordInvalid">/passwordInvalid.jsp</result>

            <result name="success">/result.jsp</result>

        </action>

    ………………

</struts>

 

…………

<struts>

    <package name="struts2" extends="struts-default">

        <global-results>

            <result name="usernameInvalid">/usernameInvalid.jsp</result>

            <result name="passwordInvalid">/passwordInvalid.jsp</result>

        </global-results>

        <global-exception-mappings>

            <exception-mapping result="usernameInvalid" exception="com.shengsiyuan.exception.UsernameException"></exception-mapping>

            <exception-mapping result="passwordInvalid" exception="com.shengsiyuan.exception.PasswordException"></exception-mapping>

        </global-exception-mappings>

    ………………

</struts>

 

posted @ 2012-02-07 00:09  维唯为为  阅读(687)  评论(0编辑  收藏  举报