JavaRush /Kurslar /All lectures for UZ purposes /Funktsional endpointlar

Funktsional endpointlar

All lectures for UZ purposes
Daraja, Dars
Mavjud

Spring WebFlux WebFlux.fn ni o'z ichiga oladi, bu funktsional dasturlashning yengil modeli, bunda funksiya so'rovlarni yo'naltirish va ularga ishlov berish uchun ishlatiladi, va shartnomalar o'zgarmaslikni ta'minlash uchun ishlab chiqilgan. Bu annotatsiyalarning asosiy dasturlash modeliga alternativ, lekin qolgan qismlarda Reactive Core dan foydalanadi.

Qisqacha tavsif

WebFlux.fn da HTTP-so'rov HandlerFunction yordamida qayta ishlanadi: bu funksiya ServerRequest ni qabul qilib, kechiktirilgan ServerResponse ni qaytaradi (ya'ni. Mono<ServerResponse>). Va so'rov va javob obyektlari o'zgarmas shartnomalarga ega, bu HTTP so'rov va javobga kirishni ta'minlaydi, ular JDK 8 bilan mos keladi. HandlerFunction - bu annotatsiyaga asoslangan dasturlash modelidagi @RequestMapping bilan metod tanasining ekvivalenti.

Kiruvchi so'rovlar RouterFunction yordamida funksiyaga yo'naltiriladi: bu funksiya ServerRequest ni qabul qilib, kechiktirilgan HandlerFunction ni qaytaradi (ya'ni. Mono<HandlerFunction>). Agar marshrut funksiyasi mos kelsa, ishlov beruvchi funksiya qaytariladi; aks holda bo'sh Mono qaytariladi. RouterFunction - bu @RequestMapping annotatsiyasining ekvivalenti, lekin muhim farqi, marshrut funksiyalari nafaqat ma'lumotlar, balki ishchi mantiqni ham ta'minlaydi.

RouterFunctions.route() marshrutlarni qurish vositasini taqdim etadi, bu marshrutlarni yaratishni osonlashtiradi, quyidagi misolda ko'rsatilganidek:

Java
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
PersonRepository repository = ...
PersonHandler handler = new PersonHandler(repository);
RouterFunction<ServerResponse> route = route()
.GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson)
.GET("/person", accept(APPLICATION_JSON), handler::listPeople)
.POST("/person", handler::createPerson)
.build();
public class PersonHandler {
// ...
public Mono<ServerResponse> listPeople(ServerRequest request) {
// ...
}
public Mono<ServerResponse> createPerson(ServerRequest request) {
// ...
}
public Mono<ServerResponse> getPerson(ServerRequest request) {
// ...
}
}
Kotlin
val repository: PersonRepository = ...
val handler = PersonHandler(repository)
val route = coRouter { 
accept(APPLICATION_JSON).nest {
GET("/person/{id}", handler::getPerson)
GET("/person", handler::listPeople)
}
POST("/person", handler::createPerson)
}
class PersonHandler(private val repository: PersonRepository) {
// ...
suspend fun listPeople(request: ServerRequest): ServerResponse {
// ...
}
suspend fun createPerson(request: ServerRequest): ServerResponse {
// ...
}
suspend fun getPerson(request: ServerRequest): ServerResponse {
// ...
}
}
  1. Create router using Coroutines router DSL, a Reactive alternative is also available via router { }.

RouterFunction ni ishga tushirishning bir usuli - uni HttpHandler ga aylantirish va ichki server adapterlaridan biri orqali o'rnatish:

  • RouterFunctions.toHttpHandler(RouterFunction)

  • RouterFunctions.toHttpHandler(RouterFunction, HandlerStrategies)

Aksariyat ilovalarni Java-konfiguratsiya WebFlux orqali ishga tushirish mumkin.

HandlerFunction

