Spring Boot REST服务,如何将链接作为属性进行编排?

6

这是我第一次提问,请温柔点 :)

我有一个 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
}

一切都很好,我已经在我的pom文件中添加了spring-boot-starter-data-rest,现在我得到了一个服务。这是我得到的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实体,而是创建另一个POJO来表示SignUpSheet(出于重复目的,我希望避免这样做,但如果有必要/有益的话,我可以考虑)。我已经将Jackson2HalModule添加到了ObjectMapper中,但无论是否存在都似乎没有任何区别。

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper o = new ObjectMapper();
    o.registerModule(new Jackson2HalModule());
    return o;
}

感谢您的帮助!

=======================================================

解决方案:

第一步,先阅读手册 :)

我发现我需要在新创建的DTO上扩展ResourceSupport。已经完成了。但是没有返回链接!似乎我需要在RestTemplate上的对象映射器上添加Jackson2HalModule,就像这样:

    ObjectMapper o = new ObjectMapper();
    o.registerModule(new Jackson2HalModule());
    MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter();
    c.setObjectMapper(o);
    restTemplate.getMessageConverters().add(0, c);

所以我想我会扩展RestTemplate并使用@Component,这样我就可以处理任何HATEOAS资源了。

2个回答

3
我认为您不应该尝试将JSON反序列化回JPA实体。JPA实体与应用程序数据库密切相关,应被视为服务器的实现细节。相反,我建议映射到一个特别针对REST API而建模的类型,而不是基于数据库结构和使用JPA的类型。
您正在使用强烈支持超媒体的Spring Data REST。这意味着客户端应使用URI标识资源并使用链接在它们之间导航。例如,在客户端上,注册表已经有一个ID;它是响应中“self”链接的“href”。因此,没有必要公开JPA实体的ID。事实上,这样做会暴露应用程序的实现细节,客户端不需要知道。
与其尝试填充响应中的所有属性,Spring Data REST提供了链接。例如,要访问报名表的父级,您应从响应中提取“parent”链接的“href”,并对URI执行“GET”请求。

我有一种感觉,我的问题源于对Hypermedia使用方式的误解。因此,在创建我想要编组的对象时,我如何获取链接?我是否应该使用Link类创建成员变量? - Doug Busley
是的,这听起来像是一个合理的方法。你可以重用Spring HATEOAS的Link类或者创建自己的类。 - Andy Wilkinson

0

您需要扩展RepositoryRestConfigurerAdapter,以告诉您需要导出Id,例如:

public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(SignUpSheet.class);
 }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接