Browse Source

Merge branch '4.0.x'

zhou-hao 4 years ago
parent
commit
609ccce996
33 changed files with 170 additions and 94 deletions
  1. 3 2
      README.md
  2. 1 1
      hsweb-authorization/hsweb-authorization-api/pom.xml
  3. 1 1
      hsweb-authorization/hsweb-authorization-basic/pom.xml
  4. 1 1
      hsweb-authorization/hsweb-authorization-oauth2/pom.xml
  5. 1 1
      hsweb-authorization/pom.xml
  6. 1 1
      hsweb-commons/hsweb-commons-api/pom.xml
  7. 19 9
      hsweb-commons/hsweb-commons-api/src/main/java/org/hswebframework/web/api/crud/entity/TreeSupportEntity.java
  8. 1 2
      hsweb-commons/hsweb-commons-crud/pom.xml
  9. 24 12
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java
  10. 36 19
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java
  11. 35 18
      hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java
  12. 1 1
      hsweb-commons/pom.xml
  13. 1 2
      hsweb-concurrent/hsweb-concurrent-cache/pom.xml
  14. 1 1
      hsweb-concurrent/pom.xml
  15. 1 1
      hsweb-core/pom.xml
  16. 3 2
      hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java
  17. 1 1
      hsweb-datasource/hsweb-datasource-api/pom.xml
  18. 1 1
      hsweb-datasource/hsweb-datasource-jta/pom.xml
  19. 1 1
      hsweb-datasource/hsweb-datasource-web/pom.xml
  20. 1 1
      hsweb-datasource/pom.xml
  21. 1 1
      hsweb-logging/hsweb-access-logging-aop/pom.xml
  22. 1 1
      hsweb-logging/hsweb-access-logging-api/pom.xml
  23. 1 1
      hsweb-logging/pom.xml
  24. 1 1
      hsweb-starter/pom.xml
  25. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml
  26. 18 4
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java
  27. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml
  28. 1 1
      hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml
  29. 1 1
      hsweb-system/hsweb-system-authorization/pom.xml
  30. 1 1
      hsweb-system/hsweb-system-dictionary/pom.xml
  31. 1 1
      hsweb-system/hsweb-system-file/pom.xml
  32. 1 1
      hsweb-system/pom.xml
  33. 7 1
      pom.xml

+ 3 - 2
README.md

