簡體   English   中英

將Apache Velocity與StringBuilders / CharSequences一起使用

[英]Using Apache Velocity with StringBuilders/CharSequences

我們將Apache Velocity用於動態模板。 目前,Velocity具有以下評估/替換方法:

public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader)

public static boolean evaluate(Context context, Writer out, String logTag, String instring)

我們通過提供StringWriter來使用這些方法來編寫評估結果。 我們的傳入數據以StringBuilder格式輸入,因此我們使用StringBuilder.toString並將其作為instring

問題在於我們的模板相當大(可能為兆字節,在極少數情況下為數十兆),替換操作非常頻繁,並且每個替換操作將所需內存量增加三倍 (傳入數據+ StringBuilder.toString()會創建一個新副本) +傳出數據)。

我想知道是否有辦法改善這一點。 例如,如果我能找到一種方法在同一StringBuilder實例的頂部提供一個ReaderWriter ,而該實例僅使用額外的內存來處理輸入/輸出差異,那將是一個好方法嗎? 是否有人做過類似的事情並且可以分享此類課程的任何資料? 也許對於給定的問題有更好的解決方案?

Velocity需要先分析整個模板,然后才能對其進行評估。 您將無法提供“ Reader和“ Writer來通過單個評估獲得任何收益。 但是,您可以將模板分解為較小的部分,以分別評估它們。 這將取決於其中的內容以及零件之間是否相互依賴。 根據您的情況,開銷可能不值得。

如果僅在模板中處理變量替換,則可以簡單地評估輸入的每一行。 理想情況下,您可以在將其放入StringBuilder之前對其進行攔截。 否則,您仍將不得不承擔該內存的成本以及您將其饋送到BufferedReader以進行readLine()調用的toString()的開銷。

如果有#set指令,則需要繼續傳遞相同的上下文進行評估。 如果有任何#if#foreach塊,它將變得很棘手。 實際上,我之前已經做過此工作,並讀了足夠多的行以捕獲輸入塊,以便Velocity進行解析和評估。 但是到那時,您開始從事Velocity的工作,這可能不值得。

您可以通過反射從StringBuilder讀取value字段並在其上創建CharArrayReader來保存字符串的一個副本:

    StringBuilder sb = new StringBuilder("bla");
    Field valueField = StringBuilder.class.getSuperclass().getDeclaredField("value");
    valueField.setAccessible(true);
    char[] value = (char[]) valueField.get(sb);
    Reader r = new CharArrayReader(value, 0, sb.length());

讓人驚訝。 這是對validate()的相當重的用途。 我認為您有充分的理由不使用標准的資源加載器,所以我不會之以鼻。 :)

我還沒有聽說過任何適合的解決方案,但是由於Reader不是一個特別復雜的類,因此我的直覺是僅創建自己的StringBufferReader類並將其傳遞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM