遵循rel-links时,HAL用单数名词而不是复数名词链接

时间:2019-01-31 11:05:20

标签: spring spring-data-rest spring-hateoas hal-json

我正在使用Spring Boot(2.1.1)自动创建JpaRepository接口的HAL REST API。

在大多数情况下,这些接口为空,例如:

public interface ProjectRepository extends JpaRepository<Project, Long> {}

public interface ProtocolRepository extends JpaRepository<Protocol, Long> {}

一个Project实体包含许多Protocol实体。 Protocol实体具有与其Project实体的反向链接。

当我访问http://localhost:8080/admin/protocols/4711时,会获得指向其项目的链接:

...
"project": {
  "href": "http://localhost:8080/admin/protocols/4711/project"
}
...

但是当我按照该链接进行操作时,所有其他链接都会生成错误:

  ...
  "_links": {
    "self": {
      "href": "http://localhost:8080/admin/project/1"
    },
    "project": {
      "href": "http://localhost:8080/admin/project/1"
    }
  ...
  }
  ...

链接中的错误是使用单数名词project,而不是复数形式projects

由于这些链接是自动生成的,因此如何更改此行为并不明显。

1 个答案:

答案 0 :(得分:1)

在调试Spring内部时,我发现PersistentEntityResourceAssembler使用DefaultSelfLinkProvider的实例创建自链接。 当我调试该类时,我意识到为由Hibernate代理的对象生成自链接时,该类无法正常工作。

因此,我尝试用自己的DefaultSelfLinkProvider接口实现替换SelfLinkProvider

这可以通过BeanPostProcessor完成:

  @Bean
  public BeanPostProcessor entityManagerBeanPostProcessor()
  {
    return new BeanPostProcessor()
    {
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
      {
        return bean;
      }

      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
      {
        if (bean instanceof SelfLinkProvider)
        { return new HibernateSelfLinkProvider((SelfLinkProvider) bean); }
        return bean;
      }
    };
  }

HibernateSelfLinkProviderSelfLinkProvider周围的一个简单包装:

public class HibernateSelfLinkProvider implements SelfLinkProvider
{
  private final SelfLinkProvider selfLinkProvider;

  public HibernateSelfLinkProvider(SelfLinkProvider selfLinkProvider)
  {
    this.selfLinkProvider = selfLinkProvider;
  }

  @Override
  public Link createSelfLinkFor(Object instance)
  {
    instance = Hibernate.unproxy(instance);
    return selfLinkProvider.createSelfLinkFor(instance);
  }
}

Hibernate.unproxy()的优点是,如果它不是代理对象,则它会使给定对象保持不变。

通过此添加,我获得了正确的链接:"http://localhost:8080/admin/projects/1"。 但是我不确定这是否是修改行为的最佳场所。