[TOC]
本文目的
使用反射在SpringBoot中对多个校验接口进行统一操作
反射
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
使用场景
项目那个有多个校验接口:比如身份证校验,手机号校验等,如果每个都对该次校验写一个校验方法,如果后期又出现其他组合的校验,最后会很繁琐,代码冗余,难以维护。那么这里使用反射对每个校验方法进行统一的操作,根据请求操作来判断使用那几个组合的校验方法。后期如果有新的校验添加起来也就很方便,容易维护。
实现代码
服务层校验类
代码语言:javascript复制public interface BlackValidateService {
/**
* @Description: 根据手机号判断是否在黑名单中
* @param phone
* @return com.p4.risk.entity.RiskRetCode
* @author Surpass
* @date 2020/12/2 13:56
*/
RiskRetCode getPhone(String phone);
/**
* @Description: 根据身份证号判断是否在黑名单中
* @param idCardNum
* @return com.p4.risk.entity.RiskRetCode
* @author Surpass
* @date 2020/12/2 13:56
*/
RiskRetCode getIdCardNum(String idCardNum);
/**
* @Description: 根据终端号判断是否在黑名单中
* @param termNo
* @return com.p4.risk.entity.RiskRetCode
* @author Surpass
* @date 2020/12/2 13:56
*/
RiskRetCode getTermNo(String termNo);
/**
* @Description: 根据银行卡号判断是否在黑名单中
* @param cardNum
* @return com.p4.risk.entity.RiskRetCode
* @author Surpass
* @date 2020/12/2 13:57
*/
RiskRetCode getCardNum(String cardNum);
/**
* @Description: 根据营业执照号判断是否在黑名单中
* @param busLicenseNo
* @return com.p4.risk.entity.RiskRetCode
* @author Surpass
* @date 2020/12/2 13:57
*/
RiskRetCode getBusLicenseNo(String busLicenseNo);
/**
* @Description: 根据基站号,小区号判断是否在黑名单中
* @param stationNo
* @param cellId
* @return com.p4.risk.entity.RiskRetCode
* @author Surpass
* @date 2020/12/2 13:57
*/
RiskRetCode getBaseStation(String stationNo, String cellId);
}
说明:返回值类型是一个枚举类,返回键值对数据像00、99之类的,实现类就是校验逻辑了,接口方法统一使用“get 请求参数(首字母大写)”。特殊的是最后一个有两个参数,在控制器中会特殊处理,后面接着看。
反射实现控制器
代码语言:javascript复制@Slf4j
@RestController
@RequestMapping("/mposDataValidate")
public class MposDataValidateController {
/**
* mpos黑名单校验方法
*/
@Autowired
private BlackValidateService validate;
private Gson gson = new Gson();
/**
* @Description: 利用反射将黑名单方法和参数进行绑定,根据参数key不同来查询不同的黑名单
* @param param 需要校验的参数:idCardNum,termNo,cardNum,busLicenseNo,stationNo,cellId,phone
* @return java.util.Map<java.lang.String , java.lang.Object>
* @author Surpass
* @date 2020/12/2 13:22
*/
@RequestMapping("/dataValidator")
public Map<String,Object> dataValidator(@RequestBody Map<String,Object> param){
log.info("mpos外放接口调用,校验黑名单传入参数:" gson.toJson(param));
Map<String, Object> resultMap = new HashMap<>(2);
if (param.size() == 0){
resultMap.put("rspCode","99");
resultMap.put("rspMsg","接口数据参数为空");
log.info("接口数据参数为空");
return resultMap;
}
try {
//基站号参数key
String stationNo = "stationNo";
//小区号参数key
String cellId = "cellId";
//基站黑名单方法名
String baseStationMethodName = "getBaseStation";
//基站号参数value
String stationNoVal = null;
//小区号参数value
String cellIdVal = null;
RiskRetCode result = null;
//获得接口校验的class类对象
Class<BlackValidateService> cls = BlackValidateService.class;
//遍历参数
for (Map.Entry<String, Object> entry : param.entrySet()) {
String key = entry.getKey();
String value = (String) entry.getValue();
if (StringUtils.isBlank(value)){
continue;
}
//基站信息特殊处理
if ((stationNo).equals(key)){
stationNoVal = value;
continue;
}
if ((cellId).equals(key)){
cellIdVal = value;
continue;
}
//根据参数key获取方法名 getPhone...
String methodsName = "get" key.substring(0,1).toUpperCase() key.substring(1);
//根据方法名和方法参数确定某一个方法
Method method = cls.getMethod(methodsName, String.class);
//执行,对方法进行访问赋值
result = (RiskRetCode)method.invoke(validate, value);
if (Objects.equals(result.getValue(), RiskRetCode.R00.getValue())){
//校验通过,进行下一个 00通过
resultMap.put("rspCode",RiskRetCode.R00.getValue());
resultMap.put("rspMsg",result.getDesc());
continue;
}else {
//在黑名单中,直接返回 99不通过
resultMap.put("rspCode",RiskRetCode.R99.getValue());
resultMap.put("rspMsg",result.getDesc());
return resultMap;
}
}
//基站需要基站号和小区号
if (StringUtils.isNotEmpty(stationNoVal) && StringUtils.isNotEmpty(cellIdVal)){
//根据方法名和方法参数确定某一个方法
Method method = cls.getMethod(baseStationMethodName, String.class, String.class);
//执行,对方法进行访问赋值
result = (RiskRetCode)method.invoke(validate, stationNoVal,cellIdVal);
}
if (Objects.equals(result.getValue(), RiskRetCode.R00.getValue())){
resultMap.put("rspCode",RiskRetCode.R00.getValue());
resultMap.put("rspMsg",result.getDesc());
}else {
resultMap.put("rspCode",RiskRetCode.R99.getValue());
resultMap.put("rspMsg",result.getDesc());
return resultMap;
}
}catch (Exception e){
log.error("mpos外放接口黑名单校验异常",e);
resultMap.put("rspCode",RiskRetCode.R99.getValue());
resultMap.put("rspMsg","mpos外放接口黑名单校验异常");
return resultMap;
}
if (resultMap.size() == 0){
resultMap.put("rspCode", RiskRetCode.R99.getValue());
resultMap.put("rspMsg", "本次请求没有过任何黑名单接口");
}
log.info("mpos外放接口调用,校验黑名单返回参数:" gson.toJson(resultMap));
return resultMap;
}
}
说明:每一个接口校验都会通过参数来判断,特别的基站则需要基站小区两个都存在才会去校验,那么只需要单独判断一下就可以。代码注释还是比较详细的。
尾言
其实当时博主是没有想到使用反射来做的,当收到任务时只想到了怎么if()if()的,哈哈哈,还是大佬告诉我,怎么轻巧,怎么统一,才想到能够这个样子做的,觉得眼光短浅,只注重了眼前,所以接到任务还是需要多思考思考,多回顾回顾,这样子才能成长,一起加油吧!