请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

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

老师你好:

我将自定义时间验证注解,作用于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回答

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

1 回复 有任何疑惑可以回复我~
  • 提问者 troylc #1
    收到,多谢,果然是这样
    回复 有任何疑惑可以回复我~ 2019-12-20 15:12:01
  • 老师,我正好有个相关的疑问。我看了验证相关的课程,发现验证都是一个属性自身的验证,如果像这个同学里的例子,我要验证开始时间startTime必须早于结束时间endTime,Java Bean验证有办法做到吗?
    回复 有任何疑惑可以回复我~ 2020-03-27 15:55:51
  • 这个需求验证框架是实现不了的。他能做的只是对单独属性的校验,对于多个属性间关系的校验做不到。如果这种情况很多,可以考虑使用AOP来自己实现一个比较通用的。如果用的地方不太多,可以直接写到控制层,编码写死校验逻辑。
    回复 有任何疑惑可以回复我~ 2020-03-27 16:07:00
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信