深入分析JavaWeb Item46 -- Struts2数据校验与国际化

1、用户输入数据的校验

1、校验方式

a:客户端校验。(防君子防不了小人)在页面中写js脚本。 这样做的好处是:

  • 输入错误的话提醒比较及时;
  • 减轻服务器的压力

b、服务器端校验

  • 数据安全 ,整个应用阻止非法数据的最后防线

而在实际开发中通常选择:a+b

2、服务器端数据校验:

1、编程式校验:自己Action中编写一个校验代码(缺点:验证规则都写在了代码中)

前提:动作类继承ActionSupport,重写Validateable接口中的validate()方法 ,在该方法中完成验证。

步骤如下:

* validate()方法在其他的业务方法之前执行

  • 验证出错转向的页面

    struts.xml配置<result name="input">/validate/login.jsp</result>

    其中input转向是在action中已经定义好的.

     public static final String INPUT = "input"; 
  • 什么时候表示验证出错(转向input所指向的页面)

    • this.addFieldError("sss", "错误信息");方法指向的是一个集合
    • 当集合不为空时,转向错误页面.显示错误Jsp页面: 使用<s:fielderror/>显示错误消息

1、针对动作类中的所有动作进行校验

编写UserAction继承 ActionSupport,并validate()方法。

package com.itheima.actions;

import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.interceptor.validation.SkipValidation;
import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

public String add(){
    //调用Service
    try{
        System.out.println("保存成功:"+this);
        return SUCCESS;
    }catch(Exception e){
        e.printStackTrace();
        return ERROR;
    }
}

    //在此处编写校验规则:针对所有的动作方法进行验证

public void validate() {
    //用户名不能为null或“”
    if(StringUtils.isEmpty(username)){
        addFieldError("username", "用户名不能为空");//   Map<String,String>key:字段名,value错误提示
    }
}
    @Override
    public String toString() {
        return "UserAction [username=" + username + ", password=" + password
                + ", age=" + age + ", birthday=" + birthday + ", hobby="
                + Arrays.toString(hobby) + "]";
    }

}

在struts.xml中配置action

<package name="p1" extends="struts-default">
        <action name="UserAdd" class="com.itheima.actions.UserAction" method="add">
            <result>/success.jsp</result>
            <result name="error">/error.jsp</result>
            <result name="input">/regist.jsp</result>
        </action>
</package>

分别编写三个简单的页面success.jsp–error.jsp—register.jsp

register.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>用户注册</title>
  </head>

  <body>
    <s:fielderror></s:fielderror>
    <form action="${pageContext.request.contextPath}/UserAdd.action" method="post">
        姓名:<input type="text" name="username"/><br/>
        密码:<input type="text" name="password"/><br/>
        年龄:<input type="text" name="age"/><br/>
    </form>
  </body>
</html>

error.jsp

<body>
  服务器忙
</body>

success.jsp

  <body>
    保存成功
  </body>

上述的校验方法对action的所有方法进行校验,如果要校验指定的方法,则要

2、针对指定的动作进行校验

方式一:写了一个validate方法,可以在不需要验证的动作方法前,使用@SkipValidation。比如动作方法add,可以表示为


//@SkipValidation//忽略验证
public String add(){
    //调用Service
    try{
        System.out.println("保存成功:"+this);
        return SUCCESS;
    }catch(Exception e){
        e.printStackTrace();
        return ERROR;
    }
}

方式二:validate方法有一定的书写规范。public void validate动作方法名(首字母大写),比如动作方法edit

public String edit(){
    return SUCCESS;
}

对应的验证方法

//只针对edit动作方法进行验证
public void validateEdit() {
    //用户名不能为null或“”
    if(StringUtils.isEmpty(username)){
        addFieldError("username", "用户名不能为空,咋不听话呢");//
    }
}

validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。

底层代码(ValidationInterceptor拦截器)

总结:所有验证不通过或转换不同的过的,框架都会转向name=”input”的结果视图。要显示错误提示,

