Nic*_*las 17 java rest spring spring-data-rest
我有以下REST存储库,其实现由Spring在运行时生成.
@RepositoryRestResource
public interface FooRepository extends CrudRepository<Foo, Long> {
}
Run Code Online (Sandbox Code Playgroud)
这意味着我将通过REST提供save(),find(),exists()和其他可用方法.
现在,我想覆盖其中一个方法; 例如,save().为此,我将创建一个暴露该方法的控制器,如下所示:
@RepositoryRestController
@RequestMapping("/foo")
public class FooController {
@Autowired
FooService fooService;
@RequestMapping(value = "/{fooId}", method = RequestMethod.PUT)
public void updateFoo(@PathVariable Long fooId) {
fooService.updateProperly(fooId);
}
}
Run Code Online (Sandbox Code Playgroud)
问题: 如果我启用了这个控制器,那么Spring实现的所有其他方法都不再暴露.因此,例如,我不能再对/ foo/1执行GET请求
问题: 是否有一种覆盖REST方法的方法,同时仍保留其他自动生成的Spring方法?
额外信息:
这个问题看起来非常相似: Spring Data Rest:RestController中的覆盖方法具有相同的请求映射路径 ......但我不想将路径更改为/ foo/1/save之类的东西
我想过使用@RepositoryEventHandler,但我不是很喜欢这个想法,因为我想把它封装在一个服务之下.此外,您似乎失去了对事务上下文的控制.
有时您可能希望为特定资源编写自定义处理程序.要利用Spring Data REST的设置,消息转换器,异常处理等,请使用@RepositoryRestController注释而不是标准的Spring MVC @Controller或@RestController
所以它似乎应该开箱即用,但不幸的是没有.
Mar*_*rin 13
有没有一种方法可以覆盖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
}
}
Run Code Online (Sandbox Code Playgroud)
让我们假设我们有一个Account实体:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
随着AccountRepository揭露它的CRUD端点/accounts:
@RepositoryRestResource(collectionResourceRel = "accounts", path = "accounts")
public interface AccountRepository extends CrudRepository<Account, Integer> {
}
Run Code Online (Sandbox Code Playgroud)
并且AccountController它会覆盖默认GET端点表单AccountRepository.:
@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);
}
Run Code Online (Sandbox Code Playgroud)
如果您调用,GET /accounts?size=5&page=0您将获得以下使用模拟实现的输出:
{
"_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
}
}
Run Code Online (Sandbox Code Playgroud)
只是为了完整性,可以使用以下父级和依赖项配置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>
Run Code Online (Sandbox Code Playgroud)
小智 5
只是我发现的一个更新救了我的命。正如 @mathias-dpunkt 在这个答案中精彩地说的那样 /sf/answers/2416271651/
最重要的是,RepositoryRestController 知道 Spring Data Rest 基本路径,并将在此基本路径下提供服务。
因此,如果您的基本路径是“/api”并且您正在使用@RepositoryRestController
你必须从@RequestMapping中省略“/api”
| 归档时间: |
|
| 查看次数: |
16202 次 |
| 最近记录: |