#spring-boot #rest
Вопрос:
У меня есть API Rest для весенней загрузки. Я хочу создать пользователей и установить уникальное ограничение на их электронную почту и имя пользователя. Пока это хорошо работает. Вот основные классы и методы:
@Entity @NoArgsConstructor @Getter @Setter public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(unique = true) @NotNull private String email; @Column(unique = true) @NotNull private String username; @NotNull private String password; public User(String email, String username, String password) { this.email = email; this.password = password; this.username = username; } } @Data @NoArgsConstructor @AllArgsConstructor public class SignupRequest { @NotNull private String email; @NotNull private String username; @NotNull private String password; } @CrossOrigin(value = "*") @PostMapping("/signup") public ResponseEntitylt;?gt; signup(@Valid @RequestBody SignupRequest signupRequest) { signupService.signup(signupRequest); return ResponseEntity.ok().build(); } @Service public class SignupServiceImpl implements SignupService { @Override public void signup(SignupRequest signupRequest) throws MessagingException, UnsupportedEncodingException { User user = new User(); User user = new User(signupRequest.getEmail(), signupRequest.getUsername(), signupRequest.getPassword()); user = userRepository.save(user); } } @Repository @Component public interface UserRepository extends CrudRepositorylt;User, Longgt; {}
Теперь дело в том, что, когда я отправляю запрос POST на эту конечную точку с именем пользователя или по электронной почте, которое уже существует, я просто получаю внутреннюю ошибку сервера http response 500. Но я хочу вернуть другой код состояния и некоторое сообщение об ошибке, указывающее, что адрес электронной почты/имя пользователя уже существует.
Теперь два вопроса:
- Как я могу изменить ответ в глобальном масштабе? Я мог бы окружить
userRepository.save(user)
метод блоком try catch, но мне пришлось бы делать это во всех методах, где я сохраняю пользователя отдельно. Могу ли я определить что-то подобное глобально? userRepository.save(user)
Метод просто возвращает.JdbcSQLIntegrityConstraintViolationException
с довольно подробным сообщением. Есть ли способ четко определить, ЧТО именно пошло не так (ошибка ограничения уникального имени пользователя, ошибка ограничения уникального адреса электронной почты,…)? Я мог бы проверить, существует ли пользователь с таким именем пользователя или электронной почтой, написав метод в справочнике пользователей, но для меня это выглядит как множество ненужных sql-запросов. Есть ли лучший способ?
Ответ №1:
Чтобы ответить на ваш первый вопрос, вы можете обрабатывать исключения глобально с помощью механизма обработки исключений spring. Вы могли бы использовать spring ControllerAdvice. Здесь вы можете задать общий ответ на ошибку и пользовательский http-код. Вот пример ControllerAdvice
@ControllerAdvice public class CustomExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(UserNotFoundException.class) public final ResponseEntitylt;ErrorResponsegt; handleUserNotFoundException(UserNotFoundException ex, WebRequest request) { String details = ex.getLocalizedMessage(); ErrorResponse error = new ErrorResponse(ApplicationConstants.RECORD_NOT_FOUND, details); return new ResponseEntitylt;gt;(error, HttpStatus.NOT_FOUND); } @ExceptionHandler(Exception.class) public final ResponseEntitylt;ErrorResponsegt; handleAllExceptions(Exception ex, WebRequest request) { String details = ex.getLocalizedMessage(); ErrorResponse error = new ErrorResponse(ApplicationConstants.SERVER_ERROR, details); return new ResponseEntitylt;gt;(error, HttpStatus.INTERNAL_SERVER_ERROR); } } public class ErrorResponse { public ErrorResponse(String message, String details) { super(); this.message = message; this.details = details; } private String message; private String details; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getDetails() { return details; } public void setDetails(String details) { this.details = details; } }
Теперь о втором вопросе, вы можете просмотреть все причины и проверить уникальное имя ограничения, чтобы выяснить, какое исключение нарушено. Но лучшим подходом было бы сначала проверить, а если найдется, то выдать ошибку.
Комментарии:
1. Спасибо! Работает идеально : )