Ejemplo de aplicación reactiva Spring (versión del 14/01/2020)

¡Feliz año tardío, comunidad de primavera!

A medida que comienza el próximo año increíble de desarrollo y mejora en el ecosistema de Spring, quiero compartir con ustedes un ejemplo actualizado de una aplicación que demuestra parte del progreso realizado en la cartera de proyectos de Spring con respecto al soporte para el modelo de programación Reactivo.

La aplicación de ejemplo BookStore Service Broker se ha actualizado para demostrar la integración de varios proyectos Spring diferentes, incluidos Spring Cloud Open Service Broker, Spring Data, Spring Security, Spring HATEOAS y, por supuesto, Spring WebFlux y Spring Boot. Todos estos proyectos tienen versiones de GA, incluido el soporte reactivo y listo para la producción en sus propias aplicaciones y servicios.

Traducido por @middle_java

Para simplificar, la aplicación en sí misma funciona como un agente y como una instancia de servicio. Aunque los corredores se adhieren a la API de Open Service Broker, los servicios que brindan se definen de manera más abstracta. Los servicios pueden hacer o ser casi cualquier cosa. En el caso de nuestra aplicación, se crea un nuevo conjunto de credenciales para cada instancia del servicio. Estas credenciales se utilizan en solicitudes a la instancia de servicio. La URL de la nueva instancia de servicio se establece de la misma manera que la ruta al intermediario. Por lo tanto, las credenciales se utilizan para separar solicitudes a diferentes instancias de servicio. El objetivo era desarrollar un ejemplo totalmente equipado que demuestre muchas partes de la cartera de proyectos de Spring.

Spring Cloud Open Service Broker 3.1


Spring Cloud Open Service Broker es una plataforma para crear aplicaciones Spring Boot que implementan la API Open Service Broker, y permite a los desarrolladores proporcionar servicios a aplicaciones que se ejecutan en plataformas en la nube como Cloud Foundry, Kubernetes y OpenShift. A partir de la versión 3.0, Spring Cloud Open Service Broker es compatible con los marcos web Spring WebFlux y Spring MVC utilizando tipos reactivos en las interfaces de controlador y servicio.

Para comenzar con Spring Cloud Open Service Broker, incluya el iniciador Spring Boot en su aplicación:

implementation('org.springframework.cloud:spring-cloud-starter-open-service-broker:3.1.0.RELEASE') 

Luego implementamos ServiceInstateService y ServiceInstateBindingService . El siguiente código ilustra la API requerida. Vea la aplicación de muestra para más detalles.

 @Service public class BookStoreServiceInstanceService implements ServiceInstanceService { @Override public Mono < CreateServiceInstanceResponse > createServiceInstance( CreateServiceInstanceRequest request) { ... } @Override public Mono < GetServiceInstanceResponse > getServiceInstance( GetServiceInstanceRequest request) { ... } @Override public Mono < DeleteServiceInstanceResponse > deleteServiceInstance( DeleteServiceInstanceRequest request) { ... } } 

Spring data moore


En la familia de proyectos Spring Data , el soporte reactivo se introdujo originalmente en Spring Data Kay . Spring Data R2DBC anunció recientemente un lanzamiento de GA, pero Spring Boot aún no tiene un lanzamiento de GA que se integre con Spring Data R2DBC. Este ejemplo utiliza MongoDB como el almacén de datos de respaldo.

Para comenzar con Reactive MongoDB, incluya el iniciador Spring Boot en su aplicación:

 implementation('org.springframework.boot:spring-boot-starter-data-mongodb-reactive') 

Para demostrarlo, agregue el servidor MongoDB incorporado:

 implementation('de.flapdoodle.embed:de.flapdoodle.embed.mongo') 

Luego configure el repositorio de Jet:

 @Configuration @EnableReactiveMongoRepositories(basePackageClasses = { ServiceBrokerRepositoryPackageMarker.class, WebRepositoryPackageMarker.class }) public class ApplicationRepositoryConfiguration { } 

Finalmente, defina ReactiveCrudRepository . La siguiente interfaz es un ejemplo de una aplicación de muestra:

 public interface ServiceInstanceRepository extends ReactiveCrudRepository < ServiceInstance, String > { } 

Seguridad de primavera 5.2


El soporte reactivo se incluyó originalmente en Spring Security 5, y la integración con Spring Boot y Spring Framework continúa evolucionando.

Para usar Spring Security, agregue el iniciador Spring Boot:

 implementation('org.springframework.boot:spring-boot-starter-security') 

