在 JSF 消息中嵌入链接(或其他 html) [英] Embedding a link (or other html) in a JSF message

查看:23
本文介绍了在 JSF 消息中嵌入链接(或其他 html)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to embed a link in a JSF message, is this possible?

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

When I try it, the rendered html of the h:messages tag escapes the html characters. I tried setting the escape attribute of the h:messages tag to false, but that didn't help.

推荐答案

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

Unfortunately, this is not possible in the standard JSF implementation. The component and the renderer doesn't officially support this attribute. You can however homegrow a renderer which handles this.

由于这是一个非常普遍的要求/愿望,我想看看一切皆有可能.

Since this is a pretty common requirement/wish, I thought to take a look what's all possible.

首先介绍一些背景信息:JSF 默认使用 ResponseWriter#writeText() 写标签体,转义 HTML默认情况下.我们想让它使用 ResponseWriter#write() 而不是像 <h:outputText escape="false"/>.我们想扩展标准 JSF 实现的 MessagesRenderer 并相应地覆盖 encodeEnd() 方法.但是由于 MessagesRenderer#encodeEnd() 包含相当多的代码(约 180 行),我们不希望复制粘贴这些代码,毕竟只更改一两行,我发现最好替换 ResponseWriterResponseWriterWrapper 其中 writeText() 被覆盖以处理转义.

First some background information: JSF by default uses ResponseWriter#writeText() to write the tag body, which escapes HTML by default. We'd like to let it use ResponseWriter#write() instead like as with <h:outputText escape="false" />. We'd like to extend the MessagesRenderer of the standard JSF implementation and override the encodeEnd() method accordingly. But since the MessagesRenderer#encodeEnd() contains pretty a lot of code (~180 lines) which we prefer not to copypaste to just change one or two lines after all, I found it better to replace the ResponseWriter with a custom implementation with help of ResponseWriterWrapper wherein the writeText() is been overriden to handle the escaping.

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

So, I ended up with this:

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 注释,但它会被默认的 MessagesRenderer 实现覆盖.我怀疑这里有一个错误,所以我报告了 issue 1748.无论如何,为了让它工作,我们必须回到faces-config.xml:

In spite of the @FacesRenderer annotation, it get overriden by the default MessagesRenderer implementation. I suspect here a bug, so I reported issue 1748. To get it to work anyway, we have to fall back to the 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>

然后,要触发它,只需执行以下操作:

Then, to trigger it, just do:

<h:messages escape="false" />

它有效!:)

注意:以上仅影响 .要对 执行相同操作,只需执行相同操作,但将 anywhere "Messages" 替换为 "Message"(组件系列、渲染器类型和类名).

Note: the above affects <h:messages> only. To do the same for <h:message>, just do the same, but replace anywhere "Messages" by "Message" (component family, renderer type and classnames).

这篇关于在 JSF 消息中嵌入链接(或其他 html)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