在遵循 RESTful API 标准的同时,在同一控制器中拥有 getAll、getById 和 getByEmail 的控制器方法 [英] Have controller methods to getAll, getById and getByEmail in the same controller while following RESTful API standards
问题描述
我有一个实体 Users
,其中包含 id
和 emailAddress
.我想编写一个同时具有 3 个 get 方法的控制器:
I have an entity Users
, which contains id
and emailAddress
. I want to write a controller which has 3 get methods simultaneously:
- getAll() -
http://localhost:8080/api/users?pageNumber=0&pageSize=10
- get(UUID id) -
http://localhost:8080/api/users/209347293875928375928
- get(String email) -
http://localhost:8080/api/users/fireball%40email.com
或http://localhost:8080/api/users?emailAddress=fireball%40email.com"
注意: 两段代码的区别在于最后一个函数的参数不同(第一段是@PathVariable
,第二段是@RequestParam
.
NOTE: The difference in the two pieces of code is the arguments of the last function in both(The first is @PathVariable
and the second is a @RequestParam
.
我尝试了两种方法来实现这一点(都遇到了一个单独的问题),第一种是:
I have tried two ways to accomplish this(both run into a separate issue), the first being:
@GetMapping
@ApiOperation(value = "List all Users")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class, responseContainer = "List"),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
@Transactional(readOnly = true)
public ResponseEntity<Page<User>> getAll(
@RequestParam(required = false, defaultValue = "0") int pageNumber,
@RequestParam(required = false, defaultValue = "10") int pageSize) {
return ResponseEntity.ok(UserService.getUsers(pageNumber, pageSize));
}
@GetMapping(path = "/{id}")
@ApiOperation(value = "Get User by ID")
@Transactional(readOnly = true)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
public ResponseEntity<?> get(@PathVariable("id") final UUID id) {
return UserService.get(id)
.map(ResponseEntity::ok)
.map(ResponseEntity.class::cast)
.orElse(
ResponseEntity.status(NOT_FOUND).body(new Error(format(USER_NOT_FOUND_MESSAGE, id))));
}
@GetMapping
@ApiOperation(value = "Get User by Email Address")
@Transactional(readOnly = true)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
public ResponseEntity<?> get(@RequestParam("email") final String email) {
return UserService.get(email)
.map(ResponseEntity::ok)
.map(ResponseEntity.class::cast)
.orElse(
ResponseEntity.status(NOT_FOUND).body(new Error(format(USER_NOT_FOUND_MESSAGE, email))));
}
以上在使用 Ambiguous mapping 编译时失败.无法将userController"方法
映射为错误.基本上 getAll()
和 get(@RequestParam("email") final String email)
具有相同的 URL 路径 - /users
.
The above fails at compilation with Ambiguous mapping. Cannot map 'userController' method
as error. Essentially getAll()
and get(@RequestParam("email") final String email)
have the same URL path - /users
.
第二个是:
@GetMapping
@ApiOperation(value = "List all Users")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class, responseContainer = "List"),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
@Transactional(readOnly = true)
public ResponseEntity<Page<User>> getAll(
@RequestParam(required = false, defaultValue = "0") int pageNumber,
@RequestParam(required = false, defaultValue = "10") int pageSize) {
return ResponseEntity.ok(UserService.getUsers(pageNumber, pageSize));
}
@GetMapping(path = "/{id}")
@ApiOperation(value = "Get User by ID")
@Transactional(readOnly = true)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
public ResponseEntity<?> get(@PathVariable("id") final UUID id) {
return UserService.get(id)
.map(ResponseEntity::ok)
.map(ResponseEntity.class::cast)
.orElse(
ResponseEntity.status(NOT_FOUND).body(new Error(format(USER_NOT_FOUND_MESSAGE, id))));
}
@GetMapping(path = "/{email}")
@ApiOperation(value = "Get User by Email Address")
@Transactional(readOnly = true)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
public ResponseEntity<?> get(@PathVariable("email") final String email) {
return UserService.get(email)
.map(ResponseEntity::ok)
.map(ResponseEntity.class::cast)
.orElse(
ResponseEntity.status(NOT_FOUND).body(new Error(format(USER_NOT_FOUND_MESSAGE, email))));
}
在这里我遇到了控制器无法在 get(@PathVariable("email") final String email
和 get(@PathVariable("id");) 最终的 UUID id)
带有以下错误:
Here I run into the issue of the controller not being able to resolve between get(@PathVariable("email") final String email
and get(@PathVariable("id") final UUID id)
with the following error:
Ambiguous handler methods mapped for '/api/gems/users/fireball%40email.com': {public org.springframework.http.ResponseEntity com.personal.project.controllers.UserController.get(java.util.UUID), public org.springframework.http.ResponseEntity com.personal.project.controllers.UserController.get(java.lang.String)}
推荐答案
您可以通过将这两个 Ambiguous 路径合并为一个来解决它.对于第一种情况:
You can solve it by merging these two Ambiguous path into one. For the first case:
@GetMapping
@ApiOperation(value = "List all Users")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = User.class, responseContainer = "List"),
@ApiResponse(code = 401, message = "Unauthorized", response = Error.class),
@ApiResponse(code = 404, message = "Not Found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
@Transactional(readOnly = true)
public ResponseEntity<?> getUsers(
@RequestParam(required = false, defaultValue = "0") int pageNumber,
@RequestParam(required = false, defaultValue = "10") int pageSize,
// add email as param.
@RequestParam(required = false) String email,
) {
if(email ==null || StringUtils.isEmpty(email)){
return ResponseEntity.ok(UserService.getUsers(pageNumber, pageSize));
}else return UserService.get(email)
.map(ResponseEntity::ok)
.map(ResponseEntity.class::cast)
.orElse(
ResponseEntity.status(NOT_FOUND).body(new Error(format(USER_NOT_FOUND_MESSAGE, email))));
}
对于第二个:
// change the type UUID id to string.
@GetMapping(path = "/{id}")
...
public ResponseEntity<?> get(@PathVariable("id") final String id) {
// check if id as an uuid or email, and based on that take action
}
这篇关于在遵循 RESTful API 标准的同时,在同一控制器中拥有 getAll、getById 和 getByEmail 的控制器方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!