通过自定义约束将实体验证为参数

时间:2017-03-06 11:49:18

标签: java spring validation annotations

使用Spring Boot,我已经创建了一个示例应用程序。

package hello;

import org.springframework.web.bind.annotation.RestController;

import constraint.CheckHelloId;
import dto.HelloDto;

import javax.validation.Valid;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RestController
public class HelloController {

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String index(@RequestBody @Valid final HelloDto hello) {
        hello.setId(null);
        validateFromMethodHeader(hello);
        return "Greetings from Spring Boot!";
    }

    private void validateFromMethodHeader(@CheckHelloId final HelloDto helloDto) {
        System.out.println("Validating DTO...");
    }

}

我试图在私有方法中向DTO HelloDto添加自定义约束,以检查id字段是否为空。

界面:

package constraint;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ FIELD, ANNOTATION_TYPE, TYPE, METHOD, PARAMETER })
@Retention(RUNTIME)
@Constraint(validatedBy = CheckHelloIdValidator.class)
@Documented
public @interface CheckHelloId {

    String message() default "";

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

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

}

验证员:

package constraint;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.constraintvalidation.SupportedValidationTarget;
import javax.validation.constraintvalidation.ValidationTarget;

import org.apache.commons.lang3.StringUtils;

import dto.HelloDto;

@SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class CheckHelloIdValidator implements ConstraintValidator<CheckHelloId, HelloDto> {

    private static final String ID_VALIDATION_ERROR = "Null or blank ID.";

    @Override
    public void initialize(CheckHelloId arg0) {
    }

    @Override
    public boolean isValid(HelloDto helloDto, ConstraintValidatorContext context) {
        if (StringUtils.isBlank(helloDto.getId())){
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(ID_VALIDATION_ERROR).addConstraintViolation();
            return false;
        }
        return true;
    }

}

DTO:

package dto;

import java.io.Serializable;

public class HelloDto implements Serializable {

    private static final long serialVersionUID = 8792903048191496378L;

    private String id;

    private String message;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

如在控制器的私有方法中所见,我试图在参数级别应用DTO的验证(我知道我可以通过实体验证在索引处执行它,但我想测试这个具体的例子,这就是我在控制器上将id字段设置为null的原因。

当我运行应用程序并执行调用时,即使id字段为null,约束也不适用于private方法。有人可以对此有所了解吗?提前谢谢。

1 个答案:

答案 0 :(得分:1)

要在带注释的方法参数@RequestBody @Valid final HelloDto hello旁边的rest控制器上验证消耗json,您必须使用特殊约束来注释json数据类的字段。对于你的情况,它足以使用休眠验证约束@NotNull@NotEmpty

package dto;

import java.io.Serializable;

public class HelloDto implements Serializable {

    private static final long serialVersionUID = 8792903048191496378L;

    @NotEmpty
    private String id;