Скажем, я развиваю некоторый отдых api. У меня есть веб-уровень (контроллеры) и уровень обслуживания (модель). Является ли хорошей практикой бросать исключение с кодом HttpStatus в уровень обслуживания?Должен ли я исключать исключение из HttpStatus в модели?
Кто-то скажет, что эта модель не должна знать ничего о веб-слое, она не должна зависеть от веб-уровня.
Но, давайте рассмотрим эту ситуацию:
выбрасывающие исключений с HttpStatus в контроллере
--- Услуги ---
class userService {
public void updateUser(int userId, String username, String email) {
if (//userid not found) {
throw new UserNotFoundException("User not found");
}
if (// bad email format) {
throw new BadArgumentException("Bad email format");
}
if (// user is not active) {
throw new AccessDeniedException("User is not active");
}
... here save user ...
}
}
--- Контроллер ---
class UserController {
@RequestMapping ....
public void updateUser(int id, String username, String email) {
try{
userService.updateUser(id, username, email);
}
catch (UserNotFoundException e) {
throw new HttpException(e.getMessage(), HttpStatus.NOT_FOUND);
}
catch (BadArgumentExceptione e) {
throw new HttpException(e.getMessage(), HttpStatus.BAD_REQUEST);
}
catch (AccessDeniedException e) {
throw new HttpException(e.getMessage(), HttpStatus.FORBIDEN);
}
}
}
Вы видите? Сколько дополнительного кода я должен написать, чтобы вернуть правильный ответ клиенту Api? Кроме того, я могу забыть какое-то исключение, которое можно было бы сообщить правильно, и оно будет возвращено как исключение внутреннего сервера по умолчанию. В контроллере я всегда должен заглядывать в сервисный уровень и проверять, какие исключения могут бросить сервис, чтобы правильно их обрабатывать. (Пожалуйста, не предлагайте проверенное исключение в java).
А теперь давайте посмотрим, еще одно решение:
бросание исключения с HttpStatus в Service Layer (модель)
--- Сервис ---
класс UserService {
public void updateUser(int userId, String username, String email) {
if (//userid not found) {
throw new UserNotFoundException("User not found", HttpStatus.NOT_FOUND);
}
if (// bad email format) {
throw new BadArgumentException("Bad email format", HttpStatus.BAD_REQUEST);
}
if (// user is not active) {
throw new AccessDeniedException("User is not active", HTTP_STATUS.FORBIDEN);
}
... here save user ...
}
}
- Контроллер -
class UserController {
@RequestMapping ....
public void updateUser(int id, String username, String email) {
userService.updateUser(id, username, email);
}
}
И все. Меньше кода. Теперь мне не нужно обрабатывать каждое возможное исключение, которое может вызвать сервисный уровень. Мне не нужно каждый раз проверять служебные исключения каждый раз, когда я пишу контроллер, и я не забуду обработать какое-то исключение (потому что они правильно сформированы в слое сервиса) и это менее подвержено ошибкам.
И снова - это плохая практика для обработки данных, связанных с Http, в сервисном слое?
Если это плохо, как вы справитесь с issus, который я описал.
спасибо.
P.S .: В обоих решениях некоторый общий ErrorHandler обнаруживает исключения и формирует ответ с соответствующими кодами состояния.
также см [Спринг Ссылка] (http://docs.spring.io/spring/docs/4.2.4.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers) –