麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 開(kāi)發(fā) > Java > 正文

解決spring-boot2.0.6中webflux無(wú)法獲得請(qǐng)求IP的問(wèn)題

2024-07-14 08:42:39
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

這幾天在用 spring-boot 2 的 webflux 重構(gòu)一個(gè)工程,寫到了一個(gè)需要獲得客戶端請(qǐng)求 IP 的地方,發(fā)現(xiàn)寫不下去了,在如下的 Handler(webflux 中 Handler 相當(dāng)于 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;/** * 某業(yè)務(wù) Handler */@Componentpublic class SplashHandler {  private Mono<ServerResponse> execute(ServerRequest serverRequest) {    ... 業(yè)務(wù)代碼    // serverRequest 獲得 IP ?    ... 業(yè)務(wù)代碼  }  @Configuration  public static class RoutingConfiguration {    @Bean    public RouterFunction<ServerResponse> execute(SplashHandler handler) {      return route(          GET("/api/ad").and(accept(MediaType.TEXT_HTML)),          handler::execute      );    }  }}

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

正文

在 spring-webflux 中,有一個(gè) org.springframework.web.server.WebFilter 接口,類似于 Servlet API 中的過(guò)濾器,這個(gè) API 提供了一個(gè)方法會(huì)將一個(gè)限定名為 org.springframework.web.server.ServerWebExchange 的類暴露出來(lái),而在這個(gè)類中就包含了對(duì)于請(qǐng)求端 IP 的獲取方法:

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

因此,我們大可以實(shí)現(xiàn)一個(gè) WebFilter 在里面通過(guò)暴露的 ServerWebExchange 拿到客戶端 IP,然后再將其塞到請(qǐng)求的 header 中,這樣,后續(xù)過(guò)程就可以從 header 中取 IP 了。思路有了,我們開(kāi)始實(shí)現(xiàn)吧。

過(guò)濾、取 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 中不支持直接獲得請(qǐng)求 IP(https://jira.spring.io/browse/SPR-16681),因此寫了一個(gè)補(bǔ)丁曲線救國(guó),   * 從 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);    }  }}

后續(xù)過(guò)程 header 取值:

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

通過(guò)上述解決方案(其實(shí)嚴(yán)格上說(shuō)是 hacking)就解決了我們遇到的問(wèn)題了。

總結(jié)

以上所述是小編給大家介紹的解決spring-boot2.0.6中webflux無(wú)法獲得請(qǐng)求IP的問(wèn)題,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)VeVb武林網(wǎng)網(wǎng)站的支持!


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JAVA教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 午夜视频你懂的 | 欧美日韩免费一区二区三区 | 黄色片免费看网站 | 黄色羞羞| 亚州欧美视频 | 久久久久久久久日本理论电影 | 中文字幕 亚洲一区 | 亚洲婷婷日日综合婷婷噜噜噜 | 久久精品亚洲一区二区 | 美女亚洲 | 国产成人在线视频播放 | 午夜国产在线 | 成年人黄色片视频 | 特级毛片全部免费播放器 | 超碰97人人艹 | 亚洲乱妇19p | 一级精品| 天天干干 | 久久久一区二区三区精品 | 成人国产视频在线观看 | 国产成人精品自拍视频 | 欧美精品久久久久久久久久 | 一级α片免费看刺激高潮视频 | av电影在线观看网站 | 在线成人免费观看www | 午夜精品久久久久久中宇 | 羞羞的视频免费观看 | 久久99精品国产自在现线 | 毛片视频网站 | 黄色小视频免费在线观看 | 午夜视频在线观看免费视频 | 国产成年人小视频 | 福利四区 | 精品亚洲夜色av98在线观看 | 最新se94se在线欧美 | 亚洲一级电影在线观看 | 欧美一区二区黄 | 欧美成人一级 | 国产91久久精品一区二区 | av成人免费观看 | 久久久婷婷一区二区三区不卡 |