我知道这可能与此重复。
When to use @RestController vs @RepositoryRestResource
但是我有一些在这个问题上没有解决的问题。
使用@RepositoryRestResource
,默认情况下会公开每个方法。我觉得有点烦人。如果我在这里错了,请纠正我。例如,在下面的例子中
@RepositoryRestResource
public interface ProductRepository extends MongoRepository<Product, String> {}
如果我只想公开findAll()和findOne()而不是任何其他方法,尤其是删除。要做到这一点,我需要做这样的事情
@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方法相比要好得多。
我认为最好使用ResponseEntity从REST端点返回任何值。但是使用spring-data-rest方法,我不知道该怎么做。
我找不到任何方法来进行单元测试(非IT)RepositoryRestResource公开的REST端点。但是使用REST控制器方法,我可以使用MockServletContext
,MockMvc
,MockMvcBuilders
鉴于所有这些,使用sping-data-rest(HATEOS除外)是否仍然有利? 请澄清
答案 0 :(得分:11)
Spring-data-rest是为数据存储库提供REST端点,它确实提供了包含ALPS元数据,搜索端点等所有铃声和口哨的可靠REST。这通常涵盖了大多数用例,并提供了自定义的基础。
这里有一些提示。
关于第1页) - 自定义导出的资源和方法。
您无需在所有@RestResource(exported = false)
方法上放置delete(...)
,因为实际只导出了一个:void delete(Product entity)
。查看relevant documentation chapter和源代码。如果我不错过任何东西,你只需要提供这些:
findAll(Pageable)
findOne(id)
save(Entity)
delete(Entity)
关于导出的存储库方法的说明。有时,扩展一个非常基本的(空)Repository<Product, String>
存储库接口并仅提供您在存储库中允许的方法更容易例如:
@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 - 这是默认控制器。
关于p.2)从控制器返回ResponseEntity
非常紧张。您可以将实体包装到Resource<T>
(例如使用PersistentEntityResourceAssembler
)并使用它创建ResponseEntity
。请参阅RepositoryEntityController.java和一些示例,例如spring-restbucks。
关于第3页) - 测试休息端点
公开RepositoryRestResource的REST端点在RepositoryEntityController
(spring-data-rest的一部分)中实现。
如果您实施自己的自定义控制器,则可以照常添加单元测试,但如果您使用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());
}
}
另见"Building REST services with Spring" tutorial。
希望这有帮助。