使用<s:fieldError/>,显示字段有关的错误提示

上述的校验的流程:

  1. 类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
  2. 如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息封装到fieldErrors里,然后执行第3步。如果类型转换没有出现异常,则直接进入第3步。
  3. 系统通过反射技术调用action中的validateXxx()方法,Xxx为方法名。
  4. 调用action中的validate()方法。
  5. 经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。

2、 声明式校验:通过xml配置文件(方便)

1、针对动作类中的所有动作进行校验

在这个校验文件中,对UserAction中字符串类型的username属性进行验证,首先要求调用trim()方法去掉空格,然后判断用户名是否为空。

该文件需要和action类放在同一个包下,文件的取名应遵守ActionClassName-validation.xml规则,其中ActionClassName为action 的简单类名,-validation为固定写法。 例如:如果Action类为cn.msg.validate.UserAction. 那么该文件 的取名应为:UserAction-validation.xml

UserAction-validation.xml为文件的配置如下

<?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>
    <validate>
    <!-- 写法形式一:可以给一个字段添加好多的验证规则 -->
    <field name="username"><!-- 验证的字段名 -->
        <field-validator type="requiredstring"><!-- 不能为空 -->
            <param name="trim">false</param>
            <message>用户名不能为空哦</message>
        </field-validator>
        <field-validator type="stringlength"><!-- 验证字符串长度的 -->
            <param name="minLength">3</param>
            <param name="maxLength">9</param>
            <message>用户名必须介于${minLength}~${maxLength}之间哦</message>
        </field-validator>
    </field>
    <field name="email">
        <field-validator type="email">
            <message>请输入正确的邮箱</message>
        </field-validator>
    </field>
    <validator type="expression">
        <param name="expression">
            password==repassword
        </param>
        <message>两次密码必须一致</message>
    </validator>

    <!-- 写法形式二:用于非字段性的验证
    <validator type="requiredstring">
        <param name="fieldName">username</param>
        <message>用户名不能为空</message>
    </validator>
     -->
</validators>

**说明:

  • <validators>: 根元素
  • <field>:指定action中要校验的属性,name属性指定将被验证的表单字段的名字
  • <field-validator>:指定校验器, type 指定验证规则

    上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求

    的校验器,这些校验器的定义可以在xwork-2.x.jar中的

    com.opensymphony.xwork2.validator.validators下的default.xml中找到。

  • <param>:子元素可以向验证程序传递参数
  • <message>:子元素为校验失败后的提示信息,如果需要国际化,可以为message

    指定key属性,key的值为属性文件中的key。

2、针对指定的动作进行校验

方式一:使用@SkipValidation

方式二:声明文件遵循一定的书写规范:

如果你只需要对UserAction中的某个add方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。

UserAction-UserAdd-validation.xml

基于XML校验的一些特点

当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:

1。AconClassName-validation.xml

2。ActionClassName-ActionName-validation.xml

系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。

编写校验文件时,不能出现提示信息

在编写ActionClassName-validation.xml校验文件时,如果出现不了帮助信息,可以按下面方式解决:

windwos->preferences->myeclipse->files and editors->xml->xmlcatalog

点“add”,在出现的窗口中的location中选“File system”,然后在xwork-2.1.2解压目录的src\java目录中选择xwork-validator-1.0.3.dtd,回到设置窗口的时候不要急着关闭窗口,应把窗口中的Key Type改为URI 。Key改为http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd

校验器介绍

  • required 必填校验器
<field-validator type="required">
       <message>性别不能为空!</message>
</field-validator>
  • requiredstring 必填字符串校验器
<field-validator type="requiredstring">
       <param name="trim">true</param>
       <message>用户名不能为空!</message>
</field-validator>
  • stringlength:字符串长度校验器
<field-validator type="stringlength">
    <param name="maxLength">10</param>
    <param name="minLength">2</param>
    <param name="trim">true</param>
    <message><![CDATA[产品名称应在2-10个字符之间]]></message>
