【问题标题】:Spring Boot Rest API handling unique constraintSpring Boot Rest API 处理唯一约束
【发布时间】:2022-01-09 01:21:43
【问题描述】:

我有一个 Spring Boot Rest API。我想创建用户并对其电子邮件和用户名设置唯一约束。到目前为止效果很好。以下是主要的类和方法:

@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 ResponseEntity<?> 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 CrudRepository<User, Long> {}

现在,问题是,当我使用已存在的用户名或电子邮件向该端点发送 POST 请求时,我只会收到 http 响应 500 Internal Server Error。但我想返回一个不同的状态码和一些错误消息,表明电子邮件/用户名已经存在。

现在有两个问题:

  1. 如何全局修改响应?我可以用 try catch 块包围userRepository.save(user) 方法,但我必须在我单独保存用户的所有方法中这样做。我可以在全球范围内定义类似的东西吗?
  2. userRepository.save(user) 方法只返回一个。 JdbcSQLIntegrityConstraintViolationException 带有非常冗长的消息。有没有办法清楚地确定到底出了什么问题(唯一用户名约束失败,唯一电子邮件约束失败,......)?我可以通过在 userRepository 中编写一个方法来检查具有该用户名或电子邮件的用户是否存在,但这对我来说看起来像是很多不必要的 sql 查询。有没有更好的方法?

【问题讨论】:

    标签: spring-boot rest


    【解决方案1】:

    回答您的第一个问题,您可以通过 Spring 异常处理机制全局处理异常。您可以使用弹簧控制器建议。在这里您可以设置通用错误响应和自定义 http 代码。这是一个ControllerAdvice的例子

    @ControllerAdvice
    public class CustomExceptionHandler extends ResponseEntityExceptionHandler 
    {
        @ExceptionHandler(UserNotFoundException.class)
        public final ResponseEntity<ErrorResponse> handleUserNotFoundException(UserNotFoundException ex, WebRequest request) {
            String details = ex.getLocalizedMessage();
            ErrorResponse error = new ErrorResponse(ApplicationConstants.RECORD_NOT_FOUND, details);
            return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
        }
    
        @ExceptionHandler(Exception.class)
        public final ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex, WebRequest request) {
            String details = ex.getLocalizedMessage();
            ErrorResponse error = new ErrorResponse(ApplicationConstants.SERVER_ERROR, details);
            return new ResponseEntity<>(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;
        }
    }
    

    现在关于第二个问题,您可以遍历所有原因并检查唯一约束名称以找出违反了哪些异常。但更好的方法是先检查,如果发现则抛出错误。

    【讨论】:

    • 谢谢!完美运行:)
    猜你喜欢
    • 2015-04-22
    • 1970-01-01
    • 2021-05-25
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多