Sfoglia il codice sorgente

优化实体验证

zhouhao 3 anni fa
parent
commit
90255abc9d

+ 1 - 1
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/Entity.java

@@ -59,7 +59,7 @@ public interface Entity extends Serializable {
      * @param groups 分组
      * @see org.hswebframework.web.exception.ValidationException
      */
-    default void tryValidate(StaticMethodReferenceColumn<?> property, Class<?>... groups) {
+    default <T> void tryValidate(StaticMethodReferenceColumn<T> property, Class<?>... groups) {
         tryValidate(property.getColumn(), groups);
     }
 

+ 5 - 31
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java

@@ -269,37 +269,11 @@ public interface TreeSupportEntity<PK> extends Entity {
     static <N extends TreeSupportEntity<PK>, PK> List<N> list2tree(final Collection<N> dataList,
                                                                    final BiConsumer<N, List<N>> childConsumer,
                                                                    final Function<TreeHelper<N, PK>, Predicate<N>> predicateFunction) {
-        Objects.requireNonNull(dataList, "source list can not be null");
-        Objects.requireNonNull(childConsumer, "child consumer can not be null");
-        Objects.requireNonNull(predicateFunction, "root predicate function can not be null");
-
-        Supplier<Stream<N>> streamSupplier = () -> dataList.stream();
-        // id,node
-        Map<PK, N> cache = new HashMap<>();
-        // parentId,children
-        Map<PK, List<N>> treeCache = streamSupplier.get()
-                                                   .peek(node -> cache.put(node.getId(), node))
-                                                   .filter(e -> e.getParentId() != null)
-                                                   .collect(Collectors.groupingBy(TreeSupportEntity::getParentId));
-
-        Predicate<N> rootNodePredicate = predicateFunction.apply(new TreeHelper<N, PK>() {
-            @Override
-            public List<N> getChildren(PK parentId) {
-                return treeCache.get(parentId);
-            }
-
-            @Override
-            public N getNode(PK id) {
-                return cache.get(id);
-            }
-        });
-
-        return streamSupplier.get()
-                             //设置每个节点的子节点
-                             .peek(node -> childConsumer.accept(node, treeCache.get(node.getId())))
-                             //获取根节点
-                             .filter(rootNodePredicate)
-                             .collect(Collectors.toList());
+        return TreeUtils.list2tree(dataList,
+                                   TreeSupportEntity::getId,
+                                   TreeSupportEntity::getParentId,
+                                   childConsumer,
+                                   (helper, node) -> predicateFunction.apply(helper).test(node));
     }
 
     /**

+ 60 - 0
hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeUtils.java

@@ -0,0 +1,60 @@
+package org.hswebframework.web.api.crud.entity;
+
+import com.google.common.collect.Maps;
+
+import java.util.*;
+import java.util.function.*;
+import java.util.stream.Collectors;
+
+public class TreeUtils {
+
+    /**
+     * 列表结构转为树结构,并返回根节点集合
+     *
+     * @param dataList          数据集合
+     * @param childConsumer     子节点消费接口,用于设置子节点
+     * @param predicateFunction 根节点判断函数,传入helper,获取一个判断是否为跟节点的函数
+     * @param <N>               元素类型
+     * @param <PK>              主键类型
+     * @return 根节点集合
+     */
+    public static <N, PK> List<N> list2tree(Collection<N> dataList,
+                                            Function<N, PK> idGetter,
+                                            Function<N, PK> parentIdGetter,
+                                            BiConsumer<N, List<N>> childConsumer,
+                                            BiPredicate<TreeSupportEntity.TreeHelper<N, PK>, N> predicateFunction) {
+        Objects.requireNonNull(dataList, "source list can not be null");
+        Objects.requireNonNull(childConsumer, "child consumer can not be null");
+        Objects.requireNonNull(predicateFunction, "root predicate function can not be null");
+
+        // id,node
+        Map<PK, N> cache = Maps.newHashMapWithExpectedSize(dataList.size());
+        // parentId,children
+        Map<PK, List<N>> treeCache = dataList
+                .stream()
+                .peek(node -> cache.put(idGetter.apply(node), node))
+                .filter(e -> parentIdGetter.apply(e) != null)
+                .collect(Collectors.groupingBy(parentIdGetter));
+
+        TreeSupportEntity.TreeHelper<N, PK> helper = new TreeSupportEntity.TreeHelper<N, PK>() {
+            @Override
+            public List<N> getChildren(PK parentId) {
+                return treeCache.get(parentId);
+            }
+
+            @Override
+            public N getNode(PK id) {
+                return cache.get(id);
+            }
+        };
+
+        return dataList
+                .stream()
+                //设置每个节点的子节点
+                .peek(node -> childConsumer.accept(node, treeCache.get(idGetter.apply(node))))
+                //获取根节点
+                .filter(node -> predicateFunction.test(helper, node))
+                .collect(Collectors.toList());
+    }
+
+}

+ 9 - 10
hsweb-core/src/main/java/org/hswebframework/web/bean/DefaultToStringOperator.java

@@ -26,7 +26,7 @@ import static org.hswebframework.web.bean.ToString.Feature.nullPropertyToEmpty;
 @Slf4j
 public class DefaultToStringOperator<T> implements ToStringOperator<T> {
 
-    private PropertyDescriptor[] descriptors;
+    private final PropertyDescriptor[] descriptors;
 
     private Set<String> defaultIgnoreProperties;
 
@@ -36,10 +36,9 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
 
     private Map<String, BiFunction<Object, ConvertConfig, Object>> converts;
 
-    private Function<Object, String> coverStringConvert = (o) -> coverString(String.valueOf(o), 80);
+    private final Function<Object, String> coverStringConvert = (o) -> coverString(String.valueOf(o), 80);
 
-
-    private Function<Class, BiFunction<Object, ConvertConfig, Object>> simpleConvertBuilder = type -> {
+    private final Function<Class<?>, BiFunction<Object, ConvertConfig, Object>> simpleConvertBuilder = type -> {
         if (Date.class.isAssignableFrom(type)) {
             return (value, f) -> DateFormatter.toString(((Date) value), "yyyy-MM-dd HH:mm:ss");
         } else {
@@ -47,13 +46,14 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
         }
     };
 
-    private Predicate<Class> simpleTypePredicate = ((Predicate<Class>) String.class::isAssignableFrom)
+    private final Predicate<Class<?>> simpleTypePredicate = ((Predicate<Class<?>>) String.class::isAssignableFrom)
             .or(Class::isEnum)
             .or(Class::isPrimitive)
             .or(Date.class::isAssignableFrom)
             .or(Number.class::isAssignableFrom)
             .or(Boolean.class::isAssignableFrom);
-    private Class<T> targetType;
+
+    private final Class<T> targetType;
 
     public DefaultToStringOperator(Class<T> targetType) {
         this.targetType = targetType;
@@ -228,10 +228,9 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
         }
     }
 
-    class ConvertConfig {
+   static class ConvertConfig {
         long features;
         Set<String> ignoreProperty;
-
     }
 
     protected Map<String, Object> convertMap(Map<String, Object> obj, long features, Set<String> ignoreProperty) {
@@ -255,7 +254,7 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
                 }
                 continue;
             }
-            Class type = value.getClass();
+            Class<?> type = value.getClass();
             if (simpleTypePredicate.test(type)) {
                 value = simpleConvertBuilder.apply(type).apply(value, null);
                 if (ignoreProperty.contains(entry.getKey())) {
@@ -292,7 +291,7 @@ public class DefaultToStringOperator<T> implements ToStringOperator<T> {
                 if (ToString.Feature.hasFeature(features, ToString.Feature.nullPropertyToEmpty)) {
                     boolean isSimpleType = false;
                     PropertyDescriptor propertyDescriptor = descriptorMap.get(entry.getKey());
-                    Class propertyType = null;
+                    Class<?> propertyType = null;
                     if (propertyDescriptor != null) {
                         propertyType = propertyDescriptor.getPropertyType();
                         isSimpleType = simpleTypePredicate.test(propertyType);

+ 10 - 0
hsweb-core/src/main/java/org/hswebframework/web/validator/ValidatorUtils.java

@@ -17,6 +17,9 @@ public final class ValidatorUtils {
     public static Validator getValidator() {
         if (validator == null) {
             synchronized (ValidatorUtils.class) {
+                if (validator != null) {
+                    return validator;
+                }
                 Configuration<?> configuration = Validation
                         .byDefaultProvider()
                         .configure();
@@ -50,4 +53,11 @@ public final class ValidatorUtils {
         return bean;
     }
 
+    public static <T> void tryValidate(Class<T> bean, String property, Object value, Class<?>... group) {
+        Set<ConstraintViolation<T>> violations = getValidator().validateValue(bean, property, value, group);
+        if (!violations.isEmpty()) {
+            throw new ValidationException(violations);
+        }
+    }
+
 }