gpt4 book ai didi

java - Spring Data Rest - Bean 验证未应用于 PUT 方法?

转载 作者:太空宇宙 更新时间:2023-11-04 11:29:49 24 4
gpt4 key购买 nike

我有一个域类定义如下

@Data
@Entity
public class City {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long cityID;

@NotBlank(message = "City name is a required field")
private String cityName;


}

当我发布到没有 cityName 的端点 http://localhost:8080/cities 时,我得到一个 ConstraintViolationException,但是当我向没有 cityName 的端点 http://localhost:8080/cities/1 发送 PUT 请求时,我得到以下异常,而不是 ConstraintViolationException。

{
"timestamp": 1494510208982,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.transaction.TransactionSystemException",
"message": "Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction",
"path": "/cities/1"
}

那么如何获取 PUT 请求的 ConstraintViolationException 异常?

注意:我正在使用 Spring Data Rest,因此端点是由 Spring 生成的。没有自定义休息 Controller 。

最佳答案

我认为 Cepr0 的测试适用于 PUT 和 POST,因为当您向不存在的实体发送 PUT 请求时,Spring Data Rest 会在后台使用 create 方法。假设没有 id=100 的用户:调用“PUT users/100”与调用“POST users/”相同

当您为现有实体发送 PUT 时,它将生成令人讨厌的 TransactionSystemException。

我现在也在与 Data Rest 异常处理作斗争,其中存在很多不一致之处。

这是我当前的 RestErrorAttributes 类,它解决了我的大部分问题,但在接下来的几天里我很有可能会喜欢其他类。 :)

@Component
@Slf4j
public class RestErrorAttributes extends DefaultErrorAttributes implements MessageSourceAware {

private MessageSource messageSource;

@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}

/** {@inheritDoc} */
@Override
public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {

final Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
// Translate default message by Locale
String message = errorAttributes.get("message").toString();
errorAttributes.put("message",
messageSource.getMessage(message, null, message, LocaleContextHolder.getLocale()));
// Extend default error message by field-errors
addConstraintViolationDetails(errorAttributes, requestAttributes);
return errorAttributes;
}

private void addConstraintViolationDetails(Map<String, Object> errorAttributes,
RequestAttributes requestAttributes) {
Throwable error = getError(requestAttributes);
if (error instanceof ConstraintViolationException) {
errorAttributes.put("errors",
RestFieldError.getErrors(((ConstraintViolationException) error).getConstraintViolations()));
}
else if (error instanceof RepositoryConstraintViolationException) {
errorAttributes.put("errors", RestFieldError
.getErrors(((RepositoryConstraintViolationException) error).getErrors().getAllErrors()));
}
}

/** {@inheritDoc} */
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {

try {
Throwable cause = ex;
while (cause instanceof Exception) {
// Handle AccessDeniedException - It cannot be handled by
// ExceptionHandler
if (cause instanceof AccessDeniedException) {
response.sendError(HttpStatus.FORBIDDEN.value(), cause.getMessage());
super.resolveException(request, response, handler, (Exception) cause);
return new ModelAndView();
}
// Handle exceptions from javax validations
if (cause instanceof ConstraintViolationException) {
response.sendError(HttpStatus.UNPROCESSABLE_ENTITY.value(), "validation.error");
super.resolveException(request, response, handler, (Exception) cause);
return new ModelAndView();
}
// Handle exceptions from REST validator classes
if (cause instanceof RepositoryConstraintViolationException) {
response.sendError(HttpStatus.UNPROCESSABLE_ENTITY.value(), "validation.error");
super.resolveException(request, response, handler, (Exception) cause);
return new ModelAndView();
}
cause = ((Exception) cause).getCause();
}
} catch (final Exception handlerException) {
log.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
}
return super.resolveException(request, response, handler, ex);
}

@Getter
@AllArgsConstructor
public static class RestFieldError {
private String field;
private String code;
private String message;

public static List<RestFieldError> getErrors(Set<ConstraintViolation<?>> constraintViolations) {
return constraintViolations.stream().map(RestFieldError::of).collect(Collectors.toList());
}

public static List<RestFieldError> getErrors(List<ObjectError> errors) {
return errors.stream().map(RestFieldError::of).collect(Collectors.toList());
}

private static RestFieldError of(ConstraintViolation<?> constraintViolation) {
return new RestFieldError(constraintViolation.getPropertyPath().toString(),
constraintViolation.getMessageTemplate(), constraintViolation.getMessage());

}

private static RestFieldError of(ObjectError error) {

return new RestFieldError(error instanceof FieldError ? ((FieldError) error).getField() : null,
error.getCode(), error.getDefaultMessage());

}
}

}

关于java - Spring Data Rest - Bean 验证未应用于 PUT 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43917331/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com