• Struts2入门(四)——数据输入验证


    一、前言

    1.1、什么是输入验证?为什么需要输入验证?

    在上一篇文章中,我们学习了数据类型转换,我们提到了表示层数据处理的两个方法,也提到了用户输入数据需要进行类型转换才能得到我们想要的数据,那么,我们怎么确定类型转换后的数据,是我们想要的数据呢?这里有点绕。你可以这样想:一个成年男子年龄是18岁,你现在想要得到18这个数据,但是,用户输入32,经过类型转换也是对的,但是数据不是你想要的。这时候,我们要怎么办?所以输入验证在这里就有用处了。

    类型转换和输入验证的关系是:类型转换是输入验证的前提,如果类型转换都出错了,那就不用再进行输入验证了。但是很多时候类型转换和输入验证是同时完成的。

    输入验证有两种:

    1、客户端验证;

    2、服务端验证。这里主要讲解的是服务端验证(重写ValidateXxx方法和xml配置文件验证)

    1.2、重写ValidateXxx方法的验证流程

    1、类型转换器负责对字符串的请求参数进行类型转换,并将这些值设置成Action的属性值

    2、在执行类型转换过程中可能出现异常,如果出现异常,异常信息会自动保存到ActionContext中,conversionError拦截器负责将其封装到fieldError中

    3、通过反射调用ValidateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法名

    4、调用Action类的Validate方法

    5、如果上面的步骤没有出现fieldError,将调用Action里处理用户请求的处理方法,如果出现fieldError,系统将转入input逻辑视图所指定的视图。

    二、输入验证

    2.1、输入验证这里讲解的有两种方式:

    1、重写Validate方法或者自定义ValidateXxx方法(其中的Xxx是自己定义的名字,会先执行该方法,在执行Validate方法)

    2、新建xml进行验证

    2.2、重写Validate方法

    在MVC框架,都会提供规范的数据验证部分,Struts2在这里提供的是一个Validate方法,我们重写Validate方法就可以进行输入验证,但是,重写Validate方法有两个点需要知道:1、Validate方法会在execute方法之前被执行;2、Validate方法对所有的Action都会执行校验规则,为了区别某一个Action,我们可以使用ValidateXxx方法。

    注意:以下的例子是局部类型转换和输入验证一起使用的例子。

    简单的注册验证例子:

    新建实体类User:

    package com.validatexxx;
    
    
    public class User {
         private String username;  
         private String password;  
         private String repassword;  
        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;
        }
    }
    User

    新建视图:Register.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s" %>    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>注册用户</title>
    </head>
    <body>
        <h2>使用validateXXX()方法验证</h2>
        <form action="register_test">
            用户:<input type="text" name="user"><br/>
            密码:<input type="password" name="user"><br/>
            密码:<input type="password" name="user"><br/>
            <input type="submit" value="提交">
        </form>  
    </body>
    </html>

    新建RegisterAction类继承ActionSupport

    package com.validatexxx;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    //重写validate()和validateXXX指定方法进行验证
    /*
     * 在struts.xml配置method方法为test(),会先调用ValidateTest()方法,
     * 然后在调用validate方法
     * 之后test方法被调用
     * */
    public class RegisterAction extends ActionSupport {
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
        //2
        @Override  
        public void validate(){     
         System.out.println("重写Validate方法");
         if (null == user.getPassword()  || "".equals(user.getPassword()) || null == user.getRepassword()  || "".equals(user.getRepassword())) { 
                 this.addFieldError("repassword", "repassword should be same password");  
                return;  
             }  
         if (!user.getPassword().equals(user.getRepassword())) {  
             //当FieldError中存在数据时,服务器会自动帮我们跳转到input的逻辑视图
             this.addFieldError("repassword", "repassword should be same password");  
             } 
        }
        //1
        public void validateTest(){
            System.out.println("自定义校验方法:ValidateTest");
        }
        //3
        public String test(){
            System.out.println("test:方法");
            return SUCCESS;
        }
    }

    注意:这里的属性是User,所以你jsp页面参数的名字要写实例的名字user,然后你还需要去创建一个类型转换器,返回一个填充好数据的类

    新建struts.xml,存放在WEB-INF/classes/struts.xml

    注意:这里的method必须是你ValudateXxx()方法后面你自己定义的,笔者这里是test。使用*的话,struts2还必须配置 strict-method-invocation="false",据说是因为版本太高了,它的安全性增加了,所有必须加才能够使用*

    新建Usertypeconverter类继承StrutsTypeConverter(创建一个类型转换器)

    package com.validatexxx;
    
    import java.util.Map;
    
    import org.apache.struts2.util.StrutsTypeConverter;
    
    //类型转换的类
    public class Usertypeconverter extends StrutsTypeConverter {
    
        @Override
        public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
            System.out.println("Usertypeconverter:类型转换!");
            User user = new User();
            user.setUsername(arg1[0]);
            user.setPassword(arg1[1]);
            user.setRepassword(arg1[2]);
            return user;
        }
    
        @Override
        public String convertToString(Map arg0, Object arg1) {
            User u = (User)arg1;
            return u.getUsername()+"!";
        }
    
    }

    注意:该类型转换器创建好之后还需新建一个RegisterAction-conversion.properties,放在同级目录下

    该文件的内容有:

    前面是你在RegisterAction的属性名,后面是类型转换器的具体路径。

     新建成功视图:success.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s" %>    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Success</title>
    </head>
    <body>
          <h2>服务端使用validate方法验证</h2>
          成功
    </body>
    </html>
    success.jsp

    新建错误视图:input.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s" %>    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>    
        Error:<s:fielderror/>
    </body>
    </html>
    input.jsp

    代码执行成功的效果如下:

    Register.jsp页面 

    成功跳转的页面为:success.jsp

    控制台测试结果为:

    数据跳转到Usertypeconverter进行类型转换,之后跳转到RegisterAction,执行ValidateTest方法(),Validate,test之后返回SUCCESS,然后执行result的视图。

    我们看代码执行失败的顺序:

    Register.jsp页面

    input.jsp页面

    控制台测试效果:

    在Validate方法里面,笔者代码为:this.addFieldError(),在前面有说过,如果添加错误的话,那么服务器会自动帮我们跳转到错误的界面。它会返回input,而input在struts.xml中就有配置,会返回到input.jsp界面。

    2.3、新建xml进行输入验证

    新建视图界面:Test.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s" %>    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>使用XML校验</title>
    </head>
    <body>
        <s:form action="empinfo" method="post">
          <s:textfield name="name" label="Name" size="20" />
          <s:textfield name="age" label="Age" size="20" />
          <s:submit name="submit" label="Submit" align="center" />
       </s:form> 
    </body>
    </html>

    新建Employee类继承ActionSupport

    该类有使用重写Validate方法和Xml配置,我们可以选择其中一种进行验证就可以

    package com.validatexxx;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    //使用validate()方法验证,这是服务端验证!
    public class Employee extends ActionSupport {
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        //第二步再执行该方法
        public String execute(){
            System.out.println("execute:"+this.age);
            return SUCCESS;
        }
    /*    使用服务端的校验:重写validate方法();
        //第一步先执行该方法
        //重写validate方法有缺陷:每次都会使用validate方法验证,造成极大的资源浪费。
        public void validate(){
            System.out.println("validate");
              if (name == null || name.trim().equals(""))
              {
                 //当往该方法添加数据的时候,服务器会返回input,之后跳转到input.jsp页面中。
                 addFieldError("name","The name is required");
              } 
              if (age < 28 || age > 65)
              {
                  addFieldError("age","Age must be in between 28 and 65");
               }
        }
    */
    }

    在Struts.xml中进行配置:

    这里的success.jsp和input.jsp还是使用上面的。

    之后我们需要新建Employee-validation.xml,路径放在与Employee同级目录下,注意:-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>
       <field name="name">
          <field-validator type="required">
             <message>
                The name is required.
             </message>
          </field-validator>
       </field>
    
       <field name="age">
         <field-validator type="int">
             <param name="min">29</param>
             <param name="max">64</param>
             <message>
                Age must be in between 28 and 65
             </message>
          </field-validator>
       </field>
    </validators>

    重点:该文件的dtd限制必须有,不然回报错误:

    ERROR DefaultDispatcherErrorHandler Exception occurred during processing request: [Connection timed out: connect - [unknown location], null]

    接下来我们使用http://localhost:8080/LearStruts2/ValidateJSP/Test.jsp进行访问。

    测试成功:

    Test.jsp界面:

    success.jsp

    测试失败例子:

    input.jsp界面:

    说明例子是正确的。

    其实在Struts2中有多个内置验证器:必填验证器,必填字符串验证器,整数验证器,日期验证器,表达式验证器,字符长度验证器,正则表达式验证器...等等,这个有需要的话,笔者在一一述说。

    以上就是输入验证的两种方式。不足之处请下方留言,我会改正,谢谢!

  • 相关阅读:
    Python(1)-第一天
    读书笔记-单元测试艺术(三)-使用桩对象解除依赖
    Sql2008调试问题
    读书笔记-单元测试艺术(二)-单元测试框架
    读书笔记-单元测试艺术(一)-单元测试的基本知识
    最长回文子串
    最大连续子序列之和,最大连续子序列乘积
    计数排序与位图排序
    筛选法求素数
    传说中的华为面试题(8分钟写出代码)
  • 原文地址:https://www.cnblogs.com/IT-1994/p/6008544.html
Copyright © 2020-2023  润新知