我有一个包含所选主题列表的模型。每个主题都可以在一个房间内呈现,并且有更多的房间需要根据可用性进行选择。用户可以设置首选空间进行展示。如果它不可用,但其他一些可用,则在选定的时间应该有一条信息消息,表明房间已更改。类似于:
<form:errors path="selectedTopics[${loop.index}].room" />
loop是c:foreach标签中的varStatus属性
我将消息添加到messageContext,如下所示:
MessageContext messages = context.getMessageContext();
String source= "selectedTopics[" + i + "].room";
messages.addMessage(new MessageBuilder().info()
.source(source)
.code("topic.room.changed")
.build());
如果我将错误标记添加为错误,则错误标记有效,但它们不是错误。有没有什么方法可以像错误那样以优雅的方式显示这些信息?
答案 0 :(得分:5)
从DefaultMessageContext我看到所有消息都有一个getter,它在消息上下文中给出了一组消息,而不是通过循环遍历数组,我可以找到当前正在渲染的字段的消息:
<c:forEach var="topic" items="${model.selectedTopics}" varStatus="loop">
//omitted displaying of topic details
<c:forEach items="${flowRequestContext.messageContext.allMessages}" var="message">
<c:set var="msgSrc" value="selectedTopics[${loop.index}].room"></c:set>
<c:if test="${message.source eq msgSrc}">
<c:if test="${message.severity eq 'INFO'}">
<span class="infoText">${message.text}</span>
</c:if>
</c:if>
</c:forEach>
</c:forEach>
但是这样对所有消息的迭代都是针对每个必须渲染的字段完成的,如果你有很多字段,这可能会很慢。
另一种可以实现的方法是获取消息上下文中的消息映射。以下是jsp中输出的上下文示例,我使用了$ {flowRequestContext.messageContext}:
[DefaultMessageContext@2de69e99 sourceMessages = map[[null] -> list[[empty]], 'selectedTopics[2].room' -> list[[Message@12329bcb source = 'selectedTopics[2].room', severity = INFO, text = 'Room changed from ALU1-M1 to ALU1-M2']], 'selectedTopics[4].room' -> list[[Message@87abf31 source = 'selectedTopics[4].room', severity = INFO, text = 'Room changed from ALU1-M1 to ALU2-M1']]]]
有一个地图 sourceMessages ,用于保存可以使用源作为键检索的字段的所有消息。但问题是在实现org.springframework.binding.message.DefaultMessageContext中没有地图的getter。但是,有一个方法getMessagesBySource(java.lang.Object source),它为指定的源提供一组消息。所以我们可以在EL表达式中使用它。
重要!在EL中传递方法参数仅由EL 2.2中支持的EL规范。默认情况下,EL 2.2在Servlet 3.0 / JSP 2.2容器中提供。请参阅JSTL or JSP 2.0 EL for getter with argument
所以现在信息可以显示:
<c:forEach var="message" items="${flowRequestContext.messageContext.getMessagesBySource(msgSrc)}">
<c:if test="${message.severity eq 'INFO'}">
<span class="info">${message.text}</span></td>
</c:if>
</c:forEach>
如果您需要使用以前的版本而不是Servlet 3.0 / JSP 2.2容器,那么最好的方法是重建sourceMessages映射并在渲染视图之前将其插入flashScope。