ServerRequest va ServerResponse - bu o'zgarmas interfeyslar, ular HTTP so'rovi va javobga kirishni ta'minlaydi, ular JDK 8 bilan mos keladi. So'rov va javob Reactive Streams orqali tananing oqimlarini taqdim etadi. So'rovning tanasi Flux yoki Mono yordamida vakillanadi. Javobning tanasi istalgan Publisher dan Reactive Streams orqali vakillanadi, shu jumladan Flux va Mono.

ServerRequest

ServerRequest HTTP metodiga, URI identifikatoriga, boshliklarga va so'rov parametrlariga kirishni ta'minlaydi, va tana metodlar orqali body orqali kirishni taqdim etadi.

Quyidagi misolda so'rov tanasi Mono<String> ga olinadi:

Java
Mono<String> string = request.bodyToMono(String.class);
Kotlin
val string = request.awaitBody<String>()

Quyidagi misolda tanasi Flux<Person> (yoki Kotlinda Flow<Person>) ga olinadi, bu yerda Person obyektlari qandaydir seriyalashgan shakldan dekodlanadi, masalan JSON yoki XML:

Java
Flux<Person> people = request.bodyToFlux(Person.class);
Kotlin
val people = request.bodyToFlow<Person>()

Oldingi misollar BodyExtractor funksional strategiyasi interfeysini qabul qiladigan kengroq ServerRequest.body(BodyExtractor) dan foydalanadi. BodyExtractors yordamchi sinfi bir nechta nusxalarga kirishni ta'minlaydi. Masalan, oldingi misollar quyidagicha yozish mumkin:

Java
Mono<String> string = request.body(BodyExtractors.toMono(String.class));
Flux<Person> people = request.body(BodyExtractors.toFlux(Person.class));
Kotlin
    val string = request.body(BodyExtractors.toMono(String::class.java)).awaitSingle()
val people = request.body(BodyExtractors.toFlux(Person::class.java)).asFlow()

Quyidagi misolda, shakl ma'lumotlariga qanday kirish namoyish etiladi:

Java
Mono<MultiValueMap<String, String>> map = request.formData();
Kotlin
val map = request.awaitFormData()

Quyidagi misolda, ko'p komponentli ma'lumotlarga Map sifatida qanday kirish mumkinligi namoyish etiladi:

Java
Mono<MultiValueMap<String, Part>> map = request.multipartData();
Kotlin
val map = request.awaitMultipartData()

Quyidagi misolda har bir komponentga birma-bir oqim rejimida qanday kirish mumkinligi namoyish etiladi:

Java
Flux<Part> parts = request.body(BodyExtractors.toParts());
Kotlin
val parts = request.body(BodyExtractors.toParts()).asFlow()

ServerResponse

ServerResponse HTTP javobga kirishni ta'minlaydi va u o'zgarmas bo'lganligi sababli uni yaratish uchun build metodidan foydalanish mumkin. Javob maqomini o'rnatish, javob boshliqlarini qo'shish yoki javob mazmunini taqdim etish uchun quruvchini ishlatishingiz mumkin. Quyidagi misolda 200 (OK) javobi JSON formatdagi mazmun bilan yaratilgan:

Java
Mono<Person> person = ...
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(person, Person.class);
Kotlin
val person: Person = ...
ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(person)

Quyidagi misolda 201 (CREATED) javobi Location boshligi va tana bo'lmagan holda qanday yaratilish namoyish etiladi:

Java
URI location = ...
ServerResponse.created(location).build();
Kotlin
val location: URI = ...
ServerResponse.created(location).build()

Foydalanilayotgan codec ga qarab, tanani serializatsiya qilish yoki deserializatsiya qilish usulini sozlash uchun hint parametrlarini uzatish mumkin. Masalan, Jackson JSON asosidagi view ni o'rnatish uchun:

Java
ServerResponse.ok().hint(Jackson2CodecSupport.JSON_VIEW_HINT, MyJacksonView.class).body(...);
Kotlin
ServerResponse.ok().hint(Jackson2CodecSupport.JSON_VIEW_HINT, MyJacksonView::class.java).body(...)

