当前位置: 首页 > 知识库问答 >
问题:

具有泛型类型的WebFlux WebClient

张英范
2023-03-14

我正在尝试用来自spring WebFlux的WebClient制作一个客户端库。

服务器返回如下JSON所示的响应:

json prettyprint-override">{
  "result": [
    {
      "parent": "",
      "made_sla": "true",
      "watch_list": "",
      "upon_reject": "cancel",
      "sys_updated_on": "2016-01-19 04:52:04",
      "approval_history": "",
      "number": "PRB0000050",
      "sys_updated_by": "glide.maint",
      "opened_by": {
        "link": "https://instance.service-now.com/api/now/table/sys_user/glide.maint",
        "value": "glide.maint"
      },
      "user_input": "",
      "sys_created_on": "2016-01-19 04:51:19",
      "sys_domain": {
        "link": "https://instance.service-now.com/api/now/table/sys_user_group/global",
        "value": "global"
      },
      "state": "4",
      "sys_created_by": "glide.maint",
      "knowledge": "false",
      "order": "",
      "closed_at": "2016-01-19 04:52:04",
      "cmdb_ci": {
        "link": "https://instance.service-now.com/api/now/table/cmdb_ci/55b35562c0a8010e01cff22378e0aea9",
        "value": "55b35562c0a8010e01cff22378e0aea9"
      },
      "delivery_plan": "",
      "impact": "3",
      "active": "false",
      "work_notes_list": "",
      "business_service": "",
      "priority": "4",
      "sys_domain_path": "/",
      "time_worked": "",
      "expected_start": "",
      "rejection_goto": "",
      "opened_at": "2016-01-19 04:49:47",
      "business_duration": "1970-01-01 00:00:00",
      "group_list": "",
      "work_end": "",
      "approval_set": "",
      "wf_activity": "",
      "work_notes": "",
      "short_description": "Switch occasionally drops connections",
      "correlation_display": "",
      "delivery_task": "",
      "work_start": "",
      "assignment_group": "",
      "additional_assignee_list": "",
      "description": "Switch occasionally drops connections",
      "calendar_duration": "1970-01-01 00:02:17",
      "close_notes": "updated firmware",
      "sys_class_name": "problem",
      "closed_by": "",
      "follow_up": "",
      "sys_id": "04ce72c9c0a8016600b5b7f75ac67b5b",
      "contact_type": "phone",
      "urgency": "3",
      "company": "",
      "reassignment_count": "",
      "activity_due": "",
      "assigned_to": "",
      "comments": "",
      "approval": "not requested",
      "sla_due": "",
      "comments_and_work_notes": "",
      "due_date": "",
      "sys_mod_count": "1",
      "sys_tags": "",
      "escalation": "0",
      "upon_approval": "proceed",
      "correlation_id": "",
      "location": ""
    },
    {
      "parent": "",
      "made_sla": "true",
      "watch_list": "",
      "upon_reject": "cancel",
      "sys_updated_on": "2016-01-19 04:52:04",
      "approval_history": "",
      "number": "PRB0000050",
      "sys_updated_by": "glide.maint",
      "opened_by": {
        "link": "https://instance.service-now.com/api/now/table/sys_user/glide.maint",
        "value": "glide.maint"
      },
      "user_input": "",
      "sys_created_on": "2016-01-19 04:51:19",
      "sys_domain": {
        "link": "https://instance.service-now.com/api/now/table/sys_user_group/global",
        "value": "global"
      },
      "state": "4",
      "sys_created_by": "glide.maint",
      "knowledge": "false",
      "order": "",
      "closed_at": "2016-01-19 04:52:04",
      "cmdb_ci": {
        "link": "https://instance.service-now.com/api/now/table/cmdb_ci/55b35562c0a8010e01cff22378e0aea9",
        "value": "55b35562c0a8010e01cff22378e0aea9"
      },
      "delivery_plan": "",
      "impact": "3",
      "active": "false",
      "work_notes_list": "",
      "business_service": "",
      "priority": "4",
      "sys_domain_path": "/",
      "time_worked": "",
      "expected_start": "",
      "rejection_goto": "",
      "opened_at": "2016-01-19 04:49:47",
      "business_duration": "1970-01-01 00:00:00",
      "group_list": "",
      "work_end": "",
      "approval_set": "",
      "wf_activity": "",
      "work_notes": "",
      "short_description": "Switch occasionally drops connections",
      "correlation_display": "",
      "delivery_task": "",
      "work_start": "",
      "assignment_group": "",
      "additional_assignee_list": "",
      "description": "Switch occasionally drops connections",
      "calendar_duration": "1970-01-01 00:02:17",
      "close_notes": "updated firmware",
      "sys_class_name": "problem",
      "closed_by": "",
      "follow_up": "",
      "sys_id": "04ce72c9c0a8016600b5b7f75ac67b5b",
      "contact_type": "phone",
      "urgency": "3",
      "company": "",
      "reassignment_count": "",
      "activity_due": "",
      "assigned_to": "",
      "comments": "",
      "approval": "not requested",
      "sla_due": "",
      "comments_and_work_notes": "",
      "due_date": "",
      "sys_mod_count": "1",
      "sys_tags": "",
      "escalation": "0",
      "upon_approval": "proceed",
      "correlation_id": "",
      "location": ""
    },
    {
      "parent": "",
      "made_sla": "true",
      "watch_list": "",
      "upon_reject": "cancel",
      "sys_updated_on": "2016-01-19 04:52:04",
      "approval_history": "",
      "number": "PRB0000050",
      "sys_updated_by": "glide.maint",
      "opened_by": {
        "link": "https://instance.service-now.com/api/now/table/sys_user/glide.maint",
        "value": "glide.maint"
      },
      "user_input": "",
      "sys_created_on": "2016-01-19 04:51:19",
      "sys_domain": {
        "link": "https://instance.service-now.com/api/now/table/sys_user_group/global",
        "value": "global"
      },
      "state": "4",
      "sys_created_by": "glide.maint",
      "knowledge": "false",
      "order": "",
      "closed_at": "2016-01-19 04:52:04",
      "cmdb_ci": {
        "link": "https://instance.service-now.com/api/now/table/cmdb_ci/55b35562c0a8010e01cff22378e0aea9",
        "value": "55b35562c0a8010e01cff22378e0aea9"
      },
      "delivery_plan": "",
      "impact": "3",
      "active": "false",
      "work_notes_list": "",
      "business_service": "",
      "priority": "4",
      "sys_domain_path": "/",
      "time_worked": "",
      "expected_start": "",
      "rejection_goto": "",
      "opened_at": "2016-01-19 04:49:47",
      "business_duration": "1970-01-01 00:00:00",
      "group_list": "",
      "work_end": "",
      "approval_set": "",
      "wf_activity": "",
      "work_notes": "",
      "short_description": "Switch occasionally drops connections",
      "correlation_display": "",
      "delivery_task": "",
      "work_start": "",
      "assignment_group": "",
      "additional_assignee_list": "",
      "description": "Switch occasionally drops connections",
      "calendar_duration": "1970-01-01 00:02:17",
      "close_notes": "updated firmware",
      "sys_class_name": "problem",
      "closed_by": "",
      "follow_up": "",
      "sys_id": "04ce72c9c0a8016600b5b7f75ac67b5b",
      "contact_type": "phone",
      "urgency": "3",
      "company": "",
      "reassignment_count": "",
      "activity_due": "",
      "assigned_to": "",
      "comments": "",
      "approval": "not requested",
      "sla_due": "",
      "comments_and_work_notes": "",
      "due_date": "",
      "sys_mod_count": "1",
      "sys_tags": "",
      "escalation": "0",
      "upon_approval": "proceed",
      "correlation_id": "",
      "location": ""
    }
  ]
}

