Why Spring MVC does not allow to expose Model or BindingResult to an @ExceptionHandler?

后端 未结 6 2402
天命终不由人
天命终不由人 2021-02-12 18:32

Situation

I\'m trying to group the code that logs the exceptions and render a nice view in a few methods. At the moment the logic is sometime in the @RequestHand

6条回答
  •  后悔当初
    2021-02-12 19:01

    I've wondered this too.

    In order to handle bean validation in a way that allows for a non-global error view to display any ConstraintViolationExceptions that may be thrown, I opted for a solution along the lines of what @Stefan Haberl proposed:

    Explicitly catch the exception to tell Spring MVC that you know what you're doing (you could use the Template pattern to refactor exception handling logic into one single place)

    I created a simple Action interface:

    public interface Action {
      String run();
    }
    

    And an ActionRunner class which does the work of ensuring ConstraintViolationExceptions are handled nicely (basically the messages from each ConstraintViolationException is simply added to a Set and added to the model):

    public class ActionRunner {
      public String handleExceptions(Model model, String input, Action action) {
        try {
          return action.run();
        }
        catch (RuntimeException rEx) {
          Set errors = BeanValidationUtils.getErrorMessagesIfPresent(rEx);
          if (!errors.isEmpty()) {
            model.addAttribute("errors", errors);
            return input;
          }
          throw rEx;
        }
      }
    }
    

    Java 8 makes this pretty nice to run within the controller action method:

    @RequestMapping(value = "/event/save", method = RequestMethod.POST)
    public String saveEvent(Event event, Model model, RedirectAttributes redirectAttributes) {
      return new ActionRunner().handleExceptions(model, "event/form", () -> {
        eventRepository.save(event);
        redirectAttributes.addFlashAttribute("messages", "Event saved.");
        return "redirect:/events";
      });
    }
    

    This is to wrap up those action methods for which I'd like to explicitly handle exceptions that could be thrown due to Bean Validation. I still have a global @ExceptionHandler but this deals with only "oh crap" exceptions.

提交回复
热议问题