我无法将弹簧形式值绑定到支持对象。 以下是代码的相关部分。
这是来自page.jsp
<form:form method="post" commandName="building" action="addBuilding">
<div>
<div>
<form:label path="buildingName">Building Name:</form:label>
<form:input path="buildingName" />
<form:errors path="buildingName"></form:errors>
</div>
<div>
<form:label path="buildingType">Building Type:</form:label>
<form:select path="buildingType">
<form:option value="none">--Select One--</form:option>
<form:options items="${buildingTypeList}" itemValue="id" itemLabel="typeName"/>
</form:select>
<form:errors path="buildingType"></form:errors>
</div>
</div>
</form:form>
我想绑定的模型类如下。为了完整起见,我添加了这些
@Entity
@Table(name="tablename")
class Building {
@Column
private buildingName;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "buildingType", referencedColumnName = "id", nullable = false)
private BuildingType buildingType;
//other fields, getters and setters etc.
}
@Entity
@Table(name="tablename")
class BuildingType {
@Id
@Column
private int id;
@Column
private String typeName;
//getters, setters
}
此时我可以在组合框中看到建筑类型名称(在GET请求中)。发布表单时会出现问题。来自组合框的Itemvalue是int,我想将它绑定到Building模型中的buildingType字段。代码会更好地解释我猜。相关的控制器功能:
@RequestMapping(value = "addBuilding", method = RequestMethod.GET)
public String addBuildingPage(Model model) {
Building building = new Building();
model.addAttribute("building", building);
List<BuildingType> buildingTypeList = buildingTypeDao.findAll();
model.addAttribute("buildingTypeList", buildingTypeList);
return "addBuilding";
}
@RequestMapping(value = "addBuilding", method = RequestMethod.POST)
public String submitNewBuilding(@ModelAttribute(value = "building") @Valid Building building,
BindingResult result, Model model) {
if (result.hasErrors()) {
return "addBuilding";
}
model.addAttribute("building", building);
return "addBuilding";
}
我得到一个无法将int强制转换为BuildingType异常,经过一些搜索后我跟着写了here的博客文章。所以我决定编写一个自定义格式化程序并使用ConversionService。 这是格式化程序类
@Component
public class BuildingTypeFormatter implements Formatter<BuildingType> {
@Autowired
private BuildingTypeDao buildingTypeDao;
@Override
public String print(BuildingType buildingType, Locale arg1) {
return buildingType.getName();
}
@Override
public BuildingTypeDBO parse(String id, Locale arg1) throws ParseException {
return buildingTypeDao.findOne(Long.parseLong(id));
}
}
这是spring配置类。 (我不使用xml配置。)
@EnableWebMvc
@Configuration
@ComponentScan({ "my.packages" })
public class MvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private BuildingTypeDBOFormatter formatter;
public MvcConfig() {
super();
}
@Bean(name = "conversionService")
public FormattingConversionServiceFactoryBean conversionService() {
FormattingConversionServiceFactoryBean bean = new FormattingConversionServiceFactoryBean();
Set<Formatter<?>> formatters = new HashSet<Formatter<?>>();
formatters.add(formatter);
bean.setFormatters(formatters);
return bean;
}
我认为我需要注册转换服务,如博客文章中所述。像我这样在我的控制器中使用和初始化绑定器。
@Autowired
ConversionService conversionService;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setConversionService(conversionService);
}
问题是我在使用setConversionException时遇到以下异常。当我调试它时,我看到使用默认的conversionService初始化了绑定器。
java.lang.IllegalStateException: DataBinder is already initialized with ConversionService
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.validation.DataBinder.setConversionService(DataBinder.java:562)
at my.package.controller.MyController.initBinder(MyController.java:138)
我遇到了许多建议setConversionService的答案,但它不起作用,我该如何解决这个问题? (PS:很抱歉很长的帖子,但我认为可能有几种方法可以解决这个问题,所以我更愿意发布整篇文章。)
答案 0 :(得分:0)
您可以尝试在控制器中添加自定义属性编辑器
@InitBinder
public void initBinder(ServletRequestDataBinder binder) {
binder.registerCustomEditor(BuildingType.class, "buildingType", new PropertyEditorSupport() {
public void setAsText(String text) {
Long buildingTypeId = Long.parseLong(text);
BuildingType buildingType = (BuildingType) buildingTypeDao.findOne(buildingTypeId);
setValue(buildingType);
}
});
}