带有自定义http错误响应的自定义constraintvalidator消息

qvk1mo1f  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(524)

我正在为裁剪而努力 javax.validation.ConstraintValidator 以及 javax.validation.ConstraintValidatorContext 满足我的需要。我从格式不正确的请求主体收到的响应消息始终采用以下形状: <controller method name>.<input parameter>: <default message>, <controller method name>.<input parameter>: <specific validation message> 此消息也以500而不是400错误请求的形式返回。我无法找到一个可行的解决方案来执行以下操作:
只包括 <specific validation message> ,即排除方法+输入名称
排除默认消息
始终将500更改为400,或者可能允许自定义错误响应
我有以下代码:

控制器

import org.path.validation.ValidCreateThingRequest;
import org.path.service.ThingService;
// ... various other imports

  @PostMapping("/things")
  @ApiOperation(value = "Create a new thing")
  @ApiResponse(code = 201, message = "Newly created thing", response = Thing.class)
  @ResponseStatus(HttpStatus.CREATED)
  public ThingResponseProto createThing(
      @RequestBody @ValidCreateThingRequest final CreateThingRequestProto thingDto,
      final HttpServletRequest httpServletRequest) {
    final Context context = new RequestContext(httpServletRequest);
    final Thing createdThing = thingService.createThing(thingDto);
    return mapObjToProtoUtils.map(createdThing, ThingResponseProto.class);
  }

创建验证接口的接口

@Constraint(validatedBy = CreateThingRequestValidator.class)
@Target({ METHOD,PARAMETER })
@Retention(RUNTIME)
@Documented
public @interface ValidCreateThingRequest {
    String message() default "Request must be well-formed.";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

接口中使用的验证程序

public class CreateCodeRequestValidator
    implements ConstraintValidator<ValidCreateThingRequest, CreateThingRequestProto> {

  private static final Pattern FORBIDDEN_NAME_CHARACTERS_REGEX =
      Pattern.compile("[\\\\/\\t\\n\\r\\f?;]");

  @Override
  public void initialize(ValidCreateCodeRequest constraintAnnotation) {};

  @Override
  public boolean isValid(final CreateThingRequestProto thingDto, ConstraintValidatorContext context) {
    return isValidCharacters(thingDto, context)
        && isValidNameExists(thingDto, context)
  }

  boolean isValidCharacters(final CreateThingRequestProto thingDto, ConstraintValidatorContext context) {
    final String name = thingDto.getName();

    if (FORBIDDEN_NAME_CHARACTERS_REGEX.matcher(name).find()) {
      context
          .buildConstraintViolationWithTemplate("Name must not contain forbidden characters.")
          .addConstraintViolation();
      return false;
    } else {
      return true;
    }
  }

  boolean isValidNameExists(final CreateThingRequestProto thingDto, ConstraintValidatorContext context) {
    final String name = thingDto.getName();

    if (name != null && !name.trim().isEmpty()) {
      context
          .buildConstraintViolationWithTemplate("Name must not be null or empty.")
          .addConstraintViolation();
      return false;
    } else {
      return true;
    }
  }
}

向上述代码发送格式错误的有效负载将导致如下消息:

{
  error: "Internal Server Error",
  message: "createThing.thingDto: Request must be well-formed., createThing.thingDto: Name must not be null or empty.",
  path: "/things"
  status: 500
  timestamp: 1607110364124
}

我希望能收到这个:

{
  error: "Bad Request",
  message: "Name must not be null or empty.",
  path: "/things"
  status: 400
  timestamp: 1607110364124
}

这可能是因为 buildConstraintViolationWithTemplate() ??

h4cxqtbf

h4cxqtbf1#

也许你可以使用@controlleradvice注解

@ControllerAdvice
public class ConstraintValidatorExceptionHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public void handleConstraintViolationException(ConstraintViolationException exception,
            ServletWebRequest webRequest) throws IOException {
        webRequest.getResponse().sendError(HttpStatus.BAD_REQUEST.value(), exception.getMessage());
    }
}

相关问题