mirror of
https://github.com/hs-web/hsweb-framework.git
synced 2026-06-03 11:24:34 +08:00
Merge branch '4.0.x'
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
# hsweb4 基于spring-boot2,全响应式的后台管理框架
|
||||
[](https://codecov.io/gh/hs-web/hsweb-framework/branch/master)
|
||||
[](https://travis-ci.org/hs-web/hsweb-framework)
|
||||
[](https://travis-ci.
|
||||
com/hs-web/hsweb-framework)
|
||||
[](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] 响应式权限控制,以及权限信息获取
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
8
pom.xml
8
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>
|
||||
|
||||
Reference in New Issue
Block a user