feat:提出公共审查

This commit is contained in:
wangyu 2022-01-08 09:44:48 +08:00
parent a68ac80b4d
commit 9ebfb2cb49
11 changed files with 167 additions and 35 deletions

View File

@ -0,0 +1,9 @@
package com.flyfish.framework.validation.groups;
/**
* 公共校验可被策略忽略
*
* @author wangyu
*/
public interface CodeValid {
}

View File

@ -0,0 +1,9 @@
package com.flyfish.framework.validation.groups;
/**
* 公共校验可被策略忽略
*
* @author wangyu
*/
public interface NameValid {
}

View File

@ -9,6 +9,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 指定动态分组
*
* @author wangyu
*/
@Target({TYPE})
@ -16,5 +17,24 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
public @interface ConditionalGroup {
/**
* 自定义验证分组提供者
*
* @return 结果
*/
Class<? extends ConditionalValidGroupProvider<?>>[] value() default {};
/**
* 是否不验证编码
*
* @return 结果
*/
boolean codeless() default false;
/**
* 是否不验证名称
*
* @return 结果
*/
boolean nameless() default false;
}

View File

@ -0,0 +1,26 @@
package com.flyfish.framework.auditor;
import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.generation.CodeRules;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@Component
public class CommonBeanAuditor implements BeanAuditor<Domain> {
/**
* 对实体进行审查并补全相关字段
*
* @param data 原数据
*/
@Override
public void audit(Domain data) {
// 编码审查自动生成
if (StringUtils.isBlank(data.getId()) && StringUtils.isBlank(data.getCode())) {
String ruledCode = CodeRules.get(data);
if (null != ruledCode) {
data.setCode(ruledCode);
}
}
}
}

View File

@ -0,0 +1,36 @@
package com.flyfish.framework.auditor;
import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.generation.CodeRules;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
/**
* 异步公共审查
*
* @author wangyu
*/
@Component
public class ReactiveCommonBeanAuditor implements ReactiveBeanAuditor<Domain> {
/**
* 对实体进行审查并补全相关字段
*
* @param data 原数据
* @return 结果
*/
@Override
public Mono<Domain> audit(Domain data) {
// 编码审查自动生成
if (StringUtils.isBlank(data.getId()) && StringUtils.isBlank(data.getCode())) {
return CodeRules.retrieve(data)
.map(code -> {
data.setCode(code);
return data;
})
.thenReturn(data);
}
return Mono.just(data);
}
}

View File

@ -3,11 +3,10 @@ package com.flyfish.framework.domain.base;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.flyfish.framework.annotations.Generation;
import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.generation.CodeRules;
import lombok.AccessLevel;
import com.flyfish.framework.validation.groups.CodeValid;
import com.flyfish.framework.validation.groups.NameValid;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.index.Indexed;
@ -34,9 +33,8 @@ public abstract class Domain implements Po, Named, Serializable {
* 编号
*/
@Property(title = "编码", inherited = true)
@NotBlank(message = "编码不可为空")
@NotBlank(message = "编码不可为空", groups = CodeValid.class)
@Generation(Generation.Strategy.CODE)
@Getter(AccessLevel.NONE)
protected String code;
/**
@ -44,7 +42,7 @@ public abstract class Domain implements Po, Named, Serializable {
*/
@Indexed
@Property(title = "名称", inherited = true)
@NotBlank(message = "名称不可为空")
@NotBlank(message = "名称不可为空", groups = NameValid.class)
@Generation(Generation.Strategy.NAME)
protected String name;
@ -56,18 +54,6 @@ public abstract class Domain implements Po, Named, Serializable {
@Property(readonly = true)
private IUser currentUser;
/**
* 自动生成code环节
*
* @return 结果
*/
public String getCode() {
if (StringUtils.isBlank(id) && StringUtils.isBlank(code)) {
code = CodeRules.getCode(this);
}
return code;
}
@Override
public int hashCode() {
if (id != null) {

View File

@ -1,6 +1,7 @@
package com.flyfish.framework.generation;
import com.flyfish.framework.domain.base.Domain;
import reactor.core.publisher.Mono;
/**
* 代码规则策略
@ -16,4 +17,14 @@ public interface CodeRuleStrategy {
* @return 结果
*/
String generate(Domain domain);
/**
* 异步方式支持异步请求
*
* @param domain 实体
* @return 结果
*/
default Mono<String> retrieve(Domain domain) {
return Mono.just(generate(domain));
}
}

View File

@ -5,7 +5,7 @@ import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.generation.strategy.TransactionCodeRuleStrategy;
import com.flyfish.framework.generation.strategy.UUIDCodeRuleStrategy;
import com.flyfish.framework.utils.ReflectionUtils;
import org.apache.commons.lang3.StringUtils;
import reactor.core.publisher.Mono;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -32,12 +32,27 @@ public interface CodeRules {
* @param instance 实体
* @return 结果
*/
static String getCode(Domain instance) {
static String get(Domain instance) {
CodeRule rule = instance.getClass().getAnnotation(CodeRule.class);
if (null != rule && StringUtils.isBlank(instance.getId())) {
if (null != rule) {
CodeRuleStrategy strategy = strategies.computeIfAbsent(rule.value(), ReflectionUtils::instantiate);
return strategy.generate(instance);
}
return null;
}
/**
* 异步获取code
*
* @param instance 实体
* @return 结果
*/
static Mono<String> retrieve(Domain instance) {
CodeRule rule = instance.getClass().getAnnotation(CodeRule.class);
if (null != rule) {
CodeRuleStrategy strategy = strategies.computeIfAbsent(rule.value(), ReflectionUtils::instantiate);
return strategy.retrieve(instance);
}
return Mono.empty();
}
}

View File

@ -1,6 +1,8 @@
package com.flyfish.framework.configuration.resolver;
import com.flyfish.framework.configuration.annotations.ValidRequestBody;
import com.flyfish.framework.validation.groups.CodeValid;
import com.flyfish.framework.validation.groups.NameValid;
import com.flyfish.framework.validation.spi.ConditionalGroup;
import com.flyfish.framework.validation.spi.ConditionalValidGroupProvider;
import org.apache.commons.collections4.CollectionUtils;
@ -30,7 +32,6 @@ import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.validation.groups.Default;
import java.util.*;
import java.util.stream.Collectors;
@ -153,17 +154,27 @@ public class ValidRequestBodyMethodArgumentResolver extends AbstractMessageReade
@NonNull
private Object[] extractValidationHints(Object target) {
ConditionalGroup group = AnnotationUtils.findAnnotation(target.getClass(), ConditionalGroup.class);
if (null != group && ArrayUtils.isNotEmpty(group.value())) {
List<Class<?>> groups = new ArrayList<>();
for (Class<? extends ConditionalValidGroupProvider<?>> clazz : group.value()) {
try {
groups.addAll(Arrays.asList(clazz.newInstance().provide(CastUtils.cast(target))));
} catch (InstantiationException | IllegalAccessException ignored) {
List<Class<?>> groups = new ArrayList<>();
if (null != group) {
if (!group.codeless()) {
groups.add(CodeValid.class);
}
if (!group.nameless()) {
groups.add(NameValid.class);
}
if (ArrayUtils.isNotEmpty(group.value())) {
for (Class<? extends ConditionalValidGroupProvider<?>> clazz : group.value()) {
try {
groups.addAll(Arrays.asList(clazz.newInstance().provide(CastUtils.cast(target))));
} catch (InstantiationException | IllegalAccessException ignored) {
}
}
}
if (CollectionUtils.isNotEmpty(groups)) {
return groups.toArray();
}
} else {
groups = Arrays.asList(CodeValid.class, NameValid.class);
}
if (CollectionUtils.isNotEmpty(groups)) {
return groups.toArray();
}
return new Object[]{};
}

View File

@ -44,6 +44,8 @@ public class BaseReactiveServiceImpl<T extends Domain> implements BaseReactiveSe
@Autowired(required = false)
protected ReactiveBeanPoster<T> poster;
@Autowired
private ReactiveBeanAuditor<Domain> commonAuditor;
@Autowired
private ReactiveBeanAuditor<AuditDomain> operationAuditor;
@Autowired
private ReactiveBeanAuditor<AuthorizedDomain> authorizeAuditor;
@ -373,19 +375,22 @@ public class BaseReactiveServiceImpl<T extends Domain> implements BaseReactiveSe
*
* @param entity 实体
*/
@SuppressWarnings("unchecked")
protected Mono<T> audit(T entity) {
Mono<T> mono = Mono.just(entity);
// 首先自定义审查可能返回自定义对象
if (auditor != null) {
mono = mono.flatMap(auditor::audit);
}
// 操作信息审查
// 然后公共审查
mono = (Mono<T>) mono.flatMap(commonAuditor::audit);
// 接着操作信息审查
if (entity instanceof AuditDomain) {
mono = CastUtils.cast(mono.cast(AuditDomain.class).flatMap(operationAuditor::audit));
mono = (Mono<T>) mono.cast(AuditDomain.class).flatMap(operationAuditor::audit);
}
// 权限审查
// 最后权限审查
if (entity instanceof AuthorizedDomain) {
mono = CastUtils.cast(mono.cast(AuthorizedDomain.class).flatMap(authorizeAuditor::audit));
mono = (Mono<T>) mono.cast(AuthorizedDomain.class).flatMap(authorizeAuditor::audit);
}
return mono;
}

View File

@ -35,6 +35,8 @@ public class BaseServiceImpl<T extends Domain> implements BaseService<T> {
@Autowired(required = false)
protected BeanPoster<T> poster;
@Autowired
private BeanAuditor<Domain> commonAuditor;
@Autowired
private BeanAuditor<AuditDomain> operationAuditor;
@Autowired
private BeanAuditor<AuthorizedDomain> authorizeAuditor;
@ -348,6 +350,8 @@ public class BaseServiceImpl<T extends Domain> implements BaseService<T> {
if (auditor != null) {
auditor.audit(entity);
}
// 公共审查
commonAuditor.audit(entity);
// 用户审查
if (entity instanceof AuditDomain) {
operationAuditor.audit((AuditDomain) entity);