API Spring Boot Rest обрабатывает уникальное ограничение

#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. Но я хочу вернуть другой код состояния и некоторое сообщение об ошибке, указывающее, что адрес электронной почты/имя пользователя уже существует.

Теперь два вопроса:

  1. Как я могу изменить ответ в глобальном масштабе? Я мог бы окружить userRepository.save(user) метод блоком try catch, но мне пришлось бы делать это во всех методах, где я сохраняю пользователя отдельно. Могу ли я определить что-то подобное глобально?
  2. 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. Спасибо! Работает идеально : )