Spring Cloud Gateway如何獲取body體數據

很久沒有使用gateway了 偶爾看到大家在問如何獲取完整body體,這裏放上我的方法。
org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory 中定義 在路由中配置了該謂詞 就可以將 body體中的數據放到exchange.getAttribute(“cachedRequestBodyObject”);
我們怎麼使用呢?

    @Bean
    public RouteLocator requestBodyCacheRoute(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        RouteLocatorBuilder.Builder serviceProvider = routes
                .route("requestBodyCacheRoute",
                        r -> r.method(HttpMethod.POST)
                                .and()
                                .readBody(String.class, readBody -> true)
                                .and()
                                .path(SERVICE)
                                .uri(URI));
        RouteLocator routeLocator = serviceProvider.build();
        return routeLocator;
    }

該方式能夠獲取到完整的body體並且不會產生body體被讀一次後無法再次讀取的問題
使用

 String requestBody = exchange.getAttribute("cachedRequestBodyObject");
        try {
            requestBody = URLDecoder.decode(requestBody, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

即可獲取參數
我封裝了一個統一處理get post 參數的方法

/**
 * @Description 封裝ServerWebExchange統一獲取參數方法
 * @Author changyandong
 * @Emoji (゜ - ゜)つ乾杯
 * @Created Date: 2019/8/27 9:21
 * @ClassName ServerWebExchangeUtils
 * @Version: 1.0
 */
public abstract class ServerWebExchangeUtils {

    public static Map<String, String> getParam(ServerWebExchange exchange) {
        HttpMethod method = exchange.getRequest().getMethod();
        if (Objects.equals(HttpMethod.GET, method)) {
            return handlingGetRequestParam(exchange);
        }
        return handlingPostRequestParam(exchange);
    }

    public static Map<String, String> handlingPostRequestParam(ServerWebExchange exchange) {
        // 這個屬性就是readBody 謂詞寫入的 完整body體內容
        String requestBody = exchange.getAttribute("cachedRequestBodyObject");
        try {
            requestBody = URLDecoder.decode(requestBody, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String contentType = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
        //當 參數爲 json
        if (Objects.equals(contentType, MediaType.APPLICATION_JSON_VALUE)) {
            JSONObject json = JSONObject.parseObject(requestBody);
            Map<String, Object> innerMap = json.getInnerMap();
            Map<String, String> returnMap = new LinkedHashMap<>();
            innerMap.forEach((k, v) -> returnMap.put(k, String.valueOf(v)));
            return returnMap;
        } else if (Objects.equals(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
            String[] params = requestBody.split("&");
            Map<String, String> returnMap = new LinkedHashMap<>();
            String lastKey = "";
            for (int i = 0; i < params.length; i++) {
                int index = params[i].indexOf('=');
                // 處理 value中含 &的情況
                if (index < 0) {
                    returnMap.put(lastKey, returnMap.get(lastKey) + "&" + params[i]);
                    continue;
                }
                // 取第一個=號 後面的都是value
                String value = params[i].substring(index + 1);
                String key = params[i].substring(0, index);
                returnMap.put(key, value);
                lastKey = key;
            }
            return returnMap;
        }
        return new LinkedHashMap<>();
    }

    public static Map<String, String> handlingGetRequestParam(ServerWebExchange exchange)     {
        return exchange.getRequest().getQueryParams().toSingleValueMap();
    }



}

具體原理就是我使用一個全局的Route 給他塞了readBody ReadBodyPredicateFactory就會解析 放到
exchange.getAttributes()中。我這個工具類並不全面,大家看個大概,我的工具類適用於我 並不一定適用於所有場景。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章