使用BeanUtils.getProperty()时出现未知属性错误

时间:2017-01-24 04:46:48

标签: java reflection spring-boot apache-commons-beanutils

这是我的班级。

@DateRange.List({
        @DateRange(start = "startDate", end = "endDate", message = "Start date should be earlier than end date.")
})
public class MyClass {
    @NotNull
    @Pattern(regexp = DateConstants.DATE_FORMAT_REGEX, message = "Invalid date format.")
    public String startDate;

    @NotNull
    @Pattern(regexp = DateConstants.DATE_FORMAT_REGEX, message = "Invalid date format.")
    public String endDate;
}

我添加了@DateRange注释,声明如下。

@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = DateRangeValidator.class)
@Documented
public @interface DateRange {
    String message() default "{constraints.daterange}";

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

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

    String start();

    String end();

    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        DateRange[] value();
    }
}

验证器类是

public class DateRangeValidator implements ConstraintValidator<DateRange, Object> {
    private String startDateFieldName;
    private String endDateFieldName;

    @Override
    public void initialize(final DateRange constraintAnnotation) {
        startDateFieldName = constraintAnnotation.start();
        endDateFieldName = constraintAnnotation.end();
    }

    @Override
    public boolean isValid(final Object value, final ConstraintValidatorContext context) {

        final String startDate = (String) BeanUtils.getProperty(value, startDateFieldName);
        final String endDate = (String) BeanUtils.getProperty(value, endDateFieldName);

        return isValidDateRange(startDate, endDate);
    }

    private boolean isValidDateRange(String start, String end) {
        DateFormat dateFormat = new SimpleDateFormat(DateConstants.DATE_FORMAT);
        try {
            Date startDate = dateFormat.parse(start);
            Date endDate = dateFormat.parse(end);

            if (startDate.before(endDate)) return true;
        } catch (ParseException e) {}

        return false;
    }
}

验证器检查开始日期是否在结束日期之前。

在执行此操作时,BeanUtils.getProperty()会将java.lang.NoSuchMethodExceptionUnknown property 'startDate'一起投掷。

java.lang.NoSuchMethodException: Unknown property 'startDate' on class 'class mypackage.domain.rest.MyClass'
    at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1322)
    at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:770)
    at org.apache.commons.beanutils.BeanUtilsBean.getNestedProperty(BeanUtilsBean.java:715)
    at org.apache.commons.beanutils.BeanUtilsBean.getProperty(BeanUtilsBean.java:741)
    at org.apache.commons.beanutils.BeanUtils.getProperty(BeanUtils.java:382)
    at bd.com.ipay.offer.validation.imp.DateRangeValidator.isValid(DateRangeValidator.java:36)
    at org.hibernate.validator.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:278)
    at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:153)
    at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:117)
    at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:84)
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:452)
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:397)
    at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:361)
    at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:313)
    at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:139)
    at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:108)
    at org.springframework.validation.DataBinder.validate(DataBinder.java:866)
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.validateIfApplicable(AbstractMessageConverterMethodArgumentResolver.java:268)
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:130)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)

startDate中有MyClass。该变量是公共的,并命名为camel case。为什么会出现问题?任何的想法?

1 个答案:

答案 0 :(得分:1)

我找到了解决方案。我只需要编写MyClass的getter。似乎找不到该属性,因为没有getter函数。

所以最后的MyClass看起来像。

@DateRange.List({
        @DateRange(start = "startDate", end = "endDate", message = "Start date should be earlier than end date.")
})
public class MyClass {
    @NotNull
    @Pattern(regexp = DateConstants.DATE_FORMAT_REGEX, message = "Invalid date format.")
    public String startDate;

    @NotNull
    @Pattern(regexp = DateConstants.DATE_FORMAT_REGEX, message = "Invalid date format.")
    public String endDate;

    public String getStartDate() {
        return startDate;
    }

    public String getEndDate() {
        return endDate;
    }
}