zoukankan      html  css  js  c++  java
  • 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中有多个内置验证器:必填验证器,必填字符串验证器,整数验证器,日期验证器,表达式验证器,字符长度验证器,正则表达式验证器...等等,这个有需要的话,笔者在一一述说。

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

  • 相关阅读:
    Sum Root to Leaf Numbers 解答
    459. Repeated Substring Pattern
    71. Simplify Path
    89. Gray Code
    73. Set Matrix Zeroes
    297. Serialize and Deserialize Binary Tree
    449. Serialize and Deserialize BST
    451. Sort Characters By Frequency
    165. Compare Version Numbers
    447. Number of Boomerangs
  • 原文地址:https://www.cnblogs.com/IT-1994/p/6008544.html
Copyright © 2011-2022 走看看