使用 Spring Boot 时如何为 Spring HATEOAS 配置自定义 RelProvider?

How to configure a custom RelProvider for Spring HATEOAS when using Spring Boot?

我正在使用派对模式:

@Entity
@Inheritance(strategy=...)
@JsonTypeInfo(use= JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@DiscriminatorColumn(name = "type")
public abstract class Party {

  @Column(updatable = false, insertable = false)
  private String type;

  ...
}

@Entity
public class Individual extends Party {
  ...
}

@Entity class Organization extends Party {
  ...
}

Spring 数据 REST 响应如下:

{
  "_embedded": {
    "organizations": [
      {
        "type":"Organization",
        "name": "Foo Enterprises",
        "_links": {
          "self": {
            "href": "http://localhost/organization/2"
          },
          "organization": {
            "href": "http://localhost/organization/2"
          }
        }
      }
    ],
    "individuals": [
      {
        "type":"Individual",
        "name": "Neil M",
        "_links": {
          "self": {
            "href": "http://localhost/individual/1"
          },
          "individual": {
            "href": "http://localhost/individual/1"
          }
        }
      }
    ]
  }
}

但我需要它像这样回应:

{
  "_embedded": {
    "parties": [
      {
        "type": "Organization",
        "name": "Foo Enterprises",
        "_links": {
          "self": {
            "href": "http://localhost/party/2"
          },
          "organization": {
            "href": "http://localhost/party/2"
          }
        }
      },
      {
        "type": "Individual",
        "name": "Neil M",
        "_links": {
          "self": {
            "href": "http://localhost/party/1"
          },
          "individual": {
            "href": "http://localhost/party/1"
          }
        }
      }
    ]
  }
}

这样做,我明白我 need to provide a custom RelProvider:

@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class MyRelProvider implements RelProvider {

    public MyRelProvider() {}

    @Override
    public String getItemResourceRelFor(Class<?> aClass) {
        return "party";

    }

    @Override
    public String getCollectionResourceRelFor(Class<?> aClass) {
        return "parties";
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.isAssignableFrom(Party.class);
    }
}

我尝试在 Application.java 中配置它:

@SpringBootApplication
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    RelProvider myRelProvider() {
        return new MyRelProvider();
    }
}

虽然这不起作用。它似乎没有注册,或者注册不正确。参见 http://andreitsibets.blogspot.ca/2014/04/hal-configuration-with-spring-hateoas.html

我该如何解决这个问题?

你有没有用 @ExposesResourceFor

注释你的控制器 类

来自spring hateos docs

  1. SPIs

3.1. RelProvider API

When building links you usually need to determine the relation type to be used > for the link. In most cases the relation type is directly associated with a (domain) type. We encapsulate the detailed algorithm to lookup the relation types behind a RelProvider API that allows to determine the relation types for single and collection resources. Here’s the algorithm the relation type is looked up:

  1. If the type is annotated with @Relation we use the values configured in the annotation.

  2. if not, we default to the uncapitalized simple class name plus an appended List for the collection rel.

  3. in case the EVO inflector JAR is in the classpath, we rather use the plural of the single resource rel provided by the pluralizing algorithm.

  4. @Controller classes annotated with @ExposesResourceFor (see EntityLinks for details) will transparently lookup the relation types for the type configured in the annotation, so that you can use relProvider.getSingleResourceRelFor(MyController.class) and get the relation type of the domain type exposed.

A RelProvider is exposed as Spring bean when using @EnableHypermediaSupport automatically. You can plug in custom providers by simply implementing the interface and exposing them as Spring bean in turn.

我有同样的问题,如果您有兴趣,我有一个肮脏的解决方案。为

这样的子类实现私有存储库
@RepositoryRestResource(path = "parties")    
interface IndividualRepository extends PagingAndSortingRepository<Individual, Long>{
}

希望这能让您暂时松一口气。