一、應用場景
上游通過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;
}
}