Enable HAL serialization in Spring Boot for custom controller method

后端 未结 3 555
清歌不尽
清歌不尽 2020-11-29 06:47

I\'m trying to build a RESTful API with Spring Boot using spring-boot-starter-data-rest. There are some entities: accounts, transactions, categories and users - just the usu

相关标签:
3条回答
  • 2020-11-29 07:35

    To use PersistentEntityResourceAssembler in the controller we should mark it as @RepositoryRestController

    @RestController
    @RequestMapping("/categories")
    @RepositoryRestController
    public class CategoryController implements ValidableController {
    
    // dependencies
    
    @RequestMapping(method = POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<PersistentEntityResource> create(@Valid @RequestBody CategoryForm category,
                                                           BindingResult validation,
                                                           PersistentEntityResourceAssembler resourceAssembler)
    {
        validate(validation);
        Category entity = categoryConverter.convert(category);
        entity = categoryService.save(entity);
        return ResponseEntity.ok(resourceAssembler.toFullResource(entity));
    }
    

    It builds pretty nice HAL styled response

    {
    "createdTime": "2018-07-24T00:55:32.854",
    "updatedTime": "2018-07-24T00:55:32.855",
    "name": "cfvfcdfgdfdfdfs32",
    "options": [
        "aaa",
        "bbb"
    ],
    "_links": {
        "self": {
            "href": "http://localhost:8080/shop/categories/34"
        },
        "category": {
            "href": "http://localhost:8080/shop/categories/34{?projection}",
            "templated": true
        },
        "products": {
            "href": "http://localhost:8080/shop/categories/34/products"
        },
        "categories": {
            "href": "http://localhost:8080/shop/categories/34/categories{?projection}",
            "templated": true
        },
        "parent": {
            "href": "http://localhost:8080/shop/categories/34/parent{?projection}",
            "templated": true
        }
    }
    

    }

    0 讨论(0)
  • 2020-11-29 07:40

    There's a lot of aspects here:

    1. I doubt that the collection resource at /transactions really returns an individual transaction as you described. Those representations are returned for item resources.

    2. If TransactionRepository already is a PageableAndSortingRepository the collection resource can be tweaked by expanding the URI template exposed in the API root for the link named transactions. By default that's a page, size and sort parameter. That means clients can request what you want to expose already.

    3. If you want to default the paging and sorting options, implementing a controller is the correct way. However, to achieve a representation like Spring Data REST exposes you need to return at least instances of ResourceSupport as this is the type the HAL mapping is registered for.

      There's nothing magically here if you think about it. A plain entity does not have any links, the ResourcesSupport and types like Resource<T> allow you to wrap the entity and enrich it with links as you see fit. Spring Data REST basically does that for you using a lot of the knowledge about the domain and repository structure that's available implicitly. You can reuse a lot of as shown below.

      There are a few helper you need to be aware of here:

      • PersistentEntityResourceAssembler - which is usually injected into the controller method. It renders a single entity in a Spring Data REST way, which means that associations pointing to managed types will be rendered as links etc.
      • PagedResourcesAssembler - usually injected into the controller instance. Takes care of preparing the items contained in the page, optionally by using a dedicated ResourceAssembler.

      What Spring Data REST basically does for pages is the following:

      PersistentEntityResourceAssembler entityAssembler = …;
      Resources<?> … = pagedResourcesAssembler.toResources(page, entityAssembler);
      

      That's basically using the PagedResourcesAssembler with the PersistentEntityResourceAssembler to render the items.

      Returning that Resources instance should give you the representation design you expected.

    0 讨论(0)
  • 2020-11-29 07:46

    You do not need to create your own controller to limit query results or sort the results. Just create a query method in your repository:

    public interface TransactionRepository extends MongoRepository<Transaction, String> {
    
        List<Transaction> findFirst10ByOrderByDateDesc();
    
    }
    

    Spring Data REST will automatically export it as a method resource at /transactions/search/findFirst10ByOrderByDateDesc.

    0 讨论(0)
提交回复
热议问题