当前位置: 首页 > 知识库问答 >
问题:

处理Spring MVC控制器上的异常

唐高朗
2023-03-14

你们能分享一些关于如何在Spring MVC中设计一个处理异常的良好实现的建议吗?以下是我在网上花了一些时间试图找出处理异常的合适或更好的实现后的一些想法。

以下是我正在进行的项目的一些背景:

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

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

方法A

>

  • 相同的异常被重用于mvc控制器中的特定方法。例如,

    public String methodA()引发AException{//bla bla}

    然后将有唯一的AExceptionHandler在一个单独的java文件中处理此异常。可能有其他方法调用在方法A()中抛出不同的异常。但是,将实现一个尝试捕获块来包装抛出其他类型异常的方法,并使用AExc,重新抛出。

    方法B

    • 另一种在控制器或服务层使用唯一的异常。但是,将为每个异常实现指定的异常处理程序。
    • 由于异常是唯一的,细节(返回消息和视图名)可以放在异常处理程序中,而不会污染控制器层。这样它们会更干净。但是,将会有更多的样板代码只是用于异常处理程序,以及许多不同独特情况下的异常,我希望终止特定方法块的代码执行。

    所以,这些是我现在面临的问题。我希望我在处理 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;
    }
    

    所以使用方法A:

    //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 页面上的长返回消息都可以在此特定的异常处理程序中进行编码。

  • 共有2个答案

    孟鸿德
    2023-03-14

    对于异常唯一字段:

    try{
    
    }
    catch(DataIntegrityViolationException e)
    {
    
    }
    
    魏学智
    2023-03-14

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

    但是,如果您想处理应用程序中可能发生的未经检查的异常的错误响应,那么我将使用方法 B。

     类似资料:
    • 我有一个spring-boot应用程序,没有任何控制器类。如何为该应用程序编写异常处理程序。用@ControllerAdvice注释的异常处理程序类不起作用。

    • 我一直在尝试使用: 使用此链接: 但我有一个错误: 当我换成: 是工作。我能做些什么来和日期一起工作? 谢啦

    • 我想要一些关于如何实现以下目标的建议。我不提供代码,因为我的问题是理论上的,但应要求我可以。所以情况是这样的: 我有多个控制器,每个控制器都可以抛出XYException 我有一个@ControllerAdvice类,其中有一个@ExceptionHandler监视XYExceptions。当它发生时,它打印出“xy”。 在一个(且仅有一个)控制器中,当抛出XYException时,我希望执行一些

    • 我有过 我通过这种方式传递profileJson: 但是我的配置文件Json对象具有所有空字段。我应该怎么做才能让Spring解析我的json?

    • 我有一个简单的Spring控制器。 当我在查询字符串中传递a=1时,它工作正常。 但是当我通过a=abc时,它给了我这个。 有没有办法让我可以处理这个错误并回复给用户,就像必须是数字一样。 提前感谢。

    • 本文向大家介绍springmvc处理异步请求的示例,包括了springmvc处理异步请求的示例的使用技巧和注意事项,需要的朋友参考一下 springmvc 3.2开始就支持servlet3.0的异步请求。平常我们请求一个controller一般都是同步的,如果在代码执行中,遇到耗时的业务操作,那servlet容器线程就会被锁死,当有其他请求进来的时候就会受堵了。 springmvc3.2之后支持异