@@ -1,10 +1,11 @@
 # hsweb4 基于spring-boot2,全响应式的后台管理框架
 [![Codecov](https://codecov.io/gh/hs-web/hsweb-framework/branch/4.0.x/graph/badge.svg)](https://codecov.io/gh/hs-web/hsweb-framework/branch/master)
-[![Build Status](https://travis-ci.org/hs-web/hsweb-framework.svg?branch=4.0.x)](https://travis-ci.org/hs-web/hsweb-framework)
+[![Build Status](https://api.travis-ci.com/hs-web/hsweb-framework.svg?branch=4.0.x)](https://travis-ci.
+com/hs-web/hsweb-framework)
 [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html)
 
 # 功能,特性
-- [x] 基于[r2dbc](https://github.com/r2dbc) ,[easy-orm](https://github.com/hs-web/hsweb-easy-orm/tree/4.0.x)的通用响应式CRUD
+- [x] 基于[r2dbc](https://github.com/r2dbc) ,[easy-orm](https://github.com/hs-web/hsweb-easy-orm/tree/4.0.x) 的通用响应式CRUD
     - [x] H2,Mysql,SqlServer,PostgreSQL
 - [x] 响应式r2dbc事务控制
 - [x] 响应式权限控制,以及权限信息获取

+ 1 - 1
hsweb-authorization/hsweb-authorization-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-basic/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/hsweb-authorization-oauth2/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-authorization/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-commons/hsweb-commons-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

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

@@ -20,6 +20,7 @@ package org.hswebframework.web.api.crud.entity;
 
 
 import org.hswebframework.utils.RandomUtil;
+import org.hswebframework.web.exception.ValidationException;
 import org.hswebframework.web.id.IDGenerator;
 import org.springframework.util.CollectionUtils;
 
@@ -49,6 +50,14 @@ public interface TreeSupportEntity<PK> extends Entity {
 
     <T extends TreeSupportEntity<PK>> List<T> getChildren();
 
+    @Override
+    default void tryValidate(Class<?>... groups) {
+        Entity.super.tryValidate(groups);
+        if (getId() != null && Objects.equals(getId(), getParentId())) {
+            throw new ValidationException("parentId", "子节点ID不能与父节点ID相同");
+        }
+    }
+
     /**
      * 根据path获取父节点的path
      *
@@ -180,7 +189,8 @@ public interface TreeSupportEntity<PK> extends Entity {
      * @return 树形结构集合
      */
     static <N extends TreeSupportEntity<PK>, PK> List<N> list2tree(Collection<N> dataList, BiConsumer<N, List<N>> childConsumer) {
-        return list2tree(dataList, childConsumer, (Function<TreeHelper<N, PK>, Predicate<N>>) predicate -> node -> node == null || predicate.getNode(node.getParentId()) == null);
+        return list2tree(dataList, childConsumer, (Function<TreeHelper<N, PK>, Predicate<N>>) predicate -> node -> node == null || predicate
+                .getNode(node.getParentId()) == null);
     }
 
     static <N extends TreeSupportEntity<PK>, PK> List<N> list2tree(Collection<N> dataList,
@@ -211,9 +221,9 @@ public interface TreeSupportEntity<PK> extends Entity {
         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));
+                                                   .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
@@ -228,11 +238,11 @@ public interface TreeSupportEntity<PK> extends Entity {
         });
 
         return streamSupplier.get()
-                //设置每个节点的子节点
-                .peek(node -> childConsumer.accept(node, treeCache.get(node.getId())))
-                //获取根节点
-                .filter(rootNodePredicate)
-                .collect(Collectors.toList());
+                             //设置每个节点的子节点
+                             .peek(node -> childConsumer.accept(node, treeCache.get(node.getId())))
+                             //获取根节点
+                             .filter(rootNodePredicate)
+                             .collect(Collectors.toList());
     }
 
     /**

+ 1 - 2
hsweb-commons/hsweb-commons-crud/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-commons</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -88,7 +88,6 @@
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>28.0-jre</version>
             <scope>test</scope>
         </dependency>
 

+ 24 - 12
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/EasyormRepositoryRegistrar.java

@@ -38,6 +38,14 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
 
     private final MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
 
+    @SneakyThrows
+    private Stream<Resource> doGetResources(String packageStr) {
+        String path = ResourcePatternResolver
+                .CLASSPATH_ALL_URL_PREFIX
+                .concat(packageStr.replace(".", "/")).concat("/**/*.class");
+        return Arrays.stream(resourcePatternResolver.getResources(path));
+    }
+
     @Override
     @SneakyThrows
     @SuppressWarnings("all")
@@ -47,33 +55,36 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
         if (attr == null) {
             return;
         }
-        boolean reactivePrecent = org.springframework.util.ClassUtils.isPresent("io.r2dbc.spi.ConnectionFactory", this.getClass().getClassLoader());
+        boolean reactivePrecent = org.springframework.util.ClassUtils.isPresent("io.r2dbc.spi.ConnectionFactory", this
+                .getClass()
+                .getClassLoader());
         String[] arr = (String[]) attr.get("value");
-        String path = Arrays.stream(arr)
-                .map(str -> ResourcePatternResolver
-                        .CLASSPATH_ALL_URL_PREFIX
-                        .concat(str.replace(".", "/")).concat("/**/*.class"))
-                .collect(Collectors.joining());
+        Set<Resource> resources = Arrays
+                .stream(arr)
+                .flatMap(this::doGetResources)
+                .collect(Collectors.toSet());
 
         Class<Annotation>[] anno = (Class[]) attr.get("annotation");
 
         Set<EntityInfo> entityInfos = new HashSet<>();
 
-        for (Resource resource : resourcePatternResolver.getResources(path)) {
+        for (Resource resource : resources) {
             MetadataReader reader = metadataReaderFactory.getMetadataReader(resource);
             String className = reader.getClassMetadata().getClassName();
-            Class<?> entityType = org.springframework.util.ClassUtils.forName(className,null);
+            Class<?> entityType = org.springframework.util.ClassUtils.forName(className, null);
             if (Arrays.stream(anno)
-                    .noneMatch(ann -> AnnotationUtils.findAnnotation(entityType, ann) != null)) {
+                      .noneMatch(ann -> AnnotationUtils.findAnnotation(entityType, ann) != null)) {
                 continue;
             }
 
             ImplementFor implementFor = AnnotationUtils.findAnnotation(entityType, ImplementFor.class);
             Reactive reactive = AnnotationUtils.findAnnotation(entityType, Reactive.class);
-            Class genericType = Optional.ofNullable(implementFor)
+            Class genericType = Optional
+                    .ofNullable(implementFor)
                     .map(ImplementFor::value)
                     .orElseGet(() -> {
-                        return Stream.of(entityType.getInterfaces())
+                        return Stream
+                                .of(entityType.getInterfaces())
                                 .filter(e -> GenericEntity.class.isAssignableFrom(e))
                                 .findFirst()
                                 .orElse(entityType);
@@ -97,7 +108,8 @@ public class EasyormRepositoryRegistrar implements ImportBeanDefinitionRegistrar
                 idType = implementFor.idType();
             }
 
-            EntityInfo entityInfo = new EntityInfo(genericType, entityType, idType, reactivePrecent && (reactive == null || reactive.enable()));
+            EntityInfo entityInfo = new EntityInfo(genericType, entityType, idType, reactivePrecent && (reactive == null || reactive
+                    .enable()));
             if (!entityInfos.contains(entityInfo) || implementFor != null) {
                 entityInfos.add(entityInfo);
             }

+ 36 - 19
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/service/ReactiveTreeSortEntityService.java

@@ -32,16 +32,16 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
         return query(paramEntity)
                 .collectList()
                 .map(list -> TreeSupportEntity.list2tree(list,
-                        this::setChildren,
-                        this::createRootNodePredicate));
+                                                         this::setChildren,
+                                                         this::createRootNodePredicate));
     }
 
     default Mono<List<E>> queryIncludeChildrenTree(QueryParamEntity paramEntity) {
         return queryIncludeChildren(paramEntity)
                 .collectList()
                 .map(list -> TreeSupportEntity.list2tree(list,
-                        this::setChildren,
-                        this::createRootNodePredicate));
+                                                         this::setChildren,
+                                                         this::createRootNodePredicate));
     }
 
     default Flux<E> queryIncludeChildren(Collection<K> idList) {
@@ -68,11 +68,11 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
     @Override
     default Mono<Integer> insertBatch(Publisher<? extends Collection<E>> entityPublisher) {
         return this.getRepository()
-                .insertBatch(Flux.from(entityPublisher)
-                        .flatMap(Flux::fromIterable)
-                        .flatMap(this::applyTreeProperty)
-                        .flatMap(e -> Flux.fromIterable(TreeSupportEntity.expandTree2List(e, getIDGenerator())))
-                        .collectList());
+                   .insertBatch(Flux.from(entityPublisher)
+                                    .flatMap(Flux::fromIterable)
+                                    .flatMap(this::applyTreeProperty)
+                                    .flatMap(e -> Flux.fromIterable(TreeSupportEntity.expandTree2List(e, getIDGenerator())))
+                                    .collectList());
     }
 
     default Mono<E> applyTreeProperty(E ele) {
@@ -80,25 +80,42 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
                 StringUtils.isEmpty(ele.getParentId())) {
             return Mono.just(ele);
         }
-        return findById(ele.getParentId())
-                .doOnNext(parent -> ele.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4)))
-                .thenReturn(ele);
+
+        return this.checkCyclicDependency(ele.getId(), ele)
+                   .then(this.findById(ele.getParentId())
+                             .doOnNext(parent -> ele.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4))))
+                   .thenReturn(ele);
+    }
+
+    //校验是否有循环依赖,修改父节点为自己的子节点?
+    default Mono<E> checkCyclicDependency(K id, E ele) {
+        if (StringUtils.isEmpty(id)) {
+            return Mono.empty();
+        }
+        return this
+                .queryIncludeChildren(Collections.singletonList(id))
+                .doOnNext(e -> {
+                    if (Objects.equals(ele.getParentId(), e.getId())) {
+                        throw new IllegalArgumentException("不能修改父节点为自己或者自己的子节点");
+                    }
+                })
+                .then(Mono.just(ele));
     }
 
     @Override
     default Mono<SaveResult> save(Publisher<E> entityPublisher) {
         return this.getRepository()
-                .save(Flux.from(entityPublisher)
-                        .flatMap(this::applyTreeProperty)
-                        //把树结构平铺
-                        .flatMap(e -> Flux.fromIterable(TreeSupportEntity.expandTree2List(e, getIDGenerator())))
-                );
+                   .save(Flux.from(entityPublisher)
+                             .flatMap(this::applyTreeProperty)
+                             //把树结构平铺
+                             .flatMap(e -> Flux.fromIterable(TreeSupportEntity.expandTree2List(e, getIDGenerator())))
+                   );
     }
 
     @Override
     default Mono<Integer> updateById(K id, Mono<E> entityPublisher) {
-        return save(entityPublisher
-                .doOnNext(e -> e.setId(id)))
+        return this
+                .save(entityPublisher.doOnNext(e -> e.setId(id)))
                 .map(SaveResult::getTotal);
     }
 

