【问题标题】:Spring REST response is different in a custom controller自定义控制器中的 Spring REST 响应不同
【发布时间】:2016-12-01 23:49:36
【问题描述】:

我有几个自动创建 REST 端点的控制器。

@RepositoryRestResource(collectionResourceRel = "books", path = "books")
public interface BooksRepository extends CrudRepository<Books, Integer> {
    public Page<Books> findTopByNameOrderByFilenameDesc(String name);
}

当我访问时:http://localhost:8080/Books

我回来了:

{
    "_embedded": {
        "Books": [{
            "id": ,
            "filename": "Test123",
            "name": "test123",
            "_links": {
                "self": {
                    "href": "http://localhost:8080/books/123"
                },
                "Books": {
                    "href": "http://localhost:8080/books/123"
                }
            }
        }]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/books"
        },
        "profile": {
            "href": "http://localhost:8080/profile/books"
        },
        "search": {
            "href": "http://localhost:8080/books/search"
        },
        "page": {
            "size": 20,
            "totalElements": 81,
            "totalPages": 5,
            "number": 0
        }
    }
}

当我创建自己的控制器时:

@Controller
@RequestMapping(value = "/CustomBooks")
public class CustomBooksController {
    @Autowired
    public CustomBookService customBookService;

    @RequestMapping("/search")
    @ResponseBody
    public Page<Book> search(@RequestParam(value = "q", required = false) String query,
                                 @PageableDefault(page = 0, size = 20) Pageable pageable) {
        return customBookService.findAll();
    }
}

我会得到一个与自动生成的控制器响应完全不同的响应:

{
    "content": [{
        "filename": "Test123",
        "name" : "test123"
    }],
    "totalPages": 5,
    "totalElements": 81,
    "size": 20,
    "number": 0,
}

我需要做什么才能使我的回复看起来像自动生成的回复?我想保持一致,所以我不必为不同的响应重写代码。我应该以不同的方式来做吗?


编辑: 发现这个:Enable HAL serialization in Spring Boot for custom controller method

但我不明白我需要在 REST 控制器中进行哪些更改才能启用:PersistentEntityResourceAssembler。我在 Google 上搜索了 PersistentEntityResourceAssembler,但它不断引导我回到类似的页面而没有太多示例(或者该示例似乎对我不起作用)。

【问题讨论】:

  • 你试过@ResourceRestController吗?
  • 不确定我是否正确理解了您的问题,但我猜您正在寻找的是 HATEOAS spring.io/guides/gs/rest-hateoas
  • 一个返回一个 Page 另一个返回一个 Page (注意 s),但我猜这是一个错字?
  • @chrylis 我认为没有“@ResourceRestController”?你的意思是“@RestController”吗?
  • @KevinVasko 我的错误——它是 @RepositoryRestController,正如 Alex 指出的那样。

标签: java spring spring-data spring-data-rest spring-rest


【解决方案1】:

正如@chrylis 建议的那样,您应该将@Controller 注释替换为@RepositoryRestController,以便spring-data-rest 调用它的ResourceProcessors 来自定义给定资源。

为了让您的资源遵循 HATEOAS 规范(如您的 spring-data-rest BooksRepository),您的方法声明返回类型应类似于 HttpEntity&lt;PagedResources&lt;Resource&lt;Books&gt;&gt;&gt; 将您的 Page 对象转换为 PagedResources:

  • 你需要自动装配这个对象。

    @Autowired private PagedResourcesAssembler<Books> bookAssembler;

  • 你的退货声明应该是这样的

    return new ResponseEntity&lt;&gt;(bookAssembler.toResource(customBookService.findAll()), HttpStatus.OK);

这些更改应该可以帮助您获得符合 org.springframework.hateoas.Resources 的响应,其中包含 "_embedded""_links" 属性。

【讨论】:

  • 作为参考,您可以使用此回复[link]stackoverflow.com/questions/31758862/…
  • 你的意思是“@RestController”吗?我在网上的任何地方都看不到“@ResourceRestController”。当我添加“@Autowired”私有 PagedResourcesAssembler intelliJ 抱怨它不能自动装配它。它确实编译并且springboot确实启动了。但是,当我调用我的控制器时,我收到此错误“出现意外错误(类型 = 内部服务器错误,状态 = 500)。无法编组 [PagedResource { 内容:[资源 { 内容:....”最重要的是,这个错误页面是 XML 而不是 JSON。我从 Solr 中提取这个应该没关系吧?书籍是我的榜样。
  • 为了拥有上述功能,您的 CustomBooksController 应该与您的 BooksRepository 类在同一个项目中。
  • 几个问题——构造函数注入(通常),然后我相信如果你只返回一个Collection&lt;Book&gt;,SDR 将自动处理资源组装。仅当您需要以编程方式设置响应标头或状态(而不是使用注释或异常)时才需要使用 ResponseEntity。这应该使代码更加简单。
  • 如果您想返回单个实体,请使用PersistentEntityResourceAssembler。如果方法声明中存在,它将被自动注入(@AlexCiocan,很高兴在这里看到你的答案:)。
猜你喜欢
  • 2017-01-07
  • 2019-04-03
  • 2016-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 2018-09-12
  • 1970-01-01
相关资源
最近更新 更多