Редактировать: Я рассмотрел аннотацию @ExceptionHandler
в Spring 3 и объединил ее с Вариант 1 ниже, выглядит довольно чистым решением.
См. http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers
Я также нашел, что это хорошее чтение: http://blog.decaresystems.ie/index.php/2006/04/07/difficult-choices-in-handling-exceptions-in-enterprise-java-applications/
Я уже некоторое время занимаюсь разработкой с использованием среды Spring MVC, однако я изо всех сил пытаюсь найти «хороший» способ передачи ошибок, возникающих на уровне обслуживания, обратно в JSP.
По сути, я не верю, что бизнес-логика (кроме «это поле обязательно») должна присутствовать в Валидаторах, особенно любая логика, требующая доступа к БД. Итак, что я делал, так это помещал дальнейшую, более сложную проверку и бизнес-логику на уровень обслуживания.
Например, допустим, у меня есть страница, которая позволяет пользователю купить книгу. Они нажимают «Купить» на JSP, и контроллер вызывает службу, чтобы все это произошло ... Теперь, что произойдет, если служба обнаружит, что у них недостаточно средств - как мне вернуть это сообщение в JSP, так что приятно Сообщение «Недостаточно средств» может отображаться пользователю? Я рассмотрел два пути, и я не уверен, что является правильным ...
Вариант 1: Исключения
Первый способ, который я подумал, - вызвать исключение на уровне службы, перехватить его в контроллере и добавить сообщение в BindingResult.
Услуги:
public void pay(Book book) throws InsufficientFundsException {
// Some logic goes here, which ends up throwing the above exception
}
Контроллер:
public ModelAndView(@ModelAttribute("book") Book book, BindingResult errors) {
try {
pay(book);
} catch (InsufficientFundsException ex) {
errors.reject("insufficient.funds");
}
return new ModelAndView(blahblahblah);
}
Вариант 2: Передать BindingResult на сервисный уровень
Второй способ состоял в том, чтобы передать объект BindingResult на сервисный уровень и вызвать дополнительные ошибки для него.
Услуги:
public void pay(Book book, BindingResult errors) {
// User has insufficient funds, so...
errors.reject("insufficient.funds);
}
Я вижу проблемы с обоими этими способами. Вариант 1 чувствует себя неловко, потому что я должен не только перехватить исключение, но и добавить ошибку к результату привязки, чтобы я чувствовал, что я делаю одно и то же дважды. А вариант 2, похоже, слишком тесно связывает сервисный уровень с контроллером.
Наконец , я понимаю, что есть SimpleMappingExceptionResolver
, который можно использовать в сочетании с вариантом 1, но я не уверен, насколько он уместен (возможно, я не видел подходящего примера?) , В приведенном выше примере, давайте просто скажем, ради аргумента, что я бы хотел, чтобы пользователь вернулся в исходную форму с красной ошибкой над формой, а не с перенаправлением на совершенно другую страницу. SimpleMappingExceptionResolver представляется мне полезным, когда вы хотите перенаправить пользователя на стандартную страницу ошибки при возникновении определенного исключения (что не совсем то, что я хочу знать, как это сделать).