休息控制器与 spring-data-rest RepositoryRestResource [英] Rest Controllers vs spring-data-rest RepositoryRestResource

查看:32
本文介绍了休息控制器与 spring-data-rest RepositoryRestResource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这可能让人感觉像这个的重复.
何时使用@RestController vs @RepositoryRestResource
但是我有几件事没有在那个问题中得到解决.

I know this might feel like a duplicate of this.
When to use @RestController vs @RepositoryRestResource
But I have a few things which were not addressed in that question.

  1. 使用 @RepositoryRestResource,默认情况下每个方法都是公开的.我觉得有点烦人.如果我在这里错了,请纠正我.比如下面这种情况

  1. With @RepositoryRestResource, every method is by default exposed. Which I feel is a bit annoying. Correct me if I am wrong here. For example in the below case

@RepositoryRestResource  
public interface ProductRepository extends MongoRepository<Product, String> {} 

如果我只想公开 findAll() 和 findOne() 而不是任何其他方法,尤其是删除.为了实现这一点,我需要做这样的事情

If I want only findAll() and findOne() to be exposed and not any other methods, especially delete. To achieve this I need to do something like this

    @RepositoryRestResource
    public interface ProductRepository extends MongoRepository<Product, String> {
      @RestResource(exported = false)
      @Override
      default void delete(String s) {
      }
      @RestResource(exported = false)
      @Override
      default void delete(Product product) {
      }
      @RestResource(exported = false)
      @Override
      default void delete(Iterable<? extends Product> iterable) {
      }
      @RestResource(exported = false)
      @Override
      default void deleteAll() {
      }
    }

我觉得确实有很多不需要的代码.这与 Rest Controller 方法相比要好得多

Which I feel is really lot of unwanted code. This is much better to do with Rest Controller approach

  1. 我认为最好使用 ResponseEntity 从 REST 端点返回任何值.但是使用 spring-data-rest 方法,我不知道该怎么做.

  1. I believe it is better to return any value from REST endpoints using ResponseEntity. But with spring-data-rest approach, I am not sure how to do it.

我找不到任何方法来对 RepositoryRestResource 公开的(不是 IT)REST 端点进行单元测试.但是使用 REST 控制器方法,我可以使用 MockServletContextMockMvcMockMvcBuilders

I could not find any way to unit test(Not IT) REST endpoints exposed by the RepositoryRestResource. But with REST controller approach, I can test my REST endpoints using MockServletContext, MockMvc, MockMvcBuilders

考虑到所有这些,使用 sping-data-rest(HATEOS 除外)是否仍然有利?
请澄清

Given all these, is it still advantageous to use sping-data-rest(except for HATEOS)?
please clarify

推荐答案

Spring-data-rest 是关于为数据存储库提供 REST 端点,它确实提供了可靠的 REST,包括 ALPS 元数据、搜索端点等.这通常涵盖大多数用例并为定制提供基础.

Spring-data-rest is about providing REST endpoints for data repositories and it does provides solid REST with all bells and whistles including ALPS metadata, search endpoints, etc. This usually covers most use cases and provides basis for customisations.

这里有一些提示.

关于 p.1) - 自定义导出的资源和方法.

Regarding p.1) - Customising exported resources and methods.

您不需要将 @RestResource(exported = false) 放在所有 delete(...) 方法上,因为实际上只导出了一个方法:void删除(产品实体).查看相关文档章节和源代码.如果我没有遗漏什么,您只需要提供这些:

You do not need to put @RestResource(exported = false) on all delete(...) methods because only one is actually exported: void delete(Product entity). Look into relevant documentation chapter and the source code. If i do not miss something, you just need to provide these:

  • findAll(Pageable)
  • findOne(id)
  • 保存(实体)
  • 删除(实体)

关于导出存储库方法的说明. 有时扩展一个非常基本的(空)Repository<Product, String> 存储库接口并仅提供您允许的方法会更容易存储库,例如:

A note about exported repository methods. Sometimes it's easier to extend a very basic (empty) Repository<Product, String> repository interface and provide only methods you allow on the repository, for example:

@RepositoryRestResource
public interface ProductRepository extends Repository<Product, String> {
  long count();
  Page<Product> findAll(Pageable pageable);
  Product findOne(String entity);
  <S extends Product> S save(S entity);
}

关于自定义控制器.要自定义默认行为,最简单的方法是使用 @RespositoryRestController 注释控制器.查看文档并查看 RepositoryEntityController.java - 这是默认控制器.

Regarding a custom controller. To customise a default behaviour the easiest is to annotate controllers with @RespositoryRestController. Check-out docs and look into RepositoryEntityController.java - that's the default controller.

关于 p.2) 从控制器返回 ResponseEntity

Regarding p.2) Returning ResponseEntity from controllers

这是非常紧张的.您可以将实体包装到 Resource<T> 中(例如,使用 PersistentEntityResourceAssembler)并用它创建一个 ResponseEntity.见 RepositoryEntityController.java 和一些例子,比如 spring-restbucks.

It's very straingforward. You can wrap entity into Resource<T> (e.g. using a PersistentEntityResourceAssembler) and create a ResponseEntity with it. See RepositoryEntityController.java and some examples, like spring-restbucks.

关于 p.3) - 测试剩余端点

暴露 RepositoryRestResource 的 REST 端点在 RepositoryEntityController(spring-data-rest 的一部分)中实现.

REST endpoints that expose the RepositoryRestResource are implemented in the RepositoryEntityController (part of the spring-data-rest).

如果您实现自己的自定义控制器,则可以像往常一样添加 单元测试,但如果使用 PersistentEntityResourceAssembler,事情会变得更加复杂.

If you implement your own custom controller, you can add unit tests as usual but things get more complex if you use PersistentEntityResourceAssembler.

单元测试示例:

public class FooControllerTests {

  @Mock
  PersistentEntityResourceAssembler assembler;

  @Mock
  PersistentEntityResourceAssemblerArgumentResolver assemblerResolver;

  @Mock
  PersistentEntity<Foo, ?> entity;

  @InjectMocks
  FooController fooController;

  @Mock
  FooService fooService;

  private MockMvc mockMvc;

  @Rule
  public MockitoRule rule = MockitoJUnit.rule();

  @Before
  public void setup() {
    this.mockMvc = MockMvcBuilders.standaloneSetup(fooController)
        .setCustomArgumentResolvers(assemblerResolver)
        .build();
  }

  @Test
  public void test_GetItem_Success() throws Exception {
    final Foo foo = new Foo();
    
    when(fooService.findOne(1)).thenReturn(foo);
    when(assemblerResolver.supportsParameter(any())).thenReturn(true);
    when(assemblerResolver.resolveArgument(any(), any(), any(), any())).thenReturn(assembler);
    when(assembler.toResource(foo))
        .thenReturn(PersistentEntityResource.build(foo, entity).build());
    
    this.mockMvc.perform(get("/foo/1")).andExpect(status().isOk());
  }
}

另请参阅使用 Spring 构建 REST 服务"教程.

希望这会有所帮助.

这篇关于休息控制器与 spring-data-rest RepositoryRestResource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