当前位置: 首页 > 知识库问答 >
问题:

Spring Hateoas问题渲染HAL内容

钦耀
2023-03-14

我一直在检查类似的问题,没有找到任何解决我所观察到的问题的答案。

问题是,当我检索1个资源时,我很容易在我的REST API中获得HAL格式的超媒体,但当我遇到检索实体列表的控制器方法时,超媒体就不一样了。

以下是输出:

>

  • 返回的单个资源

    “\u links”:{“self”:{“href”:”http://localhost:8080/celsvs/api/books/123567891099“},“books”:{“href”:http://localhost:8080/celsvs/api/books" } }

    >

  • 资源列表

    "链接": [ { "rel":"自己","href":"http://localhost:8080/celsvs/api/books/123567891099 " }, { "rel":"书籍","href":"http://localhost:8080/celsvs/api/books"}]

    我从Spring hateoas 0.25开始,但由于我必须升级Spring boot,我看到hateoas API已经更改,我现在使用Spring hateoas 1.0。。。即使在我的代码适应了新的API之后,我仍然得到了相同的结果。

    我正在使用SymationModelAssemblerSupport类来保持我的控制器从代码中干净以生成hateoas内容。所以这是它的样子:

    @Component
    public class BookModelAssembler extends RepresentationModelAssemblerSupport<BookDto, BookDto> {
    
        public BookModelAssembler() {
            super(BooksController.class, BookDto.class);
        }
    
        @Override
        public BookDto toModel(BookDto entity) {
            return entity.add(linkTo(methodOn(BooksController.class).getResource(entity.getIsbn())).withSelfRel())
                         .add(linkTo(methodOn(BooksController.class).getAllResources()).withRel("books"));
        }
        
    }
    

    在控制器中,用于检索一个或所有资源的endpoint:

    @Override
    @GetMapping(value = {QueryConstants.BOOKS_ISBN_PATH, QueryConstants.BOOKS_SIG_PATH})
    public BookDto getResource(@PathVariable("isbn") final String isbn) {
        
        return this.modelAssembler.toModel(this.findOneResource(isbn));
    }
    
    
    // GET - retrieve all resources
    
    @Override
    @GetMapping (produces = { "application/hal+json" })
    public List<BookDto> getAllResources() {
        
        return (findAllResources().stream().map(this.modelAssembler::toModel).collect(Collectors.toList()));
    }
    

    如您所见,即使返回的列表中的所有实体都已使用方法getResource()中使用的相同方法toModel()进行映射,渲染的超媒体也是不同的。

    在所有资源的情况下,我能够看到正确返回的HAL格式的唯一方法是更改控制器的实现以返回集合模型:

    //@GetMapping
    public CollectionModel<BookDto> getAll() {
            return this.modelAssembler.toCollectionModel(findAllResources());
    }
    

    但是然后所有的实体都捆绑在一个_embedded元素中,这不是我返回实体集合时想要的。

    Spring Hateoas文档声明HAL是默认的,所以我现在还没有考虑过配置任何东西。。。

    所以,我只看到:

    • 我缺少一些配置,以便在我可以获得呈现的实体集合时(_embedded元素下没有)...但是我在HalConfiguration bean中没有看到任何合适的东西。
    • 我假设返回所请求资源类型的集合的正确方法不是在_embedded属性中...但也许我错了。到目前为止,我的理解是,当您请求资源Person并且您想返回它的联系人时,这些联系人也可以通过他们自己的endpoint直接访问,然后您将它们与其他Person属性一起嵌入返回的内容中...我没有发现任何说明集合预计将在_embedded属性中呈现的内容。

    有人有什么建议吗?我没有时间和想法了,实现客户端的团队正在等待消费超媒体内容。谢谢

  • 共有2个答案

    方博
    2023-03-14

    在进一步阅读之后,我下定了决心,并得出结论,在响应中发回的正确内容是\u嵌入元素中的集合。

    我参考了几篇参考文献:

    • JSON HAL rfc草案第6节(这是我找到的最新版本),有一个文档示例,该文档是由于请求资源列表而返回的,其中资源列表嵌入在_embedded元素内部的数组中。
    • 在其他作者专用于集合的部分中,解释是相同的,集合的元素在_embedded属性中返回。

    因此,根据这一点,如果我将控制器更改为返回CollectionModel,那么我将在HAL中获得正确的内容格式。

    代码为:

    @GetMapping 
    public CollectionModel<BookDto> getAll() {
        
        return this.modelAssembler.toCollectionModel(findAllResources()).add(linkTo(methodOn(BooksController.class).getAll()).withSelfRel());
    }
    

    结果是:

    {
    "_embedded": {
        "bookDtoList": [
            {
                "isbn": "123567891099",
                "signature": "AA-23-EEE",
                "title": "Electromagnetismo",
                "subtitle": "Introducción a las aplicaciones del electromagnetismo",
                "authors": [
                    "Idoia Mendieta",
                    "Bonifacio Pérez"
                ],
                "available": false,
                "numOfCopies": 0,
                "library": null,
                "detailedInfo": null,
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/celsvs/api/books/123567891099"
                    },
                    "books": {
                        "href": "http://localhost:8080/celsvs/api/books"
                    }
                }
            },
            {
                "isbn": "123567891012",
                "signature": "AA-23-EFD",
                "title": "Electromagnetismo",
                "subtitle": "Introducción a las aplicaciones del electromagnetismo",
                "authors": [
                    "Idoia Mendieta",
                    "Bonifacio Pérez"
                ],
                "available": false,
                "numOfCopies": 0,
                "library": null,
                "detailedInfo": null,
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/celsvs/api/books/123567891012"
                    },
                    "books": {
                        "href": "http://localhost:8080/celsvs/api/books"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/celsvs/api/books"
        }
    }
    

    }

    尽管如此,如果有人能告诉我为什么在之前的实现中附加的链接没有遵循HAL格式,我将不胜感激。谢谢

    乌灿
    2023-03-14

    HAL规范说属性_embedded用于存储资源对象数组。

    编辑:用阿尔贝托自己的答案回答他的问题

    尽管如此,如果有人能告诉我为什么在之前的实现中附加的链接没有遵循HAL格式,我将不胜感激。谢谢

    Spring HATEOAS自定义SymationModel的JSON序列化,它是CollexiModel的父类。

    // org.springframework.hateoas.mediatype.hal.RepresentationModelMixin
    public abstract class RepresentationModelMixin extends RepresentationModel<RepresentationModelMixin> {
    
        @Override
        @JsonProperty("_links")
        @JsonInclude(Include.NON_EMPTY)
        @JsonSerialize(using = Jackson2HalModule.HalLinkListSerializer.class)
        @JsonDeserialize(using = Jackson2HalModule.HalLinkListDeserializer.class)
        public abstract Links getLinks();
    }
    

    将JSON属性名称定义为链接@JsonSerialize定义要使用的序列化程序。查看方法<代码>组织。springframework。哈提奥斯。mediatype。哈尔。Jackson2Hal模块。HalLinkListSerializer#serialize用于序列化逻辑。

     类似资料:
    • 问题内容: 在过去的六个月中,我一直在与Backbone合作。前两个月很混乱,学习并弄清楚我要如何围绕它构建代码。接下来的4个月,该公司推出了适合生产的应用程序。不要误会我的意思,Backbone使我摆脱了以前标准的成千上万行客户端代码的混乱,但是它使我能够在更短的时间内完成更多宏伟的事情,从而带来了一系列全新的问题。对于我在这里提出的所有问题,有一些简单的解决方案,感觉像是骇客或只是 错误 。我

    • 我是android studio的新手,安装了一个新版本(1.5.1版)。出于某种原因,我一直收到一条错误消息(每次我使用应用程序主题时),说有渲染问题:缺少样式。我在网上寻找解决方案,但大多数都过时了,或者根本不起作用。 谢谢你的帮助。 清单文件: 构建渐变:

    • 从昨天开始,我已经开始与Android Studio的工作。我的问题是当我做我的布局。我有下一个错误(观看屏幕截图了解更多信息): 渲染问题:此版本的渲染库比您的Android Studio版本更新。请更新Android Studio 如果我检查更新,他会说我已经有了最新版本的Android studio,所以我无法更新。 我也在SDK管理器中安装了一些东西,请看下面的截图。 有人能帮我解决这个问

    • 我们刚刚将本地Android SDK更新到了新的22版,我们也在尝试更新我们的应用程序,但在Android Studio的布局设计视图中SearchView呈现似乎有一个问题:每当设计师试图呈现SearchView元素时,它都会抛出一个异常: java.lang.nullPointerException · 在Android.content.res.typedarray.hasValueOremp

    • 我有这个xml文件。如果我编译,它可以正常工作,但如果我去看预览,它会显示出这个错误: 我试着找这个身份证,但到处都找不到。这个@id/visible是什么?我怎么才能修好?谢谢

    • 问题内容: 我刚刚安装了grails渲染插件,并希望将其用于生成PDF文件。我已经创建了简单的模板,但是没有任何CSS样式即可将其导出。如果仅从grails渲染模板,则页面将在Web浏览器中显示所有样式。 所以,我的问题是-在PDF生成过程中如何正确包含CSS文件? 我的模板: 而且我的webui.css中具有样式.odd,但是它不适用于该行。 任何帮助,将不胜感激。 Edit1:我发现以以下方式