Freemarker 中的管道流问题
我需要在 freemarker 中加载和处理模板。我正在使用管道流来读回 freemarker 生成的结果。
示例代码:
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
Writer writer = new OutputStreamWriter(po);
configuration.getTemplate("xx").process(rootMap, writer);
问题是有时它会在 freemarker process 方法中冻结。 没有错误,没有异常,但它没有从 process
方法返回。
如果我将管道流转换为 ByteArray 流,它就可以正常工作。
我是否以正确的方式使用管道流?
I need to load and process a template in freemarker. I am using a piped stream to read back the generated result by freemarker.
Sample code:
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
Writer writer = new OutputStreamWriter(po);
configuration.getTemplate("xx").process(rootMap, writer);
The issue is that sometimes it's freezing inside freemarker procsss method.
No Error, no Exception, but it's not returning back from the process
method.
If I convert the piped stream to a ByteArray stream, it works fine.
Am I using piped stream in correct way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不,管道流旨在在两个线程之间传递数据。管道两端之间只有一个小的缓冲区。如果写入管道输出流,则如果缓冲区已满,您的线程将被阻塞,直到另一个线程从相应的管道输入流中读取数据。这不适用于仅一个线程。
来自 Javadoc:
因此,对于小型模板,只需使用
StringWriter
,对于大型模板,您可以在由File.createTempFile()
创建的临时文件上使用FileWriter
。No, piped streams are designed to pass data between two threads. There is only a small buffer between the ends of the pipe. If you write into the piped output stream, your thread will be blocked if the buffer is full until another thread will read from the corresponding piped input stream. This will not work with just one thread.
From the Javadoc:
So for small templates just use a
StringWriter
, for large ones you may use aFileWriter
on a temp file created byFile.createTempFile()
.正如 Arne 所写,管道流中的缓冲区空间量相当小。如果您无法使用可以容纳所有数据(无论是在内存中还是在磁盘上)的缓冲区,那么您可以尝试的一件事是看看是否可以在另一个线程中运行模板处理,并使用管道流将结果发送回到你正在执行此操作的主线程。
您可能需要将
final
关键字添加到其他变量中,以使其在实际代码中发挥作用。这取决于变量configuration
、getTemplate
的参数或rootMap
变量是局部变量还是实例(或类)变量。(当然,在指定线程的行为时,我可以对
Thread
进行子类化,但我更喜欢实例化一个接口 - 在本例中是Runnable
- 用于此类事情。)As Arne writes, the amount of buffer space in a piped stream is fairly small. If you can't use a buffer that can hold all of the data (whether in memory or on disk) then one thing you could try is to see if you can run the template processing in another thread with a piped stream sending the results back to the main thread where you're doing this.
You might need to add
final
keywords to other variables to make this work in your real code. It depends on whether the variableconfiguration
, the argument togetTemplate
or therootMap
variable are local variables or instance (or class) variables.(I could have subclassed
Thread
when specifying the thread's behavior of course, but I prefer to instantiate an interface –Runnable
in this case – for such things.)这就是我让它发挥作用的方法。
This is how I made it work.