结果字段包含元素数组,这些元素可以根据使用的API而不同。

有关该API的更多信息,请参阅ServiceNow产品中的表API。

正如您在文档中所看到的,API路径如下所示:GET/now/table/{tableName},其中tableName可以是不同的值,tipology将依赖于提取的表中的结果元素。

因此,结果字段中的响应元素可以用不同的名称或不同数量的属性组成。基本上,它是一个通过HTTP公开的数据库,因此每个表可以由不同数量的列组成。

我的GET实现:

public Mono<Result> get(){
    return client.get()
            .uri(uriBuilder -> uriBuilder
                    .path(this.tablePath)
                    .queryParam("active", "true")
                    .queryParam("state", "1")
                    .build())
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(Result.class);
}

波约斯

@Data
public class ProjectTask {

    private String project;

}
@Data
public class Result <T> {

    List<T> result;

}

获取错误的简单用法:

List<ProjectTask> projectTasks = Objects.requireNonNull(
        client.table("pm_project_task")
                .get().block())
        .getResult();

for (ProjectTask task : projectTasks){
    System.out.println("========PROJECT=============== "+task.getProject());
}

(ProjectTask任务:projectTasks){的行处出现我的运行时错误

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to my.namespace.api.services.servicenow.model.ProjectTask

响应需求:

  • 结果POJO必须使用泛型类型来管理不同的响应元素类型。
  • 如果第一点无法完成,请尝试给出一个解决方案,通过不同表类型可重用GET实现来获取API。
  • 我不想从我的客户端返回列表,我的想法是这个库只返回Mono或Flux对象。

共有1个答案

荆城
2023-03-14

您需要使用parameterizedtypereference将json反序列化为result的确切类型。否则,spring将任何未知类型反序列化为LinkedHashMap。例如。

  public Mono<Result<ProjectTask>> get(){
    return client.get()
        .uri(uriBuilder -> uriBuilder
            .path(this.tablePath)
            .queryParam("active", "true")
            .queryParam("state", "1")
            .build())
        .accept(MediaType.APPLICATION_JSON)
        .retrieve()
        .bodyToMono(new ParameterizedTypeReference<Result<ProjectTask>>() {
        });
  }

如果您想使这个get方法成为一个通用的方法,它将适用于所有类型的result,那么您应该看看这个stackoverflow问题。

 类似资料:
  • 问题内容: 所以我有一张地图: 我会像这样添加元素: 我有如下通用方法: 现在,这段代码可以很好地工作,并且没有编译器问题: 但是,当我尝试这样做时: 编译器向我显示以下警告:类型安全:通用方法verifyType(String,Class)的未经检查的调用verifyType(String,Class) 这让我感到困惑…请帮助… 问题答案: 更改: 至 通过仅将类型声明为“ Class”,就失去

  • 在java 8中创建新代码后,我想清除声纳问题。 我的代码: 声纳说: Lambda应该替换为方法引用。方法/构造函数引用比使用lambda更紧凑和可读性,因此是首选。同样,空检查可以替换为对Object::isNull和Object::nonNull方法的引用。 我想要更改映射(arg-

  • 我试图在一个方法中使用泛型,在这个方法中,我将一个json反序列化为pojo,这样它就可以返回任何对象类型。 这里我的代码: 问题是

  • 问题内容: 目前,我在Java中遇到通用类问题。 我有这样的事情: 现在,我实例化了一个没有类型参数的类的对象,因为我对此没有兴趣或不知道。 问题是,尽管编译器不依赖于参数,但它不仅丢弃有关类型参数的信息,而且还丢弃有关集合(字符串)的类型的信息。 我是在做错什么,还是Java的限制?如果是这样,那为什么会有限制? 问题答案: 你做错了 如果您不知道T类型,则只需使用通配符: GenericCla

  • 介绍 针对 java.lang.reflect.Type 的工具类封装,最主要功能包括: 获取方法的参数和返回值类型(包括Type和Class) 获取泛型参数类型(包括对象的泛型参数或集合元素的泛型类型) 方法 首先我们定义一个类: public class TestClass { public List<String> getList(){ return new Arra

  • (沙盒) 获取此错误: 类型“number”不可分配给类型“T”“number”可分配给“T”类型的约束,但“T”可以用约束{}的不同子类型实例化。(2322)输入。ts(1,26):预期类型来自此签名的返回类型。 我希望typescript能够自动推断T为数字,然后直接使用它。为什么它在抱怨?写这样的东西的正确方法是什么?谢谢