Handler sinflari

Handler funksiyasini lambda-ifadada yozish mumkin, quyidagi misolda ko'rsatilganidek:

Java
HandlerFunction<ServerResponse> helloWorld =
request -> ServerResponse.ok().bodyValue("Hello World");
Kotlin
val helloWorld = HandlerFunction<ServerResponse> { ServerResponse.ok().bodyValue("Hello World") }

Bu qulay, lekin ilovada bizga bir nechta funksiya kerak bo'ladi va bir nechta lambda-ifadalar tartibsizlikka olib kelishi mumkin. Shuning uchun maloik vaziyatda bir guruh bog'liq handler funksiyalarni handler sinfida to'plash foydali, bu annotatsiyalarga asoslangan ilovadagi @Controller annotatsiyasi bilan bir xil rolni o'ynaydi. Misol uchun, quyidagi sinf reaktiv Person omborini namoyish etadi:

Java
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
public class PersonHandler {
private final PersonRepository repository;
public PersonHandler(PersonRepository repository) {
this.repository = repository;
}
public Mono<ServerResponse> listPeople(ServerRequest request) { 
Flux<Person> people = repository.allPeople();
return ok().contentType(APPLICATION_JSON).body(people, Person.class);
}
public Mono<ServerResponse> createPerson(ServerRequest request) { 
Mono<Person> person = request.bodyToMono(Person.class);
return ok().build(repository.savePerson(person));
}
public Mono<ServerResponse> getPerson(ServerRequest request) { 
int personId = Integer.valueOf(request.pathVariable("id"));
return repository.getPerson(personId)
    .flatMap(person -> ok().contentType(APPLICATION_JSON).bodyValue(person))
    .switchIfEmpty(ServerResponse.notFound().build());
}
}
  1. listPeople - bu handler funksiya bo'lib, omborda topilgan barcha Person obyektlarini JSON formatida qaytaradi.
  2. createPerson - bu handler funksiya bo'lib, so'rovt tanasida mavjud yangi Person obyektini saqlaydi. E'tibor bering, PersonRepository.savePerson(Person) Mono<Void> ni qaytaradi: bo'sh Mono, agar Person so'rovdan o'qilgan va saqlangan bo'lsa, tugatish signali yaratadi. Shuning uchun build(Publisher<Void>) metodi javob yuborish uchun ishlatiladi, tugatish signali qachon kelgani (ya'ni, Person saqlanganda) qaytariadi.
  3. getPerson - bu handler funksiya bo'lib, id yo'l o'zgaruvchisi bilan identifikatsiyalangan bitta Person obyektini qaytaradi. Biz bu Person obyektini ombordan olamiz va agar topilgan bo'lsa, JSON formatida javob yaratamiz. Agar topilmasa, switchIfEmpty(Mono<T>) 404 Not Found javobini qaytarish uchun ishlatiladi.
Kotlin
class PersonHandler(private val repository: PersonRepository) {
suspend fun listPeople(request: ServerRequest): ServerResponse { 
val people: Flow<Person> = repository.allPeople()
return ok().contentType(APPLICATION_JSON).bodyAndAwait(people);
}
suspend fun createPerson(request: ServerRequest): ServerResponse { 
val person = request.awaitBody<Person>()
repository.savePerson(person)
return ok().buildAndAwait()
}
suspend fun getPerson(request: ServerRequest): ServerResponse { 
val personId = request.pathVariable("id").toInt()
return repository.getPerson(personId)?.let { ok().contentType(APPLICATION_JSON).bodyValueAndAwait(it) }
        ?: ServerResponse.notFound().buildAndAwait()
}
}
  1. listPeople - bu handler funksiya bo'lib, omborda topilgan barcha Person obyektlarini JSON formatida qaytaradi.
  2. createPerson - bu handler funksiya bo'lib, so'rovt tanasida mavjud yangi Person obyektini saqlaydi. E'tibor bering, PersonRepository.savePerson(Person) Mono<Void> ni qaytaradi: bo'sh Mono, agar Person so'rovdan o'qilgan va saqlangan bo'lsa, tugatish signali yaratadi. Shuning uchun build(Publisher<Void>) metodi javob yuborish uchun ishlatiladi, tugatish signali qachon kelgani (ya'ni, Person saqlanganda) qaytariadi.
  3. getPerson - bu handler funksiya bo'lib, id yo'l o'zgaruvchisi bilan identifikatsiyalangan bitta Person obyektini qaytaradi. Biz bu Person obyektini ombordan olamiz va agar topilgan bo'lsa, JSON formatida javob yaratamiz. Agar topilmasa, switchIfEmpty(Mono<T>) 404 Not Found javobini qaytarish uchun ishlatiladi.

