国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

解決spring-boot2.0.6中webflux無法獲得請求IP的問題

2024-07-14 08:42:39
字體:
來源:轉載
供稿:網友

這幾天在用 spring-boot 2 的 webflux 重構一個工程,寫到了一個需要獲得客戶端請求 IP 的地方,發現寫不下去了,在如下的 Handler(webflux 中 Handler 相當于 mvc 中的 Controller)中

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.MediaType;import org.springframework.stereotype.Component;import org.springframework.web.reactive.function.server.RouterFunction;import org.springframework.web.reactive.function.server.ServerRequest;import org.springframework.web.reactive.function.server.ServerResponse;import reactor.core.publisher.Mono;import static org.springframework.web.reactive.function.server.RequestPredicates.GET;import static org.springframework.web.reactive.function.server.RequestPredicates.accept;import static org.springframework.web.reactive.function.server.RouterFunctions.route;/** * 某業務 Handler */@Componentpublic class SplashHandler {  private Mono<ServerResponse> execute(ServerRequest serverRequest) {    ... 業務代碼    // serverRequest 獲得 IP ?    ... 業務代碼  }  @Configuration  public static class RoutingConfiguration {    @Bean    public RouterFunction<ServerResponse> execute(SplashHandler handler) {      return route(          GET("/api/ad").and(accept(MediaType.TEXT_HTML)),          handler::execute      );    }  }}

我發現 org.springframework.web.reactive.function.server.ServerRequest 根本沒有暴露用于獲得客戶端 IP 的 API,想想這在傳統 MVC 中是相當基本的需求啊,竟然獲取不到,然后 Google 了一下,發現這個是 spring-webflux 的一個 BUG ,這個 BUG 在 spring-webflux 5.1 中解決了,但是,略有些尷尬的是當前最新穩定版的 spring-boot 還是依賴 5.0.x 的 spring-webflux 的。難道要等官方升級么,那不知道得等到什么時候,因此我接著搜了搜資料,看了看文檔和源碼,自己想了個曲線救國的辦法。

正文

在 spring-webflux 中,有一個 org.springframework.web.server.WebFilter 接口,類似于 Servlet API 中的過濾器,這個 API 提供了一個方法會將一個限定名為 org.springframework.web.server.ServerWebExchange 的類暴露出來,而在這個類中就包含了對于請求端 IP 的獲取方法:

org.springframework.web.server.ServerWebExchange#getRequestorg.springframework.http.server.reactive.ServerHttpRequest#getRemoteAddress

因此,我們大可以實現一個 WebFilter 在里面通過暴露的 ServerWebExchange 拿到客戶端 IP,然后再將其塞到請求的 header 中,這樣,后續過程就可以從 header 中取 IP 了。思路有了,我們開始實現吧。

過濾、取 IP、放 header,一氣呵成:

import org.springframework.context.annotation.Configuration;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.stereotype.Component;import org.springframework.web.reactive.config.CorsRegistry;import org.springframework.web.reactive.config.WebFluxConfigurer;import org.springframework.web.server.ServerWebExchange;import org.springframework.web.server.WebFilter;import org.springframework.web.server.WebFilterChain;import reactor.core.publisher.Mono;import java.net.InetSocketAddress;import java.util.Objects;/*If you want to keep Spring Boot WebFlux features and you want to add additional WebFlux configuration, you can add your own @Configuration class of type WebFluxConfigurer but without @EnableWebFlux.If you want to take complete control of Spring WebFlux, you can add your own @Configuration annotated with @EnableWebFlux. */@Configurationpublic class WebConfiguration implements WebFluxConfigurer {  @Override  public void addCorsMappings(CorsRegistry registry) {    registry        .addMapping("/**")        .allowedOrigins("*")        .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTION")        .allowedHeaders("header1", "header2", "header3")        .exposedHeaders("header1", "header2")        .allowCredentials(true)        .maxAge(3600);  }  /**   * https://stackoverflow.com/questions/51192630/how-do-you-get-clients-ip-address-spring-webflux-websocket?rq=1   * https://stackoverflow.com/questions/50981136/how-to-get-client-ip-in-webflux   * https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-filters   * 由于在低版本的 spring-webflux 中不支持直接獲得請求 IP(https://jira.spring.io/browse/SPR-16681),因此寫了一個補丁曲線救國,   * 從 org.springframework.web.server.ServerWebExchange 中獲得 IP 后,在放到 header 里   */  @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();      ServerHttpRequest mutatedServerHttpRequest = exchange.getRequest().mutate().header("X-CLIENT-IP", clientIp).build();      ServerWebExchange mutatedServerWebExchange = exchange.mutate().request(mutatedServerHttpRequest).build();      return chain.filter(mutatedServerWebExchange);    }  }}

后續過程 header 取值:

private Mono<ServerResponse> execute(ServerRequest serverRequest) {  String clientIp = serverRequest.headers().asHttpHeaders().getFirst("X-CLIENT-IP")  ... 業務代碼}

通過上述解決方案(其實嚴格上說是 hacking)就解決了我們遇到的問題了。

總結

以上所述是小編給大家介紹的解決spring-boot2.0.6中webflux無法獲得請求IP的問題,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 桂阳县| 莱州市| 永年县| 龙海市| 遵义县| 苏尼特左旗| 靖江市| 安顺市| 津市市| 花垣县| 博客| 南平市| 辉南县| 海晏县| 南陵县| 开远市| 松溪县| 黑龙江省| 贵南县| 吴桥县| 绥芬河市| 重庆市| 房产| 伊春市| 屏东市| 新巴尔虎左旗| 连云港市| 灵寿县| 余庆县| 柘荣县| 鄂尔多斯市| 泉州市| 安康市| 云霄县| 邵东县| 新宾| 南江县| 洛川县| 驻马店市| 子长县| 临高县|