如何优雅的处理SpringBoot接口中参数校验
相信我们在处理接口参数校验时,都不会使用大量的if,else 进行来处理,这样显得太繁琐,下面就来介绍一下如何能够简单而有效的处理方式:
一、使用注解来处理参数校验
1、实体类
package com.dongl.bean.mybean; import com.dongl.utils.annotation.CheckField; import lombok.Data; import org.hibernate.validator.constraints.Range; import javax.validation.constraints.NotNull; import java.util.Date;
@Data public class User { /**主键*/ private Long id; /**姓名*/ @NotNull private String name; /**性别*/ @CheckField(fieldValues = {"男", "女"}) private String sex; /**出生日期*/ private Date birthDay; /**年龄*/ @Range(min = 20 , max = 99) private Short age; /**详细地址*/ private String address; }
2、Controller层
package com.dongl.controller; import com.dongl.bean.mybean.User; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; /** * @author D-L * @Classname AnnotationController * @Version 1.0 * @Description 接口参数校验异常处理 * @Date 2020/8/26 */ @RestController @RequestMapping("Annotation") public class AnnotationController { @PostMapping(value = "user") public String test(@Validated @RequestBody User user /*, BindingResult bindingResult*/) { System.out.println(user); return "do something you like ------"; } }
3、响应结果
测试参数:
{ "name":"admin", "sex":"男", "age":120, "address":"杭州市西湖区" }
response:
{ "timestamp": "2020-08-26T07:25:45.547+0000", "status": 400, "error": "Bad Request", "errors": [ { "codes": [ "Range.user.age", "Range.age", "Range.java.lang.Short", "Range" ], "arguments": [ { "codes": [ "user.age", "age" ], "arguments": null, "defaultMessage": "age", "code": "age" }, 99, 20 ], "defaultMessage": "需要在20和99之间", "objectName": "user", "field": "age", "rejectedValue": 120, "bindingFailure": false, "code": "Range" } ], "message": "Validation failed for object='user'. Error count: 1", "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.dongl.controller.AnnotationController.test(com.dongl.bean.mybean.User): [Field error in object 'user' on field 'age': rejected value [120]; codes [Range.user.age,Range.age,Range.java.lang.Short,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],99,20]; default message [需要在20和99之间]] \r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.lang.Thread.run(Thread.java:748)\r\n", "path": "/Annotation/user" }
【结论】:这样的响应结果显然有点不够优雅,太繁琐,有没有更好的处理方式,当然有,下面使用 BindResult 处理。
二、针对接口处理 Validator + BindResult进行校验
1、处理响应结果
package com.dongl.controller; import com.dongl.bean.mybean.User; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @author D-L * @Classname AnnotationController * @Version 1.0 * @Description 处理参数校验异常 * @Date 2020/8/24 */ @RestController @RequestMapping("Annotation") public class AnnotationController { @PostMapping(value = "user") public String test(@Validated @RequestBody User user , BindingResult bindingResult) { List<ObjectError> allErrors = bindingResult.getAllErrors(); // 如果有参数校验失败,会将错误信息封装成对象组装在BindingResult里 for(ObjectError error : allErrors){ return error.getDefaultMessage(); } System.out.println(user); return "do something you like ------"; } }
2、响应结果
需要在20和99之间
【结论】当然这种方式已经解决了返回体繁琐的问题,但是每一处理接口参数都需要添加,还是有点不尽人意,有没有更好的解决方法,当然有,下面通过全局的方式处理。
三、全局异常处理 Validator + 自动抛出异常
1、全局处理响应结果
首先,我们需要新建一个类,在这个类上加上@ControllerAdvice或@RestControllerAdvice注解,这个类就配置成全局处理类了。(这个根据你的Controller层用的是@Controller还是@RestController来决定)
这里就以@RestController为例:
package com.dongl.utils.error; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; /** * @author D-L * @Classname ExceptionControllerAdvice * @Version 1.0 * @Description 全局处理参数校验异常返回提示 * @Date 2020/8/26 */ @RestControllerAdvice public class ExceptionControllerAdvice { @ExceptionHandler(MethodArgumentNotValidException.class) public String MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { // 从异常对象中拿到ObjectError对象 ObjectError objectError = e.getBindingResult().getAllErrors().get(0); // 然后提取错误提示信息进行返回 return objectError.getDefaultMessage(); } }
2、测试结果:
需要在20和99之间
【注释】:这里说明一下如果你进行了全局的处理,但在接口上又进行了手动处理,这时命中的是接口上的,也就是全局配置不生效了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」