为什么我得到IllegalArgumentException在Spring中无法将String类型的值转换为必需的类型Product?

时间:2010-12-06 16:48:55

标签: spring spring-mvc illegalargumentexception

我收到例外

  

无法转换属性值   输入必需的[java.lang.String]   输入属性的[beans.Product]   产品;嵌套异常是   java.lang.IllegalArgumentException异常:   无法转换类型的值   [java.lang.String]到必需的类型   [beans.Product]属性产品:   没有匹配的编辑器或转换   战略发现

甚至在我的DetailProductValidator开始通过validate方法验证之前,错误错误对象中的

我不明白为什么Spring这样做。我没有任何直接映射到产品属性/对象的输入字段。我只是在jsp中使用product对象的属性。例如,我使用:

<form:options items="${dpBackObj.product.colorMap}"/>
<!-- or -->
${dpBackObj.product.priceInDollars}

但我从不使用:

<form:input path="product"/>

任何人都可以解释为什么会这样吗?也许告诉我一个简单的解决方案?

控制器的bean配置是:

    <!-- DETAIL PRODUCT FORM CONTROLLER -->
<bean id="productDetailFormController" name="/detail.htm /addToCart.htm" 
        class="detailProduct.DetailProductFormController">
    <property name="sessionForm" value="true" />
    <property name="commandName" value="dpBackObj" />
    <property name="commandClass" value="detailProduct.DetailProductBackingObject" />
    <property name="validator">
        <bean class="detailProduct.DetailProductValidator" />
    </property>
    <property name="formView" value="detail" />
    <property name="successView" value="redirect:/viewCart.htm" />
    <property name="cartService" ref="cartServiceImpl"/>
</bean>

DetailProductFormController的后备对象是:

public class DetailProductBackingObject {
    private String quantityOverflowError;
    private Product product;
    private int quantity;
    private ShoppingCart shoppingCart;
    private long sizeId;
    private long colorId;
    public DetailProductBackingObject() {
        this.product = new Product();
        this.sizeId = -1;
        this.colorId = -1;
    }
    //getters and setters
}

如果您需要其他信息,我会提供。我使用的是Spring 2.5.5。

亲切的问候,

EDIT1 由于来自axtavt 的请求):

<form:form method="post" commandName="dpBackObj">
<table width="730" border="0" cellspacing="0" cellpadding="0">
    <c:if test="${!empty dpBackObj.quantityOverflowError}">
        <tr>
            <td>
                <c:out value="${dpBackObj.quantityOverflowError}"/>
            </td>
        </tr>
    </c:if>
    <spring:bind path="dpBackObj.*">
        <c:if test="${not empty status.errorMessages}">
            <div class="val-summary text-error" id="errorDivId">
                <div style="" class="val-summary text-error" id="errorDivId">
                    <fmt:message key="detail.error.header"/>
                    <ul>
                        <c:forEach items="${status.errorMessages}" var="error">
                            <li><c:out value="${error}"/></li>
                        </c:forEach>
                    </ul>
                </div>
            </div>
        </c:if>
    </spring:bind>
    <tr>
        <td width="310" align="left" valign="top">
            <img src="${imagesPath}/${dpBackObj.product.largeImageUrl}" alt="${dpBackObj.product.description}" />
        </td>
        <td width="420" align="left" valign="top">
            <div id="tls_detPName">
                <c:out value="${dpBackObj.product.name}"></c:out>
            </div>
            <div >  
                <strong class="numeric">${dpBackObj.product.priceInDollars}</strong>
            </div>
            <div id="tls_detPDescLong">
                ${dpBackObj.product.largeDescription}
                <br />
            </div>
            <div >
                <table cellpadding="2" border="0">
                    <tr>
                        <td align="right">
                            <label for="p_sizes" class="label"><fmt:message key="viewCart.Size"/></label>
                        </td>
                        <td>
                            <form:select path="sizeId" > 
                                <form:option  value="-1" label="x"/> 
                                <form:options items="${dpBackObj.product.sizeMap}"/>
                            </form:select>
                        </td>
                    </tr>
                    <tr>
                        <td align="right">
                            <label for="p_colors" class="label"><fmt:message key="viewCart.Color"/></label>
                        </td>
                        <td>
                            <form:select path="colorId" > 
                                <form:option value="-1" label="y"/> 
                                <form:options items="${dpBackObj.product.colorMap}"/>
                            </form:select>
                        </td>
                    </tr>
                </table>
            </div>
            <div id="tls_addToCart">
                <div >
                    <label for="quantityId" class="label"><fmt:message key="viewCart.Quantity"/>:</label>
                    <form:input path="quantity" onkeypress="return checkForNumber(this, event)" maxlength="10" size="3" id="quantityId" cssClass="textbox-center"/>
                    <input type="image" name="addToCartButtonName" src="${imagesPath}/addToCartBtn.jpg" /> 
                </div>
            </div>
        </td>
    </tr>
</table>
</form:form>

EDIT2 由于JacobM的请求): 这是我的验证员:

public class DetailProductValidator implements Validator {
    public boolean supports(Class clazz) {
        return DetailProductBackingObject.class.equals(clazz);
    }

    public void validate(Object obj, Errors errors) {
        DetailProductBackingObject detailProductBackingObject = (DetailProductBackingObject) obj;
        if (detailProductBackingObject.getSizeId() == -1) {
            errors.rejectValue("sizeId", "error.detail.jsp.choose.size", null, "Input size.");
        }
    }
}

当我到达 DetailProductBackingObject detailProductBackingObject = 行时,我已经有错误了。
将请求参数转换为支持对象属性发生在http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/mvc/BaseCommandController.html中。这就是Spring关于转换的说法:

  

使用请求参数填充   和PropertyEditors:收到一个   请求,任何BaseCommandController   将尝试填写命令   使用请求参数的对象。   这是使用典型和   众所周知的JavaBeans属性   符号。当一个请求参数   命名'firstName'存在,   框架将尝试调用   setFirstName([value])传递   参数的值。嵌套   当然支持属性。   例如,一个名为的参数   'address.city'将导致a   getAddress()。setCity([value])调用   命令类。

     

认识到自己很重要   不限于String中的String参数   你的JavaBeans。使用   PropertyEditor-notion由提供者提供   java.beans包,你会的   能够将字符串转换为对象   而另一种方式。例如   setLocale(Locale loc)非常完美   可能是名为的请求参数   具有en值的语言环境   当你注册合适的   控制器中的PropertyEditor(参见   initBinder()获取更多信息   那件事。

     

验证器:控制器完成后   成功填充了该命令   带有参数的对象   请求,它将使用任何配置   验证对象的验证器。   验证结果将放入   可用于的错误对象   查看以呈现任何输入问题。

1 个答案:

答案 0 :(得分:4)

由于我无法看到表单有任何问题,我可以想象的唯一可能的原因是您在表单页面的URL中有一个名为product的参数。

如果是这样,您可以更改网址或使用DataBinder.setDisallowedFields()禁用尝试绑定该参数。