</field-validator>
  • int:整数校验器
<field-validator type="int">
    <param name="min">1</param>
    <param name="max">150</param>
    <message>年龄必须在1-150之间</message>
</field-validator>
  • date: 日期校验器
<field-validator type="date">
    <param name="min">1900-01-01</param>
    <param name="max">2050-02-21</param>
    <message>生日必须在${min}到${max}之间</message>
</field-validator>
  • url: 网络路径校验器
<field-validator type="url">
    <message>传智播客的主页地址必须是一个有效网址</message>
</field-validator>
  • email:邮件地址校验器
<field-validator type="email">
    <message>电子邮件地址无效</message>
</field-validator>
  • regex:正则表达式校验器
<field-validator type="regex">
     <param name="expression"><![CDATA[^13\d{9}$]]></param>
     <message>手机号格式不正确!</message>
</field-validator>
  • fieldexpression : 字段表达式校验
<field-validator type="fieldexpression">
       <param name="expression"><![CDATA[(password==repassword)]]></param>
       <message>两次密码输入不一致</message>
</field-validator>

3、自定义声明式校验

自定义验证程序必须实现 Validator 接口.

Validation 拦截器负责加载和执行各种验证程序. 在加载了一个验证程序之后, 这个拦截器将调用那个验证程序的 setValidatorContext 方法, 把当前的 ValidatorContext 对象传递给它, 这使程序员可以访问当前 Action. 接下来, Validation 拦截器将调用 validate 方法并把需要验证的对象传递给它. validate 方法是编写一个自定义的验证程序时需要覆盖的方法.

ValidatorSupport 和 FieldValidatorSupport 实现了 Validator 接口

  • 若需要普通的验证程序, 可以继承 ValidatorSupport
  • 若需要字段验证程序, 可以继承 FieldValidatorSupport
  • 若验证程序需要接受一个输入参数, 需要为这个参数增加一个相应的属性

案例:验证密码的强度

开发步骤:

1、编写一个StrongPasswordValidator类:实现Validator接口或者继承ValidatorSupport。如果是验证表单字段有关,建议继承FieldValidatorSupport。

package com.itheima.actions;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

public class StrongPasswordValidator extends FieldValidatorSupport {

    private int minLength  = -1;

    public int getMinLength() {
        return minLength;
    }
    public void setMinLength(int minLength) {
        this.minLength = minLength;
    }
    //验证方法:针对不符合要求的内容进行判断,向Map中添加信息即可
    //参数:object就是当前的动作对象
    public void validate(Object object) throws ValidationException {
        //获取要验证的字段名称
        String fieldName = getFieldName();
        Object fieldValue = getFieldValue(fieldName, object);
        if(fieldValue==null)
            return;
        if(!isStrong((String)fieldValue)){
            addFieldError(fieldName, object);
        }
        if((minLength>-1)&&((String)fieldValue).length()<minLength){
            // 添加一个消息
            addFieldError(fieldName, object);
        }

    }

     //判断s是否强大
    private static final String GROUP1 = "abcdefghijklmnopqrstuvwxyz";
    private static final String GROUP2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String GROUP3 = "0123456789";
    //判断密码是否强壮:至少一个大写字母、一个小写字母、一个数字
    private boolean isStrong(String s) {
        boolean ok1 = false;
        boolean ok2 = false;
        boolean ok3 = false;
        int length = s.length();
        for(int i=0;i<length;i++){
            if(ok1&&ok2&&ok3)
                break;
            String character = s.substring(i,i+1);
            if(GROUP1.contains(character)){
                ok1 = true;
                continue;
            }
            if(GROUP2.contains(character)){
                ok2 = true;
                continue;
            }
            if(GROUP3.contains(character)){
                ok3 = true;
                continue;
            }
        }
        return ok1&&ok2&&ok3;
    }

}

2、要注册校验器

在WEB-INF\classes目录下,建立一个固定名称为validators.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator Definition 1.0//EN"
        "http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd">

