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

删除HATEOAS链接中的_embedded

毋承基
2023-03-14

我正在使用sping-boot-2.2.1和sping-HATEOAS。超媒体链接工作正常,但是我在返回链接时看到了_embedded属性,请在这里找到下面的代码作为参考和github中的项目,

终点:

a)将返回集合模型=

b) 将返回列表

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-boot-unittest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-unittest</name>
    <description>Demo project for Spring Boot unit test</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-mongodb</artifactId>
            <version>4.1.4</version>
        </dependency>

        <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>4.1.4</version>
        </dependency>
        <!-- Embedded  MongoDB for Testing -->
        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.2.21</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.mysema.maven</groupId>
                <artifactId>apt-maven-plugin</artifactId>
                <version>1.1.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>process</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/generated-sources/java</outputDirectory>
                            <!--<processor>com.querydsl.mongodb.morphia.MorphiaAnnotationProcessor</processor>-->
                            <processor>org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor</processor>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

控制器。Java

@RestController
@RequestMapping(value = "/api/v1/capability")
@RequiredArgsConstructor
@CrossOrigin
public class CapabilityController {

    private final CapabilityService capabilityService;
    private final CapabilityResourceAssembler capabilityResourceAssembler;

    @GetMapping(value = "/list")
    public CollectionModel<EntityModel<Capability>> getAllCapabilities() {
       List<EntityModel<Capability>> capabilities = capabilityService.listCapabilities().stream()
               .map(capability -> new EntityModel<>(capability,
                       linkTo(methodOn(CapabilityController.class).getCapabilityById(capability.getId())).withRel("getThisCapability"),
                       linkTo(methodOn(CapabilityController.class).getAllCapabilities()).withRel("getAllCapabilities")
               )).collect(Collectors.toList());
        return new CollectionModel<>(capabilities);
    }
}

实际反应

{
  "_embedded": {
    "capabilityList": [
      {
        "id": "sample",
        "techStack": "Java",
        "numOfDevelopers": 25,
        "numOfAvailableDevelopers": 10,
        "_links": {
          "getThisCapability": {
            "href": "http://localhost:8099/api/v1/capability/sample"
          },
          "getAllCapabilities": {
            "href": "http://localhost:8099/api/v1/capability/list"
          },
          "deleteThisCapability": {
            "href": "http://localhost:8099/api/v1/capability/sample"
          },
          "createCapability": {
            "href": "localhost:8099/api/v1/capability"
          }
        }
      }
    ]
  }
}

预期反应:

[
  {
    "id": "sample",
    "techStack": "Java",
    "numOfDevelopers": 25,
    "numOfAvailableDevelopers": 10,
    "_links": {
      "getThisCapability": {
        "href": "http://localhost:8099/api/v1/capability/sample"
      },
      "getAllCapabilities": {
        "href": "http://localhost:8099/api/v1/capability/list"
      }
    }
  }
]

我试过了

Spring数据RestdefaultMediaType=application/json

spring.hateoas.use默认为json-media-type

但是没有运气,我仍然能够在响应中看到_embedded属性。有人能帮我识别这个问题吗?

在此之前,我使用的是spring-boot-1.5.10,在没有_embedded的情况下,我能够正确地呈现链接,请参考这里。

在我在主类中添加了下面的注释之后,如果我返回列表,它就可以正常工作了

@EnableHypermediaSupport(type=EnableHypermediaSupport.HypermediaType.HAL)

localhost:9771/api/v1/capability/list

这将产生以下结果:

[
  {
    "capabilityId": "sample",
    "techStack": "Java",
    "numOfDevelopers": 25,
    "numOfAvailableDevelopers": 10,
    "_links": {
      "getThisCapability": {
        "href": "http://localhost:9771/api/v1/capability/sample"
      },
      "getAllCapabilities": {
        "href": "http://localhost:9771/api/v1/capability/list"
      }
    }
  }
]

不幸的是,它在最新版本中不起作用。任何帮助都将不胜感激。

共有3个答案

严开宇
2023-03-14

我建议用一个collection类型的字段@JsonValue扩展CollectionModel,然后在汇编程序中重写CollectionModel以返回自定义CollectionModel

public class CustomCollectionModel<T> extends CollectionModel<CollectionModel<T>>  {
@JsonValue
private Collection<T> content;

protected CustomCollectionModel() {
    this(new ArrayList<>());
}

public CustomCollectionModel(Iterable<T> content, Link... links) {
    this(content, Arrays.asList(links));
}


public CustomCollectionModel(Iterable<T> content, Iterable<Link> links) {

    Assert.notNull(content, "Content must not be null!");

    this.content = new ArrayList<>();

    for (T element : content) {
        this.content.add(element);
    }

    this.add(links);
}}

然后在你的汇编程序里

  @Override
