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

当我的请求出现问题时,我需要有自己的错误响应正文,并且我正在尝试使用约束消息属性来返回错误消息,@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);
    }
}

这样,我可以在出现验证错误时返回自己的响应正文。CustomResponseEntityExceptionHandler

我现在尝试的是从验证约束中获取消息。

这是我的控制器,带有约束: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 不能为空,并在我的错误响应中显示它。

我还检查了该类,并且有返回默认消息的方法。MissingServletRequestParameterExceptiongetMessage


答案 1

是的,它是可行的,春天很好地支持它。您只是缺少一些配置以在春季启用它。

  • 使用弹簧注释使弹簧能够验证控制器@Validated
  • 中的句柄以捕获所有失败的验证消息。ConstraintViolationExceptionControllerAdvice
  • 标记 ,这样它就不会抛出 MissingServletRequestParameterException,而是进入约束验证的下一步。required=false@RequestParam
@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 验证消息,因为它是在请求生命周期中发生约束验证之前引发的。


答案 2

如果这可以提供帮助,我在这里找到了这个问题的解决方案:https://howtodoinjava.com/spring-boot2/spring-rest-request-validation/

您必须将此方法添加到 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);
    }

推荐