选择Tag with Object - Thymeleaf和Spring MVC

Joh*_*lla 7 spring spring-mvc thymeleaf

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

Type.java

public class Type { 

    private Integer id; 
    private String type; 
   ...getters and setters 
}
Run Code Online (Sandbox Code Playgroud)

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; 
    } 
Run Code Online (Sandbox Code Playgroud)

seedstartermng.html

<select th:field="*{type}">
    <option th:each="type : ${allTypes}" th:value="${type}" th:text="${type.type}">Wireframe</option>
</select>
Run Code Online (Sandbox Code Playgroud)

所以,我不能添加种子入门.

我的输出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>
Run Code Online (Sandbox Code Playgroud)

而错误是

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

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

Aym*_*bsi 14

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

为了解决这个问题,Thymeleaf使用Formatters在Object和String之间进行转换.

  • 在显示阶段(GET),Formatter Service将Object转换为String.
  • 在提交阶段(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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • print:将对象转换为字符串.
  • parse:将字符串转换为对象.

现在,我们要告诉Spring-Thymeleaf abbout我们的格式化程序,或者我们可以称之为转换器.要做到这一点,我们要在WebConfig中注册这个格式化程序(Configuration class whic extends 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

<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>
Run Code Online (Sandbox Code Playgroud)
  • th:field ="*{type}"默认应用已注册的Formatter服务.它会将类型转换为String(此处字符串将为Type Id)
  • th:value ="$ {{type}}"也将类型转换为字符串.
  • 在提交中,Spring将使用Formatter服务将Id转换回对象.

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


ger*_*tan 12

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

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

常用方法是使用id属性:

<option th:each="type : ${allTypes}" th:value="${type.id}" th:text="${type.type}">Wireframe</option>
Run Code Online (Sandbox Code Playgroud)

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