Validatsiya

Funktsional endpoint Spring ni tekshirish vositalarini ishga solib, so'rov tanasiga validatsiya qo'llanishi mumkin. Masalan, Person obyekti uchun Spring ni o'ziga xos Validator chiqib:

Java
public class PersonHandler {
private final Validator validator = new PersonValidator(); 
// ...
public Mono<ServerResponse> createPerson(ServerRequest request) {
Mono<Person> person = request.bodyToMono(Person.class).doOnNext(this::validate); 
return ok().build(repository.savePerson(person));
}
private void validate(Person person) {
Errors errors = new BeanPropertyBindingResult(person, "person");
validator.validate(person, errors);
if (errors.hasErrors()) {
    throw new ServerWebInputException(errors.toString()); 
}
}
}
  1. Validator ni yaratamiz.
  2. Validatsiya qo'llash.
  3. 400 javobda istisno yaratiladi.
Kotlin
class PersonHandler(private val repository: PersonRepository) {
private val validator = PersonValidator() 
// ...
suspend fun createPerson(request: ServerRequest): ServerResponse {
val person = request.awaitBody<Person>()
validate(person) 
repository.savePerson(person)
return ok().buildAndAwait()
}
private fun validate(person: Person) {
val errors: Errors = BeanPropertyBindingResult(person, "person");
validator.validate(person, errors);
if (errors.hasErrors()) {
    throw ServerWebInputException(errors.toString()) 
}
}
}
  1. Validator ni yaratamiz.
  2. Validatsiya qo'llash.
  3. 400 javobda istisno yaratiladi.

Handlerlar shuningdek, binlarning an'anaviy API validatsiyasidan (JSR-303) foydalanishi mumkin, LocalValidatorFactoryBean asosida global Validator ning nusxasini yaratish va kiritish orqali.

RouterFunction

Marshrut funksiyalari so'rovlarni mos HandlerFunction ga yo'naltirish uchun ishlatiladi. Odatda, marshrut funksiyalari mustaqil yozilmaydi, lekin yordamchi sinf RouterFunctions uchun metod yordamida yaratiladi. RouterFunctions.route() (parametrlarsiz) marshrut funksiyasini yaratish uchun qulay quruvchi bo'lib xizmat qiladi, RouterFunctions.route(RequestPredicate, HandlerFunction) esa marshrutni yaratish uchun to'g'ridan-to'g'ri usulni taklif qiladi.

Ma'qul qilib, route() quruvchini ishlatish tavsiya etiladi, chunki u statik elementlarni import qilishni talab qilmasdan ko'rinishi qiyin bo'lgan odatiy xaritlash stsenariylari uchun qulay qisqartmalar ta'minlaydi. Masalan, marshrut funksiyalari quruvchisi GET so'rovlari uchun xarita yaratish uchun GET(String, HandlerFunction) ni taklif qiladi; va POST so'rovlari uchun POST(String, HandlerFunction).

