欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 用 Java Record 简化 DTO:Spring Boot + Jakarta Validation 的完美搭配

用 Java Record 简化 DTO:Spring Boot + Jakarta Validation 的完美搭配

2025/3/18 20:22:05 来源:https://blog.csdn.net/yuxzlucy/article/details/146249380  浏览:    关键词:用 Java Record 简化 DTO:Spring Boot + Jakarta Validation 的完美搭配

在 Spring Boot 项目中,DTO(Data Transfer Object)是 Controller 和 Service 之间的“搬运工”,但传统写法冗长乏味。Java 16 引入的 Records 让 DTO 瘦身成功,再结合 Jakarta Bean Validation(如 Hibernate Validator),还能轻松校验输入。今天我们聊聊这套组合拳,配上实战代码,带你打造优雅又健壮的 DTO!


Records 简介:DTO 的“减肥神器”

Records 是 Java 的记录类,天生为不可变数据设计,一行代码就能搞定字段、构造器、getter、equalshashCodetoString。相比传统 DTO,它省去了大量样板代码。

传统 DTO:

public class UserDto {private final String name;private final int age;public UserDto(String name, int age) {this.name = name;this.age = age;}public String getName() { return name; }public int getAge() { return age; }// 还有 equals, hashCode, toString...
}

Records 重写:

public record UserDto(String name, int age) {}

效果:简洁到飞起,还自带不可变性,完美契合 DTO 的需求。


与 Spring Boot 集成

Spring Boot 无缝支持 Records,但在 Controller 中使用时,需注意 JSON 序列化(默认字段名如 name())和校验配置。

依赖配置,在 pom.xml 中添加:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
</dependencies>

加入 Jakarta Bean Validation,定义带校验的 DTO

Jakarta Bean Validation(JSR 380)提供注解(如 @NotNull@Min)校验字段,我们用它强化 Records。

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Email;public record UserDto(@NotBlank(message = "姓名不能为空")String name,@Min(value = 0, message = "年龄不能为负数")int age,@Email(message = "邮箱格式无效")String email
) {}

说明

  • @NotBlank:确保 name 非空且非空白。
  • @Min:限制 age 最小值。
  • @Email:校验 email 格式。

Spring Boot 实战

Controller 层
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/users")
@Validated
public class UserController {@PostMappingpublic ResponseEntity<String> createUser(@Valid @RequestBody UserDto userDto) {return ResponseEntity.ok("User created: " + userDto);}@GetMapping("/{id}")public ResponseEntity<UserDto> getUser(@PathVariable Long id) {UserDto user = new UserDto("Alice", 25, "alice@example.com");return ResponseEntity.ok(user);}
}

关键点

  • @Valid:触发 DTO 的校验。
  • @Validated:启用方法级校验。
测试输入
  • 合法请求

    POST /users
    {"name": "Alice", "age": 25, "email": "alice@example.com"}

    响应:User created: UserDto[name=Alice, age=25, email=alice@example.com]

  • 非法请求

    POST /users
    {"name": "", "age": -1, "email": "invalid"}

    响应:400 Bad Request,错误信息:

    {"errors": [{"field": "name", "message": "姓名不能为空"},{"field": "age", "message": "年龄不能为负数"},{"field": "email", "message": "邮箱格式无效"}]
    }

自定义校验逻辑

想加更复杂的校验?Records 支持自定义构造器:

public record UserDto(@NotBlank(message = "姓名不能为空")String name,@Min(value = 0, message = "年龄不能为负数")int age,@Email(message = "邮箱格式无效")String email
) {public UserDto {if (name != null && name.length() > 50) {throw new IllegalArgumentException("姓名长度不能超过 50");}}
}

效果:Spring 会捕获异常,返回 400 错误。


JSON 序列化兼容性

默认情况下,Jackson 用 name() 而非 getName() 访问字段,可能与前端期望不符。解决办法:

  1. 加注解

    import com.fasterxml.jackson.annotation.JsonProperty;public record UserDto(@JsonProperty("userName") String name,int age,String email
    ) {}

    输出 JSON:{"userName": "Alice", "age": 25, "email": "alice@example.com"}

  2. 全局配置: 在 application.yml 中:

    spring:jackson:property-naming-strategy: SNAKE_CASE

    输出:{"name": "Alice", "age": 25, "email": "alice@example_com"}


Records 的优势

  1. 简洁:一行定义 DTO,省去 getter/setter。
  2. 健壮:结合 Validation,输入安全有保障。
  3. Spring 友好:与 Controller、JSON 序列化无缝衔接。
  4. 不可变:天生适合 REST API 数据传递。

注意事项

  • 版本:Java 16+(Spring Boot 3.x 默认支持)。
  • 限制:无 setter,不适合可变对象。
  • 异常处理:建议全局配置 ControllerAdvice 统一返回校验错误。

小结

Records 让 DTO 摆脱臃肿,Jakarta Bean Validation 加上防护盾,再融入 Spring Boot,简直是现代 Java 开发的梦幻组合。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词