public CustomCollectionModel toCollectionModel(Iterable<? extends T> entities) {
    List<EntityModel<T>> resourceList = new ArrayList<>();

    for (T entity : entities) {
        resourceList.add(toModel(entity));
    }
    return new CustomCollectionModel(resourceList);
}
牟正真
2023-03-14

如果我正确理解HAL规范,这将是无效的HAL,这就是为什么Spring HATEOAS不会产生这个结果,只要您在请求中返回CollectionModel。请注意,集合也可能有链接,链接将位于\u links属性中嵌入的\u属性旁边,如本示例文档所示。

如果你真的想摆脱_embedded属性并生成一个EntityModel列表

@RestController
@RequestMapping(value = "/api/v1/capability")
@RequiredArgsConstructor
@CrossOrigin
public class CapabilityController {

    private final CapabilityService capabilityService;
    private final CapabilityResourceAssembler capabilityResourceAssembler;

    @GetMapping(value = "/list")
    public List<EntityModel<Capability>> getAllCapabilities() {
       List<EntityModel<Capability>> capabilities = capabilityService.listCapabilities().stream()
               .map(capability -> new EntityModel<>(capability,
                       linkTo(methodOn(CapabilityController.class).getCapabilityById(capability.getId())).withRel("getThisCapability"),
                       linkTo(methodOn(CapabilityController.class).getAllCapabilities()).withRel("getAllCapabilities")
               )).collect(Collectors.toList());
        return capabilities;
    }
}

我强烈建议不要这样做,因为你失去了SpringHATEOAS的优势。

此外,我建议利用您的功能ResourcesAssembler创建实体模型

黄俊智
2023-03-14

使用Spring Boot 1.5时,您依赖于Spring HATEOAS的限制,这导致JacksonObjectMapper被用作应用程序范围内的ObjectMapper。这种污染意味着HAL格式应用于本不应该应用的响应。

Spring HATEOAS 1.0解决了这一限制,其特定于HAL的ObjectMapper不再污染整个应用程序。如果您想让主应用程序ObjectMapper应用HAL样式的序列化,您可以通过自定义它来重新选择:

@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder,
                                 HypermediaMappingInformation mappingInformation) {
    ObjectMapper objectMapper = builder.build();
    mappingInformation.configureObjectMapper(objectMapper);
    return objectMapper;
}

虽然我认为上述方法会奏效,但我将回应Daniel在回答中提出的关于响应格式和HAL规范合规性的担忧。

 类似资料:
  • 本文向大家介绍Linux中移除(删除)符号链接的命令,包括了Linux中移除(删除)符号链接的命令的使用技巧和注意事项,需要的朋友参考一下 你可能有时需要在 Linux 上创建或者删除符号链接。如果有,你知道该怎样做吗?之前你做过吗?你踩坑没有?如果你踩过坑,那没什么问题。如果还没有,别担心,我们将在这里帮助你。 使用 rm 和 unlink 命令就能完成移除(删除)符号链接的操作。 什么是符号链

  • 我如何描述HAL中的帖子链接? 我正在设计一个带有HATEOAS约束的RESTful API,类似于Wikipedia的HATEOAS示例,但用HAL JSON表示(为了清晰起见,删除了scheme、host等): 为了执行“转移”操作,客户大概会这样做: 通过GET调用“transfer”链接会在“transfers”中创建一个新的ressource。但是创建一个新资源并不是幂等的,它“感觉”不

  • 问题内容: 我有一个指向重要目录的符号链接。我想摆脱该符号链接,同时保留目录。 我试着回来。 我试着回来 ,然后逐步前进,然后 然后我去找我的后援。 有没有一种方法可以消除符号链接,而不会把婴儿和洗澡水一起扔掉? 问题答案: 基本上,您需要告诉它删除 文件 ,而不是删除 目录 。我相信之间的差异和存在的,因为在C库将每一个的方式不同。 无论如何,第一个应该工作,而第二个应该抱怨foo是目录。 如果

  • 问题内容: 我试图将链接显示为白色,但不带下划线。文本颜色正确显示为白色,但蓝色下划线顽固地保持不变。我试图和在CSS删除链接的下划线。两者都不起作用。 如何从链接中删除蓝色下划线? 问题答案: 如我所料,您不是要应用到锚点(),而是要应用到span元素()。 尝试这个:

  • 我想要一些关于在数组中管理超链接的建议 我有一个功能,可以将列数据从我的“数据”谷歌工作表电子表格传输到我的“度量”谷歌工作表电子表格。这很有效。 但是,我正在传输的列包含一个超链接。 (=超链接(“https://www.instagram.com/p/B5wVG5bn_6C/?igshid=1237ljejed19t“,“帖子链接#2655”) 当该值被传输到指标表时,超链接被剥离。 是否仍然