Java web(SpringBoot)通过REST API给前端调用,后端通用的返回格式为JSON格式形如:
{"code":200, "msg":"OK", "data":null }
或:
{"code":40006, "msg":"用户名不合法", "data":null }
现在有个用户管理模块,设计userService的createUser(User user)方法,我现在是如果发现校验不通过的情况,通过异常中断业务,然后通过在Controller类的AOP @ControllerAdvice捕获异常,根据不同的异常转换为上面的JSON数据返回前端,代码大概如下:
service层:
public User create(User user) {
if (!checkName(user)) {
throw new MyServiceException("用户名不合法");
}
if (exist(user)) {
throw new MyServiceException("用户已存在");
}
return dao.save(user);
}
Controller类:
@PostMapping("/users/")
public JsonResult create(User user) {
User user = userService.create(user);
return JsonResult.ok(user);
}
@ControllerAdvice的类:
@ExceptionHandler({ Throwable.class })
@ResponseBody
public JsonResult handleException(Exception e) {
return JsonResult.build(4006, e.getMessage());
}
这样做的好处:
service方法很好设计,如果成功就返回实体,不成功就抛异常,controller层不需要关心这些逻辑,只需默认认为接口调用是成功的然后返回给前端即可(因为如果不成功就交由@ControllerAdvice处理了)。如果有其他的service层调用这个userService的创建用户的接口,处理逻辑也很直接,默认这个接口是调用成功的,拿到user后进行下一步处理,不需要判断“如果没有成功创建用户怎么处理”的问题。
service层通过异常携带前端需要的业务息(即返回前端的msg字段),在@ControllerAdvice类里方便统一异常,根据不同异常转换为不同JSON给前端(上面例子只把所有异常都转换为同一JSON)。
疑虑的问题:
这样做是否会对性能造成比较大的影响?因为Java异常的构建需要获取方法调用栈等息。(其实我已经在自定义异常类里重写了fillInStackTrace方法)
这样做是否对整个系统的设计带来什么影响?有违最佳实践?因为 有说法是不应该用异常控制流程,但我不认为这样的设计是异常控制流程。