<!-- START SNIPPET: validators-default -->
<validators>
    <validator name="strongpassword" class="com.itheima.actions.StrongPasswordValidator"/>
</validators>

3、可以像使用requiredstring这样的验证器来使用了

2、Struts2的国际化

之前讲到过国际化

ResourceBundle rb = ResourceBundle.getBunle(“message”,Locale);

这里讲在struts2中,先准备资源文件,资源文件的命名格式如下:

baseName_language_country.properties

baseName_language.properties

baseName.properties

其中baseName是资源文件的基本名,我们可以自定义,但language和country必须是java支持的语言和国家。如:

中国大陆: baseName_zh_CN.properties

美国: baseName_en_US.properties

现在为应用添加两个资源文件:

第一个存放中文:msg_zh_CN.properties

hello=\u60A8\u5403\u4E86\u5417\u554A\u6CA1\u5403
username=\u7528\u6237\u540D

第二个存放英语(美国): msg_en_US.properties

内容为:

hello=good morning
username=Username

对于中文的属性文件,我们编写好后,应该使用jdk提供的native2ascii命令把文件转换为unicode编码的文件。命令的使用方式如下:

native2ascii  源文件.properties  目标文件.properties

1、配置全局国际化消息资源包

a、配置全局消息资源包

当准备好资源文件之后,我们可以在struts.xml中通过struts.custom.i18n.resources常量把资源文件定义为全局资源文件,如下:

<constant name="struts.custom.i18n.resources" value="msg" />

msg为资源文件的基名。

b、如何访问

  • 在动作类中:

    前提,动作类继承ActionSupport

package com.itheima.actions;

import com.opensymphony.xwork2.ActionSupport;
//在动作类中访问国际化消息
public class I18nAction extends ActionSupport {
    public String execute(){
        String value = getText("hello");// TextProvider
        System.out.println(value);
        return SUCCESS;
    }
}
  • 在页面中:
    <!-- 取不到,就显示key值 -->
    <s:text name="hello"></s:text><br/>

或者

    <s:textfield key="username"></s:textfield><br/>
  • 自由指定消息资源包,借助struts2的有关国际化的标签:
  <s:i18n name="message"><!-- 指定消息资源包的位置 -->
        <s:text name="hello"></s:text>
</s:i18n>

如果消息资源包在com.itheima.resources.msg_zh_CN.properties

  <s:i18n name="com/itheima/resources/message"><!-- 指定消息资源包的位置 -->
        <s:text name="hello"></s:text>
</s:i18n>

2、配置局部消息资源包

一定要经过Action才行:

书写规范:在动作类所在包中,建立名字”动作类名-zh-CN.properties”的配置文件。动作类中访问,发现局部的比全局的优先级高。

3、包范围的消息资源包

也得经过action访问

书写有规范的,名称为package_zh_CN.properties,放在类的包中。可以被包中及子包的所有动作类来访问。

当查找指定key的消息时,系统会先从ActionClassName_language_country.properties资源文件查找,如果没有找到对应的key,然后沿着当前包往上查找基本名为package 的资源文件,一直找到最顶层包。如果还没有找到对应的key,最后会从常量struts.custom.i18n.resources指定的资源文件中寻找。

顺序如下

时间: 2024-10-24 23:00:48

深入分析JavaWeb Item46 -- Struts2数据校验与国际化的相关文章

深入分析JavaWeb 46 -- Struts2数据校验与国际化

1.用户输入数据的校验 1.校验方式 a:客户端校验.(防君子防不了小人)在页面中写js脚本. 这样做的好处是: 输入错误的话提醒比较及时: 减轻服务器的压力 b.服务器端校验. 数据安全 ,整个应用阻止非法数据的最后防线 而在实际开发中通常选择:a+b 2.服务器端数据校验: 1.编程式校验:自己Action中编写一个校验代码(缺点:验证规则都写在了代码中) 前提:动作类继承ActionSupport,重写Validateable接口中的validate()方法 ,在该方法中完成验证. 步骤如

