Java Spring数据REST:覆盖控制器上的存储库方法
我有以下REST存储库,它的实现是由Spring在运行时生成的Java Spring数据REST:覆盖控制器上的存储库方法,java,spring,rest,spring-data-rest,Java,Spring,Rest,Spring Data Rest,我有以下REST存储库,它的实现是由Spring在运行时生成的 @RepositoryRestResource public interface FooRepository extends CrudRepository<Foo, Long> { } 问题: 如果启用此控制器,那么Spring实现的所有其他方法将不再公开。例如,我不能再对/foo/1执行GET请求 问题: 有没有一种方法可以覆盖REST方法,同时保留其他自动生成的Spring方法 额外信息: 这个问题似乎很相似:
@RepositoryRestResource
public interface FooRepository extends CrudRepository<Foo, Long> {
}
问题:
如果启用此控制器,那么Spring实现的所有其他方法将不再公开。例如,我不能再对/foo/1执行GET请求
问题:
有没有一种方法可以覆盖REST方法,同时保留其他自动生成的Spring方法
额外信息:
@RepositoryRestController
public class FooController {
@Autowired
FooService fooService;
@RequestMapping(value = "/foo/{fooId}", method = RequestMethod.PUT)
public void updateFoo(@PathVariable Long fooId) {
fooService.updateProperly(fooId);
}
// edited after Sergey's comment
@RequestMapping(value = "/foo/{fooId}", method = RequestMethod.PUT)
public RequestEntity<Void> updateFoo(@PathVariable Long fooId) {
fooService.updateProperly(fooId);
return ResponseEntity.ok().build(); // simplest use of a ResponseEntity
}
}
@RepositoryRestController
公共类FooController{
@自动连线
食品服务;
@RequestMapping(value=“/foo/{fooId}”,method=RequestMethod.PUT)
public void updateFoo(@PathVariable Long fooId){
fooService.updateProperty(fooId);
}
//根据谢尔盖的评论进行编辑
@RequestMapping(value=“/foo/{fooId}”,method=RequestMethod.PUT)
public RequestEntity updateFoo(@PathVariable Long fooId){
fooService.updateProperty(fooId);
return ResponseEntity.ok().build();//ResponseEntity的最简单用法
}
}
如果您使用Java 8,我发现了一个简洁的解决方案-只需在接口中使用默认方法即可
@RepositoryRestResource
public interface FooRepository extends CrudRepository<Foo, Long> {
default <S extends T> S save(S var1) {
//do some work here
}
}
@RepositoryRestResource
公共接口FoodRepository扩展了Crudepository{
默认S保存(S var1){
//在这里做些工作
}
}
让我们假设我们有一个账户
实体:
@Entity
public class Account implements Identifiable<Integer>, Serializable {
private static final long serialVersionUID = -3187480027431265380L;
@Id
private Integer id;
private String name;
public Account(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以及一个覆盖默认GET
端点表单AccountRepository
的AccountController
:
@RepositoryRestController
public class AccountController {
private PagedResourcesAssembler<Account> pagedAssembler;
@Autowired
public AccountController(PagedResourcesAssembler<Account> pagedAssembler) {
this.pagedAssembler = pagedAssembler;
}
private Page<Account> getAccounts(Pageable pageRequest){
int totalAccounts= 50;
List<Account> accountList = IntStream.rangeClosed(1, totalAccounts)
.boxed()
.map( value -> new Account(value, value.toString()))
.skip(pageRequest.getOffset())
.limit(pageRequest.getPageSize())
.collect(Collectors.toList());
return new PageImpl(accountList, pageRequest, totalAccounts);
}
@RequestMapping(method= RequestMethod.GET, path="/accounts", produces = "application/hal+json")
public ResponseEntity<Page<Account>> getAccountsHal(Pageable pageRequest, PersistentEntityResourceAssembler assembler){
return new ResponseEntity(pagedAssembler.toResource(getAccounts(pageRequest), (ResourceAssembler) assembler), HttpStatus.OK);
}
为了完整起见,POM可以配置为具有以下父级和依赖项:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>2.6.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
org.springframework.boot
spring启动程序父级
1.5.2.1发布
org.springframework.boot
SpringBootStarterWeb
org.springframework.data
spring数据rest webmvc
2.6.1.1发布
org.springframework.boot
spring引导启动器数据jpa
com.h2数据库
氢
这只是我发现的一个救了我一命的更新。
正如@mathias dpunkt在这个回答中精彩地说的那样
最重要的是,RepositoryRestController知道spring数据rest
基本路径,并将在此基本路径下提供服务
因此,如果您的基本路径是“/api”,并且您正在使用@RepositoryRestController
你必须从@RequestMapping中ommit“/api”这可能对你有帮助吗?我意识到这个问题不是Grails的问题,但这个概念与这里描述的问题/答案类似:@Tarmo:虽然我认为这可能可行,但它会迫使我继续向存储库中添加逻辑,我更喜欢将其保留在服务中。不幸的是,这也不起作用。如果我这样做了,那么Spring实现的GET方法就不起作用了。我似乎也能起作用(SpringBootStarter数据REST1.4.1.RELEASE)另外,
@RepositoryRestController
vs@RestController
也起到了作用。还必须将@ResponseBody
添加到重写的控制器方法中。这样做会丢失HATEOAS格式。。。有没有办法保持相同的格式?@Rafael:没有办法。您必须使用(扩展)和。官方文件中有相关信息。您还可以读取,这将覆盖此存储库的整个应用程序的save
方法。如果这不是期望的行为,就不应该使用它,否则它是一个有效的选项。这就是答案!ResourceAssembler来自hateoas 1.0,称为RepresentationModelAssembler。看见
@RepositoryRestController
public class AccountController {
private PagedResourcesAssembler<Account> pagedAssembler;
@Autowired
public AccountController(PagedResourcesAssembler<Account> pagedAssembler) {
this.pagedAssembler = pagedAssembler;
}
private Page<Account> getAccounts(Pageable pageRequest){
int totalAccounts= 50;
List<Account> accountList = IntStream.rangeClosed(1, totalAccounts)
.boxed()
.map( value -> new Account(value, value.toString()))
.skip(pageRequest.getOffset())
.limit(pageRequest.getPageSize())
.collect(Collectors.toList());
return new PageImpl(accountList, pageRequest, totalAccounts);
}
@RequestMapping(method= RequestMethod.GET, path="/accounts", produces = "application/hal+json")
public ResponseEntity<Page<Account>> getAccountsHal(Pageable pageRequest, PersistentEntityResourceAssembler assembler){
return new ResponseEntity(pagedAssembler.toResource(getAccounts(pageRequest), (ResourceAssembler) assembler), HttpStatus.OK);
}
{
"_embedded": {
"accounts": [
{
"name": "1",
"_links": {
"self": {
"href": "http://localhost:8080/accounts/1"
},
"account": {
"href": "http://localhost:8080/accounts/1"
}
}
},
{
"name": "2",
"_links": {
"self": {
"href": "http://localhost:8080/accounts/2"
},
"account": {
"href": "http://localhost:8080/accounts/2"
}
}
},
{
"name": "3",
"_links": {
"self": {
"href": "http://localhost:8080/accounts/3"
},
"account": {
"href": "http://localhost:8080/accounts/3"
}
}
},
{
"name": "4",
"_links": {
"self": {
"href": "http://localhost:8080/accounts/4"
},
"account": {
"href": "http://localhost:8080/accounts/4"
}
}
},
{
"name": "5",
"_links": {
"self": {
"href": "http://localhost:8080/accounts/5"
},
"account": {
"href": "http://localhost:8080/accounts/5"
}
}
}
]
},
"_links": {
"first": {
"href": "http://localhost:8080/accounts?page=0&size=5"
},
"self": {
"href": "http://localhost:8080/accounts?page=0&size=5"
},
"next": {
"href": "http://localhost:8080/accounts?page=1&size=5"
},
"last": {
"href": "http://localhost:8080/accounts?page=9&size=5"
}
},
"page": {
"size": 5,
"totalElements": 50,
"totalPages": 10,
"number": 0
}
}
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
<version>2.6.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>