Feign 实现 GET 方法传递 POJO

feign,实现,get,方法,传递,pojo · 浏览次数 : 476

小编点评

## Feign 实现 GET 方法传递 POJO 以下是 Feign 实现 GET 方法传递 POJO 的几种解决方案方案及其优缺点: **1. 将 POJO 拆散成一个一个单独的属性放在方法参数里** 优点:简单易实现,每个方法参数对应一个属性。 缺点:方法参数数量可能增加,代码可读性降低。 **2. 将方法参数变成Map传递** 优点:方法参数和请求体都封装在同一个Map中,方便处理。 缺点:代码可读性降低,方法参数可能会非常多。 **3. 使用 GET 传递 @RequestBody ,但此方式违反 Restful 规范** 优点:方便快捷,可以根据需要调整请求参数。 缺点:不符合 RESTful 规范,无法使用浏览器访问请求。 **4. 通过实现 Feign 的 RequestInterceptor 中的 apply 方法来进行统一拦截转换处理 Feign 中的 GET 方法多参数传递问题** 优点:代码简洁,可以处理多参数请求。 缺点:该方法需要编写多个拦截器实现不同参数的处理。 **最佳实践:通过实现 Feign 的 RequestInterceptor 中的 apply 方法来进行统一拦截转换处理 Feign 中的 GET 方法多参数传递问题** 由于 Feign 目前无法直接传递 POJO,我们可以通过在 RequestInterceptor 中进行统一拦截转换处理多参数请求。以下是最佳实践的步骤: 1. **创建一个 RequestInterceptor 接口**,继承 `RequestInterceptor` 类。 2. **在 apply 方法中解析 JSON 数据并将 POJO 封装成所需的格式**,例如 Map 或 POJO。 3. **将解析后的 POJO 发送给服务端**。 4. **使用 `@RequestHeader` 注解在方法参数上设置请求头**,用于传递 POJO 的标识信息。 **示例代码:** ```java @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 { // 解析 JSON 数据并将 POJO 封装成 Map Map data = objectMapper.readValue(template.body(), Map.class); // 设置请求头 template.headers().put("userId", String.valueOf(data.get("id"))); // 发送请求 String response = template.uri().toString() + "/user/" + data.get("id"); // 处理响应 } catch (IOException e) { e.printStackTrace(); } } } } ``` **注意:** 1. 需要在项目配置中添加 `@FeignClient` 注解标记服务客户端。 2. 服务端需要根据请求头中的 `userId` 进行数据库查询并返回结果。 3. 该方法仅适用于处理多个参数的 GET 请求。如果需要处理多个参数的 POST 或 PUT 请求,需要使用其他方法。

正文

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 方法传递 POJO相似的内容:

Feign 实现 GET 方法传递 POJO

Feign 实现 GET 方法传递 POJO 作者:Grey 原文地址: 博客园:Feign 实现 GET 方法传递 POJO CSDN:Feign 实现 GET 方法传递 POJO 需求 Spring MVC 支持 GET 方法直接绑定 POJO 的,但是 Feign 目前无法做到,有几种解决方案

Postman 的 Basic Auth 如何通过 Feign 实现

Postman 的 Basic Auth: 分析 根据以上图片分析: Postman 的 Authorization 实际为: header 中添加 Authorization: ******* ******* => "Base" + " " + base64("Username"+":"+"Pas

微服务使用openfeign调用单点的会话失效问题

# 项目Springcloud,认证中心方式实现SSO使用开源框架Sa-Token >本身的单独访问每个客户端服务的单点就没有问题。然后单点通过Fegin调用就不好使了! ##### 主要使用的Sa-Token的微服务单点功能 ##### 使用的依赖如下 ```xml cn.dev33 sa-tok

基于人形检测的划区域客流统计

摘要:通过本教程,我们学习了一类客流统计应用——区域内客流统计,通常用于室外安防,或室内客流热力图,经过简单改造还可以实现区域入侵检测、人员在离岗检测等应用。 本文分享自华为云社区《客流分析之基于人形检测的划区域客流统计》,作者:HiLens_feige 。 在智慧园区、智慧门店等商业场景中,划区域

AI开发实践丨客流分析之未佩戴口罩识别

摘要:通过本教程,我们可以学习客流统计应用的扩展——过线客流统计+口罩佩戴识别,可用于商超、写字楼入口安检。 本文分享自华为云社区《客流分析之未佩戴口罩识别》,作者: HiLens_feige 。 疫情虽然过去了,口罩佩戴防护依然十分重要,本文在 基于头肩部检测的过线客流统计 博文基础上增加口罩佩戴

SpringCloud解决feign调用token丢失问题

背景讨论 feign请求 在微服务环境中,完成一个http请求,经常需要调用其他好几个服务才可以完成其功能,这种情况非常普遍,无法避免。那么就需要服务之间的通过feignClient发起请求,获取需要的 资源。 认证和鉴权 一般而言,微服务项目部署环境中,各个微服务都是运行在内网环境,网关服务负责请

基于头肩部检测的过线客流统计

摘要:通过本教程,我们学习了另一类客流统计应用——过线客流统计,通常用于室内出入口,摄像头会架设在高处俯拍,使用头肩部检测可以减少人与人之间的遮挡。 本文分享自华为云社区《客流分析之基于头肩部检测的过线客流统计》,作者:HiLens_feige 。 1.基于头肩部检测的过线客流统计 除了划区域客流统