A different world
In a normal Spring Web project, it is very easy to get the Request object and many libraries provide static methods to get it. The code to get it is as follows.
The class RequestContextHolder provides static methods, which means you can call it from anywhere. And it uses ThreadLocal to hold the Request object, which means that different threads can get their own Request objects.
But in the responsive WebFlux world, 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.
Save first, then get
To make it easy to get the Request object 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.
-
Where does the
Requestobject come from. -
Where to store the
Request?
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 the Reavtive request is needed. Use reactor.util.context.Context.
A look at the official documentation for reactor shows the following passage.
Since version
3.1.0, Reactor comes with an advanced feature that is somewhat comparable toThreadLocalbut can be applied to aFluxor aMonoinstead of aThread. This feature is calledContext.
And the official website also gives an explanation why ThreadLocal does not work in some scenarios. Take a look if you are interested.
Implementation
WebFilter fetch and save
First, get the Request object in the 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.
Tool Classes - Holder
Implement a tool class to provide static methods that can be used in any scenario after Filter.
Using in 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.
Reference https://springboot.io/t/topic/3837