• 解决:SpringCloud中Feign支持GET请求POJO传参


    在日常的开发中,当遇到一个请求需要传递多个参数时,我们习惯将参数封装到一个POJO对象中,已提高程序的可读性和简化编写。但是在使用SpringCloud时,Feign对SpringMVC注解支持并不完善,其中一点就是,当发送的GET请求携带多个参数时,不能使用POJO来封装参数,这个就比较蛋疼了。一种使之支持GET请求POJO传递参数的方法如下:

    添加Maven依赖

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>com.netflix.feign</groupId>
                <artifactId>feign-httpclient</artifactId>
                <version>8.15.1</version>
            </dependency>
       
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-hystrix</artifactId>
                <version>10.2.0</version>
                <scope>compile</scope>
            </dependency>
    
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
            </dependency>
            <dependency>
                <groupId>io.github.openfeign</groupId>
                <artifactId>feign-okhttp</artifactId>
            </dependency>
    

    application.yml

            feign:
              hystrix:
                enabled: true
              httpclient:
                enabled: true
              okhttp:
                enabled: true
    

    添加对GET请求的拦截器

            
    import com.alibaba.fastjson.JSON;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import feign.RequestInterceptor;
    import feign.RequestTemplate;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpMethod;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    import javax.annotation.Resource;
    import java.io.IOException;
    import java.util.*;
    
    /**
     * 拦截Fegin的get请求,使之支持get请求pojo传参
     */
    @Component
    public class FeignRequestInterceptor implements RequestInterceptor {
        private static final Logger log = LoggerFactory.getLogger(FeignRequestInterceptor.class);
        @Resource
        private ObjectMapper objectMapper;
    
        @Override
        public void apply(RequestTemplate template) {
            if (HttpMethod.GET.name().equals(template.method())
                    && null != template.body()) {
                try {
                    JsonNode jsonNode = objectMapper.readTree(template.body());
                    template.body(null);
    
                    Map<String, Collection<String>> queries = new HashMap<>();
                    buildQuery(jsonNode, "", queries);
                    template.queries(queries);
                } catch (IOException e) {
                    log.error("【拦截GET请求POJO方式】-出错了:{}", JSON.toJSONString(e));
                    throw new RuntimeException();
                }
            }
        }
    
        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 (null == values) {
                    values = new ArrayList<>();
                    queries.put(path, values);
                }
                values.add(jsonNode.asText());
                return;
            }
            // 数组节点
            if (jsonNode.isArray()) {
                Iterator<JsonNode> it = jsonNode.elements();
                while (it.hasNext()) {
                    buildQuery(it.next(), path, queries);
                }
            } else {
                Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
                while (it.hasNext()) {
                    Map.Entry<String, JsonNode> entry = it.next();
                    if (StringUtils.hasText(path)) {
                        buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                    } else {  // 根节点
                        buildQuery(entry.getValue(), entry.getKey(), queries);
                    }
                }
            }
        }
    
    }
    

    其他

    此时你的应用程序就可以通过POJO封装参数向其他服务发起调用了。但是如果你请求的Content-Type是application/json的,那么你要需要指定请求的consumes为 consumes = MediaType.APPLICATION_JSON_VALUE

  • 相关阅读:
    poj 3126 Prime Path
    poj 2255 Tree Recovery
    spoj 7259 LITE
    poj 1742 Coins
    poj 1915 Knight Moves
    poj 2352 Stars
    【祝贺】gooogleman嵌入式开发板联盟图标设计完成,Let me Show!
    【讨论】TE6410/OK6410 开发板dnw c0008000是什么意思, ?
    【讨论】为什么我的300W摄像头偶尔会拍照不成功?
    【探讨】关于2440 触摸屏驱动的怪异现象分析
  • 原文地址:https://www.cnblogs.com/QullLee/p/10682719.html
Copyright © 2020-2023  润新知