소스 검색

新增基于groovy的动态验证支持

周浩 9 년 전
부모
커밋
7308dd5a7e

+ 23 - 6
hsweb-web-service-impl-common/src/main/java/org/hsweb/web/service/impl/form/DefaultFormParser.java

@@ -15,10 +15,7 @@ import org.webbuilder.utils.common.BeanUtils;
 import org.webbuilder.utils.common.StringUtils;
 
 import java.lang.reflect.Field;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * Created by zhouhao on 16-4-20.
@@ -34,7 +31,6 @@ public class DefaultFormParser implements FormParser {
         metaData.setComment(form.getRemark());
         JSONObject object = JSON.parseObject(meta);
         object.forEach((id, field) -> {
-            if ("main".equals(id)) return;
             FieldMetaData fieldMeta = new FieldMetaData();
             fieldMeta.attr("field-id", id);
             JSONArray obj = ((JSONArray) field);
@@ -42,6 +38,23 @@ public class DefaultFormParser implements FormParser {
                 JSONObject def = ((JSONObject) defT);
                 String key = def.getString("key");
                 Object value = def.get("value");
+                if ("main".equals(id)) {
+                    metaData.attr(key,value);
+                    return;
+                }
+                if ("validator-list".equals(key)) {
+                    Set<String> validatorList = new LinkedHashSet<>();
+                    if (value instanceof String) {
+                        List<JSONObject> jsonArray = JSON.parseArray((String) value, JSONObject.class);
+                        jsonArray.forEach(json -> {
+                            String validator = json.getString("validator");
+                            if (validatorSupport(validator))
+                                validatorList.add(validator);
+                        });
+                    }
+                    fieldMeta.setValidator(validatorList);
+                    return;
+                }
                 Field ftmp = ReflectionUtils.findField(FieldMetaData.class, key);
                 if (ftmp != null) {
                     try {
@@ -63,13 +76,17 @@ public class DefaultFormParser implements FormParser {
                 }
             });
             //name为空的时候 不保持此字段
-            if (!StringUtils.isNullOrEmpty(fieldMeta.getName())) {
+            if (!"main".equals(id)&&!StringUtils.isNullOrEmpty(fieldMeta.getName())) {
                 metaData.addField(fieldMeta);
             }
         });
         return metaData;
     }
 
+    protected boolean validatorSupport(String validator) {
+        return !StringUtils.isNullOrEmpty(validator);
+    }
+
     protected static Map<String, Class> typeMapper = new HashMap() {{
         put("", String.class);
         put("null", String.class);

+ 75 - 0
hsweb-web-service-impl-common/src/main/java/org/hsweb/web/service/impl/form/validator/GroovyDycBeanValidator.java

@@ -0,0 +1,75 @@
+package org.hsweb.web.service.impl.form.validator;
+
+import org.hsweb.web.bean.valid.ValidResults;
+import org.hsweb.web.core.exception.BusinessException;
+import org.webbuilder.sql.validator.Validator;
+import org.webbuilder.utils.common.BeanUtils;
+import org.webbuilder.utils.common.ClassUtils;
+import org.webbuilder.utils.script.engine.DynamicScriptEngine;
+import org.webbuilder.utils.script.engine.DynamicScriptEngineFactory;
+
+import javax.validation.ConstraintViolation;
+import javax.xml.bind.ValidationException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 基于Groovy动态Bean对象验证
+ * 原理,通过调用groovy脚本获取一个已编译的动态bean实例,然后进行赋值后验证
+ * Created by 浩 on 2015-12-24 0024.
+ */
+public class GroovyDycBeanValidator implements Validator {
+
+    protected static DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine("groovy");
+
+    private String className;
+    private javax.validation.Validator hibernateValidator;
+
+
+    public GroovyDycBeanValidator(String className, javax.validation.Validator hibernateValidator) {
+        this.className = className;
+        this.hibernateValidator = hibernateValidator;
+    }
+
+    public List valid(Object data, boolean insert) {
+        ValidResults results = new ValidResults();
+        try {
+            if (!(data instanceof Map)) {
+                throw new ValidationException("数据类型错误!");
+            }
+            Object bean = engine.execute(className + ".getInstance", new HashMap<>()).getResult();
+            Map<String, Object> mapData = ((Map) data);
+            for (Map.Entry<String, Object> entry : mapData.entrySet()) {
+                BeanUtils.attr(bean, entry.getKey(), entry.getValue());
+            }
+            Set<ConstraintViolation<Object>> result = hibernateValidator.validate(bean);
+            if (result.size() > 0) {
+                for (ConstraintViolation<Object> violation : result) {
+                    String property = violation.getPropertyPath().toString();
+                    if (insert) {
+                        results.addResult(property, violation.getMessage());
+                    } else if (mapData.containsKey(property)) {
+                        results.addResult(property, violation.getMessage());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new BusinessException("验证器异常!", e, 500);
+        }
+        if (results.size() > 0) throw new BusinessException(results.toString(), 400);
+        return null;
+        //采用异常通知方式
+    }
+
+    @Override
+    public List insertValid(Object data) {
+        return valid(data, true);
+    }
+
+    @Override
+    public List updateValid(Object data) {
+        return valid(data, false);
+    }
+}

+ 97 - 0
hsweb-web-service-impl-common/src/main/java/org/hsweb/web/service/impl/form/validator/GroovyDycBeanValidatorFactory.java

@@ -0,0 +1,97 @@
+package org.hsweb.web.service.impl.form.validator;
+
+import org.hsweb.web.core.exception.BusinessException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.webbuilder.sql.FieldMetaData;
+import org.webbuilder.sql.TableMetaData;
+import org.webbuilder.sql.validator.Validator;
+import org.webbuilder.sql.validator.ValidatorFactory;
+import org.webbuilder.utils.common.StringUtils;
+import org.webbuilder.utils.script.engine.DynamicScriptEngine;
+import org.webbuilder.utils.script.engine.DynamicScriptEngineFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 基于groovy动态bean的校验器
+ */
+@Component
+public class GroovyDycBeanValidatorFactory implements ValidatorFactory {
+
+    @Autowired
+    private javax.validation.Validator hibernateValidator;
+
+    private Map<String, Validator> base = new HashMap<>();
+
+    protected static DynamicScriptEngine engine = DynamicScriptEngineFactory.getEngine("groovy");
+
+    public static final String basePackage = "org.hsweb.web.bean.dyn_form";
+
+    private static final String[] imports = {
+            "import org.hibernate.validator.constraints.*;",
+            "import javax.validation.constraints.*;"
+    };
+
+    @Override
+    public Validator getValidator(TableMetaData metaData) {
+        return base.get(metaData.getName());
+    }
+
+    /**
+     * 根据表结构动态生成一个基于hibernate-validator的bean
+     *
+     * @param metaData 表结构
+     * @return 验证器对象
+     */
+    @Override
+    public Validator initValidator(TableMetaData metaData) {
+        StringBuilder script = new StringBuilder();
+        String className = StringUtils.concat(basePackage, ".", metaData.getName());
+        script.append("package ").append(basePackage).append(";\n");
+        for (String anImport : imports) {
+            script.append(anImport).append("\n");
+        }
+        script.append("public class ").append(metaData.getName()).append("{\n");
+        boolean hasValidator = false;
+        for (FieldMetaData fieldMetaData : metaData.getFields()) {
+            for (String ann : fieldMetaData.getValidator()) {
+                hasValidator = true;
+                script.append("\t@").append(ann).append("\n");
+            }
+            script.append("\tprivate ")
+                    .append(fieldMetaData.getJavaType().getName()).append(" ")
+                    .append(fieldMetaData.getName()).append(";\n\n");
+        }
+        //没有配置验证器
+        if (!hasValidator) return null;
+        for (FieldMetaData fieldMetaData : metaData.getFields()) {
+            script.append("public ")
+                    .append(fieldMetaData.getJavaType().getName()).append(" get")
+                    .append(StringUtils.toUpperCaseFirstOne(fieldMetaData.getName()))
+                    .append("(){\n")
+                    .append("\treturn this.").append(fieldMetaData.getName()).append(";")
+                    .append("\n}\n");
+            script.append("public void set").append(StringUtils.toUpperCaseFirstOne(fieldMetaData.getName()))
+                    .append("(")
+                    .append(fieldMetaData.getJavaType().getName()).append(" ").append(fieldMetaData.getName())
+                    .append(")")
+                    .append("{\n")
+                    .append("\tthis.").append(fieldMetaData.getName()).append("=").append(fieldMetaData.getName()).append(";")
+                    .append("\n}\n\n");
+        }
+        script.append("}");
+        try {
+            engine.compile(className, script.toString());
+            engine.compile(className + ".getInstance", "return new " + className + "();");
+        } catch (Exception e) {
+            throw new BusinessException("创建动态表单验证器失败!", e, 500);
+        }
+        GroovyDycBeanValidator validator = new GroovyDycBeanValidator(className, hibernateValidator);
+        base.put(metaData.getName(), validator);
+        return validator;
+    }
+
+
+}