使用@ControllerAdvice/@RestControllerAdvice
配合@ExceptionHandler
注解配置全局的异常处理器,处理调用dubbo
服务时的Exception
。
测试代码基于Spring MVC + dubbo
的分布式项目,为了简单起见,代码不太完整,只是想引导一下使用dubbo
设计架构时,异常处理可以这样处理。
注:JsonResult
和ResultStatus
是响应实体,不必过多关注;对于系统中的异常,根据实际的情况,实现不同的异常即可,本文中为了简便,使用了RuntimeException
和FileNotFoundException
。由于能力有限,异常处理的解决方案只能给到这里,请各位大佬多多指教。
全局异常处理器
@ControllerAdvice
public class ExceptionHandle {
private static final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
@ResponseBody
@ExceptionHandler(RuntimeException.class)
public Object handleRuntimeException(Exception e) {
logger.info(e.toString());
return JsonResult.fail(new ResultStatus(-1, e.toString()));
}
@ResponseBody
@ExceptionHandler(FileNotFoundException.class)
public Object handleFileNotFoundException(Exception e){
logger.info(e.toString());
return JsonResult.fail(new ResultStatus(-1, e.toString()));
}
}
在分布式或多模块/多工程的环境下,全局异常处理器可以配置在公共模块中,各个控制层均可扫描到公共模块的异常处理器。例如:公共模块api-commons-auth
中定义了认证的全局异常处理器,代码如下:
@ControllerAdvice
public class UnauthorizedExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(UnauthorizedExceptionHandler.class);
@ExceptionHandler({UnauthorizedException.class})
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public Object processUnauthenticatedException(UnauthorizedException e) {
return JsonResult.fail(new ResultStatus(-1, e.toString()));
}
}
假如有api-web-auth
模块,pom文件中引入api-commons-auth
依赖,在web模块的spring-servlet.xml中配置注解扫描如下:
<context:component-scan base-package="com.xxx.assa" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
<!-- 扫描ControllerAdvice此注解,初始化 api-commons-auth 中的全局异常处理器 -->
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
<mvc:annotation-driven/>
Controller
@Controller
@RequestMapping("/exception")
public class ExceptionController {
@Resource
private ExceptionService exceptionService ;
@ResponseBody
@RequestMapping(value = "/runtime")
public Object runtime() {
exceptionService.testRuntimeException();
return JsonResult.success();
}
/**
* 一般此处不会直接抛出异常
*/
@ResponseBody
@RequestMapping(value = "/check")
public Object check() throws FileNotFoundException {
exceptionService.testFileNotFoundException();
return JsonResult.success();
}
}
Service
@Service("exceptionService")
public class ExceptionServiceImpl implements ExceptionService {
@Override
public void testRuntimeException() {
throw new RuntimeException("这里有点错误哦");
}
@Override
public void testFileNotFoundException() throws FileNotFoundException {
throw new FileNotFoundException("这里有点错误哦");
}
}
dubbo服务注册和消费
<!-- 服务消费配置 -->
<dubbo:reference id="exceptionService" interface="com.xxx.ExceptionService" check="false" retries="${dubbo.retry}" timeout="5000"/>
<!-- 服务注册配置 -->
<dubbo:service interface="com.xxx.ExceptionService" ref="exceptionService" timeout="${dubbo.service.timeout}" />
请求结果
{
"code": -1,
"msg": "java.io.RuntimeException: 这里有点错误哦"
}
{
"code": -1,
"msg": "java.io.FileNotFoundException: 这里有点错误哦"
}