+ 35 - 18
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java

@@ -1,5 +1,7 @@
 package org.hswebframework.web.crud.web;
 
+import io.r2dbc.spi.R2dbcDataIntegrityViolationException;
+import io.r2dbc.spi.R2dbcNonTransientException;
 import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.authorization.exception.AccessDenyException;
 import org.hswebframework.web.authorization.exception.AuthenticationException;
@@ -42,7 +44,7 @@ public class CommonErrorControllerAdvice {
     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
     public Mono<ResponseMessage<Object>> handleException(BusinessException e) {
         return Mono.just(ResponseMessage.error(e.getCode(), e.getMessage()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
     }
 
     @ExceptionHandler
@@ -72,7 +74,8 @@ public class CommonErrorControllerAdvice {
     @ExceptionHandler
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public Mono<ResponseMessage<List<ValidationException.Detail>>> handleException(ValidationException e) {
-        return Mono.just(ResponseMessage.<List<ValidationException.Detail>>error(400, "illegal_argument", e.getMessage()).result(e.getDetails()));
+        return Mono.just(ResponseMessage.<List<ValidationException.Detail>>error(400, "illegal_argument", e.getMessage())
+                                 .result(e.getDetails()));
     }
 
     @ExceptionHandler
@@ -84,7 +87,8 @@ public class CommonErrorControllerAdvice {
     @ExceptionHandler
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public Mono<ResponseMessage<List<ValidationException.Detail>>> handleException(BindException e) {
-        return handleException(new ValidationException(e.getMessage(), e.getBindingResult().getAllErrors()
+        return handleException(new ValidationException(e.getMessage(), e
+                .getBindingResult().getAllErrors()
                 .stream()
                 .filter(FieldError.class::isInstance)
                 .map(FieldError.class::cast)
@@ -95,7 +99,8 @@ public class CommonErrorControllerAdvice {
     @ExceptionHandler
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public Mono<ResponseMessage<List<ValidationException.Detail>>> handleException(WebExchangeBindException e) {
-        return handleException(new ValidationException(e.getMessage(), e.getBindingResult().getAllErrors()
+        return handleException(new ValidationException(e.getMessage(), e
+                .getBindingResult().getAllErrors()
                 .stream()
                 .filter(FieldError.class::isInstance)
                 .map(FieldError.class::cast)
@@ -107,7 +112,8 @@ public class CommonErrorControllerAdvice {
     @ExceptionHandler
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public Mono<ResponseMessage<List<ValidationException.Detail>>> handleException(MethodArgumentNotValidException e) {
-        return handleException(new ValidationException(e.getMessage(), e.getBindingResult().getAllErrors()
+        return handleException(new ValidationException(e.getMessage(), e
+                .getBindingResult().getAllErrors()
                 .stream()
                 .filter(FieldError.class::isInstance)
                 .map(FieldError.class::cast)
@@ -125,7 +131,7 @@ public class CommonErrorControllerAdvice {
     @ResponseStatus(HttpStatus.GATEWAY_TIMEOUT)
     public Mono<ResponseMessage<Object>> handleException(TimeoutException e) {
         return Mono.just(ResponseMessage.error(504, "timeout", e.getMessage()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
 
     }
 
@@ -134,7 +140,7 @@ public class CommonErrorControllerAdvice {
     @Order
     public Mono<ResponseMessage<Object>> handleException(RuntimeException e) {
         return Mono.just(ResponseMessage.error(e.getMessage()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
 
     }
 
@@ -143,14 +149,14 @@ public class CommonErrorControllerAdvice {
     public Mono<ResponseMessage<Object>> handleException(NullPointerException e) {
 
         return Mono.just(ResponseMessage.error(e.getMessage()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
     }
 
     @ExceptionHandler
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public Mono<ResponseMessage<Object>> handleException(IllegalArgumentException e) {
         return Mono.just(ResponseMessage.error(400, "illegal_argument", e.getMessage()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
     }
 
     @ExceptionHandler
@@ -163,29 +169,40 @@ public class CommonErrorControllerAdvice {
     @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
     public Mono<ResponseMessage<Object>> handleException(MediaTypeNotSupportedStatusException e) {
         return Mono.just(ResponseMessage
-                .error(415, "unsupported_media_type", "不支持的请求类型")
-                .result(e.getSupportedMediaTypes()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                                 .error(415, "unsupported_media_type", "不支持的请求类型")
+                                 .result(e.getSupportedMediaTypes()))
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
     }
 
     @ExceptionHandler
     @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
     public Mono<ResponseMessage<Object>> handleException(NotAcceptableStatusException e) {
         return Mono.just(ResponseMessage
-                .error(406, "not_acceptable_media_type", "不支持的响应类型")
-                .result(e.getSupportedMediaTypes()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                                 .error(406, "not_acceptable_media_type", "不支持的响应类型")
+                                 .result(e.getSupportedMediaTypes()))
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
     }
 
     @ExceptionHandler
     @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
     public Mono<ResponseMessage<Object>> handleException(MethodNotAllowedException e) {
         return Mono.just(ResponseMessage
-                .error(405, "method_not_allowed", "不支持的请求方法:" + e.getHttpMethod())
-                .result(e.getSupportedMethods()))
-                .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
+                                 .error(405, "method_not_allowed", "不支持的请求方法:" + e.getHttpMethod())
+                                 .result(e.getSupportedMethods()))
+                   .doOnEach(ReactiveLogger.onNext(r -> log.error(e.getMessage(), e)));
     }
 
+    @ExceptionHandler
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public Mono<ResponseMessage<Object>> handleException(R2dbcDataIntegrityViolationException exception) {
+        if (exception.getMessage().contains("Duplicate")) {
+            return Mono.just(ResponseMessage.error("存在重复的数据"));
+        }
+        log.warn(exception.getMessage(), exception);
+        return Mono.just(ResponseMessage.error("数据错误"));
+    }
+
+
     @ExceptionHandler
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public Mono<ResponseMessage<List<ValidationException.Detail>>> handleException(ServerWebInputException e) {

+ 1 - 1
hsweb-commons/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 2
hsweb-concurrent/hsweb-concurrent-cache/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-concurrent</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -40,7 +40,6 @@
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>28.0-jre</version>
             <optional>true</optional>
         </dependency>
 

+ 1 - 1
hsweb-concurrent/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-core/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 3 - 2
hsweb-core/src/main/java/org/hswebframework/web/bean/FastBeanCopier.java

@@ -17,6 +17,7 @@ import java.beans.PropertyDescriptor;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.function.Supplier;
@@ -29,7 +30,7 @@ import java.util.stream.Stream;
  */
 @Slf4j
 public final class FastBeanCopier {
-    private static final Map<CacheKey, Copier> CACHE = new HashMap<>();
+    private static final Map<CacheKey, Copier> CACHE = new ConcurrentHashMap<>();
 
     private static final PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance().getPropertyUtils();
 
@@ -96,7 +97,7 @@ public final class FastBeanCopier {
     }
 
     public static <T, S> T copy(S source, T target, Converter converter, String... ignore) {
-        return copy(source, target, converter, (ignore == null || ignore.length == 0) ? new java.util.HashSet<>() : new HashSet<>(Arrays.asList(ignore)));
+        return copy(source, target, converter, (ignore == null || ignore.length == 0) ? Collections.emptySet() : new HashSet<>(Arrays.asList(ignore)));
     }
 
     public static <T, S> T copy(S source, T target, Set<String> ignore) {

+ 1 - 1
hsweb-datasource/hsweb-datasource-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-datasource</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-datasource/hsweb-datasource-jta/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-datasource</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
 
     </parent>

+ 1 - 1
hsweb-datasource/hsweb-datasource-web/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-datasource</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-datasource/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
 
         <relativePath>../pom.xml</relativePath>
     </parent>

+ 1 - 1
hsweb-logging/hsweb-access-logging-aop/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-logging</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-logging/hsweb-access-logging-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-logging</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-logging/pom.xml

@@ -23,7 +23,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-starter/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 18 - 4
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-api/src/main/java/org/hswebframework/web/system/authorization/api/entity/DimensionEntity.java

@@ -7,29 +7,43 @@ import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType;
 import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
 import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec;
 import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
+import org.hswebframework.web.validator.CreateGroup;
 
 import javax.persistence.Column;
+import javax.persistence.GeneratedValue;
 import javax.persistence.Index;
 import javax.persistence.Table;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
 import java.sql.JDBCType;
 import java.util.List;
 import java.util.Map;
 
 @Getter
 @Setter
-@Table(name = "s_dimension",indexes = {
-        @Index(name = "idx_dims_path",columnList = "path")
+@Table(name = "s_dimension", indexes = {
+        @Index(name = "idx_dims_path", columnList = "path")
 })
 public class DimensionEntity extends GenericTreeSortSupportEntity<String> {
 
+    @Override
+    @Pattern(
+            regexp = "^[0-9a-zA-Z_\\-]+$",
+            message = "ID只能由数字,字母,下划线和中划线组成",
+            groups = CreateGroup.class)
+    public String getId() {
+        return super.getId();
+    }
+
     @Comment("维度类型ID")
-    @Column(length = 32,name = "type_id")
+    @Column(length = 32, name = "type_id")
     @Schema(description = "维度类型ID")
     private String typeId;
 
     @Comment("维度名称")
     @Column(length = 32)
     @Schema(description = "维度名称")
+    @NotBlank(message = "名称不能为空", groups = CreateGroup.class)
     private String name;
 
     @Comment("描述")
@@ -42,7 +56,7 @@ public class DimensionEntity extends GenericTreeSortSupportEntity<String> {
     @Comment("其他配置")
     @JsonCodec
     @Schema(description = "其他配置")
-    private Map<String,Object> properties;
+    private Map<String, Object> properties;
 
     @Schema(description = "子节点")
     private List<DimensionEntity> children;

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-default/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-authorization/hsweb-system-authorization-oauth2/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system-authorization</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
hsweb-system/hsweb-system-authorization/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>

+ 1 - 1
hsweb-system/hsweb-system-dictionary/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/hsweb-system-file/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-system</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
hsweb-system/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>hsweb-framework</artifactId>
         <groupId>org.hswebframework.web</groupId>
-        <version>4.0.9</version>
+        <version>4.0.10-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 7 - 1
pom.xml

@@ -24,7 +24,7 @@
 
     <groupId>org.hswebframework.web</groupId>
     <artifactId>hsweb-framework</artifactId>
-    <version>4.0.9</version>
+    <version>4.0.10-SNAPSHOT</version>
     <modules>
         <module>hsweb-starter</module>
         <module>hsweb-core</module>
@@ -338,6 +338,12 @@
                 <version>1.0.2.Final</version>
             </dependency>
 
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>30.1.1-jre</version>
+            </dependency>
+
             <dependency>
                 <groupId>io.vavr</groupId>
                 <artifactId>vavr</artifactId>