Java Spring Boot如何返回我自己的验证约束错误消息

Java Spring Boot如何返回我自己的验证约束错误消息,java,validation,spring-boot,exception-handling,query-parameters,Java,Validation,Spring Boot,Exception Handling,Query Parameters,当我的请求出现问题时,我需要有自己的错误响应主体,并且我试图使用@NotEmpty约束消息属性返回错误消息 这是我的类,它使用我需要的正文返回错误消息: package c.m.nanicolina.exceptions; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MissingS

当我的请求出现问题时,我需要有自己的错误响应主体,并且我试图使用
@NotEmpty
约束消息属性返回错误消息

这是我的类,它使用我需要的正文返回错误消息:

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);
    }
}
在我的例外情况下,我无法找到获取该消息的方法
Product.sku不能为空
并在我的错误响应中显示它。


我还检查了类
MissingServletRequestParameterException
,还有返回默认消息的方法
getMessage

您应该将其放在处理程序上

@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);
    }
}

是的,它是可行的&spring非常支持它。您只是缺少一些在spring中启用它的配置

  • 使用Spring
    @Validated
    注释启用Spring来验证控制器
  • ControllerAdvice
    中处理
    ConstraintViolationException
    ,以捕获所有失败的验证消息
  • @RequestParam
    中标记
    required=false
    ,这样它就不会抛出MissingServletRequestParameterException,而是转到约束验证的下一步
@ControllerAdvice
公共类CustomResponseEntityExceptionHandler{
@例外处理程序
公共响应属性句柄(ConstraintViolationException异常){
//您将得到所有javax失败的验证,可以是多个
//因此,您可以返回一组错误消息,也可以只返回第一条消息
String errorMessage=new ArrayList(exception.getConstraintViolations()).get(0.getMessage();
APIRROR APIRROR=新的APIRROR(errorMessage,errorMessage,1000);
返回新的ResponseEntity(apiError,null,HttpStatus.BAD_请求);
}
}
@RestController
@验证
公共类最小库存控制器{
@请求映射(value=“/minimumstock”)
公共产品(
@RequestParam(value=“product.sku”,required=false)@NotEmpty(message=“product.sku不能为空”)字符串sku,
@RequestParam(value=“stock.branch.id”,required=false)字符串branchID){
返回null;
}
}

注意:
MissingServletRequestParameterException
将无法访问javax验证消息,因为它是在请求生命周期中进行约束验证之前抛出的。

是的,这是可能的。这样做:

@ExceptionHandler(MethodArgumentNotValidException.class)
公共响应处理方法无效(MethodArgumentNotValidException ex){
ServiceException=ServiceException.wrap(例如,ErrorCode.FIELD\u验证);
BindingResult=ex.getBindingResult();
for(FieldError e:results.getFieldErrors()){
exception.addLog(e.getDefaultMessage(),e.getField());
}
//在日志中记录详细信息
错误(“无效参数异常:{}”,异常.logWithDetails(),异常);
返回ResponseEntity.status(exception.getErrorCode().getHttpStatus())
.body(ArgumentsErrorResponseDTO.builder()
.code(异常.getErrorCode().getCode())
.message(异常.getMessage())
.details(exception.getProperties())
.build());
}

如果这有帮助,我在这里找到了解决此问题的方法:

必须将此方法添加到CustomResponseEntityExceptionHandler类:

 @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);
    }
@覆盖
受保护的ResponseEntity handleMethodArgumentNotValid无效(MethodArgumentNotValidException ex、HttpHeaders标头、HttpStatus状态、WebRequest请求){
列表详细信息=新建ArrayList();
对于(ObjectError错误:例如getBindingResult().getAllErrors()){
add(error.getDefaultMessage());
}
ErrorMessage error=新的ErrorMessage(new Date(),details.toString());
返回新的ResponseEntity(错误,HttpStatus.BAD_请求);
}

但是有什么方法可以让我从控制器中的
@NotEmpty
注释中获取消息吗?@Gerep我不知道你是否能做到,但我已经用一种解决方法更新了我的答案。希望这有帮助。
@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;
}
@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;
    }
}
 @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);
    }