zoukankan      html  css  js  c++  java
  • 解决: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

  • 相关阅读:
    第一章 工欲善其事 必先利其器—Android SDK工具(3)
    UVa 11063
    Remember the Word,LA3942(Trie树+DP)
    Atitit.Gui控件and面板----数据库区-mssql 2008 权限 配置 报表查看成员
    Android手机令牌教程
    cocos2d-x 在mac下执行 demo
    Install Oracle 10g on Red Hat Linux 5.3 Step by Step
    Python根据内嵌的数字将字符串排序(sort by numbers embedded in strings)
    mysql一次运行多个SQL文件
    CentOS/Linux 卸载MATLAB
  • 原文地址:https://www.cnblogs.com/QullLee/p/10682719.html
Copyright © 2011-2022 走看看