选择带有对象的标签 - Thymeleaf 和 Spring MVC
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25234357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Select Tag with Object - Thymeleaf and Spring MVC
提问by JohnPortella
I'm trying to change the code of this example thymeleafexamples-stsm, so I changed enum type for class type:
我正在尝试更改此示例thymeleafexamples-stsm的代码,因此我更改了类类型的枚举类型:
Type.java
类型.java
public class Type {
private Integer id;
private String type;
...getters and setters
}
SeedStarterMngController.java
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
种子启动器.html
<select th:field="*{type}">
<option th:each="type : ${allTypes}" th:value="${type}" th:text="${type.type}">Wireframe</option>
</select>
So, I can't Add Seed Starter.
所以,我不能添加种子启动器。
My Output html is
我的输出 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>
and the error is
错误是
Failed to convert property value of type java.lang.String to required type thymeleafexamples.stsm.business.entities.Type for property type; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [thymeleafexamples.stsm.business.entities.Type] for property type: no matching editors or conversion strategy found
无法将 java.lang.String 类型的属性值转换为属性类型所需的类型 thymeleafexamples.stsm.business.entities.Type;嵌套异常是 java.lang.IllegalStateException:无法将类型 [java.lang.String] 的值转换为属性类型所需的类型 [thymeleafexamples.stsm.business.entities.Type]:找不到匹配的编辑器或转换策略
How I can do to be mapped to type correctly? I hope you can help me. Thank you.
我该怎么做才能正确映射到类型?我希望你能帮助我。谢谢你。
回答by Ayman Al-Absi
I know this question is old but below answer may help someone as I could not find it easily.
我知道这个问题很老,但下面的答案可能对某人有所帮助,因为我找不到它。
To solve this issue, Thymeleaf uses Formatters to convert between Object and String.
为了解决这个问题,Thymeleaf 使用 Formatters 在 Object 和 String 之间进行转换。
- In display phase (GET), Formatter Service will convert Object to String.
In submitting phase (POST), Formatter Service will convert String back to
object.
- 在显示阶段(GET),Formatter Service 会将 Object 转换为 String。
在提交阶段 (POST),Formatter Service 会将 String 转换回
目的。
First implement Formatter service for your Class to be used in tag:
首先为要在标签中使用的 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
}
}
It is very simple class with two methods:
这是一个非常简单的类,有两种方法:
- print: converts object to string.
- parse: converts string to object.
- 打印:将对象转换为字符串。
- parse: 将字符串转换为对象。
Now, we've to tell Spring-Thymeleaf abbout our formatter or we may call it converter. To do that we've to register this formatter in our WebConfig (Configuration class whic extends WebMvcConfigurerAdapter):
现在,我们必须告诉 Spring-Thymeleaf 关于我们的格式化程序,或者我们可以称之为转换器。为此,我们必须在我们的 WebConfig(扩展 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);
}
}
Now our solution is ready to be implemented in html file but how to tell Thymeleaf to apply conversion? Answer is by using th:field="*{type}"attribute and using Double-bracket syntax th:value="${{type}}":
现在我们的解决方案已准备好在 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>
- th:field="*{type}"is applying registered Formatter service by default. It will convert type to String (here the string will be Type Id)
- th:value="${{type}}"is converting type to string as well.
- In submit, Spring will use the Formatter service to convert Id back to object.
- th:field="*{type}"默认应用注册的 Formatter 服务。它将类型转换为字符串(这里的字符串将是类型 ID)
- th:value="${{type}}"也将类型转换为字符串。
- 在提交时,Spring 将使用 Formatter 服务将 Id 转换回对象。
Last thing to tell, sometimes we want to add a header to the dropdown list like "-----Select Type-----" in order to prevent default selection as well as explain to user. In this case you must set th:value="NULL"unless you'll get conversion error.
最后要说的是,有时我们想在下拉列表中添加一个标题,例如“-----选择类型-----”,以防止默认选择以及向用户解释。在这种情况下,您必须设置th:value="NULL"除非您会收到转换错误。
回答by gerrytan
That error message basically says Spring don't know how to convert the string thymeleafexamples.stsm.business.entities.Type@2c08cec0into an instance of Type. This is a bug on your code because it doesn't make any sense trying to do so.
该错误消息基本上是说 Spring 不知道如何将字符串thymeleafexamples.stsm.business.entities.Type@2c08cec0转换为 Type 的实例。这是您代码中的一个错误,因为尝试这样做没有任何意义。
You're not supposed to use the toString()value of Object as a form dropdown identifier. You need to have a (much) better strategy for the code to identify the Type selected by user.
您不应该使用toString()Object的值作为表单下拉标识符。您需要有一个(更好)的代码策略来识别用户选择的类型。
Common approach is to use the idattribute:
常用的方法是使用id属性:
<option th:each="type : ${allTypes}" th:value="${type.id}" th:text="${type.type}">Wireframe</option>
When the form is submitted, you then need to retireve an instance of Type based on its id name on your controller
提交表单后,您需要根据控制器上的 id 名称停用 Type 的实例

