如何删除 Spring HATEOAS 中的“_embedded”属性
Posted
技术标签:
【中文标题】如何删除 Spring HATEOAS 中的“_embedded”属性【英文标题】:How to remove the "_embedded" property in Spring HATEOAS 【发布时间】:2015-05-02 17:05:30 【问题描述】:我正在使用 Spring Boot 和 HATEOAS 构建一个 REST API,当我的 API 返回一个集合时,它被包装在一个“_embedded”属性中,如下所示:
"_links":
"self":
"href":"http://localhost:8080/technologies"
,
"_embedded":
"technologies":[
"id":1,
"description":"A",
"_links":
"self":
"href":"http://localhost:8080/technologies/1"
,
"id":2,
"description":"B",
"_links":
"self":
"href":"http://localhost:8080/technologies/2"
]
我希望回复是这样的:
"_links":
"self":
"href":"http://localhost:8080/technologies"
,
"technologies":[
"id":1,
"description":"A",
"_links":
"self":
"href":"http://localhost:8080/technologies/1"
,
"id":2,
"description":"B",
"_links":
"self":
"href":"http://localhost:8080/technologies/2"
]
我的技术控制器:
@RestController
@ExposesResourceFor(Technology.class)
@RequestMapping(value = "/technologies")
public class TechnologiesController
...
@ResquestMapping(method = RequestMethod.GET, produces = "application/vnd.xpto-technologies.text+json")
public Resources<Resource<Technology>> getAllTechnologies()
List<Technology> technologies = technologyGateway.getAllTechnologies();
Resources<<Resource<Technology>> resources = new Resources<Resource<Technology>>(technologyResourceAssembler.toResources(technologies));
resources.add(linkTo(methodOn(TechnologiesController.class).getAllTechnologies()).withSelfRel());
return resources;
配置类有注解@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)。
在没有“_embedded”的情况下产生响应的最佳方法是什么?
【问题讨论】:
如果您从响应中删除_embedded
,则响应将不再是有效的 HAL。您要么需要坚持使用_embedded
,要么使用其他媒体类型。
HAL 草案显示“保留的“_embedded”属性是可选的”
它是可选的,因为资源不必具有任何嵌入式资源。但是,如果确实如此,那么它们应该在_embedded
之下。
我也遇到了同样的问题。我在一个对象上有一个投影,并将其限制为仅显示名称。问题是有超过 20 个关系,所以 _embedded 对象很大。我也没有找到克服这个问题的好方法。
【参考方案1】:
您在生成的和预期的结果中描述的内容在语义上是不同的。前者是Collection<Technology>
的 HAL 表示。后者,您期望的是:
class Wrapper
Resources<Technology> technologies;
请注意,我们实际上是如何创建您希望在回复中看到的*** technologies
属性的。您不会在控制器中创建任何后者。***Resources
instance 基本上是一个集合,在HAL 中表示*** 集合的唯一方法是_embedded
。显然你不想这样,但这就是你在控制器方法中写的。
假设你有Wrapper
,这样的东西应该可以工作(未经测试):
Wrapper wrapper = new Wrapper(assembler.toCollectionModel(technologies);
EntityModel<Wrapper> model = EntityModel.of(wrapper);
model.add(linkTo(…));
PS:从 Spring HATEOAS 1.0 开始,Resources
是 CollectionModel
和 Resource
是 EntityModel
。
【讨论】:
【参考方案2】:对于那些使用 Spring Data,并将其视为问题的人 - 解决方案是设置
spring.data.rest.defaultMediaType = application/json
在应用程序属性中。 仍有链接可用,但不再有_embedded。
【讨论】:
这对我没有任何改变。 这从请求中删除了 _embedded ,而是添加了“内容”。真正的休息界面应该返回“技术”。没有?【参考方案3】:您可以在服务中使用此代码
constructor(
private httpClient: HttpClient
)
retrieveAllStudents()
return this.httpClient.get<any[]>(`http://localhost:8080/students`);
这将处理 Json 的 _embedded 部分并提取所需的数据。
export class ListStudentsComponent implements OnInit
// declaring variables to be used
student: Student;
students: Student[];
message: string;
// injecting student service into the constuctor
constructor(
private studentService: StudentService,
)
ngOnInit()
this.refreshStudents();
refreshStudents()
this.studentService.retrieveAllStudents().subscribe(
response =>
console.log(response);
this.students = response._embedded.students as Student[];
);
【讨论】:
【参考方案4】:我关闭了 HAL 功能,因为restTemplate 很难使用Resources/Resource。我通过以下代码禁用此功能:
public class SpringRestConfiguration implements RepositoryRestConfigurer
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config)
config.setDefaultMediaType(MediaType.APPLICATION_JSON);
config.useHalAsDefaultJsonMediaType(false);
它对我有用。如果有更多对 restTemplate 的支持,HAL 会很好。
【讨论】:
它有效,但实际上根本没有解决问题。它不是在_embedded
字段中返回数据,而是创建一个更好的content
字段,但不会创建作者所需的technologies
字段;【参考方案5】:
正如documentation 所说
application/hal+json 响应应该发送给接受的请求 应用程序/json
为了在您的回复中省略_embedded
,您需要添加
spring.hateoas.use-hal-as-default-json-media-type=false
到application.properties
。
【讨论】:
我做到了。但不幸的是,它仍然存在【参考方案6】:将此Accept
标头添加到请求中:
Accept : application/x-spring-data-verbose+json
【讨论】:
对我来说,这会返回一个406
并带有以下消息:“找不到可接受的表示”以上是关于如何删除 Spring HATEOAS 中的“_embedded”属性的主要内容,如果未能解决你的问题,请参考以下文章
删除 Spring RepositoryRestResource 中的“_embedded”属性
将 Zuul、Hystrix(和 Feign)与 Spring Cloud HATEOAS 一起使用时如何转发标头?
带有 RepositoryRestResource-s 和常规控制器的 Spring REST HATEOAS 中的根请求的自定义响应
Spring Boot:HATEOAS 和自定义 JacksonObjectMapper