最近博主在做的就是把TR系统所有对接APP接口的返回信息进行拦截做国际化处理,尝试用自定义注解对需要校验的Controller方法进行拦截,根据这些参数确定唯一资源,通过对接口返回的参数进行拦截,根据返回的错误码获取文案系统中配置的文案信息返回消息提示给前端。
定义切点,自定义一个名为ParameterIntHandler的注解
/**
* @Author: zengxin
* APP固定格式的响应
* @Date: 2019/11/26
*/
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParameterIntHandler {
}
定义切面,利用环绕通知进行方法拦截和校验逻辑处理
我这里是针对异常也做了处理,通过捕获不同异常类型对返回的参数errorCode进行国际化处理。
@Pointcut("@annotation(com.jd.overseas.hkbank.sme.core.aop.ParameterIntHandler)")
public void validate() {}
@Around("validate()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
String language = "";
try {
Object str = proceedingJoinPoint.proceed();//获取返回信息
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
LOGGER.info("拦截到请求url:{}",request.getRequestURI().toString());
Object[] args = proceedingJoinPoint.getArgs();
for (Object requestObject : args) {
if (requestObject instanceof RpcRequest) {
RpcRequest rpcRequest = ((RpcRequest) requestObject);
language = rpcRequest.getLanguage();//语言种类
}
}
//转换为APP通用格式
CommonResponseModel result = (CommonResponseModel)str;
String resultCode = result.getResultCode();//响应code
LOGGER.info("语言类型:{}",language);
//返回失败并且语种不为空,否则按原信息返回
if (!resultCode.equals(Constants.APP_SUCCESS_CODE) && StringUtils.isNotEmpty(language)) {
CommonErrorData errorData = result.getErrorData();
String code =result.getErrorData().getCode();//错误码
LOGGER.info("====待转码的msg====,{}",errorData.getMsg());
String newMsg = MessageUtil.convertByLang(code, language);
LOGGER.info("====转码成功newMsg====,{}",newMsg);
errorData.setMsg(newMsg);
}
return result;
} catch (Throwable e) {
LOGGER.error("对不同异常拦截信息处理!");
//根据错误信息组装文案信息
return dealExceptionResult(e,language);
}
}
/***
* 针对不同异常进行拦截替换
* */
private Object dealExceptionResult(Throwable e, String language) {
CommonResponseModel result = new CommonResponseModel();
CommonErrorData commonErrorData = new CommonErrorData();
try {
if (e instanceof BusinessException) {//业务异常错误码处理
BusinessException businessException = (BusinessException) e;
//组装参数
commonErrorData.setCode(businessException.getCode());
commonErrorData.setMsg(MessageUtil.convertByLang(businessException.getCode(), language));
result.setErrorData(commonErrorData);
result.setResultCode("0");
return result;
} else if (e instanceof PersistentException) {//持久层异常错误码处理
PersistentException persistentException = (PersistentException) e;
//组装参数
commonErrorData.setCode(persistentException.getCode());
commonErrorData.setMsg(MessageUtil.convertByLang(persistentException.getCode(), language));
result.setErrorData(commonErrorData);
result.setResultCode("0");
return result;
} else {//其他异常 统一返回error
return baseController.buildCommonResponseModel(JSFResultFactory.getRpcResponse(JSFCodeEnum.ERROR));
}
} catch (Throwable e1) {//统一返回error
return baseController.buildCommonResponseModel(JSFResultFactory.getRpcResponse(JSFCodeEnum.ERROR));
}
}
**这边使用的异常是内部封装一些异常,所以能根据不同异常获取到不同的错误码进行国际化处理。**
/**
* 持久层异常
*
* @author zhangzuizui
*/
public class PersistentException extends AbstractSystemException {
private static final long serialVersionUID = 6643482569602370581L;
public PersistentException(JSFCodeEnum codeEnum) {
super(codeEnum.getCode(),codeEnum.getI18NMessage());
}
}
/**
* 业务异常
* @author zhangzuizui
*/
public class BusinessException extends AbstractSystemException {
private static final long serialVersionUID = 6643482569602370581L;
public BusinessException(JSFCodeEnum codeEnum) {
super(codeEnum.getCode(),codeEnum.getI18NMessage());
}
public BusinessException(String code, String msg) {
super(code, msg);
}
**
**
使用方法
在需要拦截的方法上面加上注解即可
@ResponseBody
@RequestMapping("/hello")
@ParameterIntHandler
public Object hello(HttpServletRequest request) {
return "hello world";
}
*总结:使用自定义注解作为切面拦截,可以更加灵活的指定某些方法做拦截处理。
**