【问题标题】:HAL with Spring Hateoas and Mvc (without Boot)带有 Spring Hateoas 和 Mvc 的 HAL(无引导)
【发布时间】:2015-11-03 09:37:01
【问题描述】:

我正在使用 spring mvc 和 hateoas 来构建一个宁静的 api。以前,我将 spring boot 与 hatoas 一起使用,服务器按预期呈现响应。现在,我没有使用 spring boot,服务器没有正确呈现响应。根据我的研究,我发现有些人在谈论涉及配置消息转换器的解决方案。那么,除了注解@EnableHypermediaSupport,在没有spring boot的情况下设置媒体类型HAL还需要什么?

ApiConfiguration.java:

@Configuration
@ComponentScan
@EnableWebMvc
@EnableHypermediaSupport(type = { HypermediaType.HAL })
public class ApiConfiguration {
}

ApiInitializer.java:

public class ApiInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
  protected Class<?>[] getRootConfigClasses() {
      return null;
  }

  @Override
  protected Class<?>[] getServletConfigClasses() {
      return new Class[] { ApiConfiguration.class };
  }

  @Override
  protected String[] getServletMappings() {
      return new String[] { "/" };
  }

}

pom.xml:

...
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>4.2.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.hateoas</groupId>
        <artifactId>spring-hateoas</artifactId>
        <version>0.19.0.RELEASE</version>
    </dependency>
    ...

AdaptationRestController.java:

@RestController
@ExposesResourceFor(Adaptation.class)
@RequestMapping(value = "/adaptations")
public class AdaptationRestController {

    ...
    @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/vnd.xpto-adaptation+json")
    public ResponseEntity<AdaptationResource> getAdaptation(@PathVariable("id") String adaptationId) {
        Adaptation adaptation = adaptationGateway.getAdaptation(adaptationId);
        AdaptationResource adaptationResource = adaptationResourceAssembler.toResource(adaptation);

        return new ResponseEntity<AdaptationResource>(adaptationResource, HttpStatus.OK);
    }
}

AdaptationResource.java:

public class AdaptationResource extends Resource<Adaptation> {

    public AdaptationResource(Adaptation adaptation) {
        super(adaptation);
    }

}

我得到了什么:

"links": [
    {
        "rel": "self",
        "href": "http://xpto.com"
    }
],
...

假设:

"_links": {
    "self": {"href": "http://xpto.com"}
},
...

【问题讨论】:

  • 不够是什么意思?你期望什么,你得到什么? spring boot 添加了像 jackson 这样的依赖项,这可能会产生神奇的效果。
  • 我编辑了我的问题,包括我得到的和我期望的。我已经尝试包含以下依赖项并且问题仍然存在:json-path、jackson-databind、jackson-core 和 jackson-annotations
  • 好奇,不想用Spring Boot的原因是什么?
  • 最初我使用的是 spring boot,但放弃它的原因之一是我在使用 @ControllerAdvice 进行错误处理时遇到了困难。

标签: spring spring-mvc spring-hateoas hal


【解决方案1】:

如果您使用 Spring Data JPA 进行数据访问,您可以通过添加 EnableSpringDataWebSupport 以声明方式启用其 Web 支持。这将为Controller 方法注册一堆ArgumentResolvers。简而言之,您可以将 PagedResourcesAssembler 参数添加到您的方法中,并使用其 toResource 方法将 Pageed 实体转换为资源,如下所示:

    @RequestMapping(method = GET)
    public ResponseEntity getAll(PagedResourcesAssembler ass) {
        Page<User> users = userRepository.findAll(new PageRequest(0, 10));
        PagedResources pagedResources = ass.toResource(users, assembler);

        return ok(pagedResources);
    }

使用这个 json 输出:

{"_embedded":{...},"_links":{"self":{"href":"http://localhost:8080/users"}},"page":{...}}

【讨论】:

  • 我没有在我的项目中使用数据访问。无论如何,我尝试添加注释 EnableSpringDataWebSupport 并且 json 保持不变。
  • 你有没有想过这个问题?从 Spring Boot 迁移到 Spring 后,我也面临这个问题。
【解决方案2】:

一个选项是让你的模型扩展 org.springframework.hateoas.ResourceSupport

public class MyModelClass extends ResourceSupport

然后

@RequestMapping(value="/myresource", method=RequestMethod.GET)
public ResponseEntity<Iterable<MyModelClass>> getAll() {
Iterable<MyModelClass> all= repository.findAll();
for(MyModelClass p : all) {
p.add(linkTo(methodOn(MyController.class).getAll()).slash(p.getId()).withSelfRel());
}
return new ResponseEntity<>(all, HttpStatus.OK);
}

【讨论】:

  • 我正在这样做。我编辑了问题以包括控制器和资源实体。
【解决方案3】:

基本上我使用EntityLinks 来构建链接,而不是从任何依赖于框架的类扩展我的 Pojo。

@RestController
@ExposesResourceFor(ProjectServiceResponse.class) 
public class ProjectController {
  @Autowired
  private org.springframework.hateoas.EntityLinks entityLinks;

  public HttpEntity<Resource<ProjectServiceResponse>> get(...){
    Resource resource = new Resource<ProjectServiceResponse>(response);
    resource.add(entityLinks.linkToCollectionResource(ProjectServiceResponse.class).withSelfRel());
    return new ResponseEntity<Resource<ProjectServiceResponse>>(resource, HttpStatus.OK);
  }
}

回复:

"_links": {
"self": {
  "href": "http://localhost:8080/project"
}

在我上面的代码中,ProjectServiceResponse.class 是 POJO。

你可以在github上参考完整的项目

【讨论】:

  • 思路是一样的。我刚刚实现了一个扩展 Resource<...> 的附加类,以避免泛型的所有冗长,并实现了一个汇编程序类,该类使用来自域实体的链接构建资源。您正在使用 Spring Boot。在我的代码中使用 Spring Boot 时我没有任何问题。当我删除 Spring Boot 时,向 HAL 的转换不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 2021-07-17
  • 2011-11-02
  • 2017-03-14
  • 2016-06-13
  • 1970-01-01
相关资源
最近更新 更多