一、应用场景
上游通过RPC调用我们的系统,我们首先通过API层受理,然后API层调用BIZ层处理业务逻辑。
二、受理接口步骤
1、参数转换
将Map<String, Object>类型的入参转为我们接口文档定好的对象,通常使用fastJson来处理。
FridsUserLoginInfoDto dto = JSON.parseObject(JSON.toJSONString(params), FridsUserLoginInfoDto.class);
2、参数校验
通常使用javax.validation包来校验入参是否为空,长度校验等,在属性上加上注解,如下所示。
@NotBlank(message = "手机号不能为空")
@Length(max = 16, message = "手机号超过最大长度")
private String phoneNo;
使用javax.validation包
//参数校验
validator.validateUserActionOperation(dto);
public void validateUserActionOperation(FridsUserLoginInfoDto dto) {
LOGGER.debug("validateUserActionOperation start, dto:{}", dto);
//校验公共数据
Set<ConstraintViolation<FridsUserLoginInfoDto>> validate = validator.validate(dto);
Map<String, String> messageMap = BeanValidators.extractPropertyAndMessage(validate);
if (MapUtils.isNotEmpty(messageMap)) {
LOGGER.error("会员号:{},手机号:{},操作类型:{}的操作下发失败,失败原因为{}",
dto.getUserNo(), dto.getPhoneNo(), dto.getOperationType(), messageMap.toString());
throw new AppException(CoreErrorCode.REQUEST_PARAM_VALIDATION_FALIURE, messageMap.toString());
}
LOGGER.debug("validateUserActionOperation end");
}
3、代码逻辑
校验完就可以写代码逻辑处理业务了。
4、异常处理
针对异常,向上反馈。
try {
//业务逻辑
}
} catch (AppException app) {
result.fail(app.getErrorCode(), app.getMessage());
LOGGER.error("fundOperationAccept AppException:{}", app);
} catch (Exception e) {
result.fail(ReturnCode.HANDLE_FAILE, ReturnCode.HANDLE_FAILE_CN);
LOGGER.error("fundOperationAccept Exception:{}", e);
}
三、代码实例:
public DecisionResponse fundOperationAccept(Map<String, Object> params) {
DecisionResponse result = new DecisionResponse();
//参数转换
FridsUserLoginInfoDto dto = JSON.parseObject(JSON.toJSONString(params), FridsUserLoginInfoDto.class);
LOGGER.info("fundOperationAccept start, dto:{}", dto);
//参数校验
validator.validateUserActionOperation(dto);
FridsUserLoginInfo dmo = RequestConvert.packageUserLoginInfoDtoToDmo(dto);
try {
//业务逻辑
}
} catch (AppException app) {
result.fail(app.getErrorCode(), app.getMessage());
LOGGER.error("fundOperationAccept AppException:{}", app);
} catch (Exception e) {
result.fail(ReturnCode.HANDLE_FAILE, ReturnCode.HANDLE_FAILE_CN);
LOGGER.error("fundOperationAccept Exception:{}", e);
}
return result;
}
四、Validator工具类:
用于处理校验结果的类型转换:
public class BeanValidators {
/**
* 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException, 而不是返回constraintViolations.
*/
public static void validateWithException(Validator validator, Object object, Class<?>... groups)
throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>.
*/
public static List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<message>
*/
public static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = new ArrayList<String>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property, message>.
*/
public static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>.
*/
public static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = new HashMap<String, String>(CommonConstants.INITIAL_CAPACITY);
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}
/**
* 辅助方法, 转换Set<ConstraintViolations>为List<propertyPath message>.
*/
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath + separator + message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<propertyPath + separator + message>.
*/
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations,
String separator) {
List<String> errorMessages = new ArrayList<String>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
return errorMessages;
}
}