Spring 引导休息服务,如何让它将链接编组为属性?
Spring boot rest service, how to get it to marshal the links as properties?
这里是第一个问题所以要温和 :)
我有一个 JPA 项目,我想将其公开为 REST。到目前为止我已经这样做了:
我的实体:
@Entity
public class SignUpSheet {
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@Column
private String description;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date dateTime;
@ManyToOne
private User parent;
@OneToMany
private List<Volunteer> volunteers;
//getter and setters
}
一切顺利,我调用添加 spring-boot-starter-data-rest 到我的 pom,现在我得到了服务。这是我回来的 JSON。
http://localhost:8080/api-0.1.0/signUpSheets/1
{
"name": "Auction",
"description": "My First Sign Up Sheet",
"dateTime": "2015-04-22T03:47:12.000+0000",
"volunteers": [
{
"role": "Bringing stuff",
"comments": "I have comments!"
}
],
"endpoint": "/signUpSheets",
"_links": {
"self": {
"href": "http://localhost:8080/api-0.1.0/signUpSheets/1"
},
"parent": {
"href": "http://localhost:8080/api-0.1.0/signUpSheets/1/parent"
},
"user": {
"href": "http://localhost:8080/api-0.1.0/signUpSheets/1/user"
}
}
}
超级棒!几乎是我所期望的。现在我使用 Spring 的 RestTemplate 调用我的服务,这就是我卡住的地方。当它编组回 SignUpSheet 对象时,它会拉入大部分对象,但 ID 字段为空(这是有道理的,因为 Json 中没有 ID 字段,只是一个自引用)和所有 OneToMany和 ManyToOne 对象为空(我假设原因相同)。
我的问题是:如何告诉 Spring Hateoas 将 ID 添加到 json 或告诉 Jackson 如何将 ID 编组到 ID 字段中?此外,我如何获得链接?我是否应该重新编组到 JPA 实体中,而是为 SignUpSheet 创建另一个 POJO(出于重复目的我想避免这种情况,但如果它是 necessary/desirable 由于某种原因我丢失了,可以讨论)。我已将 Jackson2HalModule 添加到我的 ObjectMapper,但它是否存在似乎没有任何区别。
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper o = new ObjectMapper();
o.registerModule(new Jackson2HalModule());
return o;
}
在此先感谢您的帮助!
============================================= ==========
解决方案:
第一步,阅读手册:)
所以我发现我需要在我新创建的 DTO 上扩展 ResourceSupport。完成了。但是我没有得到任何链接!似乎我需要将 Jackson2HalModule 添加到 RestTemplate 上的对象映射器 ,如下所示:
ObjectMapper o = new ObjectMapper();
o.registerModule(new Jackson2HalModule());
MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter();
c.setObjectMapper(o);
restTemplate.getMessageConverters().add(0, c);
所以我想我会扩展 RestTemplate 和 @Component 它,我应该对任何 HATEOAS 资源都有好处。
我认为您不应该尝试将 JSON 反序列化回您的 JPA 实体。 JPA 实体与应用程序的数据库紧密相关,应被视为服务器的实现细节。相反,我建议映射到专门基于 REST API 建模的类型,而不是基于数据库结构和 JPA 的使用。
您正在使用 Spring 强烈支持超媒体的数据 REST。这意味着客户端应该使用 URI 来标识资源并使用 links 在它们之间导航。比如在客户端,一个注册sheet已经有一个ID;它是响应中 self
link 的 href
。因此,无需公开 JPA 实体的 ID。事实上,这样做会暴露客户不需要知道的应用程序的实现细节。
Data REST 没有尝试填充响应中的所有属性,而是提供 links。例如,要访问注册 sheet 的父级,您应该从响应中提取 parent
link 的 href
并执行 GET
请求在 URI 上。
您需要扩展 RepositoryRestConfigurerAdapter
来告诉您需要导出 ID,例如:
public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(SignUpSheet.class);
}
}
这里是第一个问题所以要温和 :)
我有一个 JPA 项目,我想将其公开为 REST。到目前为止我已经这样做了:
我的实体:
@Entity
public class SignUpSheet {
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@Column
private String description;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date dateTime;
@ManyToOne
private User parent;
@OneToMany
private List<Volunteer> volunteers;
//getter and setters
}
一切顺利,我调用添加 spring-boot-starter-data-rest 到我的 pom,现在我得到了服务。这是我回来的 JSON。
http://localhost:8080/api-0.1.0/signUpSheets/1
{
"name": "Auction",
"description": "My First Sign Up Sheet",
"dateTime": "2015-04-22T03:47:12.000+0000",
"volunteers": [
{
"role": "Bringing stuff",
"comments": "I have comments!"
}
],
"endpoint": "/signUpSheets",
"_links": {
"self": {
"href": "http://localhost:8080/api-0.1.0/signUpSheets/1"
},
"parent": {
"href": "http://localhost:8080/api-0.1.0/signUpSheets/1/parent"
},
"user": {
"href": "http://localhost:8080/api-0.1.0/signUpSheets/1/user"
}
}
}
超级棒!几乎是我所期望的。现在我使用 Spring 的 RestTemplate 调用我的服务,这就是我卡住的地方。当它编组回 SignUpSheet 对象时,它会拉入大部分对象,但 ID 字段为空(这是有道理的,因为 Json 中没有 ID 字段,只是一个自引用)和所有 OneToMany和 ManyToOne 对象为空(我假设原因相同)。
我的问题是:如何告诉 Spring Hateoas 将 ID 添加到 json 或告诉 Jackson 如何将 ID 编组到 ID 字段中?此外,我如何获得链接?我是否应该重新编组到 JPA 实体中,而是为 SignUpSheet 创建另一个 POJO(出于重复目的我想避免这种情况,但如果它是 necessary/desirable 由于某种原因我丢失了,可以讨论)。我已将 Jackson2HalModule 添加到我的 ObjectMapper,但它是否存在似乎没有任何区别。
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper o = new ObjectMapper();
o.registerModule(new Jackson2HalModule());
return o;
}
在此先感谢您的帮助!
============================================= ==========
解决方案:
第一步,阅读手册:)
所以我发现我需要在我新创建的 DTO 上扩展 ResourceSupport。完成了。但是我没有得到任何链接!似乎我需要将 Jackson2HalModule 添加到 RestTemplate 上的对象映射器 ,如下所示:
ObjectMapper o = new ObjectMapper();
o.registerModule(new Jackson2HalModule());
MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter();
c.setObjectMapper(o);
restTemplate.getMessageConverters().add(0, c);
所以我想我会扩展 RestTemplate 和 @Component 它,我应该对任何 HATEOAS 资源都有好处。
我认为您不应该尝试将 JSON 反序列化回您的 JPA 实体。 JPA 实体与应用程序的数据库紧密相关,应被视为服务器的实现细节。相反,我建议映射到专门基于 REST API 建模的类型,而不是基于数据库结构和 JPA 的使用。
您正在使用 Spring 强烈支持超媒体的数据 REST。这意味着客户端应该使用 URI 来标识资源并使用 links 在它们之间导航。比如在客户端,一个注册sheet已经有一个ID;它是响应中 self
link 的 href
。因此,无需公开 JPA 实体的 ID。事实上,这样做会暴露客户不需要知道的应用程序的实现细节。
Data REST 没有尝试填充响应中的所有属性,而是提供 links。例如,要访问注册 sheet 的父级,您应该从响应中提取 parent
link 的 href
并执行 GET
请求在 URI 上。
您需要扩展 RepositoryRestConfigurerAdapter
来告诉您需要导出 ID,例如:
public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(SignUpSheet.class);
}
}