使用Converter for type Boolean时,Spring复选框JSP标记被破坏

我已经使用Spring Roo和Spring MVC设置了一个CRUD Web应用程序。 我的问题是:因为我使用转换器来本地化显示布尔值,所以Spring JSP Tag 复选框被破坏,这意味着复选框不会从支持bean中获取实际值。 他们总是虚假和不受控制。

我做了一些研究,可能在org.springframework.web.servlet.tags.form.CheckboxTagwriteTagDetails方法中发现了错误。 以下是此方法的有趣部分:

// the concrete type may not be a Boolean - can be String if (boundValue instanceof String) { boundValue = Boolean.valueOf((String) boundValue); } Boolean booleanValue = (boundValue != null ? (Boolean) boundValue : Boolean.FALSE); renderFromBoolean(booleanValue, tagWriter); 

因为我使用转换器来显示yes / no而不是true / false,所以boundValue是一个String,并且Boolean.valueOf的调用总是导致false,因为valueOf方法不知道使用的Spring Converter并解释是/不是假的。

我怎样才能用Spring解决这个问题? 有人有线索吗? 我的大脑已经到了一条死胡同。

只是为了完整性:布尔类型的转换器正在按预期工作(代码见下文)。

 public class BooleanConverter implements Converter, Formatter { @Autowired private MessageSource messageSource; @Override public String print(Boolean object, Locale locale) { return (object) ? messageSource.getMessage("label_true", null, LocaleContextHolder.getLocale()) : messageSource.getMessage("label_false", null, LocaleContextHolder.getLocale()); } @Override public String convert(Boolean source) { return this.print(source, null); } } 

这似乎有可能克服。 那就是你想要一个人类可读的Formatter来向用户显示模型中布尔值的yes / no。 但你仍然希望复选框HTML元素工作,看起来那些HTML复选框元素/小部件/ JSP标签需要使用true / false字符串(或布尔Java类型)它似乎不使用转换器来获取任意是/否字符串返回布尔类型。

对我来说这个问题表现为,当模型设置了Boolean.TRUE值时,永远不会勾选复选框的初始状态。 这意味着对记录的任何读取 – 修改 – 更新(不编辑该字段,当用户未更改时,最终会从“true”转换为“false”)。 这是由于UI中的初始状态与模型不一致(它显示总是未经检查,即假状态),即使模型是真状态也是如此。 显示的值是HTML编辑记录屏幕中未选中的复选框,即使模型的值为Boolean.TRUE也是如此。 这是因为HTML复选框元素不会将“yes”解释为“true”,并且默认为false(因为这是默认的布尔值)。

因此,定义您的Formatter / Converter(就像您已经在做的那样)。 但是在你的@Controller中添加:

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Boolean.class, "friesWithThat", new CustomBooleanEditor(false)); } 

这似乎使字符串显示值继续为是/否,但使用并传递给复选框HTML元素的值继续为true / false。

现在,当编辑/更新记录时(在CRUD中),复选框的初始状态与模型一致,保存数据(不编辑任何字段)不会转换复选框状态(这是我对您遇到的问题的理解)。

因此,我认为我们可以理解转换器/格式化器用于一般数据显示,而PropertyEditors用于映射模型数据,因此UI小部件需要数据。

您可能应该编写自己的类型,名为Choice ,其中Choice.YESChoice.NO作为序数枚举,根据存储在数据库中的值对应于1或0。

然后,您可以在应用程序中为此类型定义自己的显示标记和输入标记,以解决此问题。

添加到上一个答案,从3.2版开始,您可以为所有控制器和所有布尔字段注册属性编辑器,如下所示:

 package your.package.path; import org.springframework.beans.propertyeditors.CustomBooleanEditor; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.context.request.WebRequest; @ControllerAdvice public class GlobalBindingInitializer { @InitBinder public void registerCustomEditors(WebDataBinder binder, WebRequest request) { binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(false)); } } 

如果您来自Spring Roo基本配置,请记住在webmvc-config.xml中添加此行

   

像这样: