Статьи

Spring Webflux — написание фильтров

Spring Webflux — это новый реактивный веб-фреймворк, доступный как часть Spring 5+. То, как фильтры были написаны в традиционном приложении на основе Spring MVC ( Servlet Filter , HandlerInterceptor ), сильно отличается от того, как фильтр пишется в приложении на основе Spring Webflux, и в этом посте кратко рассмотрим подход WebFlux к фильтрам.

Подход 1 — WebFilter

Первый подход с использованием WebFilter затрагивает все конечные точки в целом и охватывает конечные точки Webflux, написанные в функциональном стиле, а также конечные точки, написанные с использованием стиля аннотаций . WebFilter в Котлине выглядит так:

1
2
3
4
5
6
7
8
9
@Bean
    fun sampleWebFilter(): WebFilter {
        return WebFilter { e: ServerWebExchange, c: WebFilterChain ->
            val l: MutableList<String> = e.getAttributeOrDefault(KEY, mutableListOf())
            l.add("From WebFilter")
            e.attributes.put(KEY, l)
            c.filter(e)
        }
    }

WebFilter добавляет атрибут запроса со значением, представляющим собой коллекцию, в которой фильтр просто помещает сообщение о том, что он перехватил запрос.

Подход 2 — HandlerFilterFunction

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

Рассмотрим конечную точку Spring Webflux, определенную следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
@Bean
fun route(): RouterFunction<*> = router {
    GET("/react/hello", { r ->
        ok().body(fromObject(
                Greeting("${r.attribute(KEY).orElse("[Fallback]: ")}: Hello")
        ))
    POST("/another/endpoint", TODO())
         
    PUT("/another/endpoint", TODO())
})
         
}

Функция HandlerFilterFunction, которая перехватывает только эти API, может быть добавлена ​​с высокой степенью фокусировки следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
fun route(): RouterFunction<*> = router {
    GET("/react/hello", { r ->
        ok().body(fromObject(
                Greeting("${r.attribute(KEY).orElse("[Fallback]: ")}: Hello")
        ))
    })
     
    POST("/another/endpoint", TODO())
     
    PUT("/another/endpoint", TODO())
     
}.filter({ r: ServerRequest, n: HandlerFunction<ServerResponse> ->
    val greetings: MutableList<String> = r.attribute(KEY)
            .map { v ->
                v as MutableList<String>
            }.orElse(mutableListOf())
 
    greetings.add("From HandlerFilterFunction")
 
    r.attributes().put(KEY, greetings)
    n.handle(r)
})

Обратите внимание, что нет необходимости быть явным о типах в Kotlin, я добавил это просто для ясности о типах в некоторых лямбда-выражениях

Вывод

Подход WebFilter и функция HandlerFilterFunction сильно отличаются от подхода, основанного на Spring WebMVC, при написании фильтров с использованием спецификаций сервлета или с помощью HandlerInterceptors, и в этом посте кратко изложены новые подходы — в моем git- репозитории есть примеры, которые рассматриваются более подробно.

Смотрите оригинальную статью здесь: Spring Webflux — Написание фильтров

Мнения, высказанные участниками Java Code Geeks, являются их собственными.