你们可以分享一些关于如何设计一个处理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页面显示的长返回消息都可以在这个特定的异常处理程序中编码。
PLOG感谢您的答复unchecked异常错误响应。我相信他们主要是检查异常。我用一个具体的例子更新了我的问题。你能帮我再看一下吗?谢谢。 – theMojo
当然,在我看来,您可以在特定的异常处理程序中定义长的错误消息,方法B中的好处同样可以在方法A中完成。只需将这个长的错误消息包含在您的异常处理的构造函数中。我认为在这种情况下使用单个异常处理程序会更好。 – Plog
是的。我看到了在异常构造函数中包含长错误消息的方法。但是,我担心的是,长的错误消息应该显示在用户的视图层上。我不确定它是否会以太多的返回错误信息污染控制器层。除此之外,可以说如果异常是从服务类抛出的,在服务类抛出的异常构造函数中定义长错误信息会好吗? – theMojo