我处理的是大文件,需要在base64负载周围包装xml。我的第一个简单实现将有效负载作为java.lang.String
传递到[velocity template][0]中,但是对于大文件,我希望使用java.io.InputStream
来代替。
这是我的模板:
<?xml version="1.0" encoding="UTF-8"?>
<Request>
<AdditonalParameters>
#if( $headers.additionalParameters )
#foreach( $key in $headers.additionalParameters.keySet() )
<Parameter>
<Key>${key}</Key>
<Value>${headers.additionalParameters.get($key)}</Value>
</Parameter>
#end
#end
</AdditonalParameters>
<Content>${body}</Content>
</Request>
$body
可能非常大,所以我想避免使用String
或byte[]
。是否可以将InputStream
作为$body
传递到我的模板中,或者我不能使用velocity进行此操作? 最佳答案
是的,这是可以做到的。它所需要的只是一个逐行打印InputString
的迭代。由于velocity缺少一个类似于while
的构造,而且只知道foreach
循环,因此在其最简单的实现中,迭代看起来就像一个丑陋的黑客:
#foreach ($i in [0..100000])
#set ($line = false)
#set ($line = $body.readLine())
#if ($line)
${line}
#else
#break
#end
#end
这里用一个很大的数值范围来模拟一个无止境的循环。当无法从
#break
(theInputStream
)中提取更多行时,循环将$body
。第三行是一个警告:#set (line = $body.readLine())
与速度一样,赋值的左侧只有在右侧的值不为空时才会更改。因为
$line
永远不会被分配空值,所以我们需要将其预先设置为false
(布尔值,而不是readLine
返回的字符串)。这样,如果第二次$line
后false
仍然是#set
,我们知道readLine
返回null,是退出迭代的时间。这种方法的一个问题是在行之间插入模板中的空白。有一些技巧可以避免这种情况(see here)。此外,可以通过创建java
#foreach
来避免List
黑客攻击,javaiterator()
的Iterator
方法返回一个在InputStream
行上迭代的。这将是少吻,但它将使您的代码更可重用。