Feign 实现 GET 方法传递 POJO

作者:Grey

原文地址:

博客园:Feign 实现 GET 方法传递 POJO

CSDN:Feign 实现 GET 方法传递 POJO

需求

Spring MVC 支持 GET 方法直接绑定 POJO 的,但是 Feign 目前无法做到,有几种解决方案

方案一:把 POJO 拆散成一个一个单独的属性放在方法参数里。

方案二:把方法参数变成Map传递。

方案三:使用 GET 传递 @RequestBody ,但此方式违反 Restful 规范。

方案四(最佳实践):通过实现 Feign 的 RequestInterceptor 中的 apply 方法来进行统一拦截转换处理 Feign 中的 GET 方法多参数传递的问题。

接下来介绍方案四,即最佳实践。

环境

Java 版本:17

Spring Boot 版本:2.7.5

Spring Cloud 版本:2021.0.5

项目结构和说明

  • feign-usage:父项目名称

    • register-server : 仅作注册中心,无其他业务方法

      • src/
      • pom.xml
    • provider : 服务端端模块
      • src/
      • pom.xml
    • consumer : 客户端模块
      • src/
      • pom.xml
    • pom.xml:父项目 pom 配置

代码说明

provider 项目中,定义了一个 Controller ,用于接收用户请求,有如下的一个方法。

@RestController
@RequestMapping("/user")
public class UserController { @RequestMapping(value = "/add", method = RequestMethod.GET)
public String addUser(User user, HttpServletRequest request) {
String token = request.getHeader("oauthToken");
return "hello, add user : " + user.getName();
} ……
}

基于上述两个服务,客户端 consumer 定义了一个 feign 客户端用于请求服务端的服务

@FeignClient(name = "provider")
public interface UserFeignService { @RequestMapping(value = "/user/add", method = RequestMethod.GET)
String addUser(User user);
……
}

用于 feign 使用 GET 无法直接传递 POJO,所以定义如下一个拦截器,在 apply 方法种处理请求并封装成 POJO 发送给服务端,本实例中,我们要封装的是 User 对象

public class User {

    private Long id;
private String name;
private int age; // 省略 Get / Set 方法
}

定义的拦截器代码如下


@Component
public class FeignRequestInterceptor implements RequestInterceptor { private final ObjectMapper objectMapper; public FeignRequestInterceptor(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
} @Override
public void apply(RequestTemplate template) {
if (template.method().equals("GET") && template.body() != null) {
try {
JsonNode jsonNode = objectMapper.readTree(template.body());
template.body(null, StandardCharsets.UTF_8);
Map<String, Collection<String>> queries = new HashMap<>();
buildQuery(jsonNode, "", queries);
template.queries(queries);
} catch (IOException e) {
e.printStackTrace();
}
}
} private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
if (!jsonNode.isContainerNode()) {
if (jsonNode.isNull()) {
return;
}
Collection<String> values = queries.computeIfAbsent(path, k -> new ArrayList<>());
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);
}
}
}
}
}

测试一下,分别启动 register-server,provider,consumer 三个项目,使用 Postman 做如下请求

返回成功结果。

完整代码见:feign-usage

参考资料

重新定义 Spring Cloud 实战

