自定义时间验证注解,为啥作用于controller上的方法上无效

来源:8-16 实战:自定义手机号验证

troylc

2019-12-19

老师你好:

我将自定义时间验证注解,作用于controller上的方法上,结果发现它并没有执行时间的校验直接进入了方法体,这个有啥说道 ?

以下是我controller中的方法:
图片描述
自定义的时间校验注解:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE_USE;
import com.xxxxxx.annotation.impl.DateTimeFormatValidator;

@Documented
// 注解的作用目标
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
// 注解的保留策略
@Retention(RetentionPolicy.RUNTIME)
// 不同之处:于约束注解关联的验证器
@Constraint(validatedBy = DateTimeFormatValidator.class)
public @interface ApiDateTimeFormat {

    // 约束注解验证时的输出信息
    String message() default "时间不能为空或格式错误";

    String format() default "yyyy-MM-dd";

    // 约束注解在验证时所属的组别
    Class<?>[] groups() default {};

    // 约束注解的有效负载
    Class<? extends Payload>[] payload() default {};
}

注解验证解析DateTimeFormatValidator类:

import com.xxxxxx.annotation.ApiDateTimeFormat;
import org.apache.commons.lang3.StringUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.text.SimpleDateFormat;

public class DateTimeFormatValidator implements ConstraintValidator<ApiDateTimeFormat, String> {

    private ApiDateTimeFormat apiDateTimeFormat;
    @Override
    public void initialize(ApiDateTimeFormat apiDateTimeFormat) {
        this.apiDateTimeFormat = apiDateTimeFormat;
    }
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 如果 value 为空则不进行格式验证,为空验证可以使用 @NotBlank @NotNull @NotEmpty 等注解来进行控制,职责分离
        if (StringUtils.isBlank(value)) {
            return false;
        }
        String format = apiDateTimeFormat.format();

        if (value.length() != format.length()) {
            return false;
        }

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);

        try {
            simpleDateFormat.parse(value);
        } catch (Exception e) {
            return false;
        }
        return true;
    }
}

但是我把这个@ApiDateTimeFormat,作用在我的一个实体类的时间属性上,验证是生效的。

public class DataSyncProDto implements Serializable {

    .......

    /**
     * 开始时间
     */
    @ApiDateTimeFormat(groups = {StartEndTimeValidView.class}, format = "yyyy-MM-dd", message = "开始时间,格式错误,正确格式为:yyyy-MM-dd")
    private String startTime;

    /**
     * 结束时间
     */
    @ApiDateTimeFormat(groups = {StartEndTimeValidView.class}, format = "yyyy-MM-dd", message = "结束时间,格式错误,正确格式为:yyyy-MM-dd")
    private String endTime;

    ......
}

作用的controller方法为:

 @PostMapping(value = "/execFinancePro", produces = "application/json;charset=UTF-8")
    public ResultMsg<String> executorFinanceProJobData(@Validated({DataSyncProDto.DateTimeValidView.class})
                                                       @RequestBody DataSyncProDto dataSyncProDto,
                                                       BindingResult bindingResult) throws Exception {
        ResultMsg<String> errorMsg = validatedErrorMsgStr(bindingResult);
        if (errorMsg == null && dataSyncProDto != null) {
            //省略逻辑
            ......
        }
        return errorMsg;
    }
写回答

1回答

张小喜

2019-12-19

对基础类型字段的验证,要在controller类上添加@Validated注解才能启动参数校验。对于对象的验证不用这样。建议参数超过两个就封装城对象做参数。

1
5
张小喜
回复
慕码人1018289
欢迎随时交流
2020-03-27
共5条回复

Java高效编程技巧实践 告别996

可以改变的编程效率

1451 学习 · 326 问题

查看课程