判断Bean对象指定字段非空。
方案:
在bean对象上增加注解,指定字段非空,返回异常信息有明确字段描述,省去不必要的if、else判断。
新建注解类
/**
* 参数校验,判断字段非空、返回异常文字(国际化)
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamsAnn {
/**
* 主键标识
*/
boolean primaryKey() default false;
/**
* 不为空属性
*/
boolean isNotNull() default true;
/**
* 字段描述名,可以是中文、英文,可以配置在缓存里面
*/
String colName() default "";
}
BeanHelper工具类,实现非空判断和抛异常
public class BeanHelper {
/**
*
* @Function: com.ai.ruleframe.tools.BeanHelper::validate
* @Description: 根据xxBean对象的字段注解,判断非空并且返回相应的描述(需要支持中英文多语言)
* @param t
* Bean对象
* @return
* @throws Exception
* @version: v1.1.0
* @author: rule_team
* @date: 2019年6月15日 上午10:48:53
*/
public static <T> boolean validate(T t) throws Exception {
// 获取Bean对象中的字段枚举
Field[] fields = t.getClass().getDeclaredFields();
for (Field field : fields) {
// ParamsAnn类型的注解是否在field类上。
if (field.isAnnotationPresent(ParamsAnn.class)) {
ParamsAnn paramsAnn = field.getAnnotation(ParamsAnn.class);
// 主键不校验非空,DAO层会自动补充完整
if (paramsAnn.primaryKey()) {
continue;
}
String colName = field.getName().split("_")[1];// 字段名,首字母大写形式,从xxBean中获取。
if (paramsAnn.isNotNull()) {
Boolean result = true;
Method m = t.getClass().getMethod("get" + colName);
// 如果类型是String
if ("class java.lang.String".equals(m.getGenericReturnType().toString())) { // 如果type是类类型,则前面包含"class ",后面跟类名
// 拿到该属性的get方法
String val = String.valueOf(m.invoke(t));// 调用getter方法获取属性值
if (StringUtils.isEmpty(val) || "null".equalsIgnoreCase(val)) {
result = false;
}
} else if ("long".equals(m.getGenericReturnType().toString())) {
// 如果是long是类型,需要看不能小于注解说明的最小值
Long val = (Long) m.invoke(t);// 调用getter方法获取属性值
if (val <= paramsAnn.minValue()) {
result = false;
}
} else if ("class java.lang.Integer".equals(m.getGenericReturnType().toString())) { // 如果type是类类型,则前面包含"class ",后面跟类名
Integer val = (Integer) m.invoke(t);// 调用getter方法获取属性值
if (val < 0) {
result = false;
}
}
// 校验失败,统一抛出异常
if (!result) {
String colNameDesc = CrmLocaleFactory.getResource(paramsAnn.colName());// 字段名描述,采用国际化方式
// RFS0000017 = {0}[{1}]字段不能为空! -- 例如:SIM卡号[ICC_ID]不能为空!
ExceptionUtil.throwBusinessException("RFS0000017", colNameDesc, colName);// 国际化翻译方法
}
}
}
}
return true;
}
}
JavaBean对象示例
public class BORfKnowledgeBaseBean extends DataContainer implements DataContainerInterface, IBORfKnowledgeBaseValue {
private static String m_boName = "com.ai.ruleframe.mgmt.tenant.bo.BORfKnowledgeBase";
@ParamsAnn(colName = "RFS0010001") // 国际化编码,保存在 BASE.BS_I18N_RESOURCE 中
public final static String S_State = "STATE";
@ParamsAnn(colName = "RFS0010003")
public final static String S_BaseCode = "BASE_CODE";
public final static String S_Remarks = "REMARKS";
@ParamsAnn(colName = "RFS0010005", primaryKey = true)
public final static String S_BaseId = "BASE_ID";
@ParamsAnn(colName = "RFS0010004")
public final static String S_BaseName = "BASE_NAME";
@ParamsAnn(colName = "RFS0010002")
public final static String S_TenantId = "TENANT_ID";
public final static String S_Notes = "NOTES";
// 后面的get、set方法就不贴了。。。
}
验证main方法
public class TestCheckField {
public static void main(String[] args) throws Exception {
// 默认前台传过来的key值和bean对象中字段保持一致,如果不一致,做一个mapping转换。参考吉利给的java内省
Map input = new HashMap();
input.put("TENANT_ID", "1000000000");
input.put("BASE_CODE", "TEST_RULE_4");
input.put("BASE_NAME", "规则引擎测试4");
input.put("NOTES", "规则引擎测试4");
input.put("STATE", "");
input.put("REMARKS", "");
// 直接将入参input转成后台能识别的bean对象
BORfKnowledgeBaseBean bean = PartTool.toBo(input, BORfKnowledgeBaseBean.class);
// 判断关键字段不能为空
BeanWrapper.validate(bean);
// 新增保存方法注释掉
// bean.setStsToNew();
// RfFactory.getIRfKnowledgeBaseDAO().add(bean);// 新增
// return createReturnMap(null, 1, "执行完成", ReturnCode.SUCCESS);
}
}
验证结果
Exception in thread "main" com.ai.common.i18n.BusinessException:
状态[State]字段不能为空!
at com.ai.common.util.ExceptionUtil.throwBusinessException(ExceptionUtil.java:59)
at com.ai.ruleframe.tools.BeanWrapper.validate(BeanWrapper.java:59)
at generatetemp.TestCheckField.main(TestCheckField.java:23)