springcloud feign接口get傳封裝類參數修復

1.環境信息

    spring-boot : 2.2.1.RELEASE

    spring-cloud :  Hoxton.SR1

2.feign get接口傳封裝類參數時,需要添加RequestBody server端才能獲取到參數,測試如下:

3.這樣對前端來說不是太友好,前端需要get傳json

4.解決方法:

新增 feignConfig文件:

/**
 * Copyright (c) 2020 CQLIVING, Inc. All rights reserved.
 * This software is the confidential and proprietary information of 
 * CQLIVING, Inc. You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the 
 * license agreement you entered into with CQLIVING.
 */
package com.leo.api.handler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
 * Title: feign請求頭轉發策略
 * <p>Description:</p>
 * Copyright (c) CQLIVING 2020
 * @author liuzongyang on 2020年1月10日
 */
@Slf4j
@AllArgsConstructor
public class FeignConfigInterceptor implements RequestInterceptor {

    private final ObjectMapper objectMapper;

    @Override
    public void apply(RequestTemplate requestTemplate) {

        // get封裝參數修復
        if ("GET".equals(requestTemplate.method()) && (requestTemplate.requestBody().asBytes() != null)) {
            try {
                Request.Body body = requestTemplate.requestBody();
                JsonNode jsonNode = objectMapper.readTree(body.asBytes());
                requestTemplate.body(Request.Body.empty());
                Map<String, Collection<String>> queries = new HashMap<>();
                // 構建 Map
                buildQuery(jsonNode, "", queries);
                // queries 就是 POJO 解析爲 Map 後的數據
                requestTemplate.queries(queries);
            } catch (IOException e) {
                log.debug("get參數轉換失敗:{}", e);
            }
        }

        // 請求頭修復
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String values = request.getHeader(name);
                requestTemplate.header(name, values);
            }
        }
    }

    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
        if (!jsonNode.isContainerNode()) {
            // 如果是葉子節點
            if (jsonNode.isNull()) {
                return;
            }
            Collection<String> values = queries.get(path);
            if (CollectionUtils.isEmpty(values)) {
                values = new ArrayList<>();
                queries.put(path, values);
            }
            values.add(jsonNode.asText());
            return;
        }
        if (jsonNode.isArray()) {
            // 如果是數組節點
            Iterator<JsonNode> elements = jsonNode.elements();
            while (elements.hasNext()) {
                buildQuery(elements.next(), path, queries);
            }
        } else {
            Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> entry = fields.next();
                if (StringUtils.hasText(path)) {
                    buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                } else {
                    // 根節點
                    buildQuery(entry.getValue(), entry.getKey(), queries);
                }
            }
        }
    }

}

feignClient:

/**
 * Copyright (c) 2020 CQLIVING, Inc. All rights reserved.
 * This software is the confidential and proprietary information of 
 * CQLIVING, Inc. You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the 
 * license agreement you entered into with CQLIVING.
 */
package com.leo.api.feign;

import org.springframework.cloud.openfeign.FeignClient;

import com.leo.api.SdkTest;
import com.leo.api.handler.FeignConfigInterceptor;

/**
 * Title:sdktest
 * <p>Description:</p>
 * Copyright (c) CQLIVING 2020
 * @author liuzongyang on 2020年1月10日
 */
@FeignClient(name = "leo-cloud", url = "${leo-cloud-url:}", path = "test", configuration = FeignConfigInterceptor.class)
public interface SdkFeign extends SdkTest{

}

 

發佈了50 篇原創文章 · 獲贊 69 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章