[英]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
實例的頂部提供一個Reader
和Writer
,而該實例僅使用額外的內存來處理輸入/輸出差異,那將是一個好方法嗎? 是否有人做過類似的事情並且可以分享此類課程的任何資料? 也許對於給定的問題有更好的解決方案?
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.