我处理的是大文件,需要在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可能非常大,所以我想避免使用Stringbyte[]。是否可以将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返回的字符串)。这样,如果第二次$linefalse仍然是#set,我们知道readLine返回null,是退出迭代的时间。
这种方法的一个问题是在行之间插入模板中的空白。有一些技巧可以避免这种情况(see here)。此外,可以通过创建java#foreach来避免List黑客攻击,javaiterator()Iterator方法返回一个在InputStream行上迭代的。这将是少吻,但它将使您的代码更可重用。

10-08 10:56
查看更多