微服务架构下的统一异常处理
微服务架构实际上是一种将具有不同功能、不同部署位置的服务协调起来共同工作的分布式系统。由于分布式系统的复杂性,对这些服务之间的协调产生的异常处理就显得尤为重要了,好的异常处理不仅便于在异常发生的时候定位跟踪问题,还有利于保证系统的稳定性并可提高系统交互体验的友好性。所以,微服务开发过程中考虑异常情况的处理与考虑正常逻辑同等重要。
本文简单串联Java异常的基础知识和Spring提供的异常处理机制以及Spring Cloud服务间的异常处理机制,以实际项目实践为例说明在Spring Cloud微服务架构下自定义异常及统一处理异常的要点。
Java异常基础知识
Throwable 类是 Java 语言中所有错误或异常的超类,其子类分为Error、Exception。
Error是合理的应用程序不应该试图捕获的严重问题
Exception是合理的应用程序想要捕获的问题,Exception又分为CheckedException和UnCheckedException。
[ ] CheckedException是对于可恢复的条件使用被检查的异常,需要用try…catch…显式的捕获并且进行处理,例如IOException。
[ ] UncheckedException又叫做RuntimeException不是必须捕获的,对于导致程序无法执行的异常,必要时转化成有具体业务描述说明的异常。
异常处理的注意事项:
- 一般来说异常处理首先要防止异常丢失,避免使用覆盖式异常处理块,可以考虑使用异常链的特性处理,即使用从Throwable继承的initCause()。
- 在截获异常进行处理时要注意对异常进行一番处理,如:修正错误,给出明确位置,描述,原因以及提醒。
- 使用Try…finally结构保证发生异常时,资源也能正确释放、关闭。
- 截获异常后进行相应处理,根据业务逻辑需要,必要时可以重新抛出异常。
- 最好的处理方法是对异常信息分类,然后进行封装处理。
- 尤其需要注意的是避免把异常截获后不做任何处理,直接吞了,项目上不少初级程序员犯这类错误可能导致程序出错,不好查找原因。
Spring异常处理的三种方式
- 使用
@ExceptionHandlerannotation 实现在配置的Controller中拦截并处理异常
@Controller
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);
@RequestMapping(value="/user/{id}", method=RequestMethod.GET)
public String getUser(@PathVariable("id") int id, Model model) throws Exception{
if(id==1){
throw new UserNotFoundException(id);
}
}
@ExceptionHandler(UserNotFoundException.class)
public ModelAndView handleUserNotFoundException(HttpServletRequest request, Exception ex){
logger.error("Requested URL="+request.getRequestURL());
logger.error("Exception Raised="+ex);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("exception", ex);
modelAndView.addObject("url", request.getRequestURL());
modelAndView.setViewName("error");
return modelAndView;
}
/** 输入参数仅有exception
@ExceptionHandler
public String handleException(UserNotFoundException exception) {
return "errorView";
}
*/
}
实现HandlerExceptionResolver接口,进行全局的异常拦截,使用时需要在MVCConfiguration中初始化异常处理器
public class ServiceHandlerExceptionResolver implements HandlerExceptionResolver {
Logger logger = LoggerFactory.getLogger(ServiceHandlerExceptionResolver.class);
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) {
e.printStackTrace();
Throwable rex = e;
if (rex instanceof CIBaseException) {
this.writeError(((CIBaseException) rex).getErrCode(), rex.getMessage(), httpServletResponse);
} else {
this.writeError("", "系统运行出错", httpServletResponse);
}
return new ModelAndView();
}
}
@Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter {
//需要在MVCConfiguration中初始化异常处理器