HTTP-metodlariga asoslangan xaritadan tashqari, marshrutlar quruvchisi so'rovlarga xaritani kiritish uchun qo'shimcha predikatlarni kiritish usulini taklif qiladi. Har bir HTTP-metodi uchun qo'shimcha cheklovlar ifodalash uchun RequestPredicate ni parametr sifatida qabul qiladigan ortiqcha variant mavjud.

Predikatlar

O'z RequestPredicate ni yozishingiz mumkin, lekin yordamchi sinf RequestPredicates tez-tez ishlatiladigan ilovalarni taklif qiladi, so'rov yo'li, HTTP-metodi, kontent turi va hokazo. Quyidagi misolda so'rov predikati Accept boshligi asosida cheklovni yaratadi:

Java
RouterFunction<ServerResponse> route = RouterFunctions.route()
.GET("/hello-world", accept(MediaType.TEXT_PLAIN),
request -> ServerResponse.ok().bodyValue("Hello World")).build();
Kotlin
val route = coRouter {
GET("/hello-world", accept(TEXT_PLAIN)) {
ServerResponse.ok().bodyValueAndAwait("Hello World")
}
}

Bir nechta so'rov predikatlarini quyidagi yordamida birlashtirishingiz mumkin:

  • RequestPredicate.and(RequestPredicate) – ikkisi ham mos kelishi kerak.

  • RequestPredicate.or(RequestPredicate) – har qanday biri mos kelishi mumkin.

Ko'plab ilovalar RequestPredicates dan tarkibiy hisoblanadi. Masalan, RequestPredicates.GET(String) tarkibida RequestPredicates.method(HttpMethod) va RequestPredicates.path(String) mavjud. Keltirilgan misolda marshrut funksiyalari RequestPredicates.GET ni ichki darajada ishlatish orqali accept predikati bilan birlashtiradi.

Marshrutlar

Marshrut funksiyalari tartibda baholanadi: agar birinchi marshrut mos kelmasa, ikkinchisi baholanadi va hokazo. Shuning uchun aniqroq marshrutlarni umumiylardan oldin e'lon qilish ma'qul. Bu marshrut funksiyalarini Spring bini sifatida ro'yxatga olishda ham muhim, keyinroq tasvirlanadi. E'tibor bering, bu ish mantiqi annotatsiyaga asoslangan dasturlash modelidan farq qiladi, bu yerda "eng aniq" controller method avtomatik ravishda tanlanadi.

Marshrutlar quruvchisidan foydalanishda, barcha belgilangan marshrutlar bitta RouterFunction ga tuziladi, bu esa build() dan qaytariladi. Bir nechta marshrut funksiyalarini yig'ishda boshqa usullar mavjud:

  • add(RouterFunction) on the RouterFunctions.route() builder

  • RouterFunction.and(RouterFunction)

  • RouterFunction.andRoute(RequestPredicate, HandlerFunction) - RouterFunction.and() bilan birga RouterFunctions.route() ichiga qilingan qisqartma.

Quyidagi misolda to'rtta marshrut tuzilishi ko'rsatilgan:

Java
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;
PersonRepository repository = ...
PersonHandler handler = new PersonHandler(repository);
RouterFunction<ServerResponse> otherRoute = ...
RouterFunction<ServerResponse> route = route()
.GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson) 
.GET("/person", accept(APPLICATION_JSON), handler::listPeople) 
.POST("/person", handler::createPerson) 
.add(otherRoute) 
.build();
  1. GET /person/{id} bilan Accept boshligi JSON bilan mos keladigan holda PersonHandler.getPerson ga yo'naltiriladi
  2. GET /person bilan Accept boshligi JSON formatida mos keladi va PersonHandler.listPeople ga yo'naltiriladi
  3. POST /person qo'shimcha predikatsiz PersonHandler.createPerson ga xaritada ko'rsatiladi, va
  4. otherRoute - bu boshqa joyda yaratilgan va tuzilgan marshrutga qo'shilgan marshrut funksiyasi hisoblanadi.
