我应该在模型中使用HttpStatus抛出异常吗?

时间:2015-11-27 14:30:11

标签: java spring web-services rest exception

假设我开发了一些休息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捕获异常并使用适当的状态代码形成响应。

1 个答案:

答案 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