我正在尝试在Struts2(2.3.16)中构建自定义验证器,如下所示。

package validator;

import actions.DiscountAction;
import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.ValidatorSupport;
import org.joda.time.DateTime;

public final class DiscountDateValidator extends ValidatorSupport
{
    private DateTime startDate;
    private DateTime endDate;

    //Getters and setters.

    @Override
    public void validate(Object o) throws ValidationException
    {
        System.out.println("startDate = "+startDate);
        System.out.println("endDate = "+endDate);
        System.out.println((o instanceof DiscountAction));
    }
}


validators.xml文件如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//Apache Struts//XWork Validator Config 1.0//EN"
        "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd">

<validators>
    <validator name="discountDateValidator"
               class="validator.DiscountDateValidator"/>
</validators>


并且该验证器用于以下操作。

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="struts-default")
public final class DiscountAction extends ActionSupport implements Serializable, ValidationAware, ModelDriven<Discount>
{
    @Autowired
    private final transient DiscountService discountService=null;
    private static final long serialVersionUID = 1L;

    private Discount entity=new Discount();

    @Override
    public Discount getModel() {
        return entity;
    }

    @Validations(
        customValidators={
            @CustomValidator(type="discountDateValidator", parameters={
                @ValidationParameter(name="startDate", value="${entity.discountStartDate}"),
                @ValidationParameter(name="endDate", value="${entity.discountEndDate}")},
            message="xxx zzz aaa")})
    @Action(value = "AddDiscount",
    results = {
        @Result(name=ActionSupport.SUCCESS, type="redirectAction", params={"namespace", "/admin_side", "actionName", "Discount", "currentPage", "${currentPage}", "message", "${message}", "editId", "${editId}", "status", "${status}"}),
        @Result(name = ActionSupport.INPUT, location = "Discount.jsp")},
    interceptorRefs={@InterceptorRef(value="defaultStack", params={"params.acceptParamNames", "editId, discountId, discountCode, discountPercent, discountStartDate, discountEndDate, currentPage, rowCount, totalPages, status", "validation.validateAnnotatedMethodOnly", "true"})})
    public String insert(){
        return ActionSupport.SUCCESS;
    }
}


提交表单时将调用validate()DiscountDateValidator方法,但是startDateendDate的值始终为nullo instanceof DiscountAction的计算结果为true

我在这里俯瞰什么?

最佳答案

这是因为${discountStartDate}${discountEndDate}@ValidationParameter的值属性)直接设置为验证器的字符串属性,我们需要使用Object parse(String expression, Class type)方法中的validate()方法手动对其进行解析。

通过parse()方法将此类表达式评估为OGNL表达式。这些更改后的验证器如下。

package validator;

import actions.DiscountAction;
import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.ValidatorSupport;
import org.joda.time.DateTime;

public final class DiscountDateValidator extends ValidatorSupport
{
    private String startDate; //Set to ${discountStartDate}
    private String endDate;   //Set to ${discountEndDate}

    public String getStartDate() {
        return startDate;
    }

    public void setStartDate(String startDate) {
        this.startDate = startDate;
    }

    public String getEndDate() {
        return endDate;
    }

    public void setEndDate(String endDate) {
        this.endDate = endDate;
    }

    @Override
    public void validate(Object o) throws ValidationException
    {
        DateTime discountStartDate = (DateTime)parse(startDate, DateTime.class);
        DateTime discountEndDate = (DateTime)parse(endDate, DateTime.class);

        System.out.println("startDate = "+discountStartDate);
        System.out.println("endDate = "+discountEndDate);
        System.out.println((o instanceof DiscountAction));

        //Perform validation as required using these values.
    }
}


getFieldValue("discountStartDate", o)getFieldValue("discountEndDate", o)也可以直接检索字段值(我不确定这种方法在这种验证器中的副作用)。

不需要${entity.discountStartDate}${entity.discountStartDate}(由于问题中包含entity,因此应将其排除在外)。

10-07 18:57