从零搭建后端框架——异常统一处理的三种方式

 [[327655]]

前言

项目在运行时出现异常时,如若没有对异常进行捕获并处理,就会出现如下页面:

创新互联建站是一家集网站建设,洪江企业网站建设,洪江品牌网站建设,网站定制,洪江网站建设报价,网络营销,网络优化,洪江网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

这样显然对用户是极其不友好的。

后端不应该直接返回错误页面,而应返回统一的错误信息,比如:

  
  
  
  
  1. "code": 500, 
  2. "data": null, 
  3. "message": "服务异常,请稍后重试" 
  4. 复制代码 

然后,前端根据返回的信息,显示友好的提示页面。

Spring提供了三种方式对异常统一处理:

  1. @ExceptionHandler
  2. 实现HandlerExceptionResolver接口
  3. @ControllerAdvice + @ExceptionHandler

下面我们来实际操作下。

具体实现

@ExceptionHandler

在【统一基类、接口、返回对象设计】这一篇文章中, 定义了Controller的基类BaseController,所以只要在BaseController中使用@ExceptionHandler处理异常, 其它Controller继承BaseController即可。实现如下:

  
  
  
  
  1. @Slf4j 
  2. public abstract class BaseController { 
  3.  
  4. /** 
  5. * BusinessException 异常处理 
  6. */ 
  7. @ResponseBody 
  8. @ExceptionHandler(BusinessException.class) 
  9. public ApiResult businessExceptionHandler(BusinessException e) { 
  10. log.error(e.getMessage(), e); 
  11. // do something 
  12. return ApiResult.fail(e.getMessage()); 
  13.  
  14. /** 
  15. * Exception 异常处理 
  16. */ 
  17. @ResponseBody 
  18. @ExceptionHandler(Exception.class) 
  19. public ApiResult exceptionHandler(Exception e) { 
  20. log.error(e.getMessage(), e); 
  21. return ApiResult.fail("服务异常,请稍后重试"); 
  22. 复制代码 

这里对异常BusinessException和Exception进行了处理, BusinessException是约定的业务异常的基类,若是主动抛出一般都要求是BusinessException的子类,都会被businessExceptionHandler处理。 若是其它异常,可能是意想不到的异常,则会被exceptionHandler处理。

统一处理后,返回结果如下:

实现HandlerExceptionResolver接口

  
  
  
  
  1. @Slf4j 
  2. @Component 
  3. public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver { 
  4.  
  5. @Override 
  6. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { 
  7. log.error(e.getMessage(), e); 
  8. ApiResult apiResult; 
  9. if (e instanceof BusinessException) { 
  10. BusinessException be = (BusinessException) e; 
  11. // do something 
  12. apiResult = ApiResult.fail(be.getMessage()); 
  13. } else { 
  14. apiResult = ApiResult.fail("服务异常,请稍后重试"); 
  15. WebUtils.writeJson(response, apiResult); 
  16. return null; 
  17. 复制代码 

该方式需要实现HandlerExceptionResolver接口,然后将实现类注入到Spring容器中。

但第一种方式中,通过@ResponseBody注解,Spring就帮我们返回了json格式数据,而这需要自己实现。

这里实现了工具类WebUtils,用于返回json数据,如下:

  
  
  
  
  1. public class WebUtils { 
  2.  
  3. private static final Logger log = LoggerFactory.getLogger(WebUtils.class); 
  4.  
  5. private static Gson gson = new GsonBuilder().serializeNulls().create(); 
  6.  
  7. /** 
  8. * 返回json数据 
  9. * @param response 
  10. * @param object 
  11. */ 
  12. public static void writeJson(HttpServletResponse response, int status, Object object) { 
  13. response.setHeader("Content-Type", "application/json;charset=UTF-8"); 
  14. response.setContentType("application/json;charset=UTF-8"); 
  15. response.setStatus(status); 
  16. PrintWriter out = null; 
  17. try { 
  18. String data = object instanceof String ? (String) object : gson.toJson(object); 
  19. out = response.getWriter(); 
  20. out.print(data); 
  21. out.flush(); 
  22. } catch (Exception e) { 
  23. log.error(e.getMessage(), e); 
  24. } finally { 
  25. if (out != null) { 
  26. out.close(); 
  27.  
  28. /** 
  29. * 返回json数据 
  30. * @param response 
  31. * @param object 
  32. */ 
  33. public static void writeJson(HttpServletResponse response, Object object) { 
  34. writeJson(response, HttpServletResponse.SC_OK, object); 
  35.  
  36. /** 
  37. * 返回json数据 
  38. * @param response 
  39. * @param object 
  40. */ 
  41. public static void writeJson(ServletResponse response, Object object) { 
  42. if (response instanceof HttpServletResponse) { 
  43. writeJson((HttpServletResponse) response, object); 
  44. 复制代码 

工具类中使用了Gson,需要引用:

  
  
  
  
  1.  
  2. com.google.code.gson 
  3. gson 
  4.  
  5. 复制代码 

@ControllerAdvice + @ExceptionHandler

该方式与第一种方式类似,如下:

  
  
  
  
  1. @Slf4j 
  2. @ControllerAdvice 
  3. public class GlobalExceptionHandler { 
  4.  
  5. /** 
  6. * BusinessException 异常处理 
  7. */ 
  8. @ResponseBody 
  9. @ExceptionHandler(BusinessException.class) 
  10. public ApiResult businessExceptionHandler(BusinessException e) { 
  11. log.error(e.getMessage(), e); 
  12. // do something 
  13. return ApiResult.fail(e.getMessage()); 
  14.  
  15. /** 
  16. * Exception 异常处理 
  17. */ 
  18. @ResponseBody 
  19. @ExceptionHandler(Exception.class) 
  20. public ApiResult exceptionHandler(Exception e) { 
  21. log.error(e.getMessage(), e); 
  22. return ApiResult.fail("服务异常,请稍后重试"); 
  23. 复制代码 

总结

三种方式都能很好对异常进行统一处理,但是一般推荐使用@ControllerAdvice + @ExceptionHandler方式, 这样能够使异常处理与业务逻辑分离,并且不用自己处理Json数据返回。

源码

github.com/zhuqianchan…

分享名称:从零搭建后端框架——异常统一处理的三种方式
分享网址:http://www.mswzjz.cn/qtweb/news13/69013.html

攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能