java - 使用 spring-boot-2.2.1 删除 HATEOAS 链接中的 _embedded
问题描述
我正在使用 spring-boot-2.2.1 和 spring-HATEOAS。超媒体链接工作正常,但我在返回链接时看到属性,请在此处_embedded
找到以下代码以供参考和 github 中的项目,
端点:
a) 将返回CollectionModel
=> localhost:8099/api/v1/capability/list/noembedded
和
b) 将返回 List<EntityModel< Capability>> localhost:8099/api/v1/capability/list/
<?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.data.rest.defaultMediaType = 应用程序/json
spring.hateoas.use-hal-as-default-json-media-type=false
但是我仍然无法_embedded
在响应中看到属性。谁能帮我找出问题所在。
我spring-boot-1.5.10
在那里之前使用过,我可以在没有的情况下正确呈现链接_embedded
,请参考这里。
在主类中添加下面的注释并且如果我返回 List 后它工作正常
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
本地主机: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"
}
}
}
]
不幸的是,它不适用于最新版本。任何帮助将非常感激。
解决方案
如果我正确理解HAL 规范,那将是无效的 HAL,这就是为什么只要您CollectionModel
在请求中返回 a,Spring HATEOAS 就不会产生此结果。请注意,集合也可能具有链接,如本示例文档中所述,该链接将位于_embedded
属性中的_links
属性旁边。
如果您真的想摆脱该_embedded
属性并生成EntityModel<T>
s 列表,那么如果您修改代码以返回 a ,它应该可以工作List<EntityModel<Capability>>
。然后,您将丢失Spring HATEOAS 生成的_embedded
和属性。_links
这是您修改后的代码段:
@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;
}
}
我强烈建议您不要这样做,因为您失去了 Spring HATEOAS 的优势。
此外,我建议使用你的CapabilityResourceAssembler
并通过使用创建EntityModel<Capability>
实例,capabilityResourceAssembler.toModel(...)
这样你就不必重复你在.map(...)
函数中实现的代码。
推荐阅读
- arduino - 对传入的 MQTT 消息没有反应
- php - Wordpress:将当前页面 ID(acf)放入 plugin-file.php
- powershell - Powershell:作为本地系统运行时向登录用户发送 toast 通知
- google-analytics - 记录用户的 ID 和点击次数
- linux - 如何将目录 (cd) 更改为存在指定文件的目录?
- kubernetes - 使用注释启用旧版 TLS
- mysql - IS NULL 时无法更新 mysql
- python - 如何在数据框中查找具有整数值的列并在python中的所有整数或浮点值周围添加引号?
- menu - 我的下拉菜单不会显示,我该怎么办?
- html - Web 应用程序缺少滚动条且无法滚动