我们在项目开发中,出于对数据完整性的考虑,基本上每个接口都需要参数校验,参数校验可以自己手动校验,也可以用工具校验,今天和大家分享如何利用 Spring Boot 自带的工具实现参数校验。
参数校验应该在前端完成还是后端完成?
正常来说,前后端都是需要校验的,但是前后端校验的目的各不相同。
一般来说,前端校验可以满足两个需求:
-
用户体验:前端校验可以即时反馈给用户,减少等待服务器响应的时间,提高用户体验。
-
减轻服务器负担:通过前端校验可以过滤掉一些明显无效的请求,减少不必要的服务器负载。
真正要确保数据完整性,还得要靠后端,后端校验可以起到如下作用:
-
安全性:由于前端代码可以被绕过或修改。后端校验是安全的必要保障,确保即使前端校验被绕过,数据的安全性和完整性也能得到保证。
-
数据一致性:后端校验可以确保所有通过的请求都符合业务逻辑和数据模型的要求,保持数据的一致性。
-
容错性:后端校验可以处理那些前端未能覆盖到的异常情况,作为最后一道防线。
-
跨平台一致性:后端校验确保了无论用户通过何种客户端(Web、移动应用、第三方 API 等)访问服务,数据校验的标准都是一致的。
-
维护和可扩展性:后端校验逻辑通常更容易维护和更新,因为它们集中在服务器端,而不是分散在多个客户端。
-
日志和监控:后端可以记录校验失败的请求,这对于监控系统安全和进行问题诊断非常有用。
因此,后端校验才能真正确保数据的完整性,今天也是要和大家聊一聊后端数据校验。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
-
视频教程:https://doc.iocoder.cn/video/
在 Spring Boot 中,数据校验是通过 JSR303/JSR380 规范的 Bean Validation 实现的。
这里涉及到两个概念,和大家简单说下。
JSR303 是 Bean Validation 的 1.0 版本,正式名称为《Bean Validation》。它提供了一套注解和 API 来定义 Java 对象(Bean)的验证规则。这些注解可以直接用于 Bean 的属性上,以声明式的方式定义验证逻辑。JSR303 定义了一组标准的验证注解,如
@NotNull
、
@Size
、
@Email
等,用于校验对象的属性是否满足特定的条件。
而 JSR380 则是 Bean Validation 的 2.0 版本,也称为《Jakarta Bean Validation 2.0》。随着 JavaEE 向 JakartaEE 的迁移,JSR380 成为了新的规范。JSR380 在 JSR303 的基础上进行了扩展和改进,增加了新的注解、改进了 API,并提供了更好的集成方式。JSR380 的注解与 JSR303 兼容,但增加了一些新的注解,如
@Email
的
message
属性支持国际化,以及
@PositiveOrZero
、
@NegativeOrZero
等。
下面案例主要和小伙伴们分享最新的 JSR380 规范中的参数校验注解。
现在我们创建一个 Spring Boot 项目,使用当前最新版,并且引入参数校验依赖,最终创建好的工程依赖如下:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
假设我现在有一个 UserDto 类,需要进行参数校验,那么我可以按照如下方式定义 UserDto:
public class UserDto {
@NotNull(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
@NotEmpty(message = "邮箱不能为空")
private String email;
//省略 getter/setter
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
接下来在 Controller 的方法参数前使用 @Validated 注解来开启校验。
@RestController
public class UserController {
@GetMapping("/hello")
public String hello(@Validated UserDto userDto, BindingResult bindingResult)