{"id":325758,"date":"2021-06-30T15:01:03","date_gmt":"2021-06-30T15:01:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=325758"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=325758","title":{"rendered":"\u0420\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435\u00a0\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e Spring, \u0447\u0430\u0441\u0442\u044c 3 WebFlux"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u042d\u0442\u043e \u0442\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/publication\/edit\/565000\/\" rel=\"noopener noreferrer nofollow\"><u>\u0441\u0435\u0440\u0438\u0438 \u0431\u043b\u043e\u0433\u043e\u0432 \u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438<\/u><\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044f \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u044e \u0432\u0430\u0441 \u0441 WebFlux &#8212; \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c Spring.  <\/p>\n<h3>1. \u0412\u0412\u0415\u0414\u0415\u041d\u0418\u0415 \u0412 SPRING WEBFLUX<\/h3>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f Spring &#8212; Spring Web MVC &#8212; \u0431\u044b\u043b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u0434\u043b\u044f Servlet API \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 Servlet.<\/p>\n<p>WebFlux \u0431\u044b\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c Spring Framework 5.0.&nbsp;\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Spring MVC, \u043e\u043d \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 Servlet API.&nbsp;\u041e\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e Reactive Streams \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0435\u043a\u0442 Reactor (\u0441\u043c. <a href=\"https:\/\/habr.com\/ru\/post\/565050\/\" rel=\"noopener noreferrer nofollow\"><u>\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043f\u043e\u0441\u0442 \u0432 \u0431\u043b\u043e\u0433\u0435<\/u><\/a>&nbsp;).<\/p>\n<p>WebFlux \u0442\u0440\u0435\u0431\u0443\u0435\u0442 Reactor \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043d\u043e \u043e\u043d \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 Reactive Streams.<\/p>\n<h4>1.1 \u041c\u041e\u0414\u0415\u041b\u0418 \u041f\u0420\u041e\u0413\u0420\u0410\u041c\u041c\u0418\u0420\u041e\u0412\u0410\u041d\u0418\u042f<\/h4>\n<p>Spring WebFlux \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f: \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e.<\/p>\n<p><strong>1.1.1 \u0410\u041d\u041d\u041e\u0422\u0418\u0420\u041e\u0412\u0410\u041d\u041d\u042b\u0415 \u041a\u041e\u041d\u0422\u0420\u041e\u041b\u041b\u0415\u0420\u042b<\/strong><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441\u043e Spring MVC, \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432 \u043d\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0435 \u0436\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0438\u0437 \u0432\u0435\u0431-\u043c\u043e\u0434\u0443\u043b\u044f Spring, \u0447\u0442\u043e \u0438 \u0432 Spring MVC.&nbsp;\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b Mono \u0438 Flux.&nbsp;\u0421\u043c. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 RestController \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439:<\/p>\n<pre><code class=\"java\">@RestController @RequestMapping(\"\/students\") public class StudentController {      @Autowired     private StudentService studentService;       public StudentController() {     }      @GetMapping(\"\/{id}\")     public Mono&lt;ResponseEntity&lt;Student&gt;&gt; getStudent(@PathVariable long id) {         return studentService.findStudentById(id)                 .map(ResponseEntity::ok)                 .defaultIfEmpty(ResponseEntity.notFound().build());     }      @GetMapping     public Flux&lt;Student&gt; listStudents(@RequestParam(name = \"name\", required = false) String name) {         return studentService.findStudentsByName(name);     }      @PostMapping     public Mono&lt;Student&gt; addNewStudent(@RequestBody Student student) {         return studentService.addNewStudent(student);     }      @PutMapping(\"\/{id}\")     public Mono&lt;ResponseEntity&lt;Student&gt;&gt; updateStudent(@PathVariable long id, @RequestBody Student student) {         return studentService.updateStudent(id, student)                 .map(ResponseEntity::ok)                 .defaultIfEmpty(ResponseEntity.notFound().build());     }      @DeleteMapping(\"\/{id}\")     public Mono&lt;ResponseEntity&lt;Void&gt;&gt; deleteStudent(@PathVariable long id) {         return studentService.findStudentById(id)                 .flatMap(s -&gt;                         studentService.deleteStudent(s)                                 .then(Mono.just(new ResponseEntity&lt;Void&gt;(HttpStatus.OK)))                 )                 .defaultIfEmpty(new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND));     } }<\/code><\/pre>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<ul>\n<li>\n<p><code>map <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430,&nbsp;\u0438\u0441\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u043e\u0433\u043e Mono, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u043a \u043d\u0435\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p><code>flatMap <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442,&nbsp;\u0438\u0441\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0439 Mono \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435,&nbsp;\u0438\u0437\u043b\u0443\u0447\u0430\u0435\u043c\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u0438\u043c Mono.<\/p>\n<\/li>\n<li>\n<p><code>defaultIfEmpty <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e,&nbsp;\u0435\u0441\u043b\u0438 Mono \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445 &#8212;&nbsp;\u043b\u0438\u0431\u043e \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<p><strong>1.1.2 \u0424\u0423\u041d\u041a\u0426\u0418\u041e\u041d\u0410\u041b\u042c\u041d\u042b\u0415 \u041a\u041e\u041d\u0415\u0427\u041d\u042b\u0415 \u0422\u041e\u0427\u041a\u0418<\/strong><\/p>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.&nbsp;\u041e\u043d \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f\u0445&nbsp;<code>HandlerFunctions <\/code>\u0438 <code>RouterFunctions<\/code>.<\/p>\n<p>HandlerFunctions \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"java\">@FunctionalInterface public interface HandlerFunction&lt;T extends ServerResponse&gt; {     Mono&lt;T&gt; handle(ServerRequest request); } <\/code><\/pre>\n<p>RouterFunction \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a HandlerFunctions: <\/p>\n<pre><code class=\"java\">@FunctionalInterface public interface RouterFunction&lt;T extends ServerResponse&gt; {     Mono&lt;HandlerFunction&lt;T&gt;&gt; route(ServerRequest request);     ... } <\/code><\/pre>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044f \u0441 \u0442\u0435\u043c \u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0443\u0447\u0435\u043d\u0438\u043a\u0430, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c.  <\/p>\n<p>A StudentRouter:<\/p>\n<pre><code class=\"java\">@Configuration public class StudentRouter {      @Bean     public RouterFunction&lt;ServerResponse&gt; route(StudentHandler studentHandler){         return RouterFunctions             .route(                 GET(\"\/students\/{id:[0-9]+}\")                     .and(accept(APPLICATION_JSON)), studentHandler::getStudent)             .andRoute(                 GET(\"\/students\")                     .and(accept(APPLICATION_JSON)), studentHandler::listStudents)             .andRoute(                 POST(\"\/students\")                     .and(accept(APPLICATION_JSON)),studentHandler::addNewStudent)             .andRoute(                 PUT(\"students\/{id:[0-9]+}\")                     .and(accept(APPLICATION_JSON)), studentHandler::updateStudent)             .andRoute(                 DELETE(\"\/students\/{id:[0-9]+}\")                     .and(accept(APPLICATION_JSON)), studentHandler::deleteStudent);     } }<\/code><\/pre>\n<p>\u0418 StudentHandler:<\/p>\n<pre><code class=\"java\">@Component public class StudentHandler {      private StudentService studentService;      public StudentHandler(StudentService studentService) {         this.studentService = studentService;     }      public Mono&lt;ServerResponse&gt; getStudent(ServerRequest serverRequest) {         Mono&lt;Student&gt; studentMono = studentService.findStudentById(                 Long.parseLong(serverRequest.pathVariable(\"id\")));         return studentMono.flatMap(student -&gt; ServerResponse.ok()                 .body(fromValue(student)))                 .switchIfEmpty(ServerResponse.notFound().build());     }      public Mono&lt;ServerResponse&gt; listStudents(ServerRequest serverRequest) {         String name = serverRequest.queryParam(\"name\").orElse(null);         return ServerResponse.ok()                 .contentType(MediaType.APPLICATION_JSON)                 .body(studentService.findStudentsByName(name), Student.class);     }      public Mono&lt;ServerResponse&gt; addNewStudent(ServerRequest serverRequest) {         Mono&lt;Student&gt; studentMono = serverRequest.bodyToMono(Student.class);         return studentMono.flatMap(student -&gt;                 ServerResponse.status(HttpStatus.OK)                         .contentType(MediaType.APPLICATION_JSON)                         .body(studentService.addNewStudent(student), Student.class));      }      public Mono&lt;ServerResponse&gt; updateStudent(ServerRequest serverRequest) {         final long studentId = Long.parseLong(serverRequest.pathVariable(\"id\"));         Mono&lt;Student&gt; studentMono = serverRequest.bodyToMono(Student.class);          return studentMono.flatMap(student -&gt;                 ServerResponse.status(HttpStatus.OK)                         .contentType(MediaType.APPLICATION_JSON)                         .body(studentService.updateStudent(studentId, student), Student.class));     }      public Mono&lt;ServerResponse&gt; deleteStudent(ServerRequest serverRequest) {         final long studentId = Long.parseLong(serverRequest.pathVariable(\"id\"));         return studentService                 .findStudentById(studentId)                 .flatMap(s -&gt; ServerResponse.noContent().build(studentService.deleteStudent(s)))                 .switchIfEmpty(ServerResponse.notFound().build());     } }<\/code><\/pre>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<ul>\n<li>\n<p><code>switchIfEmpty <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0442\u0443 \u0436\u0435 \u0446\u0435\u043b\u044c,&nbsp;<code>defaultIfEmpty<\/code>, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b&nbsp;\u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043e\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e Mono.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044f \u0434\u0432\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0435\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439, \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0434\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u043f\u043e\u043b\u0430\u0433\u0430\u044f\u0441\u044c \u043d\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438, \u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044f\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u0443\u0447\u0448\u0438\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<h4>1.2 \u041f\u041e\u0414\u0414\u0415\u0420\u0416\u041a\u0410 \u0421\u0415\u0420\u0412\u0415\u0420\u0410<\/h4>\n<p>WebFlux \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0441\u0440\u0435\u0434\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u043b\u0435\u0442\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Netty \u0438 Undertow (\u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0440\u0435\u0436\u0438\u043c), \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432 \u0441\u0440\u0435\u0434\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u043b\u0435\u0442\u043e\u0432 3.1+, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Tomcat \u0438 Jetty.<\/p>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0442\u0430\u0440\u0442\u0435\u0440 Spring Boot WebFlux \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Netty, \u043d\u043e \u0435\u0433\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u0438\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 Maven \u0438\u043b\u0438 Gradle.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 Tomcat, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435 spring-boot-starter-netty \u0438\u0437 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 spring-boot-starter-webflux \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 spring-boot-starter-tomcat:<\/p>\n<pre><code class=\"xml\">&lt;dependency&gt;     &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;     &lt;artifactId&gt;spring-boot-starter-webflux&lt;\/artifactId&gt;     &lt;exclusions&gt;         &lt;exclusion&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-netty&lt;\/artifactId&gt;         &lt;\/exclusion&gt;     &lt;\/exclusions&gt; &lt;\/dependency&gt; &lt;dependency&gt;     &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;     &lt;artifactId&gt;spring-boot-starter-tomcat&lt;\/artifactId&gt; &lt;\/dependency&gt;<\/code><\/pre>\n<h4>1.3 \u041a\u041e\u041d\u0424\u0418\u0413\u0423\u0420\u0410\u0426\u0418\u042f<\/h4>\n<p>Spring Boot \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 Spring WebFlux, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0431\u0449\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445.&nbsp;\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 WebFlux,&nbsp;\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@EnableWebFlux <\/code>(\u044d\u0442\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 Spring \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Spring WebFlux).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Spring Boot WebFlux \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e WebFlux, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 @Configuration \u0442\u0438\u043f\u0430 WebFluxConfigurer (\u043d\u043e \u0431\u0435\u0437 @EnableWebFlux).<\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b&nbsp;\u0441\u043c. \u0432&nbsp;\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-framework\/docs\/current\/reference\/html\/web-reactive.html#webflux-config\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 WebFlux<\/u><\/a>.<\/p>\n<h3>2. \u0417\u0410\u0429\u0418\u0422\u0410 \u0412\u0410\u0428\u0418\u0425 \u041a\u041e\u041d\u0415\u0427\u041d\u042b\u0425 \u0422\u041e\u0427\u0415\u041a<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Spring Security WebFlux, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c spring-boot-starter-security.&nbsp;\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u0432&nbsp;<code>@EnableWebFluxSecurity <\/code>\u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e \u0432 \u0441\u0432\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 Configuration (\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0441 Spring Security 5.0).<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u200b\u200b\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0432\u0443\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043e\u0434\u0438\u043d \u0441 \u0440\u043e\u043b\u044c\u044e USER, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441 \u0440\u043e\u043b\u044c\u044e ADMIN, \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e HTTP \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u043e\u043b\u044c ADMIN \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0443\u0442\u0438 \/student\/admin:<\/p>\n<pre><code class=\"java\">@EnableWebFluxSecurity public class SecurityConfig {      @Bean     public MapReactiveUserDetailsService userDetailsService() {          UserDetails user = User                 .withUsername(\"user\")                 .password(passwordEncoder().encode(\"userpwd\"))                 .roles(\"USER\")                 .build();          UserDetails admin = User                 .withUsername(\"admin\")                 .password(passwordEncoder().encode(\"adminpwd\"))                 .roles(\"ADMIN\")                 .build();          return new MapReactiveUserDetailsService(user, admin);     }      @Bean     public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {         return http.authorizeExchange()                 .pathMatchers(\"\/students\/admin\")                 .hasAuthority(\"ROLE_ADMIN\")                 .anyExchange()                 .authenticated()                 .and().httpBasic()                 .and().build();     }      @Bean     public PasswordEncoder passwordEncoder() {         return new BCryptPasswordEncoder();     }  }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0449\u0438\u0442\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434, \u0430 \u043d\u0435 \u043f\u0443\u0442\u044c, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@EnableReactiveMethodSecurity <\/code>\u043a \u0432\u0430\u0448\u0435\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438: <\/p>\n<pre><code class=\"java\">@EnableWebFluxSecurity @EnableReactiveMethodSecurity public class SecurityConfig {     ... }<\/code><\/pre>\n<p>\u0410 \u0437\u0430\u0442\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c&nbsp;<code>@PreAuthorize <\/code>\u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e \u043a \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u043c\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u0430\u043c.&nbsp;\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0445\u043e\u0442\u0435\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0438 \u043c\u0435\u0442\u043e\u0434\u044b POST, PUT \u0438 DELETE \u0431\u044b\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0438 ADMIN.&nbsp;\u0417\u0430\u0442\u0435\u043c \u043a \u044d\u0442\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e PreAuthorize, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"java\">@DeleteMapping(\"\/{id}\") @PreAuthorize(\"hasRole('ADMIN')\") public Mono&lt;ResponseEntity&lt;Void&gt;&gt; deleteStudent(@PathVariable long id) {     ... } <\/code><\/pre>\n<p>Spring Security \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0443\u044e \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 WebFlux, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u0449\u0438\u0442\u0443 CSRF, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e OAuth2 \u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e X.509.&nbsp;\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0447\u0442\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Spring Security:&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-security\/site\/docs\/current\/reference\/html5\/#reactive-applications\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/a><\/p>\n<h3>3. \u0412\u0415\u0411-\u041a\u041b\u0418\u0415\u041d\u0422<\/h3>\n<p>Spring WebFlux \u0442\u0430\u043a\u0436\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439, \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442.&nbsp;\u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439, \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0439 API, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 Reactor.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c (\u0435\u0449\u0435 \u0440\u0430\u0437) \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a WebClient \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430\u0448\u0435\u0433\u043e StudentController:<\/p>\n<pre><code class=\"java\">public class StudentWebClient {      WebClient client = WebClient.create(\"http:\/\/localhost:8080\");          public Mono&lt;Student&gt; get(long id) {             return client                     .get()                     .uri(\"\/students\/\" + id)                     .headers(headers -&gt; headers.setBasicAuth(\"user\", \"userpwd\"))                     .retrieve()                     .bodyToMono(Student.class);         }              public Flux&lt;Student&gt; getAll() {             return client.get()                     .uri(\"\/students\")                     .headers(headers -&gt; headers.setBasicAuth(\"user\", \"userpwd\"))                     .retrieve()                     .bodyToFlux(Student.class);         }              public Flux&lt;Student&gt; findByName(String name) {             return client.get()                     .uri(uriBuilder -&gt; uriBuilder.path(\"\/students\")                     .queryParam(\"name\", name)                     .build())                     .headers(headers -&gt; headers.setBasicAuth(\"user\", \"userpwd\"))                     .retrieve()                     .bodyToFlux(Student.class);         }              public Mono&lt;Student&gt; create(Student s)  {             return client.post()                     .uri(\"\/students\")                     .headers(headers -&gt; headers.setBasicAuth(\"admin\", \"adminpwd\"))                     .body(Mono.just(s), Student.class)                     .retrieve()                     .bodyToMono(Student.class);         }              public Mono&lt;Student&gt; update(Student student)  {             return client                     .put()                     .uri(\"\/students\/\" + student.getId())                     .headers(headers -&gt; headers.setBasicAuth(\"admin\", \"adminpwd\"))                     .body(Mono.just(student), Student.class)                     .retrieve()                     .bodyToMono(Student.class);         }              public Mono&lt;Void&gt; delete(long id) {             return client                     .delete()                     .uri(\"\/students\/\" + id)                     .headers(headers -&gt; headers.setBasicAuth(\"admin\", \"adminpwd\"))                     .retrieve()                     .bodyToMono(Void.class);         } }<\/code><\/pre>\n<h3>4. \u0422\u0415\u0421\u0422\u0418\u0420\u041e\u0412\u0410\u041d\u0418\u0415<\/h3>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f WebFlux \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 WebTestClient, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 API, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c WebClient.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 StudentController \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e WebTestClient:<\/p>\n<pre><code class=\"java\">@ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class StudentControllerTest {     @Autowired     WebTestClient webClient;      @Test     @WithMockUser(roles = \"USER\")     void test_getStudents() {         webClient.get().uri(\"\/students\")                 .header(HttpHeaders.ACCEPT, \"application\/json\")                 .exchange()                 .expectStatus().isOk()                 .expectHeader().contentType(MediaType.APPLICATION_JSON)                 .expectBodyList(Student.class);      }      @Test     @WithMockUser(roles = \"ADMIN\")     void testAddNewStudent() {         Student newStudent = new Student();         newStudent.setName(\"some name\");         newStudent.setAddress(\"an address\");          webClient.post().uri(\"\/students\")                 .contentType(MediaType.APPLICATION_JSON)                 .accept(MediaType.APPLICATION_JSON)                 .body(Mono.just(newStudent), Student.class)                 .exchange()                 .expectStatus().isOk()                 .expectHeader().contentType(MediaType.APPLICATION_JSON)                 .expectBody()                 .jsonPath(\"$.id\").isNotEmpty()                 .jsonPath(\"$.name\").isEqualTo(newStudent.getName())                 .jsonPath(\"$.address\").isEqualTo(newStudent.getAddress());     }      ... } <\/code><\/pre>\n<h3>5. WEBSOCKETS \u0418 RSOCKET<\/h3>\n<h4>5.1 \u0412\u0415\u0411-\u0421\u041e\u041a\u0415\u0422\u042b<\/h4>\n<p>\u0412 Spring 5 WebSockets \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438.&nbsp;\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 WebSocket, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e&nbsp;<code>WebSocketHandler <\/code>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"java\">Mono&lt;Void&gt; handle(WebSocketSession session)<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f WebSocket \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0430\u043d\u0441.&nbsp;\u041e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432&nbsp;<code>WebSocketSession <\/code>\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 Mono &lt;Void&gt;, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u0435\u0430\u043d\u0441\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>WebSocketSession \u0438\u043c\u0435\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0438 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432:<\/p>\n<pre><code class=\"java\">Flux&lt;WebSocketMessage&gt; receive() Mono&lt;Void&gt; send(Publisher&lt;WebSocketMessage&gt; messages)<\/code><\/pre>\n<p>Spring WebFlux \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442&nbsp;<code>WebSocketClient <\/code>\u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f Reactor Netty, Tomcat, Jetty, Undertow \u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 Java.<\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0447\u0442\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0433\u043b\u0430\u0432\u0443 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Spring&#8217;s Web on Reactive Stack:&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-framework\/docs\/current\/reference\/html\/web-reactive.html#webflux-websocket\" rel=\"noopener noreferrer nofollow\">WebSockets<\/a><\/p>\n<h4>5.2 RSOCKET<\/h4>\n<p>RSocket &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043f\u043e \u0441\u0435\u0442\u0438.&nbsp;\u042d\u0442\u043e \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u0430\u0445 \u0431\u0430\u0439\u0442\u043e\u0432\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a TCP, WebSockets \u0438 Aeron.&nbsp;\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443 \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u0441\u0442 \u0432 \u0431\u043b\u043e\u0433\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043c\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u0433\u0430&nbsp;P\u00e4r:&nbsp;<a href=\"https:\/\/callistaenterprise.se\/blogg\/teknik\/2020\/06\/05\/rsocket-part-1\/\" rel=\"noopener noreferrer nofollow\"><u>An introduction to RSocket<\/u><\/a><\/p>\n<p>\u0410 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 Spring Framework \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-framework\/docs\/current\/reference\/html\/web-reactive.html#rsocket\" rel=\"noopener noreferrer nofollow\"><u>RSocket<\/u><\/a><\/p>\n<h3>6. \u041f\u041e\u0414\u0412\u041e\u0414\u042f \u0418\u0422\u041e\u0413\u2026<\/h3>\n<p>\u042d\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0431\u043b\u043e\u0433\u0435 \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u043e, \u043a\u0430\u043a WebFlux \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.&nbsp;\u0412&nbsp;<a href=\"https:\/\/habr.com\/ru\/post\/565060\/\" rel=\"noopener noreferrer nofollow\"><u>\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u043f\u043e\u0441\u0442\u0435<\/u><\/a>&nbsp;\u044d\u0442\u043e\u0439 \u0441\u0435\u0440\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043d\u0430\u0448 \u0441\u0442\u0435\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u043c, \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0443\u044e \u0441\u0432\u044f\u0437\u044c \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 &#8212; \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e R2DBC (Reactive Relational Database Connectivity)!<\/p>\n<h4>\u0421\u0421\u042b\u041b\u041a\u0418<\/h4>\n<p><a href=\"https:\/\/docs.spring.io\/spring-framework\/docs\/current\/reference\/html\/web-reactive.html\" rel=\"noopener noreferrer nofollow\">Spring Framework documentation &#8212; Web on Reactive Stack<\/a><\/p>\n<p><a href=\"https:\/\/docs.spring.io\/spring-boot\/docs\/current\/reference\/html\/spring-boot-features.html#boot-features-webflux\" rel=\"noopener noreferrer nofollow\">Spring Boot Features &#8212; The Spring WebFlux framework<\/a><\/p>\n<p><a href=\"https:\/\/docs.spring.io\/spring-security\/site\/docs\/current\/reference\/html5\/#reactive-applications\" rel=\"noopener noreferrer nofollow\">Spring Security &#8212; Reactive Applications<\/a><\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/565056\/\"> https:\/\/habr.com\/ru\/post\/565056\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u042d\u0442\u043e \u0442\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/publication\/edit\/565000\/\" rel=\"noopener noreferrer nofollow\"><u>\u0441\u0435\u0440\u0438\u0438 \u0431\u043b\u043e\u0433\u043e\u0432 \u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438<\/u><\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044f \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u044e \u0432\u0430\u0441 \u0441 WebFlux &#8212; \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c Spring.  <\/p>\n<h3>1. \u0412\u0412\u0415\u0414\u0415\u041d\u0418\u0415 \u0412 SPRING WEBFLUX<\/h3>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f Spring &#8212; Spring Web MVC &#8212; \u0431\u044b\u043b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u0434\u043b\u044f Servlet API \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 Servlet.<\/p>\n<p>WebFlux \u0431\u044b\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c Spring Framework 5.0.&nbsp;\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Spring MVC, \u043e\u043d \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 Servlet API.&nbsp;\u041e\u043d \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e Reactive Streams \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0435\u043a\u0442 Reactor (\u0441\u043c. <a href=\"https:\/\/habr.com\/ru\/post\/565050\/\" rel=\"noopener noreferrer nofollow\"><u>\u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043f\u043e\u0441\u0442 \u0432 \u0431\u043b\u043e\u0433\u0435<\/u><\/a>&nbsp;).<\/p>\n<p>WebFlux \u0442\u0440\u0435\u0431\u0443\u0435\u0442 Reactor \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043d\u043e \u043e\u043d \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 Reactive Streams.<\/p>\n<h4>1.1 \u041c\u041e\u0414\u0415\u041b\u0418 \u041f\u0420\u041e\u0413\u0420\u0410\u041c\u041c\u0418\u0420\u041e\u0412\u0410\u041d\u0418\u042f<\/h4>\n<p>Spring WebFlux \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f: \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e.<\/p>\n<p><strong>1.1.1 \u0410\u041d\u041d\u041e\u0422\u0418\u0420\u041e\u0412\u0410\u041d\u041d\u042b\u0415 \u041a\u041e\u041d\u0422\u0420\u041e\u041b\u041b\u0415\u0420\u042b<\/strong><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441\u043e Spring MVC, \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432 \u043d\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0435 \u0436\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0438\u0437 \u0432\u0435\u0431-\u043c\u043e\u0434\u0443\u043b\u044f Spring, \u0447\u0442\u043e \u0438 \u0432 Spring MVC.&nbsp;\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0442\u0438\u043f\u044b Mono \u0438 Flux.&nbsp;\u0421\u043c. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 RestController \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439:<\/p>\n<pre><code class=\"java\">@RestController @RequestMapping(\"\/students\") public class StudentController {      @Autowired     private StudentService studentService;       public StudentController() {     }      @GetMapping(\"\/{id}\")     public Mono&lt;ResponseEntity&lt;Student&gt;&gt; getStudent(@PathVariable long id) {         return studentService.findStudentById(id)                 .map(ResponseEntity::ok)                 .defaultIfEmpty(ResponseEntity.notFound().build());     }      @GetMapping     public Flux&lt;Student&gt; listStudents(@RequestParam(name = \"name\", required = false) String name) {         return studentService.findStudentsByName(name);     }      @PostMapping     public Mono&lt;Student&gt; addNewStudent(@RequestBody Student student) {         return studentService.addNewStudent(student);     }      @PutMapping(\"\/{id}\")     public Mono&lt;ResponseEntity&lt;Student&gt;&gt; updateStudent(@PathVariable long id, @RequestBody Student student) {         return studentService.updateStudent(id, student)                 .map(ResponseEntity::ok)                 .defaultIfEmpty(ResponseEntity.notFound().build());     }      @DeleteMapping(\"\/{id}\")     public Mono&lt;ResponseEntity&lt;Void&gt;&gt; deleteStudent(@PathVariable long id) {         return studentService.findStudentById(id)                 .flatMap(s -&gt;                         studentService.deleteStudent(s)                                 .then(Mono.just(new ResponseEntity&lt;Void&gt;(HttpStatus.OK)))                 )                 .defaultIfEmpty(new ResponseEntity&lt;&gt;(HttpStatus.NOT_FOUND));     } }<\/code><\/pre>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<ul>\n<li>\n<p><code>map <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430,&nbsp;\u0438\u0441\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u043e\u0433\u043e Mono, \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u043a \u043d\u0435\u043c\u0443.<\/p>\n<\/li>\n<li>\n<p><code>flatMap <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442,&nbsp;\u0438\u0441\u043f\u0443\u0441\u043a\u0430\u0435\u043c\u044b\u0439 Mono \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435,&nbsp;\u0438\u0437\u043b\u0443\u0447\u0430\u0435\u043c\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u0438\u043c Mono.<\/p>\n<\/li>\n<li>\n<p><code>defaultIfEmpty <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e,&nbsp;\u0435\u0441\u043b\u0438 Mono \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445 &#8212;&nbsp;\u043b\u0438\u0431\u043e \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<p><strong>1.1.2 \u0424\u0423\u041d\u041a\u0426\u0418\u041e\u041d\u0410\u041b\u042c\u041d\u042b\u0415 \u041a\u041e\u041d\u0415\u0427\u041d\u042b\u0415 \u0422\u041e\u0427\u041a\u0418<\/strong><\/p>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u043b\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.&nbsp;\u041e\u043d \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f\u0445&nbsp;<code>HandlerFunctions <\/code>\u0438 <code>RouterFunctions<\/code>.<\/p>\n<p>HandlerFunctions \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"java\">@FunctionalInterface public interface HandlerFunction&lt;T extends ServerResponse&gt; {     Mono&lt;T&gt; handle(ServerRequest request); } <\/code><\/pre>\n<p>RouterFunction \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a HandlerFunctions: <\/p>\n<pre><code class=\"java\">@FunctionalInterface public interface RouterFunction&lt;T extends ServerResponse&gt; {     Mono&lt;HandlerFunction&lt;T&gt;&gt; route(ServerRequest request);     ... } <\/code><\/pre>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044f \u0441 \u0442\u0435\u043c \u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u0443\u0447\u0435\u043d\u0438\u043a\u0430, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0438\u043b\u044c.  <\/p>\n<p>A StudentRouter:<\/p>\n<pre><code class=\"java\">@Configuration public class StudentRouter {      @Bean     public RouterFunction&lt;ServerResponse&gt; route(StudentHandler studentHandler){         return RouterFunctions             .route(                 GET(\"\/students\/{id:[0-9]+}\")                     .and(accept(APPLICATION_JSON)), studentHandler::getStudent)             .andRoute(                 GET(\"\/students\")                     .and(accept(APPLICATION_JSON)), studentHandler::listStudents)             .andRoute(                 POST(\"\/students\")                     .and(accept(APPLICATION_JSON)),studentHandler::addNewStudent)             .andRoute(                 PUT(\"students\/{id:[0-9]+}\")                     .and(accept(APPLICATION_JSON)), studentHandler::updateStudent)             .andRoute(                 DELETE(\"\/students\/{id:[0-9]+}\")                     .and(accept(APPLICATION_JSON)), studentHandler::deleteStudent);     } }<\/code><\/pre>\n<p>\u0418 StudentHandler:<\/p>\n<pre><code class=\"java\">@Component public class StudentHandler {      private StudentService studentService;      public StudentHandler(StudentService studentService) {         this.studentService = studentService;     }      public Mono&lt;ServerResponse&gt; getStudent(ServerRequest serverRequest) {         Mono&lt;Student&gt; studentMono = studentService.findStudentById(                 Long.parseLong(serverRequest.pathVariable(\"id\")));         return studentMono.flatMap(student -&gt; ServerResponse.ok()                 .body(fromValue(student)))                 .switchIfEmpty(ServerResponse.notFound().build());     }      public Mono&lt;ServerResponse&gt; listStudents(ServerRequest serverRequest) {         String name = serverRequest.queryParam(\"name\").orElse(null);         return ServerResponse.ok()                 .contentType(MediaType.APPLICATION_JSON)                 .body(studentService.findStudentsByName(name), Student.class);     }      public Mono&lt;ServerResponse&gt; addNewStudent(ServerRequest serverRequest) {         Mono&lt;Student&gt; studentMono = serverRequest.bodyToMono(Student.class);         return studentMono.flatMap(student -&gt;                 ServerResponse.status(HttpStatus.OK)                         .contentType(MediaType.APPLICATION_JSON)                         .body(studentService.addNewStudent(student), Student.class));      }      public Mono&lt;ServerResponse&gt; updateStudent(ServerRequest serverRequest) {         final long studentId = Long.parseLong(serverRequest.pathVariable(\"id\"));         Mono&lt;Student&gt; studentMono = serverRequest.bodyToMono(Student.class);          return studentMono.flatMap(student -&gt;                 ServerResponse.status(HttpStatus.OK)                         .contentType(MediaType.APPLICATION_JSON)                         .body(studentService.updateStudent(studentId, student), Student.class));     }      public Mono&lt;ServerResponse&gt; deleteStudent(ServerRequest serverRequest) {         final long studentId = Long.parseLong(serverRequest.pathVariable(\"id\"));         return studentService                 .findStudentById(studentId)                 .flatMap(s -&gt; ServerResponse.noContent().build(studentService.deleteStudent(s)))                 .switchIfEmpty(ServerResponse.notFound().build());     } }<\/code><\/pre>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435:<\/p>\n<ul>\n<li>\n<p><code>switchIfEmpty <\/code>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0442\u0443 \u0436\u0435 \u0446\u0435\u043b\u044c,&nbsp;<code>defaultIfEmpty<\/code>, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b&nbsp;\u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043e\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e Mono.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044f \u0434\u0432\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0435\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439, \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0434\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u043f\u043e\u043b\u0430\u0433\u0430\u044f\u0441\u044c \u043d\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438, \u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u044f\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u0443\u0447\u0448\u0438\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<h4>1.2 \u041f\u041e\u0414\u0414\u0415\u0420\u0416\u041a\u0410 \u0421\u0415\u0420\u0412\u0415\u0420\u0410<\/h4>\n<p>WebFlux \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0441\u0440\u0435\u0434\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u043b\u0435\u0442\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Netty \u0438 Undertow (\u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0440\u0435\u0436\u0438\u043c), \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432 \u0441\u0440\u0435\u0434\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u043b\u0435\u0442\u043e\u0432 3.1+, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a Tomcat \u0438 Jetty.<\/p>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0442\u0430\u0440\u0442\u0435\u0440 Spring Boot WebFlux \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Netty, \u043d\u043e \u0435\u0433\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u0438\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 Maven \u0438\u043b\u0438 Gradle.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 Tomcat, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435 spring-boot-starter-netty \u0438\u0437 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 spring-boot-starter-webflux \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 spring-boot-starter-tomcat:<\/p>\n<pre><code class=\"xml\">&lt;dependency&gt;     &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;     &lt;artifactId&gt;spring-boot-starter-webflux&lt;\/artifactId&gt;     &lt;exclusions&gt;         &lt;exclusion&gt;             &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;             &lt;artifactId&gt;spring-boot-starter-netty&lt;\/artifactId&gt;         &lt;\/exclusion&gt;     &lt;\/exclusions&gt; &lt;\/dependency&gt; &lt;dependency&gt;     &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;     &lt;artifactId&gt;spring-boot-starter-tomcat&lt;\/artifactId&gt; &lt;\/dependency&gt;<\/code><\/pre>\n<h4>1.3 \u041a\u041e\u041d\u0424\u0418\u0413\u0423\u0420\u0410\u0426\u0418\u042f<\/h4>\n<p>Spring Boot \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 Spring WebFlux, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0431\u0449\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445.&nbsp;\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 WebFlux,&nbsp;\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e <code>@EnableWebFlux <\/code>(\u044d\u0442\u0430 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 Spring \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 Spring WebFlux).<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e Spring Boot WebFlux \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e WebFlux, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 @Configuration \u0442\u0438\u043f\u0430 WebFluxConfigurer (\u043d\u043e \u0431\u0435\u0437 @EnableWebFlux).<\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b&nbsp;\u0441\u043c. \u0432&nbsp;\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-framework\/docs\/current\/reference\/html\/web-reactive.html#webflux-config\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 WebFlux<\/u><\/a>.<\/p>\n<h3>2. \u0417\u0410\u0429\u0418\u0422\u0410 \u0412\u0410\u0428\u0418\u0425 \u041a\u041e\u041d\u0415\u0427\u041d\u042b\u0425 \u0422\u041e\u0427\u0415\u041a<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Spring Security WebFlux, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c spring-boot-starter-security.&nbsp;\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u0432&nbsp;<code>@EnableWebFluxSecurity <\/code>\u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044e \u0432 \u0441\u0432\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 Configuration (\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0441 Spring Security 5.0).<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u200b\u200b\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0432\u0443\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043e\u0434\u0438\u043d \u0441 \u0440\u043e\u043b\u044c\u044e USER, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441 \u0440\u043e\u043b\u044c\u044e ADMIN, \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e HTTP \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u043e\u043b\u044c ADMIN \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0443\u0442\u0438 \/student\/admin:<\/p>\n<pre><code class=\"java\">@EnableWebFluxSecurity public class SecurityConfig {      @Bean     public MapReactiveUserDetailsService userDetailsService() {          UserDetails user = User                 .withUsername(\"user\")                 .password(passwordEncoder().encode(\"userpwd\"))                 .roles(\"USER\")            <\/code><\/pre>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-325758","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/325758","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=325758"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/325758\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=325758"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=325758"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=325758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}