2

下面的 selectItems 来自 Session Scoped Map。当用户单击提交按钮时,应该在 Request Scoped 支持 bean 中设置一个日期字段并将其显示在页面上。

    <h:selectOneMenu value="#{dropDown.selectedDate}">
        <f:selectItems value="#{mapValues.dateMap.entrySet()}" var="entry" itemLabel="#{entry.value}" itemValue="#{entry.key}" />
    </h:selectOneMenu>
    <h:commandButton value="Submit" />
You selected Date #{dropDown.selectedDate}

但是,收到以下转换错误:

Conversion Error setting value 'Wed Dec 26 15:09:32 EST 2012' for 'null Converter'. 

我不确定为什么会收到此错误。我尝试在 selectOneMenu 标记上设置 javax.faces.DateTime 转换器,但随后收到更神秘的验证错误。

发现一个帖子建议检查 equal() 方法是否可用,并且项目选择是否在下拉列表中,在这种情况下两者都应该是正确的。

我能想到的一种解决方法是将我的地图更改为字符串键控,其中日期保存为字符串。但这似乎是矫枉过正。

有关如何使此设置正常工作的任何建议?

支持豆:

@Named
@RequestScoped
public class DropDown {

    private Date selectedDate;

    public Date getSelectedDate() {
        return selectedDate;
    }

    public void setSelectedDate(Date selectedDate) {
        this.selectedDate = selectedDate;
    }

}

地图豆:

@Named
@SessionScoped
public class MapValues implements Serializable {

    private Map<Date, String> dateMap;

    @PostConstruct
    public void init() {        
        dateMap = new LinkedHashMap<Date, String>();
        dateMap.put(new Date(), "DATEVALUE1");      
    }

    public Map<Date, String> getDateMap() {
        return dateMap;
    }

    public void setDateMap(Map<Date, String> dateMap) {
        this.dateMap = dateMap;
    }
}

谢谢!

4

1 回答 1

5

使用日期时间转换器应该是正确的解决方案。您的“更神秘的验证错误”原来是这样的:

它是“表单:位置:验证错误:值无效

Object#equals()当所选项目的测试没有返回true任何可用项目时,就会发生这种情况。因此,所选实例与任何可用实例Date都不匹配。Date

事实上,converter="javax.faces.DateTime"(aka <f:convertDateTime />) 默认忽略时间部分。它默认打印“短”日期样式,例如浏览器中的“Dec 27, 2012”右键单击页面,选择查看源代码自己查看。

<option value="Dec 27, 2012">DATEVALUE1</option>

当 JSF 将该格式的字符串提交值转换回具体Date实例时,它基本上变成2012-12-27 00:00:00.000了在您的地图中提供的日期显然仍然设置了时间部分的情况下,equals()除非可用日期的地图是巧合生成的,否则会导致始终失败正是00:00:00.000午夜。

这个问题有2个解决方案:

  1. 删除映射中日期的时间部分。你可以使用java.util.Calendar这个(或者更好的,Joda Time)。

  2. 而是使用<f:convertDateTime pattern="yyyyMMddHHmmssSSS"/>将整个日期/时间转换为最后一毫秒。

    <h:selectOneMenu value="#{dropDown.selectedDate}">
        <f:selectItems value="#{mapValues.dateMap.entrySet()}" var="entry" itemLabel="#{entry.value}" itemValue="#{entry.key}" />
        <f:convertDateTime pattern="yyyyMMddHHmmssSSS" />
    </h:selectOneMenu>
    

    这样期权价值就变成了

    <option value="20121227114627792">DATEVALUE1</option>
    

    当您将 JSF 配置为使用平台特定时区而不是 GMT 作为<f:convertDateTime>时区时,请注意时区问题。然后,您想向timeZone="UTC"转换器显式添加属性。

于 2012-12-27T15:41:54.690 回答