假设我开发了一些休息api。我有web层(控制器)和服务层(模型)。在服务层中使用HttpStatus代码抛出异常是一种好习惯吗?
有人会说,该模型不应该对Web层有任何了解,它不应该依赖于Web层。
但是,让我们考虑一下这种情况:
在控制器中使用HttpStatus抛出异常
---服务---
class userService {
public void updateUser(int userId, String username, String email) {
if ( //userid not found) {
throw new UserNotFoundException("User not found");
}
if ( // bad email format) {
throw new BadArgumentException("Bad email format");
}
if ( // user is not active) {
throw new AccessDeniedException("User is not active");
}
... here save user ...
}
}
---控制器---
class UserController {
@RequestMapping ....
public void updateUser(int id, String username, String email) {
try{
userService.updateUser(id, username, email);
}
catch (UserNotFoundException e) {
throw new HttpException(e.getMessage(), HttpStatus.NOT_FOUND);
}
catch (BadArgumentExceptione e) {
throw new HttpException(e.getMessage(), HttpStatus.BAD_REQUEST);
}
catch (AccessDeniedException e) {
throw new HttpException(e.getMessage(), HttpStatus.FORBIDEN);
}
}
}
你知道吗?我应该写多少额外的代码来返回对Api客户端的正确响应?此外,我可以忘记捕获一些可以正确报告的异常,它将作为默认的内部服务器异常返回。在控制器中,我总是应该查看服务层并检查哪些异常可以使服务正确处理它们。 (请不要在java中建议检查异常。)
现在让我们看看另一个解决方案:
在服务层(模型)中使用HttpStatus抛出异常
---服务---
class userService {
public void updateUser(int userId, String username, String email) {
if ( //userid not found) {
throw new UserNotFoundException("User not found", HttpStatus.NOT_FOUND);
}
if ( // bad email format) {
throw new BadArgumentException("Bad email format", HttpStatus.BAD_REQUEST);
}
if ( // user is not active) {
throw new AccessDeniedException("User is not active", HTTP_STATUS.FORBIDEN);
}
... here save user ...
}
}
- 控制器 -
class UserController {
@RequestMapping ....
public void updateUser(int id, String username, String email) {
userService.updateUser(id, username, email);
}
}
就是这样。更少的代码。现在我不必处理每个可能抛出Service层的异常,每次编写控制器时都不必手动检查服务异常,我不会忘记处理一些异常(因为它们在服务中正确形成) ())并且不容易出错。
再次,处理服务层中与Http相关的数据是不是很糟糕?
如果情况不好,你将如何处理我描述的问题。
谢谢。
P.S。:在两种解决方案中,一些通用的ErrorHandler捕获异常并使用适当的状态代码形成响应。
答案 0 :(得分:3)
您可以在Controller内的方法中使用@ExceptionHandler来管理同一控制器中的异常
@ExceptionHandler({MyException.class,OtherException.class})
public String myMethodExceptionHandler() {...}
或者您可以使用@ControllerAdvice创建一个类来管理来自所有控制器的错误
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.CONFLICT) // 409
@ExceptionHandler(MyException.class)
public void handleConflict() {
// Nothing to do
}
}
这里有一个教程。 https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc