【问题标题】:Should I throw exception with HttpStatus in model?我应该在模型中抛出 HttpStatus 异常吗?
【发布时间】:2015-11-27 14:30:11
【问题描述】:

假设我开发了一些rest 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 引发异常

--- 服务---

类用户服务{

   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);         
  }       
}

就是这样。更少的代码。现在我不必处理每个可能引发服务层的异常,我不必每次编写控制器时都手动检查服务异常,并且我不会忘记处理一些异常(因为它们在服务层中正确形成)这不太容易出错。

再说一次,在服务层处理 Http 相关数据是不好的做法吗?

如果不好,你将如何处理我描述的问题。

谢谢。

P.S.:在这两种解决方案中,一些通用的 ErrorHandler 都会捕获异常并使用适当的状态代码形成响应。

【问题讨论】:

    标签: java spring web-services rest exception


    【解决方案1】:

    您可以在 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

    【讨论】:

    猜你喜欢
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多