• Struts2第十篇【数据校验、代码方式、XML配置方式、错误信息返回样式】


    回顾以前的数据校验

    • 使用一个FormBean对象来封装着web端来过来的数据

    这里写图片描述

    • 维护一个Map集合保存着错误信息…对各个字段进行逻辑判断
    
     //表单提交过来的数据全都是String类型的,birthday也不例外!
        private String username;
        private String password;
        private String password2;
        private String email;
        private String birthday;
    
        //记录错误的信息
        private HashMap<String, String> error = new HashMap<>();
    
    
        /*用于判断表单提交过来的数据是否合法*/
        public boolean validate() {
    
            //用户名不能为空,并且要是3-8的字符 abcdABcd
            if (this.username == null || this.username.trim().equals("")) {
    
                error.put("username", "用户名不能为空,并且要是3-8的字符");
                return false;
    
            } else {
                if (!this.username.matches("[a-zA-Z]{3,8}")) {
                    error.put("username", "用户名不能为空,并且要是3-8的字符");
                    return false;
                }
            }
    
            //密码不能为空,并且要是3-8的数字
            if (this.password == null || this.password.trim().equals("")) {
                error.put("password", "密码不能为空,并且要是3-8的数字");
                return false;
            } else {
                if (!this.password.matches("\d{3,8}")) {
                    error.put("password", "密码不能为空,并且要是3-8的数字");
                    return false;
                }
            }
    
            //两次密码要一致
            if (this.password2 != null && !this.password2.trim().equals("")) {
                if (!this.password2.equals(this.password)) {
                    error.put("password2", "两次密码要一致");
                    return false;
                }
            }
    
            //邮箱可以为空,如果为空就必须合法
                if (this.email != null && !this.email.trim().equals("")) {
                    if (!this.email.matches("\w+@\w+(\.\w+)+")) {
    
                        error.put("email", "邮箱不合法!");
                        return false;
                    }
            }
    
            //日期可以为空,如果为空就必须合法
            if (this.birthday != null && !this.birthday.trim().equals("")) {
    
                try {
                    DateLocaleConverter dateLocaleConverter = new DateLocaleConverter();
                    dateLocaleConverter.convert(this.birthday);
                } catch (Exception e) {
    
                    error.put("birthday", "日期不合法!");
                    return false;
                }
            }
    
            //如果上面都没有执行,那么就是合法的了,返回true
            return true;
        }
    
        //.....各种的setter和getter
    
    • 在Servlet上判断数据是否合法
    
            //验证表单的数据是否合法,如果不合法就跳转回去注册的页面
            if(formBean.validate()==false){
    
                //在跳转之前,把formbean对象传递给注册页面
                request.setAttribute("formbean", formBean);
                request.getRequestDispatcher("/WEB-INF/register.jsp").forward(request, response);
                return;
            }
    • 最后在JSP页面使用EL表达式进行回显

    这里写图片描述


    Struts2数据校验

    Struts2为了简化我们的开发,也提供了数据校验的功能…前面已经说过了,如果想要使用数据校验的功能,在编写Action的时候就必须继承着ActionSupport类或者实现相对应的接口

    这里写图片描述

    Struts2数据校验实现思路

    现在,我们的Action类已经继承了ActionSupport类了,现在那怎么使用数据校验的功能呢??我们想一下….

    如果我们不写FormBean对象,直接在Action进行校验的话,我们可能会这样写:

    
        private Map<String, String> map;
    
        public void validation() {
    
    
            //如果有错误了,那么就将错误信息添加到map集合
            map.put();
        }
    
        public String login() {
            //判断map是否有错误信息,如果有,就直接跳转到相对应的页面了,不执行login剩下的代码了。
        }
    

    上面的思路是可行的,但是不优雅…..在login()方法验证map集合,就与数据校验耦合了….于是乎,我们想要的是在调用login()方法之前就验证map集合是否存在…如果存在了错误的信息,就不调用login()方法了


    明显地,我们就需要使用拦截器…….Struts2内部的数据校验也是使用拦截器来实现的

        <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>

    Struts2为我们提供了4种方式来实现拦截

    • 使用代码拦截所有的方法
    • 使用代码拦截部分的方法
    • 使用XML配置拦截所有的方法
    • 使用XML配置拦截部分的方法

    使用代码拦截所有的方法

    Struts2提供了我们做校验的方法….实现validate()

    
    
        @Override
        public void validate() {
            super.validate();
        }
    

    validate()方法在内部已经维护了一个Map集合了

        public synchronized void addFieldError(String fieldName, String errorMessage) {
            Map errors = this.internalGetFieldErrors();
            Object thisFieldErrors = (List)errors.get(fieldName);
            if(thisFieldErrors == null) {
                thisFieldErrors = new ArrayList();
                errors.put(fieldName, thisFieldErrors);
            }
    
            ((List)thisFieldErrors).add(errorMessage);
        }
    

    我们如果捕获到了错误信息,那么直接使用底层为我们写好的Map集合就好了!

        @Override
        public void validate() {
    
            //判断用户名是否为空
            if (user.getUsername() == null || "".equals(user.getUsername())) {
                super.addFieldError("username","用户名是空的");
            }
            //判断密码是否为空
            if (user.getPassword() == null || "".equals(user.getPassword())) {
                super.addFieldError("username","密码是空的");
            }
        }

    配置struts.xml文件

    
        <package name="xxx" extends="struts-default">
    
            <action name="user_*" class="zhongfucheng.action.UserAction" method="{1}">
    
                <!--如果校验成功,那么回到首页-->
                <result name="success">/index.jsp</result>
    
                <!--如果失败,重新回到login页面,并显示错误信息-->
                <result name="input">/login.jsp</result>
    
            </action>
        </package>

    在JSP页面中,可以使用Struts自带的标签来显示错误信息

    
        <s:fielderror></s:fielderror>
    
    • 测试:

    这里写图片描述


    使用代码拦截部分方法

    上面已经实现了数据校验的功能了,但是呢。现在我有一个list()方法。使用list()方法讲道理是不用进行数据校验的…

    
        //查看user信息
        public String list() {
    
    
            return SUCCESS;
        }

    但是呢,当我执行list()方法的时候,还是经过了数据校验….

    这里写图片描述

    因此,我们要做的是:拦截特定的方法..非常简单,只要重命名validate()方法就行了

    • 格式:validate + 要验证的方法名

    将validate()方法名改成是validateLogin(),那么Struts2就仅仅过滤指定的方法了。

    效果

    这里写图片描述


    使用XML配置拦截所有方法

    前面我们已经使用过了代码验证的方法,,,,感觉还是要写很多代码….很多代码也是啰嗦的,要判断非空啊,数值的验证啊..等等的处理…这样判断、验证往往都是通用的…于是Struts又帮我们封装了很多的校验器

    • 路径: xwork-core-2.3.4.1.jar/com.opensymphony.xwork2.validator.validators/default.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="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 -->
    

    以上的校验器我们可以通过XML文件来配置,编写XML文件的语法:

    • 名称语法: ActionClassName-validation.xml
    • xml需要与当期要验证的action在同一个目录
    • 例子:UserAction-validation.xml

    那么XML该怎么写呢????Struts2也为我们提供了DTD文件

    这里写图片描述

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!--
      XWork Validators DTD.
      Used the following DOCTYPE.
    
      <!DOCTYPE validators PUBLIC
            "-//Apache Struts//XWork Validator 1.0.3//EN"
            "http://struts.apache.org/dtds/xwork-validator-1.0.3.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|param)*>
    <!ATTLIST message
        key CDATA #IMPLIED
    >
    
    
    • 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>
    
        <!--指定Bean对象的username属性-->
        <field name="user.username">
            <!--指定类型不能是空的-->
            <field-validator type="requiredstring">
                <message>用户名不能是空的</message>
            </field-validator>
        </field>
        <!--指定Bean对象的属性-->
        <field name="user.password">
            <!--指定类型不能是空的-->
            <field-validator type="requiredstring">
                <message>密码不能是空的</message>
            </field-validator>
    
            <!--设置密码的长度6到8位-->
            <field-validator type="stringlength">
                <param name="minLength">6</param>
                <param name="maxLength">8</param>
                <message>密码只能是6-8位</message>
            </field-validator>
        </field>
    </validators>

    测试

    用户名和密码都不能为空

    密码只能是6-8位

    这里写图片描述


    使用XML配置拦截特定的方法

    和代码的方式一样,我们写上了XML文件,它也是默认拦截所有的方法。那么我们想要它只拦截特定的方法,怎么办呢???

    修改XML文件的名称:

    • 语法:ActionClassName-ActionName-validation.xml
    • 例子:UserAction-user_login-validation.xml

    返回错误信息的样式

    css修改Struts标签样式

    我们发现,返回错误信息的样式是这样的:

    这里写图片描述

    这明显不符合我们的审美的……于是乎我们是可以修改它的样式的…我们查看源文件的时候,可以发现Struts为它自动加了ul li

    这里写图片描述

    我们可以在css文件中把它们去除就行了

        <style type="text/css">
    
            ul{
                display: inline;
            }
            ul li {
                display: inline;
                color: red;;
    
            }
        </style>
    

    这里写图片描述


    修改标签定义的模板

    Struts2标签的样式是由文件来指定的…具体路径如下:

    这里写图片描述

    我们发现ul li是它指定加上去的,我们把它修改,然后覆盖掉它,那么Struts2在读取的时候就使用我们的文件

    这里写图片描述


    在src下创建template.simple包..文件是fielderror.ftl…项目在执行的时候就会把Struts2自带的给覆盖了!

    指定返回错误

    使用<s:fielderror></s:fielderror>是默认返回全部错误的,我们通常来说,都是把错误放在输入框的后面的…Struts提供了指定返回错误..只要指定fileName就行了

    <form action="${pageContext.request.contextPath}/user_login" method="post">
    
        用户名:<input type="text" name="user.username"><s:fielderror fieldName="user.username"/><br>
        密码:<input type="password" name="user.password"><s:fielderror fieldName="user.password"/><br>
        <input type="submit" value="登陆"><br>
    </form>
    

    这里写图片描述


    配置客户端校验

    Struts2也支持客户端的校验,在使用Struts2的form标签的使用,在validate属性上设置为true,那么Struts2会自动加载JavaScript的类库来实现客户端的数据校验了!


    总结

    Struts2也提供了客户端的数据校验功能….

    我们现在已经学会了使用手写代码的方式和XML配置的方式去校验数据了。。

    那么哪种方式更好呢???我们来总结一下

    手写代码方式:

    • 更加灵活,要校验的逻辑全都是自己把握
    • 但是比较繁琐,有很多的重复逻辑代码

    XML配置方式

    • 不用自己手写逻辑代码,调用Struts提供给我们的拦截器即可
    • 但是如果拦截的方法比较多的话,会出现多个XML配置文件

    最后补充:Struts2也支持通过注解的方式实现数据校验,但是这会造成Action类看起来十分冗余,一般很少使用


  • 相关阅读:
    WM_COMMAND 和 WM_NOTIFY 的区别
    C 游戏所要看的书
    Source Insight中文字体设置
    在 windows7 中使用 vs2003 时,“在文件中查找”导致无响应的问题
    解决VS2008 调试启动特别慢
    c++ 浅谈 new 的使用
    Access界面基础操作
    与孩子一起学编程12章
    YT工作日志-0911
    两种方式遍历二叉树--递归方式和非递归方式
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7202979.html
Copyright © 2020-2023  润新知