A continuación, defina la configuración de seguridad utilizando @EnableWebCardingSecurity . Este código ilustra cómo una aplicación protege los puntos finales del intermediario /v2 y /bookstars , que responden a solicitudes de instancias de servicio:

 @Configuration @EnableWebFluxSecurity public class SecurityConfiguration { @Bean public SecurityWebFilterChain securityWebFilterChain( ServerHttpSecurity http) { return http .csrf().disable() .httpBasic() .and().authorizeExchange() .pathMatchers("/bookstores/**").authenticated() .pathMatchers("/v2/**").hasAuthority( SecurityAuthorities.ADMIN) .matchers(EndpointRequest.to("info", "health")).permitAll() .matchers(EndpointRequest.toAnyEndpoint()).hasAuthority( SecurityAuthorities.ADMIN) .and().build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } 

A continuación, implementamos ReactiveUserDetailsService :

 @Service public class RepositoryUserDetailsService implements ReactiveUserDetailsService { private final UserRepository userRepository; public RepositoryUserDetailsService(UserRepository userRepository) { this.userRepository = userRepository; } } 

Finalmente, los evaluadores de permisos no son compatibles con los controladores WebFlux, pero podemos lograr una funcionalidad similar llamando al bean en la expresión SpEL y pasando el objeto Autenticación:

 @GetMapping("/{bookStoreId}") @PreAuthorize("hasAnyRole('ROLE_FULL_ACCESS','ROLE_READ_ONLY') and @bookStoreIdEvaluator.canAccessBookstore(authentication, #bookStoreId)") public Mono<ResponseEntity<BookStoreResource>> getBooks( @PathVariable String bookStoreId) { return bookStoreService.getBookStore(bookStoreId) .flatMap(this::createResponse); } 

Este ejemplo analiza los permisos para determinar si existe un identificador de librería:

 public boolean canAccessBookstore(Authentication authentication, String bookStoreId) { return authentication.getAuthorities().stream() .filter(authority - > authority.getAuthority() .startsWith(BOOK_STORE_ID_PREFIX)) .map(authority - > { String serviceInstanceId = authority.getAuthority() .substring(BOOK_STORE_ID_PREFIX.length()); return serviceInstanceId.equals(bookStoreId); }) .findFirst() .orElse(true); } 

Spring HATEOAS 1.0


Spring HATEOAS 1.0 GA fue lanzado recientemente e incluye soporte reactivo para vincular y modelar vistas.

Agregue un Spring HATEOAS Starter para activar la configuración automática de Spring Boot. Como estamos creando la aplicación reactiva Spring WebFlux, debemos excluir el iniciador Spring Web:

 implementation('org.springframework.boot:spring-boot-starter-hateoas') { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-web' } 

A continuación, puede usar WebFluxLinkBuilder para construir recursos de Hypermedia:

 public Mono < BookResource > toModel(Book book, String bookStoreId) { return Mono.just(new BookResource(book)) .flatMap(bookResource - > linkTo(methodOn( BookController.class).getBook(bookStoreId, book.getId())) .withSelfRel() .toMono() .flatMap(link - > Mono.just(bookResource.add(link))) .thenReturn(bookResource)); } 

Luego puede usar este recurso en el cuerpo de la respuesta del controlador:

 return new BookStoreResourceAssembler().toModel(bookStore) .flatMap(bookStoreResource - > Mono.just(new ResponseEntity < > (bookStoreResource, HttpStatus.OK))); 

Spring framework 5.2


Spring Framework 5 originalmente ofreció soporte reactivo en el nuevo Spring WebFlux Web Framework. Además, el nuevo WebClient y WebTestClient incluyen soporte para usar y probar aplicaciones Spring WebFlux.

Para usarlos, solo agregue los arrancadores Spring Boot:

 implementation('org.springframework.boot:spring-boot-starter-webflux') testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } 

Por ejemplo, use WebTestClient para probar la funcionalidad del controlador:

 this.client.get().uri("/bookstores/{bookStoreId}", bookStoreId) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isEqualTo(HttpStatus.OK); 

Spring boot 2.2


Spring Boot reúne todos estos proyectos, ofreciendo la configuración automática de soporte reactivo en Spring WebFlux, Spring Data, Spring Security, Spring HATEOAS, así como en herramientas de prueba. En muchos casos, la implementación solo requiere la adición de arrancadores Spring Boot específicos o dependencias relacionadas para activar la funcionalidad.

Conclusión


Esta publicación incluye una breve introducción al Soporte reactivo en algunos proyectos de primavera. A medida que más proyectos de Spring se adapten y admitan las API reactivas, los desarrolladores tendrán más opciones para usar programación imperativa o reactiva en sus aplicaciones. Además, esta aplicación de muestra solo muestra algunos de los proyectos de Spring que actualmente ofrecen soporte reactivo. ¡Busca más en el futuro! Si tiene preguntas o inquietudes sobre un proyecto Spring específico, comuníquese con los encargados del proyecto en la página de GitHub correspondiente.

Traducido por @middle_java

Source: https://habr.com/ru/post/485498/


All Articles