Skip to content

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

这样显然对用户是及其不友好的。 后端不应该直接返回错误页面,而应返回统一的错误信息,比如:

{ "code": 500, "data": null, "message": " ==服务异常,请稍后重试==

" } 然后,前端根据返回的信息,显示友好的提示页面。 Spring提供了三种方式对异常统一处理:

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

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

package com.minchengjianshe.organizationalandpersonal.controller; import com.minchengjianshe.organizationalandpersonal.common.ApiResult; import com.minchengjianshe.organizationalandpersonal.common.Common; import com.minchengjianshe.organizationalandpersonal.exception.BusinessException; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import java.util.Date; @Slf4j public abstract class BaseController {   /**    * BusinessException 异常处理

/   @ResponseBody   @ExceptionHandler(BusinessException.class)   public ApiResult businessExceptionHandler(BusinessException e) {     log.error(e.getMessage(), e);     // do something     return ApiResult.fail(e.getMessage());   }   /*    * Exception 异常处理

*/   @ResponseBody   @ExceptionHandler(Exception.class)   public ApiResult exceptionHandler(Exception e) {     log.error(e.getMessage(), e);     return ApiResult.fail(" 服务异常,请稍后重试

");   } } 这里对异常BusinessException和Exception进行了处理, BusinessException是约定的业务异常的基类,若是主动抛出一般都要求是BusinessException的子类,都会被businessExceptionHandler处理。 若是其它异常,可能是意想不到的异常,则会被exceptionHandler处理。 统一处理后,返回结果如下:

实现HandlerExceptionResolver接口

package com.minchengjianshe.organizationalandpersonal.exception; import com.minchengjianshe.organizationalandpersonal.common.ApiResult; import com.minchengjianshe.organizationalandpersonal.util.WebUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j // @Component public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {   @Override   public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o,       Exception e) {     log.error(e.getMessage(), e);     ApiResult apiResult;     if (e instanceof BusinessException) {       BusinessException be = (BusinessException) e;       // do something       apiResult = ApiResult.fail(be.getMessage());     } else {       apiResult = ApiResult.fail(" 服务异常,请稍后重试

");     }     WebUtils.writeJson(response, apiResult);     return null;   } } ==该方式需要实现==HandlerExceptionResolver==接口,然后将实现类注入到==Spring==容器中。== 但第一种方式中,通过@ResponseBody注解,Spring就帮我们返回了json格式数据,而这需要自己实现。 这里实现了工具类WebUtils,用于返回json数据,如下: 安装gson依赖 <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> package com.minchengjianshe.organizationalandpersonal.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; /**  * @author Zhu.Qianchang  * @date 2020-05-21  / public class WebUtils {   private static final Logger log = LoggerFactory.getLogger(WebUtils.class);   private static Gson gson = new GsonBuilder().serializeNulls().create();   /*    * 返回json数据

*    * @param response    * @param object    /   public static void writeJson(HttpServletResponse response, int status, Object object) {     response.setHeader("Content-Type", "application/json;charset=UTF-8");     response.setContentType("application/json;charset=UTF-8");     response.setStatus(status);     PrintWriter out = null;     try {       String data = object instanceof String ? (String) object : gson.toJson(object);       out = response.getWriter();       out.print(data);       out.flush();     } catch (Exception e) {       log.error(e.getMessage(), e);     } finally {       if (out != null) {         out.close();       }     }   }   /*    * 返回json数据

*    * @param response    * @param object    /   public static void writeJson(HttpServletResponse response, Object object) {     writeJson(response, HttpServletResponse.SC_OK, object);   }   /*    * 返回json数据

*    * @param response    * @param object    */   public static void writeJson(ServletResponse response, Object object) {     if (response instanceof HttpServletResponse) {       writeJson((HttpServletResponse) response, object);     }   } } 工具类中使用了Gson,需要引用:

  • <dependency>
  • <groupId>com.google.code.gson</groupId>
  • <artifactId>gson</artifactId>
  • </dependency>

@ControllerAdvice + @ExceptionHandler 该方式与第一种方式类似,如下:

@Slf4j@ControllerAdvicepublic class GlobalExceptionHandler { /** * BusinessException 异常处理

 */@ResponseBody@ExceptionHandler(BusinessException.class) public ApiResult businessExceptionHandler(BusinessException e) { log.error(e.getMessage(), e); // do somethingreturnApiResult.fail(e.getMessage()); } /** * Exception 异常处理

 */@ResponseBody@ExceptionHandler(Exception.class) publicApiResultexceptionHandler(Exception e) { log.error(e.getMessage(), e); returnApiResult.fail(" ==服务异常,请稍后重试==

"); }} ==复制代码== 总结 三种方式都能很好对异常进行统一处理,但是一般推荐使用@ControllerAdvice + @ExceptionHandler方式, 这样能够使异常处理与业务逻辑分离,并且不用自己处理Json数据返回。 > 来自

<https://juejin.cn/post/6844904164837818376\>

本站总访问 — 次