在JSF消息中嵌入链接(或其他html)

Bri*_*hem 16 jsf jsf-2

我想在JSF消息中嵌入一个链接,这可能吗?

当我尝试它时,h:messages标签的渲染html会转义html字符.我尝试将h:messages标记的escape属性设置为false,但这没有帮助.

Bal*_*usC 22

不幸的是,这在标准的JSF实现中是不可能的.组件和渲染器不正式支持此属性.但是,您可以生成一个处理此问题的渲染器.

由于这是一个非常常见的要求/愿望,我想看看有什么可能.

首先是一些背景信息:默认情况下,JSF ResponseWriter#writeText()用于编写标签主体,默认情况下会转义HTML.我们想让它ResponseWriter#write()像使用一样使用<h:outputText escape="false" />.我们想扩展MessagesRenderer标准的JSF实现并相应地覆盖该encodeEnd()方法.但是由于它MessagesRenderer#encodeEnd()包含了很多代码(~180行),我们不喜欢复制只是改变一行或两行,我发现更好地用ResponseWriter自定义实现代替它,ResponseWriterWrapper其中writeText()被覆盖为处理逃逸.

所以,我最终得到了这个:

package com.example;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ResponseWriterWrapper;
import javax.faces.render.FacesRenderer;

import com.sun.faces.renderkit.html_basic.MessagesRenderer;

@FacesRenderer(componentFamily="javax.faces.Messages", rendererType="javax.faces.Messages")
public class EscapableMessagesRenderer extends MessagesRenderer {

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        final ResponseWriter originalResponseWriter = context.getResponseWriter();

        try {
            context.setResponseWriter(new ResponseWriterWrapper() {

                @Override
                public ResponseWriter getWrapped() {
                    return originalResponseWriter;
                }

                @Override
                public void writeText(Object text, UIComponent component, String property) throws IOException {
                    String string = String.valueOf(text);
                    String escape = (String) component.getAttributes().get("escape");
                    if (escape != null && !Boolean.valueOf(escape)) {
                        super.write(string);
                    } else {
                        super.writeText(string, component, property);
                    }
                }
            });

            super.encodeEnd(context, component); // Now, render it!
        } finally {
            context.setResponseWriter(originalResponseWriter); // Restore original writer.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管有@FacesRenderer注释,它仍会被默认MessagesRenderer实现覆盖.我怀疑这是一个错误,所以我报告了问题1748.无论如何要让它工作,我们必须回到faces-config.xml:

<render-kit>
    <renderer>
        <component-family>javax.faces.Messages</component-family>
        <renderer-type>javax.faces.Messages</renderer-type>
        <renderer-class>com.example.EscapableMessagesRenderer</renderer-class>
    </renderer>
</render-kit>
Run Code Online (Sandbox Code Playgroud)

然后,要触发它,只需执行:

<h:messages escape="false" />
Run Code Online (Sandbox Code Playgroud)

它的工作原理!:)


注意:以上<h:messages>仅影响.为了能够做同样的<h:message>,只是做相同,但替换的任何地方 "Messages"通过"Message"(组件系列,渲染器类型和类名).

  • @ Mr.Pichler:你确实扩展了自己的.这些天有`<o:messages>`作为替代.http://showcase.omnifaces.org/components/messages (2认同)