欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2018年10月24日 10:59:55   作者:Posted on  
這幾天在用 spring-boot 2 的 webflux 重構(gòu)一個(gè)工程,寫到了一個(gè)需要獲得客戶端請(qǐng)求 IP 的地方,在寫的過(guò)程中遇到很多問(wèn)題,下面小編通過(guò)一段代碼給大家介紹解決spring-boot2.0.6中webflux無(wú)法獲得請(qǐng)求IP的問(wèn)題,感興趣的朋友跟隨小編一起看看吧

這幾天在用 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
 */
@Component
public 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 根本沒有暴露用于獲得客戶端 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#getRequest
org.springframework.http.server.reactive.ServerHttpRequest#getRemoteAddress

因此,我們大可以實(shí)現(xiàn)一個(gè) WebFilter 在里面通過(guò)暴露的 ServerWebExchange 拿到客戶端 IP,然后再將其塞到請(qǐng)求的 header 中,這樣,后續(xù)過(guò)程就可以從 header 中取 IP 了。思路有了,我們開始實(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.
 */
@Configuration
public 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ì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Mybatis實(shí)戰(zhàn)之TypeHandler高級(jí)進(jìn)階

    Mybatis實(shí)戰(zhàn)之TypeHandler高級(jí)進(jìn)階

    本文主要介紹了自定義的枚舉TypeHandler的相關(guān)知識(shí),具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • java逐行讀取文件(讀取文件每一行、按行讀取文件)附帶詳細(xì)代碼

    java逐行讀取文件(讀取文件每一行、按行讀取文件)附帶詳細(xì)代碼

    這篇文章主要給大家介紹了關(guān)于java逐行讀取文件(讀取文件每一行、按行讀取文件)的相關(guān)資料,讀取文件是我們?cè)谌粘9ぷ髦薪?jīng)常遇到的一個(gè)需求,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • java中Hibernate緩存形式總結(jié)

    java中Hibernate緩存形式總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于java中Hibernate緩存形式總結(jié)內(nèi)容,有興趣的朋友們可以參考下。
    2021-01-01
  • Springboot自動(dòng)配置與@Configuration配置類詳解

    Springboot自動(dòng)配置與@Configuration配置類詳解

    這篇文章主要介紹了SpringBoot中的@Configuration與自動(dòng)配置,在進(jìn)行項(xiàng)目編寫前,我們還需要知道一個(gè)東西,就是SpringBoot對(duì)我們的SpringMVC還做了哪些配置,包括如何擴(kuò)展,如何定制,只有把這些都搞清楚了,我們?cè)谥笫褂貌艜?huì)更加得心應(yīng)手
    2022-07-07
  • Java 類在 Tomcat 中是如何加載的(過(guò)程分析)

    Java 類在 Tomcat 中是如何加載的(過(guò)程分析)

    這篇文章主要介紹了Java 類在 Tomcat 中是如何加載的過(guò)程分析,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • mybatis foreach標(biāo)簽的使用詳解

    mybatis foreach標(biāo)簽的使用詳解

    這篇文章主要介紹了mybatis foreach標(biāo)簽的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • ThreadPoolExecutor中的submit()方法詳細(xì)講解

    ThreadPoolExecutor中的submit()方法詳細(xì)講解

    在使用線程池的時(shí)候,發(fā)現(xiàn)除了execute()方法可以執(zhí)行任務(wù)外,還發(fā)現(xiàn)有一個(gè)方法submit()可以執(zhí)行任務(wù),本文就詳細(xì)的介紹一下ThreadPoolExecutor中的submit()方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-04-04
  • Mac下用Java調(diào)用c/c++的思路詳解

    Mac下用Java調(diào)用c/c++的思路詳解

    這篇文章主要介紹了Mac下用Java調(diào)用c/c++的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Java如何獲取List<String>中的String詳解

    Java如何獲取List<String>中的String詳解

    工作了這么長(zhǎng)時(shí)間了,一直沒有記錄的習(xí)慣,以至于導(dǎo)致我即便是查過(guò)的東西總會(huì)忘記,下面這篇文章主要給大家介紹了關(guān)于Java如何獲取List<String>中String的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Java注解處理器簡(jiǎn)單實(shí)例

    Java注解處理器簡(jiǎn)單實(shí)例

    這篇文章主要介紹了Java注解處理器簡(jiǎn)單實(shí)例,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01

最新評(píng)論