前言
平常我们做校验判断的话都是通过传参或者是查库里面是否需要有相关联的校验来判断的。但是当我们系统真正用在很多地方的时候,有些地方他的需求和规定又不是一样的,对此,程序猿们又必须满足客户的一切需求,于是就想到了利用配置的形式来做,代码的话就通过反射得到对应的值,看是否需要校验,这样就满足各位客户爸爸们的要求了。好了,废话不多将,直接将代码和思路吧
配置中心的配置:
这里是可以配置多个的,具体根据情况来定
#新绩效校验
budget.new.goal.check=true
#绩效规则
goal.check.list[0]={"fiscalYears":["2021"],"mofDivCodes":["440000000"],"applyLink":"1","proLevel":"1","proKindCodes":["31","32"],"goalCheck":["kpiTarget"],"indicatorCheck":["kpiRemark","kpiLv3"]}
#绩效规则
goal.check.list[1]={"fiscalYears":["2021"],"mofDivCodes":["440000000"],"applyLink":"1","proLevel":"2","proKindCodes":["31","32"],"goalCheck":["kpiTarget"]}
#绩效规则
goal.check.list[2]={"fiscalYears":["2021"],"mofDivCodes":["440000000"],"applyLink":"1","proLevel":"2","proKindCodes":["332","333"],"goalCheck":["kpiTarget"],"indicatorCheck":["kpiLv3"]}
#绩效规则
goal.check.list[3]={"fiscalYears":["2021"],"mofDivCodes":["440000000"],"applyLink":"2","proLevel":"2","proKindCodes":["332","333"],"goalCheck":["kpiTarget"],"indicatorCheck":["kpiRemark","kpiLv3"]}
#绩效规则
goal.check.list[4]={"fiscalYears":["2021"],"mofDivCodes":["440000000"],"applyLink":"1","proLevel":"2","proKindCodes":["331"],"goalCheck":["kpiTarget"],"indicatorCheck":["kpiLv3"],"bgtAmt":"5000000"}
#绩效规则
goal.check.list[5]={"fiscalYears":["2021"],"mofDivCodes":["440000000"],"applyLink":"2","proLevel":"2","proKindCodes":["331"],"goalCheck":["kpiTarget"],"indicatorCheck":["kpiRemark","kpiLv3"],"bgtAmt":"5000000"}
配置的Java代码:
import com.cqfae.pmo.zhcz.bgt.form.apply.properf.BgtProperfGoalCheckConfigForm;
import com.cqfae.pmo.zhcz.framework.wflow.plugin.base.util.EmptyChecker;
import com.google.gson.Gson;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
*
* @ClassName ProperfGoalCheckConfig
* @Description 主要配置类的代码
* </p>
* @Author Mr.WuJie
* @Date 2020-10-14 18:24
* @Version 1.0
*/
@Data
@Slf4j
@Configuration
// 这个注解意思在Spring容器加载的时候会读取前缀prefix是以goal.check开头的配置,将他的这个配置拿出来进行处理
@ConfigurationProperties(prefix = "goal.check")
public class ProperfGoalCheckConfig {
private List<String> list;
private static Map<String, BgtProperfGoalCheckConfigForm> map = new HashMap<>();
// 这个注解意思是在Spring容器加载的时候就静态的加载出这些配置了,做一个初始化的处理
@PostConstruct
public void init() {
if (EmptyChecker.notEmpty(list)) {
list.forEach(e -> {
log.info(e);
// EmptyChecker.notEmpty()方法的意思是不能空的时候,下面一样
if (EmptyChecker.notEmpty(e)) {
BgtProperfGoalCheckConfigForm config = new Gson().fromJson(e, BgtProperfGoalCheckConfigForm.class);
List<String> proKindCodes = config.getProKindCodes();
List<String> fiscalYears = config.getFiscalYears();
List<String> mofDivCodes = config.getMofDivCodes();
// 这里就是如果需要校验的时候一些必填的判断
if (EmptyChecker.notEmpty(proKindCodes)&&EmptyChecker.notEmpty(fiscalYears)&&EmptyChecker.notEmpty(mofDivCodes)) {
for (String kindCode : proKindCodes) {
for (String mofDivCode : mofDivCodes) {
for (String fiscalYear : fiscalYears) {
String applyLink = config.getApplyLink();
String proLevel = config.getProLevel();
String mapKey = comMapKey(kindCode, applyLink, proLevel,fiscalYear,mofDivCode);
config.setProKindCode(kindCode);
config.setMofDivCode(mofDivCode);
config.setFiscalYear(fiscalYear);
map.put(mapKey, config);
}
}
}
}
}
});
}
}
// 这里就是用-横岗来区分开来的方法
private static String comMapKey(String kindCode, String applyLink, String proLevel,String fiscalYear,String mofDivCode) {
// EmptyChecker.isEmpty()是如果是空的话
if (EmptyChecker.isEmpty(kindCode)) {
kindCode = "-";
}
if (EmptyChecker.isEmpty(applyLink)) {
applyLink = "-";
}
if (EmptyChecker.isEmpty(proLevel)) {
proLevel = "-";
}
if (EmptyChecker.isEmpty(fiscalYear)) {
fiscalYear = "-";
}
if (EmptyChecker.isEmpty(mofDivCode)) {
mofDivCode = "-";
}
StringBuilder buffer = new StringBuilder();
buffer.append(kindCode).append("_").append(applyLink).append("_").append(proLevel).append("_").append(fiscalYear).append("_").append(mofDivCode);
return buffer.toString();
}
public static Map<String, BgtProperfGoalCheckConfigForm> getGoalCheckConfigMap() {
return map;
}
public static BgtProperfGoalCheckConfigForm getGoalCheckConfigForm(String kindCode, String applyLink, String proLevel,String fiscalYear,String mofDivCode) {
String mapKey = comMapKey(kindCode, applyLink, proLevel,fiscalYear,mofDivCode);
return map.get(mapKey);
}
}
下面这个是接收参数的一个form表单值,可以根据不同的情况来自己定义
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public class BgtProperfGoalCheckConfigForm {
/**
* 区划
*/
private String mofDivCode;
/**
* 多区划
*/
private List<String> mofDivCodes;
/**
* 年度
*/
private String fiscalYear;
/**
* 多年度
*/
private List<String> fiscalYears;
/**
* 申报环节
*/
private String applyLink;
/**
* 项目级次
*/
private String proLevel;
/**
* 项目类型
*/
private String proKindCode;
/**
* 项目类型集合
*/
private List<String> proKindCodes;
/**
* 需要校验的目标字段,如果为空,不校验绩效目标
*/
private List<String> goalCheck;
/**
* 需要校验的实施字段,如果为空,不校验绩效实施
*/
private List<String> implPlanCheck;
/**
* 需要校验的实施字段,如果为空,不校验绩效实施
*/
private List<String> indicatorCheck;
/**
* 该字段不为空时,当金额大于该字段才进行校验
*/
private BigDecimal bgtAmt;
}
业务代码处理:
// 读取配置看是否需要校验
private void checkSpendingBudget(List<BgtPmAnnualDO> list) {
Boolean newBudgetGoalCheck = this.bgtLibProperties.getNewBudgetGoalCheck();
for (BgtPmAnnualDO bgtPmAnnualDO : list) {
if(newBudgetGoalCheck){
this.newBudgetGoalCheck(bgtPmAnnualDO);
}
}
}
// 看一些必要的是否有值,没值的话就不做校验
private void newBudgetGoalCheck(BgtPmAnnualDO bgtPmAnnualDO) {
if (EmptyChecker.isEmpty(bgtPmAnnualDO.getApplyLink()) || EmptyChecker.isEmpty(bgtPmAnnualDO.getProLevel()) || EmptyChecker.isEmpty(bgtPmAnnualDO.getProKindCode()) || EmptyChecker.isEmpty(bgtPmAnnualDO.getProCode())) {
return;
}
//获取出配置,如果值为空,则不需要校验
BgtProperfGoalCheckConfigForm checkConfig = ProperfGoalCheckConfig.getGoalCheckConfigForm(bgtPmAnnualDO.getProKindCode(), bgtPmAnnualDO.getApplyLink(), bgtPmAnnualDO.getProLevel(),bgtPmAnnualDO.getFiscalYear(),bgtPmAnnualDO.getMofDivCode());
if(EmptyChecker.isEmpty(checkConfig)){
return;
}
// 这里就是做一些业务查询处理
// ....................................
// 这里就拿到配置里面的值
List<String> implPlanCheck = checkConfig.getImplPlanCheck();
if (EmptyChecker.notEmpty(implPlanCheck)) {
//实施
List<BgtProperfImplPlanDO> bgtProperfImplPlanDOList = this.queryImplPlan(bgtPmAnnualDO);
this.implPlanCheck(implPlanCheck, bgtProperfImplPlanDOList);
}
private void implPlanCheck(List<String> implPlanCheck, List<BgtProperfImplPlanDO> bgtProperfImplPlanDOList) {
if (EmptyChecker.isEmpty(bgtProperfImplPlanDOList)) {
throw new BizException("项目绩效实施计划不能为空");
}
for (BgtProperfImplPlanDO implPlanDO : bgtProperfImplPlanDOList) {
this.check(implPlanCheck,implPlanDO);
}
}
// 核心代码=>通过反射拿到对应字段的,如果需要校验的话没有填写就报错
private void check(List<String> checks ,Object o) {
//反射获取类里字段名称
Set<Field> fields = ReflectionUtils.getAllField(o.getClass());
for (Field field : fields) {
String name = field.getName();
if (checks.contains(name)) {
Object value = ReflectUtil.getFieldValue(o, field.getName());
if (EmptyChecker.isEmpty(value)) {
// 这里有定义一个枚举来获取名字
throw new BizException(GoalCheckEnum.getNameByCode(name) + "不能为空");
}
}
}
}
这就是主要的一些核心业务逻辑处理代码,通过配置和反射的方式来实现这个需求,希望能够帮助到大家,如果小伙伴们有更好的方法或者建议欢迎在评论底下留言,见证大佬们的神奇操作。