zoukankan      html  css  js  c++  java
  • SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js验证代码

    SpringMVC学习系列(6) 之 数据验证中我们已经学习了如何结合Hibernate-validator进行后台的数据合法性验证,但是通常来说后台验证只是第二道保险,为了更好的用户体验会现在前端进行js验证,验证通过之后数据才能提交到后台,那么我们不可避免的要在前端的页面中写对应的js验证代码。

    但是这样就需要进行一些很麻烦且重复的操作:

    1.首先要保证前端和后台的验证规则要相同,避免出现前端验证通过,提交后又出现验证失败的情况。

    2.其次要保证前端和后台的验证规则要同步,即修改一边的验证规则后要修改另一边对应的验证规则。

    3.要保证错误提示信息的一致和相应的国际化问题。(其实这个问题在js验证代码中提示错误信息的地方,绑定国际化信息可以解决,只是比较啰嗦。)

    好吧~~~以上这些都不是主要原因,主要原因是我太懒了不想在每个页面中再一个一个写对应的js验证代码,那么如何才能让后台根据我们定义的模型验证规则自动生成前端的js验证代码呢?

    下面一步一步来:

    首先我想像spring mvc的form标签一样<form:form modelAttribute="contentModel" method="post">,这样指定一下就可以生成对应的前端代码,简洁优雅,多爽!,那么我们就要先自定义taglib标签。

    1.添加一个类,这里就叫JsValidateTag,我是定义在com.demo.test包下面的。

    2.在WebContent/WEB-INF目录下面添加一个xml文件,我这里名称叫test.tld内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
            version="2.0">
            
            <description>Test</description>
            <tlib-version>1.0</tlib-version>
            <short-name>test</short-name>
            <uri>http://www.mytest.org/tags/test</uri>
            
            <tag>
                <description></description>
                <name>jsValidate</name>
                <tag-class>com.demo.test.JsValidateTag</tag-class>
                <body-content>empty</body-content>
                <attribute>
                    <description>Path to property for data binding</description>
                    <name>modelAttribute</name>
                    <required>true</required>
                    <rtexprvalue>true</rtexprvalue>
                </attribute>
            </tag>
            
    </taglib>

    上面的内容很简单,就是定义了一个叫jsValidate的标签,对应的类是com.demo.test.JsValidateTag就是我们之前新建的那个,然后有一个叫modelAttribute的参数。

    3.接下来在我们新建的类里面实现具体的处理逻辑,代码如下:

    package com.demo.test;
    
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import javax.servlet.jsp.JspException;
    import org.hibernate.validator.constraints.Email;
    import org.hibernate.validator.constraints.NotEmpty;
    import org.hibernate.validator.constraints.Range;
    import org.springframework.web.servlet.tags.form.AbstractFormTag;
    import org.springframework.web.servlet.tags.form.TagWriter;
    
    /**
     * 
     * 自动生成前台js验证代码
     * @author liukemng@sina.com
     *
     */
    @SuppressWarnings("serial")
    public class JsValidateTag extends AbstractFormTag {
        @SuppressWarnings("unused")
        private TagWriter tagWriter;
        private String modelAttribute;
    
        public void setModelAttribute(String modelAttribute) {
            this.modelAttribute = modelAttribute;
        }
        
        public String getModelAttribute() throws JspException {
            String resolvedModelAttribute = (String) evaluate("modelAttribute", this.modelAttribute);
            return (resolvedModelAttribute != null ? resolvedModelAttribute : "");
        }
    
        @Override
        protected int writeTagContent(TagWriter tagWriter) throws JspException {
            Object model;
            if(getRequestContext().getModel()!=null)
                model=getRequestContext().getModel().get(getModelAttribute());
            else
                model=this.pageContext.getRequest().getAttribute(getModelAttribute());
            if(model!=null){
                Map<String, List<String[]>> fieldValidateMap=new HashMap<String, List<String[]>>();
    
                try {
                    Field[] theFields=model.getClass().getDeclaredFields();
                    if(theFields!=null&& theFields.length>0){
                        for(Field field : theFields){
                            String fieldName=field.getName();
                            List<String[]> fieldValidateList=new ArrayList<String[]>();
                            NotEmpty notEmpty=field.getAnnotation(NotEmpty.class);
                            if(notEmpty!=null){
                                String messageName=notEmpty.message();
                                fieldValidateList.add(new String[]{"required","true",getRequestContext().getMessage(messageName.substring(1, messageName.length()-1))});
                            }
                            
                            Email email=field.getAnnotation(Email.class);
                            if(email!=null){
                                String messageName=email.message();
                                fieldValidateList.add(new String[]{"email","true",getRequestContext().getMessage(messageName.substring(1, messageName.length()-1))});
                            }
                            
                            Range range=field.getAnnotation(Range.class);
                            if(range!=null){
                                String messageName=range.message();
                                fieldValidateList.add(new String[]{"range","["+range.min()+","+range.max()+"]",getRequestContext().getMessage(messageName.substring(1, messageName.length()-1))});
                            }
                            
                            
                            if(fieldValidateList.size()>0){
                                fieldValidateMap.put(fieldName, fieldValidateList);
                            }
                        }
                    }
                }catch (SecurityException e1) {
                    e1.printStackTrace();
                }
                
                if(fieldValidateMap.size()>0){        
                    StringBuilder rulesBuilder=new StringBuilder();
                    StringBuilder messagesBuilder=new StringBuilder();
                    
                    rulesBuilder.append("rules:{");
                    messagesBuilder.append("messages:{");
    
                    int i=0;
                    Iterator<Entry<String, List<String[]>>> iterator=fieldValidateMap.entrySet().iterator();
                    while(iterator.hasNext()){
                        Entry<String, List<String[]>> entry=iterator.next();
                        rulesBuilder.append(entry.getKey()).append(":{");
                        messagesBuilder.append(entry.getKey()).append(":{");
                        
                        int j=0;
                        for(String[] array : entry.getValue()){
                            rulesBuilder.append(array[0]).append(":").append(array[1]);
                            messagesBuilder.append(array[0]).append(":"").append(array[2]).append(""");
    
                            if(j<entry.getValue().size()-1){
                                rulesBuilder.append(",");
                                messagesBuilder.append(",");
                            }
                            j++;
                        }
                        
                        rulesBuilder.append("}");
                        messagesBuilder.append("}");
    
                        if(i<fieldValidateMap.size()-1){
                            rulesBuilder.append(",");
                            messagesBuilder.append(",");
                        }
                        i++;
                    }
                    
                    rulesBuilder.append("},");
                    messagesBuilder.append("}");
                    tagWriter.startTag("script");
                    tagWriter.writeAttribute("type", "text/javascript");
                    tagWriter.appendValue("$(function() {");
                    tagWriter.appendValue("$("#");
                    tagWriter.appendValue(getModelAttribute());
                    tagWriter.appendValue("").validate({");
                    //在失去焦点时验证
                    tagWriter.appendValue("onfocusout:function(element){$(element).valid();},");
                    tagWriter.appendValue(rulesBuilder.toString());
                    tagWriter.appendValue(messagesBuilder.toString());
                    tagWriter.appendValue("});");
                    tagWriter.appendValue("});");
                    tagWriter.endTag(true);
                }    
            }
            
            this.tagWriter=tagWriter;
            return EVAL_BODY_INCLUDE;
        }
        
        @Override
        public void doFinally() {
            super.doFinally();
            this.tagWriter = null;
        }
    }

    4.接下来在页面中引用我们自定义的标签:

    <%@ taglib prefix="test" uri="http://www.mytest.org/tags/test" %>

    并指定模型名称:

    <test:jsValidate modelAttribute="contentModel"></test:jsValidate>

    页面整体内容如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%@ taglib prefix="test" uri="http://www.mytest.org/tags/test" %>
    
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Insert title here</title>
        <script src="<c:url value='/js/jquery-1.10.2.min.js'/>" type="text/javascript"></script>
        <script src="<c:url value='/js/jquery.validate.min.js'/>" type="text/javascript"></script>
    </head>
    <body>
        <form:form modelAttribute="contentModel" method="post">     
            
            <form:errors path="*"></form:errors><br/><br/>
                
            name:<form:input path="name" /><br/>
            <form:errors path="name"></form:errors><br/>
            
            
            age:<form:input path="age" /><br/>
            <form:errors path="age"></form:errors><br/>
            
            email:<form:input path="email" /><br/>
            <form:errors path="email"></form:errors><br/>
    
            <input type="submit" value="Submit" />
            
        </form:form>  
    </body>
    <test:jsValidate modelAttribute="contentModel"></test:jsValidate>
    </html>

    好了运行测试看看效果吧:

    啊哈哈哈哈哈~~~,已经生成好了~~~

    注:以上的代码只实现了@NotEmpty、@Range、@NotEmpty三个注解对应的js验证规则,其它注解的js验证规则在JsValidateTag类中添加相应的逻辑即可。

    项目源码下载:http://pan.baidu.com/s/1c0pVzFy

    保留版权,如需转载请注明出处…

  • 相关阅读:
    中国象棋评估函数建模
    C语言中指针变量传参
    STM32外部中断
    C语言中的注释
    STM32学习网址
    C语言中的布尔值
    更改KEIL背景配色
    Modbus通讯协议
    DUP
    算法的时间复杂度
  • 原文地址:https://www.cnblogs.com/liukemng/p/4618851.html
Copyright © 2011-2022 走看看