struts2 之 struts2数据校验

1. 数据校验一般分为2类:前端的校验(js校验),后端的校验(java代码):实际开发中大部分情况下都是采用js校验.在对数据安全要求较高的情况下可能会采用后端验证. 2.  Struts2提供了后端验证机制.有两种方式来实现,一种是通过硬编码来实现,一种是通过校验框架来实现.在struts2如果使用struts2提供校验机制,那么必须继承ActionSuport类.该类中有一个vaildete方法,在处理的action类中重写该方法,那么在执行所有方法的时候,会执行validate方法.va

9.struts2数据校验

手动编码方式: 1.数据校验包含两种方式,第一种是手动编码完成数据校验方式,第二种是通过配置文件完成数据校验方式(重点掌握这种方式). 2.手动编码校验方式 * 开发的步骤 > 步骤一: 封装数据 > 步骤二: 实现校验Action ,必须继承ActionSupport 类 > 步骤三: 覆盖validate方法,完成对Action的业务方法 数据校验 this.addFieldError (ActionSupport提供) > 步骤四: 在jsp中 通过 <s:fieldE

深入分析JavaWeb 47 -- Struts2拦截器与文件上传下载

一.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 过滤器VS拦截器功能是一回事.过滤器是Servlet规范中的技术,可以对请求和响应进行过滤. 拦截器是Struts2框架中的技术,实现AOP(面向切面)的编程思想,是可插拔的, 可以对访问某个 Action 方法之前或之后实施拦截. 拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在访问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用 Struts2执行原理

深入分析JavaWeb Item47 -- Struts2拦截器与文件上传下载

一.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 过滤器VS拦截器功能是一回事. 过滤器是Servlet规范中的技术,能够对请求和响应进行过滤. 拦截器是Struts2框架中的技术.实现AOP(面向切面)的编程思想.是可插拔的, 能够对訪问某个 Action 方法之前或之后实施拦截. 拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在訪问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用 Struts2运行原

深入分析JavaWeb 48 -- Struts2中OGNL表达式与ValueStack

一.OGNL表达式 1.OGNL表达式介绍 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目. Struts2框架使用OGNL作为默认的表达式语言. OGNL相对其它表达式语言具有下面几大优势: 1.支持对象方法调用,如xxx.doSomeSpecial(): 2.支持类静态的方法调用和值访问,表达式的格式: @[类全名(包括包路径)]@[方法名 | 值名],例如:@[email protected]('foo %s', '

深入分析JavaWeb 44 -- Struts2开发核心之动作类Action

一.Action动作类(一般用**Action结尾) struts2 的Action可以是POJO(Plain Old Java Object) 为了让用户开发的Action更加规范struts2提供了一个Action接口 通过method属性指定Action执行方法 没有指定method属性,默认执行execute方法 <action name="addCustomer" class="xgp.struts.actions.CustomerAction" /

深入分析JavaWeb 45 -- Struts2封装请求参数与类型转换

作为MVC框架,必须要负责解析HTTP请求参数,并将其封装到Model对象中,Struts2提供了非常强大的类型转换机制用于请求数据 到 model对象的封装. 1.Struts2 提供三种数据封装的方式 Action 本身作为model对象,通过成员setter封装 创建独立model对象,页面通过ognl表达式封装 使用ModelDriven接口,对请求数据进行封装 1. 方式一:在动作类中成员变量给予初始值. 在配置文件中struts.xml中 <package name="p1&q

深入分析JavaWeb 43 -- Struts2开发入门

一.Struts2概述 1.Struts2是什么? Struts2是一个M(模型-域–范围模型)V(View视图)C(控制器)框架(模型2).框架都是一个半成品.提高开发效率. Struts1是一个MVC框架,非常流行.有很大的缺点.此时一个webwork的框架设计超前,名气不是很大.Struts1+webworkd=struts2.用的是struts1的名字,但是与sruts1没啥关系,struts2的核心是webwork框架. 2.Struts2能干什么? web开发Strust2 核心功能