使用java开发没多久,对java体系的一些东西还不太熟悉。在项目开发过程中发现dubbo接口每个方法里都有一个try-catch的判断,都是一些重复性的工作,就想着能不能统一处理这些异常,找了一些资料果然可以,下面总结一下了解到的两种dubbo接口统一异常处理的方法方便以后查阅:
第一种方法:dubbo提供了Filter接口,我们只需继承Filter接口实现invoke方法即可。
1、实现Filter接口,实现invoke方法
1 @Activate(group = Constants.PROVIDER) 2 public class ExceptionFilter implements Filter { 3 private static final Logger logger = LogManager.getLogger(ExceptionFilter.class); 4 5 public Result invoke(Invoker<?> invoker, Invocation invocation) { 6 Result result = null; 7 try { 8 result = invoker.invoke(invocation); 9 if (result.hasException() && GenericService.class != invoker.getInterface()) { 10 Throwable exception = result.getException(); 11 String data = String.format(" [level]:Error,[createTime]:%s,[platform]:%s,[serviceName]:%s,[methodName]:%s,[inputParam]:%s", DateUtil.formatDateTime(new Date()), PlatformNameEnum.PAY, invoker.getInterface().getName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments())); 12 logger.error(data, exception); 13 ResultVo resultVo = new ResultVo(false); 14 resultVo.setResultCode(PayCenterErrorCodeEnum.PAY_ERR_100000.getCode()); 15 resultVo.setResultMessage(PayCenterErrorCodeEnum.PAY_ERR_100000.getMsg()); 16 //出现异常,打印日志后返回错误码 17 return new RpcResult(resultVo); 18 } 19 } catch (RuntimeException e) { 20 String data = String.format(" [level]:Error,[createTime]:%s,[platform]:%s,[serviceName]:%s,[methodName]:%s,[inputParam]:%s", DateUtil.formatDateTime(new Date()), PlatformNameEnum.PAY, invoker.getInterface().getName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments())); 21 logger.error(data, e); 22 } 23 return result; 24 } 25 }
2、在resources目录下添加纯文本文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容如下:
exceptionFilter=com.zcz.filter.ExceptionFilter
3、修改dubbo的provider配置文件,在dubbo:provider中添加配置的filter,如下:
<dubbo:provider filter="exceptionFilter"></dubbo:provider>
第二种方法:aop拦截
1、引入aop相关的jar包
spring-aop、spring-aspects、aspectjrt
2、编写统一异常处理AOP代码
1 public class ExceptionAop { 2 private static final Logger logger = LogManager.getLogger(ExceptionAop.class); 3 4 public Object handlerControllerMethod(ProceedingJoinPoint pjp) { 5 long startTime = System.currentTimeMillis(); 6 7 ResultVo result; 8 9 try { 10 result = (ResultVo) pjp.proceed(); 11 logger.info(pjp.getSignature() + "use time:" + (System.currentTimeMillis() - startTime)); 12 } catch (Throwable e) { 13 result = handlerException(pjp, e); 14 } 15 16 return result; 17 } 18 19 private ResultVo handlerException(ProceedingJoinPoint pjp, Throwable e) { 20 ResultVo result = new ResultVo(false); 21 pjp.getArgs(); 22 23 // 已知异常 24 if (e instanceof BusinessException) { 25 result.setResultCode(Integer.parseInt(((BusinessException) e).getExceptionCode())); 26 result.setResultMessage(((BusinessException) e).getExceptionMsg()); 27 } else { 28 logger.error(pjp.getSignature() + " error ", e); 29 30 //TODO 未知的异常,应该格外注意,可以发送邮件通知等 31 result.setResultCode(PayCenterErrorCodeEnum.PAY_ERR_100000.getCode()); 32 result.setResultMessage(PayCenterErrorCodeEnum.PAY_ERR_100000.getMsg()); 33 } 34 35 return result; 36 } 37 }
3、配置Spring Aop的XML
1 <bean id="exceptionAop" class="com.zcz.pay.aop.ExceptionAop"/> 2 <aop:config> 3 <aop:pointcut id="target" 4 expression="execution(* com.zcz.pay.api..*.*(..))"/> 5 <aop:aspect id="myAop" ref="exceptionAop"> 6 <!-- 配置环绕通知 --> 7 <aop:around method="handlerControllerMethod" pointcut-ref="target"/> 8 </aop:aspect> 9 </aop:config>