2014-01-15 34 views
1

假設我有一個Java類Formatter,其靜態方法format執行一些簡單的文本處理。我想編寫一個組件,將組件內通過文本到Formatter#format方法,像這樣:JSF:從自定義組件中訪問組件主體的文本

<test:format> 
    Hello, #{user.name}! 
</test:format> 

爲了討論的方便,假設格式化看起來是這樣的(實際上這是一個降價庫) :

public class Formatter { 
    public static format(String s) { return s.toUpperCase(); } 
} 

我想上面的標籤的渲染結果是HELLO, DANIEL!

這可行嗎?我需要做些什麼才能獲得組件下的呈現文本內容以便像這樣處理?

回答

0

我已經想出了一個方法來做到這一點,但我懷疑它是一個雜食。代碼:

@FacesComponent("MyComponent") 
public class MyComponent 
    extends UIComponentBase 
    implements NamingContainer { 

    @Override public String getFamily() { 
    return UINamingContainer.COMPONENT_FAMILY; 
    } 

    @Override public boolean getRendersChildren() { return true; } 

    @Override public void encodeChildren(FacesContext fc) throws IOException { 
    StringWriter writer = new StringWriter(); 
    ResponseWriter rw = fc.getResponseWriter(); 

    // create the response writer 
    ResponseWriter replacement = rw.cloneWithWriter(writer); 

    // this tag wrapping step is necessary for the MyFaces ResponseWriter to 
    // work correctly 
    replacement.startDocument(); 
    replacement.startElement("div", this); 

    // mask the response writer temporarily  
    fc.setResponseWriter(replacement); 

    // perform the render to get the text in our string 
    super.encodeChildren(fc); 

    // unmask the response writer 
    fc.setResponseWriter(rw); 

    // finish the wrapping calls 
    replacement.endElement("div"); 
    replacement.endDocument(); 

    // this strips the rendered <div> tag wrapper from the generated text. 
    final String renderedText = writer.toString() 
      .substring(5, writer.toString().length()-6); 

    // process the text and send it out 
    rw.append(Formatter.format(renderedText)); 
    } 
} 

這一切都取決於ResponseWriter#cloneWithWriter方法。但是,如果你只是在裏面放一個StringWriter並期待它發揮作用,MyFaces就會炸燬 - 至少需要創建一個包裝標籤來爲要呈現的文本創建一個安全的上下文。我的格式化程序不期望包裝元素,所以我之後刪除了一個總體子串的東西。除此之外,實施getRendersChildren似乎足以讓這一切。然後你用一個taglib.xml來連接它。