Kotlin
import org.springframework.http.MediaType.APPLICATION_JSON
val repository: PersonRepository = ...
val handler = PersonHandler(repository);
val otherRoute: RouterFunction<ServerResponse> = coRouter {  }
val route = coRouter {
GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson) 
GET("/person", accept(APPLICATION_JSON), handler::listPeople) 
POST("/person", handler::createPerson) 
}.and(otherRoute) 
  1. GET /person/{id} bilan Accept boshligi JSON bilan mos keladigan holda PersonHandler.getPerson ga yo'naltiriladi
  2. GET /person bilan Accept boshligi JSON formatida mos keladi va PersonHandler.listPeople ga yo'naltiriladi
  3. POST /person qo'shimcha predikatsiz PersonHandler.createPerson ga xaritada ko'rsatiladi, va
  4. otherRoute - bu boshqa joyda yaratilgan va tuzilgan marshrutga qo'shilgan marshrut funksiyasi hisoblanadi.

Ichki marshrutlar

Odatda marshrut funksiyalari guruhi umumiy predikatga ega, masalan, umumiy yo'lga. Yuqorida keltirilgan misolda umumiy predikat mavjud /person yo'lidir, uchta marshrut tomonidan ishlatiladi. Annotatsiyalardan foydalangan holda, bu takrorlashni yo'qotish uchun @RequestMapping annotatsiyasidan foydalanish mumkin, bu /person ni xaritalashda ishlatiladi. WebFlux.fn da, yo'l predikatlarini marshrut funktsiyalari quruvchisi yordamida path metodi bilan umumiy ishlatish mumkin. Masalan, yuqorida keltirilgan misolning so'nggi bir necha qatori ichki marshrutlardan foydalanib quyidagicha to'ldirilishi mumkin:

Java
RouterFunction<ServerResponse> route = route()
.path("/person", builder -> builder 
.GET("/{id}", accept(APPLICATION_JSON), handler::getPerson)
.GET(accept(APPLICATION_JSON), handler::listPeople)
.POST(handler::createPerson))
.build();
  1. Ikkinchi path parametri marshrut quruvchini qabul qiluvchi oluvchi hisoblanadi.
Kotlin
val route = coRouter {
"/person".nest {
GET("/{id}", accept(APPLICATION_JSON), handler::getPerson)
GET(accept(APPLICATION_JSON), handler::listPeople)
POST(handler::createPerson)
}
}

Yo'l asosidagi ichki joylashuvi eng keng tarqalgan bo'lsada, quruvchi vositasi yordamida istalgan turdagi predikatni ichki joylashtirish mumkin. Yuqorida keltirilgan variant umumiy Accept-header predikatini takrorlashni o'z ichiga oladi. Biz nest metodini accept bilan birga foydalanib, kodni davom ettirishimiz mumkin:

Java
RouterFunction<ServerResponse> route = route()
.path("/person", b1 -> b1
.nest(accept(APPLICATION_JSON), b2 -> b2
    .GET("/{id}", handler::getPerson)
    .GET(handler::listPeople))
.POST(handler::createPerson))
.build();
Kotlin
val route = coRouter {
"/person".nest {
accept(APPLICATION_JSON).nest {
    GET("/{id}", handler::getPerson)
    GET(handler::listPeople)
    POST(handler::createPerson)
}
}
}

Serverni ishga tushirish

Qanday qilib marshrut funksiyasini HTTP-serverda ishga tushirish mumkin? Oddiy variantlardan biri marshrut funksiyasini HttpHandler ga aylantirish bo'lib, quyidagi usullardan biri yordamida:

  • RouterFunctions.toHttpHandler(RouterFunction)

  • RouterFunctions.toHttpHandler(RouterFunction, HandlerStrategies)

Keyin HttpHandler ni qaytaringan adaptatorlar yordamida ishlatishingiz mumkin, HttpHandler ga mos server uchun ko'rsatilgan ko'rsatmalarga amal qiling.

Spring Boot da ham ishlatiladigan va DispatcherHandler ga asoslangan konfiguratsiya bilan ishlashga javob beradi. WebFlux konfiguratsiyasi Spring-konfiguratsiyadan foydalanib, so'rovlarni qayta ishlash uchun zarur bo'lgan komponentlarni e'lon qiladi. WebFlux ni Java-konfiguratsiyasi funksional endpointlarni qo'llab-quvvatlash uchun quyidagi infratuzilma komponentlarini e'lon qiladi:

  • RouterFunctionMapping: Bu Spring konfiguratsiyasida bitta yoki bir nechta RouterFunction<?> binlarini aniqlaydi, ularni tartiblaydi, RouterFunction.andOther yordamida birlashtiradi va so'rovlarni hosil bo'lgan tarkibiy RouterFunction ga yo'naltiradi.

  • HandlerFunctionAdapter: Oddiy adapter, bu DispatcherHandler ga HandlerFunction, ni so'rovga xaritada chaqirish imkonini beradi.

  • ServerResponseResultHandler: U HandlerFunction, ni chaqirish natijasini ServerResponse dagi writeTo metodini chaqirish orqali qayta ishlaydi.

Yuqoridagi komponentlar funksional endpointlar DispatcherServlet ning so'rovlarni qayta ishlash hayotiy tsikliga moslashish imkoniyatini beradi, shuningdek, agar mavjud bo'lsa, annotatsiyalangan controllerlar bilan birga ishlashini ham. Bu Spring Boot ning WebFlux uchun starter orqali funksional endpointlarni ishga tushirish uchun ham ishlatiladigan usuldir.

Quyidagi misol WebFlux ning Java-konfiguratsiyasini ko'rsatadi:

Java
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Bean
public RouterFunction<?> routerFunctionA() {
// ...
}
@Bean
public RouterFunction<?> routerFunctionB() {
// ...
}
// ...
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
// xabarnomalarni o'zgartirish...
}
@Override
public void addCorsMappings(CorsRegistry registry) {
// CORS ni sozlash...
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// HTML vizualizatsiyasi uchun ko'rinishni sozlash...
}
}
Kotlin
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
@Bean
fun routerFunctionA(): RouterFunction<*> {
// ...
}
@Bean
fun routerFunctionB(): RouterFunction<*> {
// ...
}
// ...
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
// xabarnomalarni o'zgartirish...
}
override fun addCorsMappings(registry: CorsRegistry) {
// CORS ni sozlash...
}
override fun configureViewResolvers(registry: ViewResolverRegistry) {
// HTML vizualizatsiyasi uchun ko'rinishni sozlash...
}
}

Handler funksiyalarini filtrlash

before, after yoki filter metodlaridan foydalanib funksiyalarini filtrlash mumkin. Annotatsiyalar yordamida, @ControllerAdvice, ServletFilter yoki har ikkalaisidan foydalanib o'xshash funksionallikni amalga oshirish mumkin. Filtr quruvchi vositasi tomonidan qilingan barcha marshrutlarga qo'llaniladi. Bu ichki marshrutlarda belgilangan filtrlari yuqori darajadagi marshrutlarga qo'llanmasligini anglatadi. Misol, quyidagini ko'rib chiqing:

Java
RouterFunction<ServerResponse> route = route()
.path("/person", b1 -> b1
.nest(accept(APPLICATION_JSON), b2 -> b2
    .GET("/{id}", handler::getPerson)
    .GET(handler::listPeople)
    .before(request -> ServerRequest.from(request) 
        .header("X-RequestHeader", "Value")
        .build()))
.POST(handler::createPerson))
.after((request, response) -> logResponse(response)) 
.build();
  1. Bu before filtri, foydalanuvchi so'rovi boshligini qo'shadi, faqat ikkita GET marshrutiga qo'llaniladi.
  2. Bu after filtri, javobni yozib qo'yadi, barcha marshrutlarda qo'llaniladi, ichki jo'nalishlarni o'z ichiga oladi.
Kotlin
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION