选择Tag with Object - Thymeleaf和Spring MVC

时间:2014-08-11 00:33:59

标签: spring spring-mvc thymeleaf

我试图更改此示例thymeleafexamples-stsm的代码,因此我更改了类类型的枚举类型:

Type.java

public class Type { 

    private Integer id; 
    private String type; 
   ...getters and setters 
}

SeedStarterMngController.java

@ModelAttribute("allTypes") 
    public List<Type> populateTypes() { 
        Type type1 = new Type(); 
        type1.setId(1); 
        type1.setType("OUTDOOR"); 

        Type type2 = new Type(); 
        type2.setId(2); 
        type2.setType("INDOOR"); 

        List<Type> tipos = new ArrayList<Type>(); 
        tipos.add(type1); 
        tipos.add(type2); 
        return tipos; 
    } 

seedstartermng.html

<select th:field="*{type}">
    <option th:each="type : ${allTypes}" th:value="${type}" th:text="${type.type}">Wireframe</option>
</select>

所以,我不能添加Seed Starter。

我的输出html是

<select id="type" name="type">
    <option value="thymeleafexamples.stsm.business.entities.Type@2c08cec0">OUTDOOR</option>
    <option value="thymeleafexamples.stsm.business.entities.Type@26cf024">INDOOR</option>
</select>

,错误是

  

无法将java.lang.String类型的属性值转换为必需值   输入属性类型的thymeleafexamples.stsm.business.entities.Type;   嵌套异常是java.lang.IllegalStateException:无法转换   类型[java.lang.String]的值为必需的类型   [thymeleafexamples.stsm.business.entities.Type]属性类型:否   找到匹配的编辑器或转换策略

如何映射到正确键入?我希望你能帮助我。谢谢。

2 个答案:

答案 0 :(得分:13)

我知道这个问题已经过时了,但是答案可能对某些人有帮助,因为我无法轻易找到它。

要解决此问题,Thymeleaf使用Formatters在Object和String之间进行转换。

  • 在显示阶段(GET),Formatter Service将Object转换为 串。
  • 在提交阶段(POST),Formatter Service将转换String 回到

    对象。

首先为要在标记中使用的Class实现Formatter服务:

@Service
public class TypeFormatter implements Formatter<Type> {

    @Autowired
    TypeService typeService;//Service -> DB

    @Override
    public String print(Type object, Locale locale) {
        return (object != null ? object.getId().toString() : "");
    }

    @Override
    public Type parse(String text, Locale locale) throws ParseException {
        Integer id = Integer.valueOf(text);
        return this.typeService.get(id);//return Type object form DB
    }
}

这是一个非常简单的类,有两种方法:

  • 打印:将对象转换为字符串。
  • 解析:将字符串转换为对象。

现在,我们要告诉Spring-Thymeleaf abbout我们的格式化程序,或者我们可以称之为转换器。为此,我们在WebConfig中注册了这个格式化程序(Configuration class,它扩展了WebMvcConfigurerAdapter):

@Configuration
@EnableWebMvc
@ComponentScan(value = { "your package" })
public class WebConfig extends WebMvcConfigurerAdapter {

....
    //Formatters

    @Autowired //Without autowire, this solution may not work
    private TypeFormatter typeFormatter;

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(typeFormatter);
    }
}

现在我们的解决方案已准备好在html文件中实现,但如何告诉Thymeleaf应用转换? 答案是使用 th:field =&#34; * {type}&#34; 属性并使用双括号语法 th:value =&#34; $ {{type} }&#34;

<select th:field="*{type}">
    <option th:value="NULL" th:text="---Select Type---"></option>
    <option th:each="type : ${allTypes}" th:value="${{type}}" th:text="${type.type}">Wireframe</option>
</select>
  • th:field =&#34; * {type}&#34; 默认情况下正在应用已注册的Formatter服务。它会将type转换为String(此处字符串将为Type Id)
  • th:value =&#34; $ {{type}}&#34; 也将类型转换为字符串。
  • 在提交时,Spring将使用Formatter服务将Id转换回来 反对。

最后要说的是,有时我们想在下拉列表中添加一个标题,例如&#34; -----选择类型-----&#34;为了防止默认选择以及向用户解释。在这种情况下,您必须设置 th:value =&#34; NULL&#34; ,除非您收到转换错误。

答案 1 :(得分:12)

该错误消息基本上表示Spring不知道如何将字符串thymeleafexamples.stsm.business.entities.Type@2c08cec0转换为Type的实例。这是您的代码中的错误,因为尝试这样做没有任何意义。

您不应该使用Object的toString()值作为表单下拉标识符。您需要(代码)更好的策略来识别用户选择的类型。

常用方法是使用id属性:

<option th:each="type : ${allTypes}" th:value="${type.id}" th:text="${type.type}">Wireframe</option>

提交表单后,您需要根据控制器上的ID名称退出Type的实例