2010-07-28 38 views

回答

19

不幸的是,這在標準的JSF實現中是不可能的。組件和渲染器不正式支持此屬性。然而,你可以在一個處理這個的渲染器中生長。

由於這是一個相當常見的要求/希望,我想看看什麼是可能的。

首先介紹一些背景信息:默認情況下,JSF使用ResponseWriter#writeText()來編寫標籤主體,默認情況下它會轉義HTML。我們想讓它使用ResponseWriter#write()而不是像<h:outputText escape="false" />那樣。我們想擴展標準JSF實現的MessagesRenderer,並相應地覆蓋encodeEnd()方法。但由於MessagesRenderer#encodeEnd()包含很多代碼(~180行),我們不喜歡複製粘貼來改變一兩行,所以我發現用ResponseWriterWrapper替代ResponseWriter的定製實現更好,其中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註解,它由默認MessagesRenderer實現獲取覆蓋。我懷疑這裏有一個bug,所以我報告了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"(組件族,渲染器類型和類名稱)。

+0

感謝BalusC,我今天也得到了同樣的解決方案(並提交了相同的錯誤https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1750)我使用了委託人模式我的迴應作家,但我認爲我更喜歡你用包裝紙做的事情。謝謝! – 2010-07-29 03:57:51

+0

報告問題的新鏈接: http://java.net/jira/browse/JAVASERVERFACES-1750 – 2011-12-12 13:57:20

+0

它完美地工作BalusC,謝謝! – 2013-03-31 15:18:40

1

escape="false"歸因於您的需要由OmniFaces <o:messages> component提供。 OmniFaces實用程序庫可用於JSF 2.

我發佈了@ BalusC評論中提到的此解決方案作爲答案,因爲這是最直接的解決方案。