Рубрики
Без рубрики

Записи Java в API Spring Boot Rest

Введение в записи Java 14 была выпущена в марте 2020 года, и одна из функций, которая… Помечен как java, java 16, записи, springboot.

Введение в записи

Java 14 была выпущена в марте 2020 года, и одной из функций, которая привлекла наше внимание, были записи. Давайте начнем с объяснения того, что такое запись, а затем перейдем к потенциальным вариантам использования.

Примечание: Скоро выйдет Java 17 (сентябрь 2021 года), которая является первой версией LTS с поддержкой записей.

Из Openjdk JEP359:

Записи обеспечивают компактный синтаксис для объявления классов, которые являются прозрачными держателями неглубоко неизменяемых данных.

Эта функция пытается уменьшить объем шаблонного кода в наших приложениях, так как вам нужно только определить поля (эквивалентно полям класса). Записи предоставляют общедоступный конструктор (со всеми аргументами), методы чтения для каждого поля (эквивалентные получателям) и реализацию методов hashCode, equals и toString.

Вот как будут выглядеть запись и класс для одной и той же структуры данных.

Запись
public record Person(String name, int age) {
}
Класс
public class Person {
  private String name;
  private int age;

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

  public boolean equals(Object o) {
    ...
  }

  public int hashCode() {
    ...
  }

  public String toString() {
    ...
  }
}

Как вы заметите, это значительно меньше кода, учитывая полезность класса.

Обычаи

Так где же тогда можно было бы использовать эти Записи? Одно из потенциальных применений находится в контроллерах rest. Иногда бывает довольно неприятно создавать класс только для использования в качестве возвращаемого типа или тела запроса в контроллере rest.

В следующем разделе мы продемонстрируем, как создать api spring boot rest с записями.

Демонстрация

Код для этой демонстрации можно найти здесь:

psideris89/java-записи-демо

Демонстрационный api spring boot rest для демонстрации записей java 14

Шаг 1: Создайте приложение Spring Boot

Вы можете использовать инициализатор пружины ( https://start.spring.io/ ) для создания проекта spring boot. Конфигурация для нашей демо-версии такова:

  • Проект: Градация
  • Язык: Java 16
  • Пружинный ботинок: 2.5.4
  • Название: фильмы-демо
  • Зависимости: Весенняя паутина

Все остальное можно было бы оставить со значением по умолчанию.

Шаг 2: Конфигурация проекта

Если вы используете IDE, вам необходимо использовать jdk 16. Для Intellij установите project sdk в 16 и языковой уровень проекта для 16 .

Устаревшая конфигурация (java 14)

Если вы используете java 16, вы можете пропустить этот раздел.

Чтобы использовать записи с jdk 14, необходимо включить функции предварительного просмотра. Вам может быть предложено принять некоторые условия, если вы хотите использовать функции предварительного просмотра, поэтому нажмите “Принять” и продолжайте.

Кроме того, добавьте следующую конфигурацию в build.gradle . Аналогичная конфигурация существует и для maven.

compileJava {
    options.compilerArgs += ["--enable-preview"]
}

test {
    jvmArgs(['--enable-preview'])
}

Шаг 3: Создайте контроллер Rest

Прежде чем мы создадим контроллер rest, нам нужно определить записи.

Директор
public record Director(String name, String surname) {
}
Кино
public record Movie(String id, Director director, Boolean released) {
}

Затем создайте контроллер rest с 3 конечными точками: одна для извлечения всех фильмов, другая для извлечения фильма по идентификатору и последняя для добавления фильма (на самом деле мы ничего не сохраняем, так как это для демонстрации десериализации).

@RestController
public class MoviesController {

    private List movies = List.of(
            new Movie("1", new Director("John", "Wick"), true),
            new Movie("2", new Director("Mary", "Poppins"), false),
            new Movie("3", new Director("Jack", "Sparrow"), true),
            new Movie("4", null, false));

    @GetMapping("/movies")
    public List getMovies() {
        return movies;
    }

    @GetMapping("/movies/{id}")
    public Movie getMovie(@PathVariable String id) {
        return movies
                .stream()
                .filter(s -> s.id().equals(id))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Not found"));
    }

    @PostMapping("/movies")
    public Movie addMovie(@RequestBody Movie movie) {
        // Save the movie, be careful as List.of() is immutable
        return movie;
    }
}

Шаг 4: Настройте Джексона для сериализации/десериализации

Запустите приложение и вызовите первую конечную точку, локальный хост: 8080/фильмы . Следующая ошибка возникает, так как объекты не могут быть сериализованы.

Решение этой проблемы заключается в использовании аннотаций Джексона и в конкретных аннотациях JsonProperty .

public record Director(@JsonProperty("name")String name, @JsonProperty("surname")String surname) {
}

public record Movie(@JsonProperty("id") String id, @JsonProperty("director") Director director, @JsonProperty("released") Boolean released) {
}

Перезапустите приложение, и вы сможете получить список фильмов.

Конечная точка getMovie ( локальный хост:8080/фильмы/1 ) использует метод id() , который предоставляется Записью. Таким образом, мы можем сравнить идентификатор каждого фильма с идентификатором, предоставленным в вызове api.

Наконец, конечная точка addMovie – это просто макет конечной точки, но это доказывает, что десериализация также работает. Чтобы проверить это, вам нужно отправить запрос на localhost:8080/фильмы с действительным телом.

{
    "id": "10",
    "director": {
        "name": "Jim",
        "surname": "White"
    },
    "released": false
}

Вывод

Что могут означать записи для будущего java? Возможно, они не предназначены для использования таким образом, но в целом эта функция – то, что ожидали многие разработчики java. Тот факт, что записи неизменяемы, добавляет огромную ценность. Все вышеперечисленное в сочетании с сокращением шаблонного кода делает записи многообещающей функцией.

Оригинал: “https://dev.to/psideris89/java-14-records-in-spring-boot-rest-api-n29”