【问题标题】:Spring MVC forms - model with reference to objectSpring MVC 表单 - 参考对象的模型
【发布时间】:2014-12-22 17:01:10
【问题描述】:

我创建了一个表单,其中包含 2 个字段(产品名称和价格)和类别对象的下拉列表(产品类别)。 当我在 Product 对象中设置一个 Category 对象时,我不知道如何进行这项工作。

产品:

public class Product {
    private String name;
    private Category category;
    private int price;

    public Product() {
    }

    public Product(String name, Category category, int price) {
        this.name = name;
        this.category = category;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

}

产品控制器:

    @ModelAttribute("categoryList")
    public List<Category> categoryList() {
          return categoryService.getCategories();
    }

    @RequestMapping("/products/add")
    public ModelAndView addProductForm() {
        ModelAndView mv = new ModelAndView("addProduct");

        mv.addObject("product", new Product());
        return mv;
    }
    @RequestMapping(value = "/products/add/process", method = RequestMethod.POST)
    public ModelAndView addProduct(@ModelAttribute("product") Product product) {
        ModelAndView mv = new ModelAndView("products");
        System.out.println("added " + product.getName() + " " + product.getPrice());
        return mv;
    }

形式:

<form class="form-horizontal" action="#"
        th:action="@{/products/add/process}" th:object="${product}"
        method="post">
        <fieldset>

            <!-- Form Name -->
            <legend>Add product</legend>

            <!-- Text input-->
            <div class="form-group">
                <label class="col-md-4 control-label" for="textinput">Product
                    name</label>
                <div class="col-md-4">
                    <input id="textinput" name="textinput" placeholder="Product name"
                        class="form-control input-md" required="" type="text"
                        th:field="*{name}"></input>
                </div>
            </div>

            <!-- Select Basic -->
            <div class="form-group">
                <label class="col-md-4 control-label" for="selectbasic">Category</label>
                <div class="col-md-4">
                    <select th:field="*{category}">
                        <option th:each="cat : ${categoryList}" th:value="${cat.getId()}"
                            th:text="${cat.getName()}"></option>
                    </select>
                </div>
            </div>

            <!-- Text input-->
            <div class="form-group">
                <label class="col-md-4 control-label" for="textinput">Price</label>
                <div class="col-md-4">
                    <input id="textinput" name="textinput" placeholder=""
                        class="form-control input-md" required="" type="text"
                        th:field="*{price}"></input>
                </div>
            </div>

            <!-- Button -->
            <div class="form-group">
                <label class="col-md-4 control-label" for="singlebutton"></label>
                <div class="col-md-4">
                    <button id="singlebutton" name="singlebutton"
                        class="btn btn-success">Add product</button>
                </div>
            </div>
        </fieldset>
    </form>

来自 cmets 的其他信息
当我提交它时(参见 addProduct 方法 - 它是一个表单处理程序),我得到:java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.example.shop.Category] for property 'category': no matching editors or conversion strategy found]。我根本无法将来自下拉列表的字符串转换为对象

【问题讨论】:

  • 所以我正确理解了这个问题:类别下拉列表为空,因为您从未设置它。如何获取填充的值并返回到表单?
  • @Ascalonian 我在下拉列表中显示它们,我使用 ModelAttribute 注释将它们作为列表传递(我使用 categoryService 获取它)。
  • 那么我不明白“如何使这项工作”是什么意思,因为你说下拉显示值。您能否更详细地描述您要完成的工作?
  • @Ascalonian 当我提交表单时出现问题。尽管下拉菜单完美无缺,但我无法处理。当我提交它时(请参阅 addProduct 方法 - 它是一个表单处理程序)我得到:“java.lang.IllegalStateException:无法将类型 [java.lang.String] 的值转换为所需的类型 [com.example.shop.Category] ​​属性'category': no matching editors or conversion strategy found] "我根本无法将来自下拉列表的字符串转换为对象。
  • 我看不到您在addProduct 的哪个位置调用getCategory,因此错误消息有点令人困惑。您能否将错误消息和信息放在您的问题中,以便向其他人提供更多信息?

标签: java spring forms spring-mvc spring-form


【解决方案1】:

问题是 Spring 没有内置的从 StringCategory 的转换能力。它知道它需要一个Category 才能使用ProductsetCategory(Category category) 方法,但是无法将它从您发布的下拉列表中获得的String 转换为一个。因此,您需要成为一个亲爱的并通过告诉它如何进行转换和定义转换器来帮助 Spring 一些,请参阅Spring docs 了解更多信息。

最简单的选择是使用 Converter SPI:

package com.example.shop.converter;

final class StringToCategoryConverter implements Converter<String, Category> {
  public Category convert(String source) {
    Category category;

    // Put your conversion logic here

    return category;
  }
}

在你的情况下,我猜你会想要使用:CategoryService.getCategory(int id) 或类似的方法。

然后你需要配置 Spring 以实际使用你的转换器,这里有一个 XML 示例说明如何做到这一点:

<mvc:annotation-driven conversion-service="conversionService" />

<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="com.example.shop.converter.StringToCategoryConverter" />
        </list>
    </property>
</bean>

【讨论】:

  • 非常感谢!你是对的 - 我添加了一个转换器:)。更重要的是 - 如果您启用了“注释驱动”,您还需要以这种方式注册您的转换器:
  • 好点,编辑后的答案包含在以后来这里的任何人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-10
  • 1970-01-01
  • 2019-01-07
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多