最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

這幾天在用 spring-boot 2 的 webflux 重構(gòu)一個工程,寫到了一個需要獲得客戶端請求 IP 的地方,發(fā)現(xiàn)寫不下去了,在如下的 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;
/**
 * 某業(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 中是相當基本的需求啊,竟然獲取不到,然后 Google 了一下,發(fā)現(xiàn)這個是 spring-webflux 的一個 BUG ,這個 BUG 在 spring-webflux 5.1 中解決了,但是,略有些尷尬的是當前最新穩(wěn)定版的 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#getRequest
org.springframework.http.server.reactive.ServerHttpRequest#getRemoteAddress

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

過濾、取 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 中不支持直接獲得請求 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);
    }
  }
}

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

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

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

總結(jié)

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

相關(guān)文章

  • SpringBoot整合Redis實現(xiàn)token緩存

    SpringBoot整合Redis實現(xiàn)token緩存

    于token通常會被多次使用,我們需要把它保存到緩存中,以減少頻繁地訪問數(shù)據(jù)庫,本文主要介紹了SpringBoot整合Redis實現(xiàn)token緩存,感興趣的可以了解一下
    2024-02-02
  • maven+阿里云創(chuàng)建國內(nèi)鏡像的中央倉庫(親測可用)

    maven+阿里云創(chuàng)建國內(nèi)鏡像的中央倉庫(親測可用)

    本篇文章主要介紹了maven+阿里云創(chuàng)建國內(nèi)鏡像的中央倉庫(親測可用),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • 完美解決因數(shù)據(jù)庫一次查詢數(shù)據(jù)量過大導致的內(nèi)存溢出問題

    完美解決因數(shù)據(jù)庫一次查詢數(shù)據(jù)量過大導致的內(nèi)存溢出問題

    今天小編就為大家分享一篇完美解決因數(shù)據(jù)庫一次查詢數(shù)據(jù)量過大導致的內(nèi)存溢出問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Java多線程中的CyclicBarrier詳解

    Java多線程中的CyclicBarrier詳解

    這篇文章主要介紹了Java多線程中的CyclicBarrier詳解,同步屏障,允許一組線程互相等待以到達一個公共的障礙點,當設(shè)定的線程數(shù)到達屏障時,阻塞的線程繼續(xù)執(zhí)行,需要的朋友可以參考下
    2023-11-11
  • SpringBoot基于SpringSecurity表單登錄和權(quán)限驗證的示例

    SpringBoot基于SpringSecurity表單登錄和權(quán)限驗證的示例

    這篇文章主要介紹了SpringBoot基于SpringSecurity表單登錄和權(quán)限驗證的示例。文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • SpringMVC工作原理實例詳解

    SpringMVC工作原理實例詳解

    這篇文章主要介紹了SpringMVC工作原理實例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Springboot集成fastDFS配置過程解析

    Springboot集成fastDFS配置過程解析

    這篇文章主要介紹了Springboot集成fastDFS配置過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • java自定義日期轉(zhuǎn)化類示例

    java自定義日期轉(zhuǎn)化類示例

    這篇文章主要介紹了java自定義日期轉(zhuǎn)化類示例,需要的朋友可以參考下
    2014-05-05
  • Java中SpringBoot自定義Starter詳解

    Java中SpringBoot自定義Starter詳解

    這篇文章主要介紹了Java中SpringBoot自定義Starter詳解,Starter是Spring Boot中的一個非常重要的概念,Starter相當于模塊,它能將模塊所需的依賴整合起來并對模塊內(nèi)的Bean根據(jù)環(huán)境進行自動配置,需要的朋友可以參考下
    2023-07-07
  • 使用Java和Redis實現(xiàn)高效的短信防轟炸方案

    使用Java和Redis實現(xiàn)高效的短信防轟炸方案

    在當今互聯(lián)網(wǎng)應用中,短信驗證碼已成為身份驗證的重要手段,然而,這也帶來了"短信轟炸"的安全風險?-?惡意用戶利用程序自動化發(fā)送大量短信請求,導致用戶被騷擾和企業(yè)短信成本激增,本文將詳細介紹如何使用Java和Redis實現(xiàn)高效的短信防轟炸解決方案,需要的朋友可以參考下
    2025-04-04

最新評論

台湾省| 新疆| 中宁县| 松原市| 文昌市| 宝兴县| 礼泉县| 福贡县| 通山县| 南部县| 永靖县| 翁源县| 邹平县| 富蕴县| 张家川| 阿巴嘎旗| 华安县| 东阿县| 辽阳市| 小金县| 龙口市| 深泽县| 札达县| 上饶县| 迭部县| 宁国市| 息烽县| 大洼县| 会东县| 迁西县| 西峡县| 松阳县| 吉首市| 托里县| 泊头市| 岱山县| 吉首市| 小金县| 山阳县| 华亭县| 县级市|