1 A different world
In a regular Spring Web
project, it is very easy to get the Request
object, and quite a few libraries provide static methods to do so. The code to get it is as follows.
In class RequestContextHolder
provides static methods, which means you can call them anywhere. And it uses ThreadLocal
to hold the Request
object, which means that different threads are able to get their own Request objects.
But in the world of responsive WebFlux
, there is no similar Holder
class provided, and WebFlux
is not thread-aware, any thread can handle any request at any time, and if it feels more efficient to switch the current thread, it will do so. But in a Servlet Based
application, it will schedule a thread for a request to handle the entire process.
This huge difference means that you can’t simply save and fetch Request
through ThreadLocal
anymore.
2 Save it first, then get it
In order to get the Request
object easily later, we need to store it in a container with the same scope
that we can use at the beginning. Two key issues need to be addressed here.
(1) Where does the Request
object come from.
(2) Where does it exist?
For question (1), we can think back to when the Request
object appeared, and the easiest one to think of is the WebFilter
, which has the following method signature.
|
|
We can get the Request
object directly through the ServerWebExchange
.
|
|
And since Filter
can be executed before the application logic, the requirement is satisfied and problem (1) is solved.
For problem (2), a container with the same scope as Reavtive
request is needed, and reactor.util.context.Context
can satisfy the requirement. Check the official documentation of reactor
https://projectreactor.io/docs/core/release/reference/#context to see the following passage.
Since version
3.1.0
, Reactor comes with an advanced feature that is somewhat comparable toThreadLocal
but can be applied to aFlux
or aMono
instead of aThread
. This feature is calledContext
.
And the official website also gives an explanation why ThreadLocal
doesn’t work in some scenarios, so check it out if you’re interested.
3 Code implementation
3.1 WebFilter fetching and saving
First, get the Request
object in WebFilter
and save it, the code is as follows.
|
|
Get the ServerHttpRequest
object from the ServerWebExchange
and put it into the Context
via the put
method.
3.2 Tool class Holder
Implement a tool class to provide static methods that can be used in any scenario after Filter
.
3.3 Using in the Controller
We try to use ReactiveRequestContextHolder
in the Controller
to get the Request
.
The above method gets the Request
object and then gets the Header
in the Request
.
Start the application and test it as follows.
The request header user
can be successfully retrieved.
4 Summary
The code can be found at https://github.com/LarryDpk/pkslow-samples