问题描述
在使用WebFlux
时,因为业务需要,要获取请求 IP 并作为日志输出。我使用的是RouterFunction
方式的路由:
1
2
3
4
5
6
7
8
|
@Override
@NotNull
public Mono<ServerResponse> search(ServerRequest request) {
Mono<Query> query = request.bodyToMono(Query.class);
Mono<SearchResult> result = query.map(processQuery(request))
.map(indexerService::search);
return resultOk(result, SearchResult.class);
}
|
可以看到,这里接收一个ServerRequest
,但是并没有获取请求 IP 的 API,搜索一番,结果是Spring
的一个 BUG,详情见SPR-16681,已经在5.1
版本中修复。但生产的版本没法随意升级,所以只能另寻他法了。
解决方案
其实,在WebFlux
中的Filter
的方法中,ServerWebExchange
对象是可以通过 API 获取请求 IP 的:
1
2
3
4
5
6
7
8
9
10
11
12
|
@Component
public static class RetrieveClientIpWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
String clientIp = Objects.requireNonNull(remoteAddress).getAddress().getHostAddress();
IpThreadLocal.setIp(clientIp);
ServerHttpRequest mutatedServerHttpRequest = exchange.getRequest().mutate().header("X-CLIENT-IP", clientIp).build();
ServerWebExchange mutatedServerWebExchange = exchange.mutate().request(mutatedServerHttpRequest).build();
return chain.filter(mutatedServerWebExchange);
}
}
|
可以把 IP 放到Header
中,通过ServerRequest
来获取,也可以放到全局的线程变量中。
写在最后
不得不感叹,往往很多时候我都是面向搜索编程,碰到问题,就到处搜索,到处翻文章,找到方案了,就直接CV
,这其实很难有所进步。问题是解决了,但下次再碰到,同样没记住,因为只是做了一次CV
而已。那如何才能有效提高每一次的问题解决呢?我的方法就是记录下来,做一次输出,加深自己的印象,同时也能够在以后随时复盘,逐渐掌握。
参考
曲线救国,解决spring-boot2.0.6中webflux无法获得请求IP的问题
Author
Honlyc
LastMod
2019-04-04
License
转载请注明出处。CC BY-NC-ND 4.0