Spring Validation + 统一异常返回 疑问

2023-01-30 15:19:46 +08:00
 Morii

请问这篇文章中的这段效果怎么实现呢?

http://unclechen.github.io/2018/12/15/SpringBoot%E8%87%AA%E5%AE%9A%E4%B9%89%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E6%A0%A1%E9%AA%8C/


3.6 更加细致的返回码和消息 其实还有一种比较典型的自定义返回,就是错误码( code )和消息( message )是一一对应的,比如:

51001:字符串长度过长 51002:参数取值过大 … 这种情况比较特殊,一般当参数错误的时候,会返回一个整体的参数错误的错误码,然后携带参数的错误信息。但有时,业务上就要不同的参数错误,既要错误码不同,错误信息也要不同。我想了下,有两种思路。

第一种:通过 message 同时包含错误码和错误信息,在全局异常捕获方法中,再把它们拆开。 第二种:手动校验,抛出自定义的 Exception (里面带有 code 、message )。手动校验这里,如果每一个 Controller 都去写一遍,确实比较费劲,可以结合 AOP 来实现,或者抽出一个基类 BaseController 的方式。


不知道有没有更好的方案,碰巧需要返回这种 code + msg 一一对应的效果

869 次点击
所在节点    问与答
6 条回复
cslive
2023-01-30 16:39:24 +08:00
@ExceptionHandler(value = {Exception.class})

这里捕捉不同异常,抛出不同的错误码不就行了
jackytsu
2023-01-30 16:43:18 +08:00
比较多的做法是抛出自定义异常类
然后异常的 code 是放在常量里或枚举里
message 放在项目的资源文件里或读取外部配置
方便部署时针对不同的业务需求返回不同的提示信息
szzadkk
2023-01-30 16:46:29 +08:00
1. 定义个异常信息的枚举,里面包含 code 和 message
2. 自定义异常类,把这个枚举值作为属性
3. 底层抛出自定义异常
4. GlobalExceptionHandler 里面处理,将 code 、message 取出放到 response body 里面
nothingistrue
2023-01-30 17:06:21 +08:00
首先纠正一点,这是 Spring 使用的 Bean Validation 规范下的 Hibernate Validation 实现,不是 Spring Validation 。然后,这个是验证 Java Bean 的字段的。对应到业务上,它只能验证方法参数的有效性,只能参与统一异常处理,不能替代,也不能侵入。

另外关于错误码和消息的对应关系,你引用的文章的理解都是错误的。如果有了错误码,那么错误消息就只能是错误码的外部展示,它归属于错误码,而不是跟错误码同级别,并不存在一一对应关系。异常上是只需包含 code 的,整个异常处理过程,除了最后的对外显示外,都不需要考虑 message 。message 只需要最终显示时,通过资源文件根据 code 再获取即可,多语言环境下还可以同一个 code 针对不同的语言环境显示不同的 message 。
nothingistrue
2023-01-30 17:30:01 +08:00
有一点是需要提醒的,错误码异常反馈方式,虽然是很常见的异常反馈方式,但却是很老,并且基本没啥卵用的异常反馈方式。Java 和 Spring 并没有采用这种体系。

以前没异常体系,只能靠函数返回值来做错误返回,才不得不用错误码来反馈错误信息。而 Java 有了新的 try catch throw 异常处理机制,就提供了更丰富的错误反馈机制。Java 反馈的错误信息,是 java.lang.Throwable 的子类的实例。这是一个对象,必须包含类自身定义(完整类名)和抛出追踪栈(通过 printStackTrace 打印的东西),可选包含 messge 和 localized message 。然后更重要的,java.lang.Throwable 只是一个普通类,开发者可以根据需要任意扩展。

Bean Validation 没有对原生异常体系做过多扩展,所以它也就只能定义 message 。但是,这个是 java.lang.Throwable 的 message ,不是你业务上的 message 。你可以,在定义 Bean Validation 注解的 message 时,定义成业务上的错误码,然后再统一异常处理器中,捕获 Bean Validation 的异常,通过 getMessage 方法提取出业务上的错误码,再做后续转换处理。
nothingistrue
2023-01-30 17:33:21 +08:00
Bean Validation 只包含了参数检查,这在业务异常中只是极小的一部分,如果你要在整个错误反馈体系中加错误码,那么,不但需要定制一个额外包含 code 的异常类作为所有自定义异常的基类,还需要捕获所有 Java 自身异常和使用到的第三方框架的异常并将其转换成自定义异常。这是吃力不讨好的事。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/911660

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX