51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

在 Spring Boot 中使用 Java Record

本文将带你了解如何在 Spring Boot 应用中利用 Java Record 来提高其效率和可读性。

Java Record 是什么? {#java-record-是什么}

Java Record 是一种专为保存不可变数据而设计的类。它们自动提供 equals()hashCode()toString() 等方法的实现,大大减少了模板代码。因此,它们非常适合在 Spring Boot 应用中创建数据传输对象(DTO)、实体和其他模型类。

Java Record 示例 {#java-record-示例}

举一个简单的例子,用 Java Record 来表示一个 Person

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

在本例中,Person 是一个 Record,包含两个字段:nameage。Java 自动为该 Record 提供了以下内容:

  • 一个 public 构造函数:Person(String name, int age)
  • 属性的 public Getter 方法:name()age()
  • 实现了 equals()hashCode()toString() 方法

使用 Getter 方法 {#使用-getter-方法}

Record 的主要特点之一是提供了用于访问字段的隐式 Getter 方法。这些方法以字段本身命名。

创建 Person 实例并使用其 Getter 方法:

public class Main {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        // 调用 Getter 方法
        String name = person.name();
        int age = person.age();

        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}

输出如下:

Name: Alice
Age: 30

在 Spring Boot 中使用 Record 的主要优势 {#在-spring-boot-中使用-record-的主要优势}

  1. 模板代码 :Record 自动生成构造器、Getter 方法、equals()hashCode()toString() 方法,大大减少了模板代码。
  2. 不可更改:Record 默认创建不可变的数据结构,因此非常适合数据完整性至关重要的使用场景。
  3. 职责明确:Record 的目的很明确 - 它只是数据的载体。这使代码更易于阅读和维护。
  4. 易于使用:开发人员只需一行代码就能定义一个 Record,从而使数据保存类的创建更简单、更高效。

Spring Boot 示例项目 {#spring-boot-示例项目}

软件版本:

  • JDK:16+
  • Spring Boot:3.0

你可以通过 Spring Initializr 初始化项目。添加 Spring WebSpring Data JPAH2 Database 等依赖。

示例项目由以下几层组成:

  • Controller 层:处理 HTTP 请求和响应。
  • Service 层:包含业务逻辑。
  • Repository 层:处理数据持久化。
  • Database:H2 内存数据库,以简化操作。

第 1 步:定义 Domain Record {#第-1-步定义-domain-record}

首先,定义一个 User Record,它是 Domain 实体。

import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public record User(@Id Long id, String name, String email) {}

如上,使用 Java Record 来定义实体,从而使实体定义简洁且不可更改。

第 2 步:Repository 层 {#第-2-步repository-层}

接着,创建一个用于数据访问的 Repository 接口:

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {}

Spring Data JPA 会在运行时提供 Repository 实现。

第 3 步:Service 层 {#第-3-步service-层}

UserService 包含业务逻辑并与 UserRepository 交互:

import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User createUser(User user) {
        return userRepository.save(user);
    }

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    public User getUserById(Long id) {
        return userRepository.findById(id).orElseThrow();
    }

    public User updateUser(Long id, User userDetails) {
        User user = userRepository.findById(id).orElseThrow();
        User updatedUser = new User(user.id(), userDetails.name(), userDetails.email());
        return userRepository.save(updatedUser);
    }

    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

该 Service 类使用 UserRepository 执行 CRUD 操作。

第 4 步:Controller 层 {#第-4-步controller-层}

在 Controller 中,将 CRUD 操作公开为 HTTP 端点:

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@RequestBody User user) {
        return userService.createUser(user);
    }

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        return userService.updateUser(id, user);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}

UserController 处理 HTTP 请求,并调用 UserService 来完成 CRUD 操作。

第 5 步:使用 WebClient 进行测试 {#第-5-步使用-webclient-进行测试}

使用 WebClient 作为 REST 客户端来测试应用的 CRUD REST API。

首先,需要确保在 pom.xml 中包含了 spring-boot-starter-webflux 依赖。

下面是使用 WebClient 测试 CRUD 操作的完整代码:

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class RestClient {
    private final WebClient webClient;

    public RestClient() {
        this.webClient = WebClient.create("http://localhost:8080");
    }

    public void createUser() {
        User user = new User(1L, "John Doe", "john@example.com");
        User createdUser = webClient.post()
                .uri("/users")
                .body(Mono.just(user), User.class)
                .retrieve()
                .bodyToMono(User.class)
                .block();
        System.out.println("Created User: " + createdUser);
    }

    public void getUser(Long id) {
        User user = webClient.get()
                .uri("/users/" + id)
                .retrieve()
                .bodyToMono(User.class)
                .block();
        System.out.println("User: " + user);
    }

    public void updateUser(Long id, User updatedUser) {
        User user = webClient.put()
                .uri("/users/" + id)
                .body(Mono.just(updatedUser), User.class)
                .retrieve()
                .bodyToMono(User.class)
                .block();
        System.out.println("Updated User: " + user);
    }

    public void deleteUser(Long id) {
        webClient.delete()
                .uri("/users/" + id)
                .retrieve()
                .bodyToMono(Void.class)
                .block();
        System.out.println("Deleted User with ID: " + id);
    }

    public static void main(String[] args) {
        RestClient client = new RestClient();

        // 测试创建用户
        client.createUser();

        // 测试检索用户
        client.getUser(1L);

        // 测试更新用户
        User updatedUser = new User(1L, "Jane Doe", "jane@example.com");
        client.updateUser(1L, updatedUser);

        // 测试删除用户
        client.deleteUser(1L);
    }

    private record User(Long id, String name, String email) {}
}

运行服务器,执行 RestClient 测试类,输出如下:

Created User: User[id=1, name=John Doe, email=john@example.com]
User: User[id=1, name=John Doe, email=john@example.com]
Updated User: User[id=1, name=Jane Doe, email=jane@example.com]
Deleted User with ID: 1

Ref:https://www.javaguides.net/2023/12/using-java-records-with-spring-boot.html

赞(1)
未经允许不得转载:工具盒子 » 在 Spring Boot 中使用 Java Record