代码之家  ›  专栏  ›  技术社区  ›  Brian Leathem

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

  •  15
  • Brian Leathem  · 技术社区  · 14 年前

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

    2 回复  |  直到 14 年前
        1
  •  23
  •   BalusC    10 年前

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

    因为这是一个非常普遍的要求/愿望,我想看看什么是可能的。

    首先是一些背景信息:JSF默认使用 ResponseWriter#writeText() ResponseWriter#write() 相反,就像 <h:outputText escape="false" /> . 我们想延长合同期限 MessagesRenderer 并重写 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.
            }
        }
    }
    

    @FacesRenderer 注释,默认情况下会覆盖它 消息阅读器 实施。我怀疑这里有窃听器,所以我报告了 issue 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>
    

    <h:messages escape="false" />
    


    注:以上影响 <h:messages> <h:message> ,只需执行相同的操作,但替换 "Messages" 通过 "Message"

        2
  •  2
  •   Adam    10 年前

    这个 escape="false" OmniFaces为您提供所需的属性 <o:messages> component

    我发布了@BalusC评论中提到的这个解决方案作为答案,因为这是最直接的解决方案。