restful 全局异常捕获处理

本贴最后更新于 2675 天前,其中的信息可能已经时移世改

全局异常处理

本文项目已发布到 github,后续学习项目也会添加到此工程下,欢迎 fork 点赞。
https://github.com/wangyuheng/spring-boot-sample

偷懒代码

偷懒是程序员的美德,但是有些偷懒是为了少写代码,有些则是少思考,直接 copy。

不知道你有没有见过这种代码,在最外层 catch Exception,避免抛出异常信息。。。

@RestController @RequestMapping("/user") public class UserApi { @Autowired private UserService userService; @GetMapping("/{id}") public Object getInfo(@PathVariable("id") int id) { try { return userService.getUsernameById(id); } catch (UserException) { return "用户id异常"; } catch (Exception e) { return "服务异常,请稍后再试!"; } } }

UserService 用于模拟异常抛出

@Service public class UserService { public String getUsernameById(long id) { if (0 == id % 2) { throw new IllegalArgumentException("error param!"); } else { throw new UserException("custom exception!"); } } }

全局异常处理

自定义异常

通过自定义异常,区分业务异常,并增加 errorCode 支持,返回给接口调用方。

public enum ErrorCode { Error(10000, "服务异常"), UserIdError(10001, "用户id异常"); private int code; private String message; ErrorCode(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } }
public class CustomException extends RuntimeException { private int errorCode; public CustomException(int errorCode, String message) { super(message); this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } }
public class UserException extends CustomException { public UserException(String message) { super(ErrorCode.UserIdError.getCode(), message); } public UserException() { super(ErrorCode.UserIdError.getCode(), ErrorCode.UserIdError.getMessage()); } }

@ControllerAdvice

会应用到所有的 Controller 中的 @RequestMapping 注解的方法中,通过 annotations = RestController.class 指定代理的 Controller 类中。

@ExceptionHandler

用于捕获异常,@ExceptionHandler 本身只能捕获当前类的异常信息,结合 @ControllerAdvice 可以捕获全部 controller 异常。

@ControllerAdvice(annotations = RestController.class) @ResponseBody public class GlobalExceptionHandler { private Map<String, Object> getErrorObject(int code, String message) { Map<String, Object> error = new HashMap<>(); error.put("code", code); error.put("message", message); return error; } @ExceptionHandler(Exception.class) public Object exceptionHandler() { return getErrorObject(ErrorCode.Error.getCode(), ErrorCode.Error.getMessage()); } @ExceptionHandler(CustomException.class) public Object customException(CustomException e) { return getErrorObject(e.getErrorCode(), e.getMessage()); } }

优化代码

优化后的代码简洁了,无需每次 try...catch,统一管理异常信息。

@RestController @RequestMapping("/user") public class UserApi { @Autowired private UserService userService; @GetMapping("/{id}") public Object getInfo(@PathVariable("id") int id) { return userService.getUsernameById(id); } }

测试

mockMvc 请求 api 接口,判断返回值

@RunWith(SpringRunner.class) @SpringBootTest public class UserApiTest { private MockMvc mockMvc; @Autowired private WebApplicationContext context; @Autowired private UserApi userApi; @Before public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); } private JSONObject getUserApiResult(int id) throws Exception { String path = "/user/" + id; return new JSONObject(mockMvc.perform(MockMvcRequestBuilders.get(path)) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()) .andReturn() .getResponse() .getContentAsString()); } @Test public void test_exception_handler() throws Exception { int i = 1; assertTrue(ErrorCode.UserIdError.getCode() == getUserApiResult(i).getInt("code")); i++; assertTrue(ErrorCode.Error.getCode() == getUserApiResult(i).getInt("code")); } }
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    946 引用 • 1460 回帖
  • 异常
    20 引用 • 47 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • DrJoseph

    总能在报废的边缘找到学习的曙光

    2 回复
  • Vanessa via macOS

    不放弃不抛弃

  • crick77 via macOS
    作者

    也可能是因为年底了

    1 回复
  • DrJoseph

    是因为这段时间经历的太多,有点颓吧;其次是这家公司做的东西越来越没劲了,学习的动力也丧失了。

  • loveWct

    棒棒的哟