点击上方蓝色字体,关注我 ——
一个在阿里云打工的清华学渣!
本文通过示例说明,在 Springboot 中如何自定义 Validator,以及如何实现国际化的错误信息返回。注意,本文代码千万别直接照抄,有可能会出大事情的。先留个悬念,读者朋友们能从中看出有什么问题吗?
项目初始化入
直接从 springboot 官网中下载模板,直接通过示例中的 GreetingController
添加实现逻辑。
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Response<Greeting> greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
if (!"tangleithu".equals(name)) {
throw new BadRequestException("user.notFound");
}
return Response.ok(new Greeting(counter.incrementAndGet(), String.format(template, name)));
}
}
以上代码直接源自官方 spring-guides 的 demo,我稍微改吧改吧。正常情况下,能返回正确的结果:
# curl "localhost:8080/greeting?name=tangleithu&lang=en"
{
"code": 0,
"data": {
"content": "Hello, tangleithu!",
"id": 9
},
"message": "success"
}
国际化需求
作为高大上的项目,我们肯定有海外用户,所以就需要国际化的配置。现在来模拟了下业务逻辑,假设输入的参数有一些校验功能,比如以上name
参数,假设和“tangleithu”不相等,就直接返回错误。同时希望返回的错误信息需要实现国际化,即在不同的语言环境下返回的结果不一样。例如中文:“没找到用户呢。” 对应的英文:“User does not exist.”,而对应的德文是……,算了忽略,我也不会。
用一个图来表达,即希望实现的效果是,不同国家和地区的用户(不同语言)在遇到同一个业务场景下同一个错误原因,有不同的翻译。例如在参数校验没通过,Http Status Code应该返回 400,并告知错误原因;在具体的 Service 实现时可能也会遇到其他的 case 需要返回某种具体错误信息。利用这种方式就可以很方便地统一管理起来。
注意:实际业务场景中后端可能仅仅只返回错误码,具体的展示由前端根据 key 进行翻译。不过在一些更加灵活的场景中(例如有的 app 实现方案),错误信息很有可能会由后端接口直接返回。本文只是用了一个简单的案例阐述整个流程。
统一错误处理
我们借助 Spring 中的 AOP,用一个 ControllerAdvice
统一拦截这种BadRequestException
异常。其他 Exception 也一样,做到异常信息统一处理,也不容易出现安全风险(之前有遇到过某大型网站因为后台发生异常,直接将具体的 SQL 错误暴露出来了,其中还不乏有表结构等敏感信息)。例如:
@C