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 * @author wangyu
*/ */
@Target({TYPE}) @Target({TYPE})
@ -16,5 +17,24 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented @Documented
public @interface ConditionalGroup { public @interface ConditionalGroup {
/**
* 自定义验证分组提供者
*
* @return 结果
*/
Class<? extends ConditionalValidGroupProvider<?>>[] value() default {}; 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.fasterxml.jackson.annotation.JsonIgnore;
import com.flyfish.framework.annotations.Generation; import com.flyfish.framework.annotations.Generation;
import com.flyfish.framework.annotations.Property; import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.generation.CodeRules; import com.flyfish.framework.validation.groups.CodeValid;
import lombok.AccessLevel; import com.flyfish.framework.validation.groups.NameValid;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient; import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.index.Indexed;
@ -34,9 +33,8 @@ public abstract class Domain implements Po, Named, Serializable {
* 编号 * 编号
*/ */
@Property(title = "编码", inherited = true) @Property(title = "编码", inherited = true)
@NotBlank(message = "编码不可为空") @NotBlank(message = "编码不可为空", groups = CodeValid.class)
@Generation(Generation.Strategy.CODE) @Generation(Generation.Strategy.CODE)
@Getter(AccessLevel.NONE)
protected String code; protected String code;
/** /**
@ -44,7 +42,7 @@ public abstract class Domain implements Po, Named, Serializable {
*/ */
@Indexed @Indexed
@Property(title = "名称", inherited = true) @Property(title = "名称", inherited = true)
@NotBlank(message = "名称不可为空") @NotBlank(message = "名称不可为空", groups = NameValid.class)
@Generation(Generation.Strategy.NAME) @Generation(Generation.Strategy.NAME)
protected String name; protected String name;
@ -56,18 +54,6 @@ public abstract class Domain implements Po, Named, Serializable {
@Property(readonly = true) @Property(readonly = true)
private IUser currentUser; private IUser currentUser;
/**
* 自动生成code环节
*
* @return 结果
*/
public String getCode() {
if (StringUtils.isBlank(id) && StringUtils.isBlank(code)) {
code = CodeRules.getCode(this);
}
return code;
}
@Override @Override
public int hashCode() { public int hashCode() {
if (id != null) { if (id != null) {

View File

@ -1,6 +1,7 @@
package com.flyfish.framework.generation; package com.flyfish.framework.generation;
import com.flyfish.framework.domain.base.Domain; import com.flyfish.framework.domain.base.Domain;
import reactor.core.publisher.Mono;
/** /**
* 代码规则策略 * 代码规则策略
@ -16,4 +17,14 @@ public interface CodeRuleStrategy {
* @return 结果 * @return 结果
*/ */
String generate(Domain domain); 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.TransactionCodeRuleStrategy;
import com.flyfish.framework.generation.strategy.UUIDCodeRuleStrategy; import com.flyfish.framework.generation.strategy.UUIDCodeRuleStrategy;
import com.flyfish.framework.utils.ReflectionUtils; import com.flyfish.framework.utils.ReflectionUtils;
import org.apache.commons.lang3.StringUtils; import reactor.core.publisher.Mono;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -32,12 +32,27 @@ public interface CodeRules {
* @param instance 实体 * @param instance 实体
* @return 结果 * @return 结果
*/ */
static String getCode(Domain instance) { static String get(Domain instance) {
CodeRule rule = instance.getClass().getAnnotation(CodeRule.class); 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); CodeRuleStrategy strategy = strategies.computeIfAbsent(rule.value(), ReflectionUtils::instantiate);
return strategy.generate(instance); return strategy.generate(instance);
} }
return null; 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; package com.flyfish.framework.configuration.resolver;
import com.flyfish.framework.configuration.annotations.ValidRequestBody; 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.ConditionalGroup;
import com.flyfish.framework.validation.spi.ConditionalValidGroupProvider; import com.flyfish.framework.validation.spi.ConditionalValidGroupProvider;
import org.apache.commons.collections4.CollectionUtils; 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.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import javax.validation.groups.Default;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -153,17 +154,27 @@ public class ValidRequestBodyMethodArgumentResolver extends AbstractMessageReade
@NonNull @NonNull
private Object[] extractValidationHints(Object target) { private Object[] extractValidationHints(Object target) {
ConditionalGroup group = AnnotationUtils.findAnnotation(target.getClass(), ConditionalGroup.class); ConditionalGroup group = AnnotationUtils.findAnnotation(target.getClass(), ConditionalGroup.class);
if (null != group && ArrayUtils.isNotEmpty(group.value())) { List<Class<?>> groups = new ArrayList<>();
List<Class<?>> groups = new ArrayList<>(); if (null != group) {
for (Class<? extends ConditionalValidGroupProvider<?>> clazz : group.value()) { if (!group.codeless()) {
try { groups.add(CodeValid.class);
groups.addAll(Arrays.asList(clazz.newInstance().provide(CastUtils.cast(target)))); }
} catch (InstantiationException | IllegalAccessException ignored) { 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)) { } else {
return groups.toArray(); groups = Arrays.asList(CodeValid.class, NameValid.class);
} }
if (CollectionUtils.isNotEmpty(groups)) {
return groups.toArray();
} }
return new Object[]{}; return new Object[]{};
} }

View File

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

View File

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