【问题标题】:Spring MVC ExceptionHandler for restful and normalSpring MVC ExceptionHandler 用于宁静和正常
【发布时间】:2015-08-18 11:11:42
【问题描述】:

我想处理普通请求和 rest/ajax 请求的异常。这是我的代码,

@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ModelAndView handleCustomException(Exception ex) {

        ModelAndView model = new ModelAndView("error");
        model.addObject("errMsg", ex.getMessage());
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        sw.toString();
        model.addObject("errTrace", sw);
        return model;

    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public String handleAjaxException(Exception ex) {
        JSONObject model = new JSONObject();
        model.put("status", "error");
        model.put("errMsg", ex.getMessage());
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        sw.toString();
        model.put("errTrace", sw);

        return model.toString();
    }
}

这会给我一个错误,因为我不能有两次 @ExceptionHandler(Exception.class)。那么有什么办法呢?

【问题讨论】:

    标签: spring-mvc exception-handling spring-rest


    【解决方案1】:

    查看@ControllerAdvice的配置: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

    所以你可以创建两个类(错误处理程序)并指定注解/basePackages/assignibaleTypes

    例如,对于 REST(ajax),您的控制器使用 @RestController 注释,您可以处理如下错误:

    @ControllerAdvice(annotations = RestController.class)
    public class MyExceptionHandler {
    
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public String handleAjaxException(Exception ex) {
            ...
        }
    }
    

    对于其他情况,它可以是带有注释的错误处理程序

    @ControllerAdvice(annotations = Controller.class)
    

    【讨论】:

    • 我用@Controller 注释了类,有些方法有@ResponseBody,有些是正常的返回模型。我使用了您的示例,但始终调用 annotation = Controller.class。我想只是因为我使用@Controller 作为控制器类?!!
    • 是的,您的 REST 方法应该在带有注释 @RestController 而不是 @Controller 的单独控制器中(以使此解决方案有效)。
    【解决方案2】:

    这是 spring mvc 中的全局异常处理程序。每次在您的应用程序中发现异常时都会调用它。我认为您只能借助 web.xml 控制 404 异常。

    @ControllerAdvice
    public class GlobalExceptionController {
    
        @ExceptionHandler(Throwable.class)
        @ResponseBody
        public ModelAndView handleAllException(Throwable ex,
                HttpServletResponse response) {
    
            ex.printStackTrace();
            // Set Status
            response.setStatus(500);
            // Set View
            ModelAndView model = new ModelAndView("500");
            model.addObject("navlabel", "");
            model.addObject("userActivity", new ArrayList<String>());
            // Set exception Message
            model.addObject("errMsg", ex.getMessage());
            return model;
        }
    }
    

    【讨论】:

    • 感谢您的回答。这个全局返回 ModelAndView,这对于像server/app/getCustomer 这样的正常请求是可以的,我们设置视图名称。但是对于 ajax 请求,如果出现任何错误,它应该将错误消息作为字符串发送,以便可以使用 alert() 显示。
    • 我认为@ResponseBody 会转换成json。你试过了吗?
    【解决方案3】:

    您可以创建内部静态类@RestControllerAdvice。不需要为此创建单独的@RestController。

    @ControllerAdvice
    public class BaseController {
    private static final Logger logger = 
    LoggerFactory.getLogger(BaseController.class);
    
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String handleException(Exception error, Model model) {
        logger.error("Error was: " + error.getMessage(), error);
        model.addAttribute("message", error.getMessage());
        model.addAttribute("stackTrace", error.getStackTrace());
        model.addAttribute("exception", error);
        return "error"; //return view
    }
    
    @RestControllerAdvice
    public static class RestBaseController {
    
        private static final Logger logger = LoggerFactory.getLogger(RestBaseController.class);
    
        @ExceptionHandler(Exception.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        public String handleException(Exception error) {
            logger.error("Error was: " + error.getMessage(), error);
    
            return "error"; //return "error"
        }
    }
    }
    

    【讨论】:

      【解决方案4】:

      您可以编写两个异常处理程序来处理正常和 rest/ajax 请求异常。这是说明解决方案的示例代码。

      @ControllerAdvice(annotations = RestController.class)
      @Order(1)
      class RestExceptionHandler {
          @ExceptionHandler(MyException.class)
          @ResponseBody
          ResponseEntity<ErrorResponse> exceptionHandler() {
              ....
          }   
      }
      
      @ControllerAdvice(annotations = Controller.class)
      @Order(2)
      class ExceptionHandler {
          @ExceptionHandler(Exception.class)
          public ModelAndView handleError500(HttpServletRequest request, HttpServletResponse response, Exception ex) {
              ModelAndView mav = new ModelAndView("error");
              mav.addObject("error", "500");
              return mav;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-10-29
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 2018-11-04
        • 2012-07-23
        • 2015-04-25
        • 2013-05-16
        • 1970-01-01
        相关资源
        最近更新 更多