2017-07-07 97 views
1

你们可以分享一些关于如何设计一个处理Spring MVC异常的好实现的建议吗?在花一些时间在线试图找出处理异常的合适或更好的实现之后,下面是我的一些想法。处理Spring MVC控制器的异常

这里是我米工作了项目的一些背景:

  • 使用的MVC框架是春季启动网络。与使用Spring MVC的其他项目类似,我将代码分为几层:控制器,服务和模型。
  • 在控制器中,主要是验证来自视图(前端)层的表单输入并执行一些业务逻辑。对于表单验证,我使用Spring验证注释(JSR 303),它与控制器完美地集成在一起。
  • 但是,当涉及到跨控制器和服务层分布的业务逻辑实现时,如果检查失败,我想要处理一些可能会终止控制器/服务方法块的执行的检查。
  • 所以,我认为最好的办法是使用异常来处理这个问题。
  • 我在网上找到几个实现,共享如何使用Spring现有的异常处理机制实现更好的异常处理框架。例如。控制器建议和基于控制器的异常处理程序等。

所以,这里是我的困惑。我想到了两种类型的异常处理机制。两者都是使用@ControllerAdvice实现的,它将单独的Java类中的异常处理分开。

视角下的

  • 甲相同异常用于在MVC控制器的特定方法再利用。例如,

    公共字符串了methodA()抛出AException {// 唧唧歪歪 }

  • 然后会有独特AExceptionHandler处理这个例外在一个单独的Java文件。 methodA()中可能会有其他方法调用引发不同的异常。但是,将会实现一个try catch块来包装引发其他类型异常的方法,并用AException重新抛出。

  • 因此,这种方法A重用AException。因此,BaseException类将存储一些附加属性,用于存储返回消息(要在视图中显示)和返回视图名称的详细信息。
  • 但是,这将导致控制器或服务层混杂着返回消息或返回视图名称。

方法乙

  • 其他使用在控制器或服务层唯一的例外。但是,每个异常都会执行一个指定的异常处理程序。
  • 由于异常是唯一的,因此可以将细节(返回消息和视图名称)放在异常处理程序中,而不会污染控制器层。他们会以这种方式更清洁。但是,对于异常处理程序,将会有更多的样板代码,并且我希望终止特定方法块的代码执行。

所以,这些都是我现在面临的问题。我希望我在处理Spring web异常方面朝着正确的方向前进。请让我知道你对此的想法。谢谢。

实施例:

允许使用的帐户注册方法,例如:

//In the controller class 
public String accountSignUp(@Valid AccountSignUpForm form){ 
    if(bindingResult.hasErrors()){ 
     return "signupview"; 
    } 
    accountSignUpSvc.validateEmail(form.getEmail); 
    accountSignUpSvc.createAccount(form); 
} 

// In the accountSignUpSvc class; 
public interface AccountSignUpSvc { 
    // Check if email has been used for sign up. 
    void validateEmail(String email) throws DuplicateAccountException; 
    // Create the account based on the form. 
    void createAccount(AccountSignUpForm form) throws AccountCreationException; 
} 

因此,使用方法的一个:

//In the controller class 
public String accountSignUp(@Valid AccountSignUpForm form){ 
    if(bindingResult.hasErrors()){ 
     return "signupview"; 
    } 
    try{ 
     accountSignUpSvc.validateEmail(form.getEmail); 
    } catch (DuplicateAccountException e){ 
     // Rethrow with a controller method specific exception 
     throw new AccountSignUpException("Returned error message"," Internal error message.",e); 
    } 
    // Then implement the similar try catch block for the accountSignUpSvc.createAccount method 
} 

@ControllerAdvice 
public class AccountSignUpExceptionHandler{ 
    @ExceptionHandler(AccountSignUpException.class) 
    public ModelAndView handleAccountSignUpException(HttpServletRequest request, AccountSignUpException ex){ 
    log.error(ex.getInternalError); 

    ModelAndView mav = new ModelAndView("signup"); 
    mav.addObject("returnError", ex.getReturnError()); 

    return mav; 
} 

然后,使用方法B:

//In the controller class 
public String accountSignUp(@Valid AccountSignUpForm form){ 
    if(bindingResult.hasErrors()){ 
     return "signupview"; 
    } 

    accountSignUpSvc.validateEmail(form.getEmail); 

    // Then implement the similar try catch block for the accountSignUpSvc.createAccount method 
} 

@ControllerAdvice 
public class AccountSignUpExceptionHandler{ 
    @ExceptionHandler(DuplicateAccountException.class) 
    public ModelAndView handleDuplicateAccountException(HttpServletRequest request, DuplicateAccountException ex){ 
    log.error("Error due to error"); 

    ModelAndView mav = new ModelAndView("signup"); 
    mav.addObject("returnError", "Return error message: a long error message."); 

    return mav; 
} 

我提到的好处是异常处理程序可以是特定的,因为只有某个条件才会触发它。所以,任何应该在html页面显示的长返回消息都可以在这个特定的异常处理程序中编码。

回答

0

在我看来,这取决于你所说的这些异常是否是检查异常。如果它们都是在methodA()中引发的所有检查异常,那么我会倾向于使用方法A并捕获这些异常,并将它们作为您自己的应用程序特定异常与@ControllerAdvice类中的单个处理程序一起返回。

然而,如果你是想办理,你可能希望在应用程序中发生的话,我会用方法B.

+0

PLOG感谢您的答复unchecked异常错误响应。我相信他们主要是检查异常。我用一个具体的例子更新了我的问题。你能帮我再看一下吗?谢谢。 – theMojo

+0

当然,在我看来,您可以在特定的异常处理程序中定义长的错误消息,方法B中的好处同样可以在方法A中完成。只需将这个长的错误消息包含在您的异常处理的构造函数中。我认为在这种情况下使用单个异常处理程序会更好。 – Plog

+0

是的。我看到了在异常构造函数中包含长​​错误消息的方法。但是,我担心的是,长的错误消息应该显示在用户的视图层上。我不确定它是否会以太多的返回错误信息污染控制器层。除此之外,可以说如果异常是从服务类抛出的,在服务类抛出的异常构造函数中定义长错误信息会好吗? – theMojo