Java Web, service 层应该通过异常(自定义 Exception)来中断业务吗?

问答 潇洒劫个妞 ⋅ 于 2019-05-30 17:41:24 ⋅ 最后回复由 青牛 2019-05-30 17:53:11 ⋅ 2012 阅读

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方法)

  1. 这样做是否对整个系统的设计带来什么影响?有违最佳实践?因为 有说法是不应该用异常控制流程,但我不认为这样的设计是异常控制流程。
成为第一个点赞的人吧 :bowtie:
回复数量: 1
  • 青牛 国内首批大数据从业者,就职于金山,担任大数据团队核心研发工程师
    2019-05-30 17:53:11

    通常都是异常抛到controller层

暂无评论~~
  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
Ctrl+Enter