Spring Boot WebFlux добавить, удалить, изменить и проверить полную фактическую демонстрацию

Java

03: WebFlux Web CRUD Практика

предисловие

В предыдущей статье создается простая служба на основе функциональных конечных точек, реализующая Hello . В этой статье используется технология уровня управления аннотациями Spring Boot WebFlux для создания приложения CRUD WebFlux, чтобы сделать разработку более удобной. Здесь мы не обращаемся к хранилищу базы данных, потому что поговорим об этом позже, а здесь в основном говорим о полноценном WebFlux CRUD.

структура

Этот проект будет управлять городом и осуществлять операции CRUD. После того, как проект создан и написан, получается следующая структура, и его структура каталогов выглядит следующим образом:

├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── org
│       │       └── spring
│       │           └── springboot
│       │               ├── Application.java
│       │               ├── dao
│       │               │   └── CityRepository.java
│       │               ├── domain
│       │               │   └── City.java
│       │               ├── handler
│       │               │   └── CityHandler.java
│       │               └── webflux
│       │                   └── controller
│       │                       └── CityWebFluxController.java
│       └── resources
│           └── application.properties
└── target

Как и в случае со структурой каталогов, нам нужно написать следующее по порядку:

  • объект
  • Репозиторий классов уровня доступа к данным
  • Класс обработчика Обработчик
  • Класс контроллера Контроллер

объект

Создайте новый пакет org.spring.springboot.domain в качестве класса объектов для записи объектов города. Создайте новый объект City City, код выглядит следующим образом:

/**
 * 城市实体类
 *
 */
public class City {

    /**
     * 城市编号
     */
    private Long id;

    /**
     * 省份编号
     */
    private Long provinceId;

    /**
     * 城市名称
     */
    private String cityName;

    /**
     * 描述
     */
    private String description;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getProvinceId() {
        return provinceId;
    }

    public void setProvinceId(Long provinceId) {
        this.provinceId = provinceId;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

Город содержит номер города, номер провинции, название города и описание. В конкретной разработке инструменты Lombok будут использоваться для устранения многословного кода Java, особенно методов получения/установки POJO. Подробную информацию можно найти на официальном сайте Ломбока по адресу: projectlombok.org.

Уровень доступа к данным CityRepository

Создайте новый пакет org.spring.springboot.dao в качестве репозитория для написания класса слоя доступа к данным города. Создайте новый CityRepository со следующим кодом:

import org.spring.springboot.domain.City;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;

@Repository
public class CityRepository {

    private ConcurrentMap<Long, City> repository = new ConcurrentHashMap<>();

    private static final AtomicLong idGenerator = new AtomicLong(0);

    public Long save(City city) {
        Long id = idGenerator.incrementAndGet();
        city.setId(id);
        repository.put(id, city);
        return id;
    }

    public Collection<City> findAll() {
        return repository.values();
    }


    public City findCityById(Long id) {
        return repository.get(id);
    }

    public Long updateCity(City city) {
        repository.put(city.getId(), city);
        return city.getId();
    }

    public Long deleteCity(Long id) {
        repository.remove(id);
        return id;
    }
}

@RepositoryИспользуется для маркировки компонентов доступа к данным, то есть компонентов DAO. Код реализации использует имяrepositoryОбъект Map хранится как данные памяти, и для объекта реализуется определенная бизнес-логика.CityRepository Отвечает за упаковку и организацию уровня сохраняемости книги (операции с данными) для выполнения таких операций, как добавление, запрос и удаление.

Хранилище данных здесь не задействовано, а конкретное хранилище данных будет представлено позже.

Класс обработчика Обработчик

Создайте новый пакет org.spring.springboot.handler в качестве класса обработчика города CityHandler. Создайте новый CityHandler со следующим кодом:

import org.spring.springboot.dao.CityRepository;
import org.spring.springboot.domain.City;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Component
public class CityHandler {

    private final CityRepository cityRepository;

    @Autowired
    public CityHandler(CityRepository cityRepository) {
        this.cityRepository = cityRepository;
    }

    public Mono<Long> save(City city) {
        return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.save(city)));
    }

    public Mono<City> findCityById(Long id) {
        return Mono.justOrEmpty(cityRepository.findCityById(id));
    }

    public Flux<City> findAllCity() {
        return Flux.fromIterable(cityRepository.findAll());
    }

    public Mono<Long> modifyCity(City city) {
        return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.updateCity(city)));
    }

    public Mono<Long> deleteCity(Long id) {
        return Mono.create(cityMonoSink -> cityMonoSink.success(cityRepository.deleteCity(id)));
    }
}

@ComponentОтносится к компонентам в целом. Если компоненты не классифицированы должным образом, используйте эту аннотацию для аннотации. затем используйтеfinalа также@AutowiredАннотация заключается в том, чтобы внедрить CityRepository Bean в конструктор, и код выглядит следующим образом:

    private final CityRepository cityRepository;

    @Autowired
    public CityHandler(CityRepository cityRepository) {
        this.cityRepository = cityRepository;
    }

Как видно из возвращаемого значения, Mono и Flux подходят для двух сценариев, а именно:

  • Mono: реализует издателя и возвращает 0 или 1 элемент, т.е. один объект
  • Flux: реализует издателя и возвращает N элементов, которые являются объектом списка List.

Можно спросить, почему это не возвращает объекты напрямую, такие как City/Long/List. Причина в том, что использование Flux и Mono напрямую — это неблокирующий метод записи, который эквивалентен методу обратного вызова. Использование функционального стиля уменьшает количество обратных вызовов, поэтому соответствующий интерфейс не виден. Именно в этом преимущество WebFlux: неблокирующий + асинхронный вместе взятые.

Mono

