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()中。我这个工具类并不全面,大家看个大概,我的工具类适用于我 并不一定适用于所有场景。

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