SpringMVC学习系列-后记 结合SpringMVC和Hibernate-validator,根据后台验证规则自动生成前台的js

Tags: java spring

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

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" " 
<%@ 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

   

本文链接:http://www.4byte.cn/learning/119878/springmvc-xue-xi-xi-lie-hou-ji-jie-he-springmvc-he-hibernate-validator-gen-ju-hou-tai-yan-zheng-gui-ze-zi-dong-sheng-cheng-qian-tai-de-js.html