Spring 引导如何 return 我自己的验证约束错误消息
Spring Boot how to return my own validation constraint error messages
当我的请求出现问题时,我需要有自己的错误响应主体,我正在尝试使用 @NotEmpty
约束消息属性来 return 错误消息,
这是我的 class return 使用我需要的正文的错误消息:
package c.m.nanicolina.exceptions;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class CustomResponseEntityExceptionHandler {
@ExceptionHandler(value = {MissingServletRequestParameterException.class})
public ResponseEntity<ApiError> handleConflict(MissingServletRequestParameterException ex, WebRequest request) {
ApiError apiError = new ApiError(ex.getMessage(), ex.getMessage(), 1000);
return new ResponseEntity<ApiError>(apiError, null, HttpStatus.BAD_REQUEST);
}
}
有了这个 CustomResponseEntityExceptionHandler
我可以 return 我自己的响应正文以防验证错误。
我现在正在尝试的是从验证约束中获取消息。
这是我的带有 NotEmpty
约束的控制器:
package c.m.nanicolina.controllers;
import c.m.nanicolina.models.Product;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotEmpty;
@RestController
public class MinimumStockController {
@RequestMapping(value = "/minimumstock")
public Product product(
@RequestParam(value = "product.sku") @NotEmpty(message = "Product.sku cannot be empty") String sku,
@RequestParam(value = "stock.branch.id") String branchID) {
return null;
}
}
在我的例外情况下,我找不到获取该消息的方法 Product.sku cannot be empty
并在我的错误响应中显示它。
我还检查了 class MissingServletRequestParameterException
并且有方法 getMessage
是 return 默认消息。
你应该把这个放在你的处理程序上。
@ControllerAdvice
public class CustomResponseEntityExceptionHandler {
@ExceptionHandler(value = { MissingServletRequestParameterException.class })
public ResponseEntity<ApiError> handleConflict(MissingServletRequestParameterException ex, WebRequest request) {
String message = ex.getParameterName() + " cannot be empty";
ApiError apiError = new ApiError(ex.getMessage(), message, 1000);
return new ResponseEntity < ApiError > (apiError, null, HttpStatus.BAD_REQUEST);
}
}
更新
我不知道如何获得默认消息,但作为解决方法,您可以在控制器上进行验证并在参数为空时抛出自定义异常,然后在 CustomResponseEntityExceptionHandler
.
类似于以下内容:
设置required=false
@RequestMapping(value = "/minimumstock")
public Product product(@RequestParam(required = false) String sku, @RequestParam(value = "stock.branch.id") String branchID) {
if (StringUtils.isEmpty(sku))
throw YourException("Product.sku cannot be empty");
return null;
}
是的,它是可行的 & spring 非常支持它。您只是缺少一些配置以在 spring.
中启用它
- Use Spring
@Validated
annotation to enable spring to validate controller
- Handle
ConstraintViolationException
in your ControllerAdvice
to catch all failed validation messages.
- Mark
required=false
in @RequestParam
, so it will not throw MissingServletRequestParameterException and rather move to next step of constraint validation.
@ControllerAdvice
public class CustomResponseEntityExceptionHandler {
@ExceptionHandler
public ResponseEntity<ApiError> handle(ConstraintViolationException exception) {
//you will get all javax failed validation, can be more than one
//so you can return the set of error messages or just the first message
String errorMessage = new ArrayList<>(exception.getConstraintViolations()).get(0).getMessage();
ApiError apiError = new ApiError(errorMessage, errorMessage, 1000);
return new ResponseEntity<ApiError>(apiError, null, HttpStatus.BAD_REQUEST);
}
}
@RestController
@Validated
public class MinimumStockController {
@RequestMapping(value = "/minimumstock")
public Product product(
@RequestParam(value = "product.sku", required=false) @NotEmpty(message = "Product.sku cannot be empty") String sku,
@RequestParam(value = "stock.branch.id", required=false) String branchID) {
return null;
}
}
注意: MissingServletRequestParameterException
将无法访问 javax 验证消息,因为它在请求生命周期中发生约束验证之前抛出。
是的,这是可能的。这样做:
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ArgumentsErrorResponseDTO> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
ServiceException exception = ServiceException.wrap(ex, ErrorCode.FIELD_VALIDATION);
BindingResult results = ex.getBindingResult();
for (FieldError e: results.getFieldErrors()) {
exception.addLog(e.getDefaultMessage(), e.getField());
}
// log details in log
log.error("Invalid arguments exception: {}", exception.logWithDetails(), exception);
return ResponseEntity.status(exception.getErrorCode().getHttpStatus())
.body(ArgumentsErrorResponseDTO.builder()
.code(exception.getErrorCode().getCode())
.message(exception.getMessage())
.details(exception.getProperties())
.build());
}
如果这有帮助,我在这里找到了这个问题的解决方案:https://howtodoinjava.com/spring-boot2/spring-rest-request-validation/
您必须将此方法添加到您的 CustomResponseEntityExceptionHandler class:
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
List<String> details = new ArrayList<>();
for(ObjectError error : ex.getBindingResult().getAllErrors()) {
details.add(error.getDefaultMessage());
}
ErrorMessage error = new ErrorMessage(new Date(), details.toString());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
当我的请求出现问题时,我需要有自己的错误响应主体,我正在尝试使用 @NotEmpty
约束消息属性来 return 错误消息,
这是我的 class return 使用我需要的正文的错误消息:
package c.m.nanicolina.exceptions;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class CustomResponseEntityExceptionHandler {
@ExceptionHandler(value = {MissingServletRequestParameterException.class})
public ResponseEntity<ApiError> handleConflict(MissingServletRequestParameterException ex, WebRequest request) {
ApiError apiError = new ApiError(ex.getMessage(), ex.getMessage(), 1000);
return new ResponseEntity<ApiError>(apiError, null, HttpStatus.BAD_REQUEST);
}
}
有了这个 CustomResponseEntityExceptionHandler
我可以 return 我自己的响应正文以防验证错误。
我现在正在尝试的是从验证约束中获取消息。
这是我的带有 NotEmpty
约束的控制器:
package c.m.nanicolina.controllers;
import c.m.nanicolina.models.Product;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotEmpty;
@RestController
public class MinimumStockController {
@RequestMapping(value = "/minimumstock")
public Product product(
@RequestParam(value = "product.sku") @NotEmpty(message = "Product.sku cannot be empty") String sku,
@RequestParam(value = "stock.branch.id") String branchID) {
return null;
}
}
在我的例外情况下,我找不到获取该消息的方法 Product.sku cannot be empty
并在我的错误响应中显示它。
我还检查了 class MissingServletRequestParameterException
并且有方法 getMessage
是 return 默认消息。
你应该把这个放在你的处理程序上。
@ControllerAdvice
public class CustomResponseEntityExceptionHandler {
@ExceptionHandler(value = { MissingServletRequestParameterException.class })
public ResponseEntity<ApiError> handleConflict(MissingServletRequestParameterException ex, WebRequest request) {
String message = ex.getParameterName() + " cannot be empty";
ApiError apiError = new ApiError(ex.getMessage(), message, 1000);
return new ResponseEntity < ApiError > (apiError, null, HttpStatus.BAD_REQUEST);
}
}
更新
我不知道如何获得默认消息,但作为解决方法,您可以在控制器上进行验证并在参数为空时抛出自定义异常,然后在 CustomResponseEntityExceptionHandler
.
类似于以下内容:
设置required=false
@RequestMapping(value = "/minimumstock")
public Product product(@RequestParam(required = false) String sku, @RequestParam(value = "stock.branch.id") String branchID) {
if (StringUtils.isEmpty(sku))
throw YourException("Product.sku cannot be empty");
return null;
}
是的,它是可行的 & spring 非常支持它。您只是缺少一些配置以在 spring.
中启用它
- Use Spring
@Validated
annotation to enable spring to validate controller- Handle
ConstraintViolationException
in yourControllerAdvice
to catch all failed validation messages.- Mark
required=false
in@RequestParam
, so it will not throw MissingServletRequestParameterException and rather move to next step of constraint validation.
@ControllerAdvice
public class CustomResponseEntityExceptionHandler {
@ExceptionHandler
public ResponseEntity<ApiError> handle(ConstraintViolationException exception) {
//you will get all javax failed validation, can be more than one
//so you can return the set of error messages or just the first message
String errorMessage = new ArrayList<>(exception.getConstraintViolations()).get(0).getMessage();
ApiError apiError = new ApiError(errorMessage, errorMessage, 1000);
return new ResponseEntity<ApiError>(apiError, null, HttpStatus.BAD_REQUEST);
}
}
@RestController
@Validated
public class MinimumStockController {
@RequestMapping(value = "/minimumstock")
public Product product(
@RequestParam(value = "product.sku", required=false) @NotEmpty(message = "Product.sku cannot be empty") String sku,
@RequestParam(value = "stock.branch.id", required=false) String branchID) {
return null;
}
}
注意: MissingServletRequestParameterException
将无法访问 javax 验证消息,因为它在请求生命周期中发生约束验证之前抛出。
是的,这是可能的。这样做:
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ArgumentsErrorResponseDTO> handleMethodArgumentNotValid(MethodArgumentNotValidException ex) {
ServiceException exception = ServiceException.wrap(ex, ErrorCode.FIELD_VALIDATION);
BindingResult results = ex.getBindingResult();
for (FieldError e: results.getFieldErrors()) {
exception.addLog(e.getDefaultMessage(), e.getField());
}
// log details in log
log.error("Invalid arguments exception: {}", exception.logWithDetails(), exception);
return ResponseEntity.status(exception.getErrorCode().getHttpStatus())
.body(ArgumentsErrorResponseDTO.builder()
.code(exception.getErrorCode().getCode())
.message(exception.getMessage())
.details(exception.getProperties())
.build());
}
如果这有帮助,我在这里找到了这个问题的解决方案:https://howtodoinjava.com/spring-boot2/spring-rest-request-validation/
您必须将此方法添加到您的 CustomResponseEntityExceptionHandler class:
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
List<String> details = new ArrayList<>();
for(ObjectError error : ex.getBindingResult().getAllErrors()) {
details.add(error.getDefaultMessage());
}
ErrorMessage error = new ErrorMessage(new Date(), details.toString());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}