Feign 实现 GET 方法传递 POJO的更多相关文章

  1. Spring Boot 和 Spring Cloud Feign调用服务及传递参数踩坑记录

    背景 :在Spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端.我们可以使用JDK原生的URLConnectio ...

  2. 【问题】Asp.net MVC 的cshtml页面中调用JS方法传递字符串变量参数

    [问题]Asp.net MVC 的cshtml页面中调用JS方法传递字符串变量参数. [解决]直接对变量加引号,如: <button onclick="deleteProduct('@ ...

  3. 如何解决Response.Redirect方法传递汉字丢失或乱码问题?

    为了确保传递的汉字被正确地接收,可以在传值之前使用Server对象的UrlEncode方法对所传递的汉字进行URL编码.代码如下: String name = Server.UrlEncode(&qu ...

  4. Jquery Ajax方法传递json到action

    ajax向后台传入json需要设置option,如下 contentType:'application/json' data:Json.Stringify(jsObj) 后台处理复杂json对象(不知 ...

  5. 给方法传递参数:ref参数和out参数

    /*--------------------------------------------------- 给方法传递参数:ref参数和out参数 (P106) ------------------- ...

  6. javascript重定向页面并用post方法传递消息

    javascript中重定向页面得方法很多,同时能传递消息的也不少:但可用post方法传递的我只找到两种: 第一种方法:用document.write在 JavaScript函数中,用document ...

  7. Vue把父组件的方法传递给子组件调用(评论列表例子)

    Vue把父组件的方法传递给子组件调用(评论列表例子) 效果展示: 相关Html: <!DOCTYPE html> <html lang="en"> < ...

  8. HTML的GET方法传递参数样式。

    #HTML的GET方法传递参数样式.http://127.0.0.1:8080/web1/urlinfo/getobject.html?UserId=1&UserName=ad

  9. mybatis由浅入深day01_ 7输入映射(7.1传递pojo的包装对象_7.2#{}与${}_7.3传递简单类型_7.4传递pojo对象_7.5传递hashmap)

    7 输入映射 通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型. 7.1 传递pojo的包装对象 7.1.1 需求 完成用户信息的综合查询,需要 ...

  10. tornado框架的get方法传递参数

    tornado框架的get方法传递参数,代码: # encoding: utf-8 """ @version: ?? @author: andu99 @contact: ...

随机推荐

  1. 避免jquery多次监听事件

    jQuery.event.dispatch 事件分发监听源码简单理解是将绑定的事件放入队列后进行监听,如果对一个事件多次绑定(on或者bind),事件会重复添加到队列等待jq监听,这样会导致很大资源消 ...

  2. Zookeeper+dubbo+Springboot集成总结

    1. 尽量用XML 集成,这也的Dubbo官方推荐的集成方式 自己在使用注解集成过程中发现有坑:Springmvc包扫描和dubbo包扫描冲突,导致消费端一直拿不到代理对象(null),非常蛋疼,所以 ...

  3. cmake 入门笔记

    以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/p/16667896.html 1. cmake 是什么? 这些 ...

  4. thinkphp5.1发送邮件的方法

    1.安装插件 composer require phpmailer/phpmailer 2.application下的common.php文件里加上一下代码,可自己根据需求稍加修改,我用的是验证码 u ...

  5. CVE-2022-39197(CobaltStrike XSS <=4.7)漏洞复现

    最新文章更新见个人博客 漏洞说明 根据9.20日CobaltStrike官方发布的最新4.7.1版本的更新日志中介绍,<=4.7的teamserver版本存在XSS漏洞,从而可以造成RCE远程代 ...

  6. 使用kubeoperator安装的k8s集群以及采用的containerd容器运行时,关于采用的是cgroup 驱动还是systemd 驱动的说明

    使用kubeoperator安装的k8s集群,默认使用的是systemd驱动 # kubectl get cm -n kube-system NAME DATA AGE calico-config 4 ...

  7. K8S概念理解

    Master 负责管理集群 负责协调集群中的所有活动,例如调度应用程序,维护应用程序的状态,扩展和更新应用程序. Worker节点是VM(虚拟机)或物理计算机,充当k8s集群中的工作计算机. 每个Wo ...

  8. 使用ConfigMap配置您的应用程序

    转载自:https://kuboard.cn/learning/k8s-intermediate/config/config-map.html ConfigMap 作为 Kubernetes API ...

  9. 如何调试 Docker

    开启 Debug 模式 在 dockerd 配置文件 daemon.json(默认位于 /etc/docker/)中添加 { "debug": true } 重启守护进程. $ s ...

  10. MongoDB集群搭建---副本和分片(伪集群)

    参考地址:https://blog.csdn.net/weixin_43622131/article/details/105984032 已配置好的所有的配置文件下载地址:https://files. ...