首页 > 其他分享 >Feign 实现 GET 方法传递 POJO

Feign 实现 GET 方法传递 POJO

时间:2022-11-14 22:34:12浏览次数:66  
标签:Feign GET jsonNode POJO queries public

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 做如下请求

image

返回成功结果。

完整代码见:feign-usage

参考资料

重新定义 Spring Cloud 实战

标签:Feign,GET,jsonNode,POJO,queries,public
From: https://www.cnblogs.com/greyzeng/p/16890723.html

相关文章

  • 什么是Session;request.getSession().setAttribute()
    Session:会话控制,是服务器为了保存用户状态而创建的一个特殊的对象。=>用于存储信息的一个对象   当我们在服务端使用session时,首先要获取session,下面这个图就对服务......
  • linux下使用wget命令提示cannot verify cmake.org's certificate
      1、在使用linux下载cmake编译器时,提示如上图错误可以看到上图提示,使用--no-check-certificate参数即可 ......
  • TypeScript系列 -> 遇到报错 Cannot find name ‘console‘. Do you need to change y
    学习ts遇到的报错Cannotfindname‘console‘.Doyouneedtochangeyourtargetlibrary?gingthe‘lib‘compileroption解决办法:需要安装TypeScript助手的运......
  • 5.feign整合sentinel
    feign整合sentinelSpringCloud中,微服务调用都是通过Feign来实现的,因此做客户端保护必须整合Feign和Sentinel。一、修改配置,开启sentinel功能修改OrderService的applicat......
  • LoggerFactory.getLogger 的过程(一)
    Loggerlog=LoggerFactory.getLogger(TestRunner.class);上面这行代码,就可以获取一个logger的实例,然后就可以用来打印日志了。这篇就探究这个方法都干了什么。1publicsta......
  • Nuget管理器下载插件出现依赖性相关无法正确下载
    话不多说,直接上图:  上面我采用的是PM控制台下载EntityFrameWork最新版本,之所以要这样做,是因为利用Nuget管理器好像不咋管用呀,一直说这个依赖那个依赖啥的,还不如最底层......
  • OpenFeign
    OpenFeign—服务间的调用一.什么是Feign和OpenFeign?在使用Feign或者OpenFeign前,服务之间的调用路径在函数内部设置:能不能像controller调用service一样,通过注入的方式设置呢......
  • OpenFeign
    OpenFeign—服务间的调用一.什么是Feign和OpenFeign?在使用Feign或者OpenFeign前,服务之间的调用路径在函数内部设置:能不能像controller调用service一样,通过注......
  • jquery-一行代码解决跨域问题 | 仅限get请求
    问题平时我们在开发时遇到的跨域问题,后台暂不给解决时,我们一般可以用vue代理(node)、nginx反向代理等方式来解决但是当项目要上线的时候,这些问题将又会出现就比如,自制的......
  • 35. vue响应式的get和set如何触发或者过程
    首先,vue内部使用 Object.defineProperty给data中的数据添加了getter和setter函数 ;当我们访问数据的时候,会触发getter函数return给我们数据值,当我们修改数据......