Что такое Моно? Официальное описание выглядит следующим образом: Reactive Streams Publisher с базовыми операторами rx, который успешно завершается отправкой элемента или с ошибкой.

Mono — это реактивный потоковый издатель с базовым оператором rx. Элементы или ошибки могут быть успешно опубликованы. как показано на рисунке:

file

Обычно используемые моно методы:

  • Mono.create(): используйте MonoSink для создания Mono
  • Mono.justOrEmpty(): создает Mono из необязательного объекта или нулевого объекта.
  • Mono.error(): создает Mono, содержащий только сообщение об ошибке.
  • Mono.never(): создает Mono, который не содержит уведомлений о сообщениях.
  • Mono.delay(): после указанного времени задержки создайте Mono, получая число 0 в качестве уникального значения.

Flux

Что такое Флюс? Официальное описание выглядит следующим образом: Reactive Streams Publisher с операторами rx, который выдает от 0 до N элементов, а затем завершает работу (успешно или с ошибкой).

Flux — это реактивный потоковый издатель с базовым оператором rx. Может успешно публиковать от 0 до N элементов или ошибок. Flux на самом деле является дополнением к Mono. как показано на рисунке:

file

Так что будьте осторожны: если вы знаете, что издатель равен 0 или 1, используйте Mono.

Самое примечательное в Flux — это метод fromIterable. fromIterable(Iterable it) может публиковать элементы типа Iterable. Конечно, Flux также включает в себя базовые операции: map, merge, concat, flatMap, take, которые здесь не будут представлены.

Класс контроллера Контроллер

При разработке Spring Boot WebFlux настройка не требуется. Spring Boot WebFlux может быть разработан с использованием модели, управляемой аннотациями, с автоматической настройкой.

Новый каталог пакетовorg.spring.springboot.webflux.controllerи создайте каталог с именем CityWebFluxController для обработки различных бизнес-запросов HTTP Restful. код показывает, как показано ниже:

import org.spring.springboot.domain.City;
import org.spring.springboot.handler.CityHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping(value = "/city")
public class CityWebFluxController {

    @Autowired
    private CityHandler cityHandler;

    @GetMapping(value = "/{id}")
    public Mono<City> findCityById(@PathVariable("id") Long id) {
        return cityHandler.findCityById(id);
    }

    @GetMapping()
    public Flux<City> findAllCity() {
        return cityHandler.findAllCity();
    }

    @PostMapping()
    public Mono<Long> saveCity(@RequestBody City city) {
        return cityHandler.save(city);
    }

    @PutMapping()
    public Mono<Long> modifyCity(@RequestBody City city) {
        return cityHandler.modifyCity(city);
    }

    @DeleteMapping(value = "/{id}")
    public Mono<Long> deleteCity(@PathVariable("id") Long id) {
        return cityHandler.deleteCity(id);
    }
}

Здесь интерфейс реализован в стиле REST. Так что же такое REST?

REST — это архитектурный стиль, принадлежащий самому WEB и реализованный в соответствии со спецификацией HTTP 1.1. Полное название Representational State Transfer переводится как преобразование представительного состояния. Ресурс: Ресурс. Например, лента новостей; Репрезентативность: представление, такое как JSON, форматированный текст и т. д.; Передача состояния: изменение состояния. Реализовано через действия HTTP.

Чтобы понять REST, нужно понять пять ключевых элементов:

  • Ресурс
  • Представление ресурсов
  • Государственная передача
  • Единый интерфейс
  • Гипертекстовый привод

6 основных особенностей:

  • Ресурсно-ориентированный
  • Адресуемость
  • Связность
  • Безгражданство
  • Единый интерфейс
  • Гипертекстовый привод

Детали здесь не раскрываются, см. http://www.infoq.com/cn/articles/understanding-restful-style.

Знание ввода запроса, фильтров, перенаправления, преобразования и форматирования будет таким же, как и предыдущее знание MVC.Подробности см. в документе: https://docs.spring.io/spring/docs/current/spring-framework -reference/web-reactive.html

Запустить проект

Разработан проект CRUD Spring Boot Webflux, запустим проект для проверки. Используйте панель инструментов в правой части IDEA, нажмите вкладку «Проект Maven», нажмите «Использовать подключаемый модуль Maven».installЗаказ. Или используйте форму командной строки, в корневом каталоге проекта выполните Maven, чтобы очистить и установить команду проекта:

cd springboot-webflux-2-restful
mvn clean install

Смотрите успешный вывод в консоли:

... 省略
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:30 min
[INFO] Finished at: 2017-10-15T10:00:54+08:00
[INFO] Final Memory: 31M/174M
[INFO] ------------------------------------------------------------------------

Выполнить в IDEAApplicationЗапуск класса в обычном режиме или в режиме отладки. Результат успешного запуска можно увидеть в консоли:

... 省略
2018-04-10 08:43:39.932  INFO 2052 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext     : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-04-10 08:43:39.935  INFO 2052 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2018-04-10 08:43:39.960  INFO 2052 --- [           main] org.spring.springboot.Application        : Started Application in 6.547 seconds (JVM running for 9.851)

Откройте инструмент POST MAN, необходимый для разработки. Сделайте следующее:

Добавить информацию о городе POST http://127.0.0.1:8080/city

file

Получить список информации о городе GET http://127.0.0.1:8080/city

file

Другие интерфейсы демонстрироваться не будут.

Суммировать

Здесь рассматриваются некоторые функции Spring WebFlux для создания базовых проектов CRUD без базовой базы данных. Чтобы лучше показать, как создать поток Flux и как с ним работать. Далее будет описано, как работать с хранилищем данных.

Эта статья опубликована в блогеOpenWriteвыпускать!