如何合并java.io.Reader';s或包装读取器';什么内容?
我在SpringMVC中包装Freemarker模板加载器,如前所述,在html页面中有默认转义 所以,我需要用我的字符串包装java.io.Reader中的内容,而不是读取它,也不是将它转换为字符串,也不是实现我自己。在流行的公共库中是否有类似于或com.google.common.io.MultiReader(非公共)的类 我的实施:如何合并java.io.Reader';s或包装读取器';什么内容?,java,escaping,xss,freemarker,Java,Escaping,Xss,Freemarker,我在SpringMVC中包装Freemarker模板加载器,如前所述,在html页面中有默认转义 所以,我需要用我的字符串包装java.io.Reader中的内容,而不是读取它,也不是将它转换为字符串,也不是实现我自己。在流行的公共库中是否有类似于或com.google.common.io.MultiReader(非公共)的类 我的实施: import com.google.common.io.CharStreams; import com.google.common.io.InputSuppl
import com.google.common.io.CharStreams;
import com.google.common.io.InputSupplier;
...
private final TemplateLoader delegate;
@Autowired
public HtmlEscapingTemplateLoader(ResourceLoader resourceLoader)
{
delegate = new SpringTemplateLoader(resourceLoader, "/WEB-INF/templates/");
}
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException
{
// collecting readers
Reader prologue = new StringReader("<#escape x as x?html>");
Reader originalReader = delegate.getReader(templateSource, encoding);
Reader epilogue = new StringReader("</#escape>");
// concatenating readers
return merge(prologue, originalReader, epilogue);
}
protected Reader merge(Reader prologue, Reader originalReader, Reader epilogue) throws IOException
{
return CharStreams.join(
Arrays.asList(new ReaderSupplier(prologue), new ReaderSupplier(originalReader), new ReaderSupplier(
epilogue))).getInput();
}
private static class ReaderSupplier
implements InputSupplier<Reader>
{
private final Reader reader;
public ReaderSupplier(Reader reader)
{
this.reader = reader;
}
@Override
public Reader getInput() throws IOException
{
return reader;
}
}
import com.google.common.io.CharStreams;
导入com.google.common.io.InputSupplier;
...
私人最终模板装载机代表;
@自动连线
公共HtmlEscapingTemplateLoader(ResourceLoader ResourceLoader)
{
委托=新的SpringTemplateLoader(resourceLoader,“/WEB-INF/templates/”);
}
@凌驾
公共读取器getReader(对象模板源,字符串编码)引发IOException
{
//收集读者
读取器序言=新的StringReader(“”);
Reader originalReader=delegate.getReader(templateSource,编码);
读者尾声=新的StringReader(“”);
//串联读卡器
返回合并(序言、原读者、结语);
}
受保护的读取器合并(读取器序言、读取器原始读取器、读取器尾声)引发IOException
{
返回CharStreams.join(
Arrays.asList(新的读卡器供应商(序言)、新的读卡器供应商(originalReader)、新的读卡器供应商(
(结语)).getInput();
}
私有静态类读取器供应商
执行输入供应商
{
私人最终读者;
公共阅读器供应商(阅读器)
{
this.reader=读取器;
}
@凌驾
公共读取器getInput()引发IOException
{
返回读取器;
}
}
我使用的CharStreams标记为@com.google.common.annotations.Beta。那么,是否可以在不使用CharStreams的情况下以更可靠的方式重写它呢?这里是Guava contributor。。。好的 它唯一的意思是,我们不太确定我们是否已经准备好冻结API。这只是一个问题,如果你正在开发一个库,或者计划以后升级Guava的版本。(而且,老实说,
CharStreams
与@Beta
api获得的稳定性差不多……)
您不应该有一个ReaderSupplier
类,它会破坏InputSupplier
接口的整个要点。对于这种特殊情况,您应该传递InputSupplier
s,而不是传递Reader
s。在这种特殊情况下,CharStreams.newReaderSupplier(String)
返回一个生成StringReader
s的InputSupplier
,以便完全适合此用例
在任何情况下,我的完整实现都类似于:
static final String prologue = "<#escape x as x?html>";
static final String epilogue = "</#escape>";
// ideally you shouldn't be passing around Readers at all
// the point of InputSupplier, etc. is that you should never get direct access
// to the Reader directly, so you don't have to track whether it's closed or not
public InputSupplier<Reader> getReaderSupplier(
final Object templateSource, final String encoding) {
return CharStreams.join(
CharStreams.newReaderSupplier(prologue),
new InputSupplier<Reader>() {
public Reader getInput() {
return delegate.getReader(templateSource, encoding);
}
},
CharStreams.newReaderSupplier(epilogue));
}
静态最终字符串序言=”“;
静态最终字符串尾声=“”;
//理想情况下,你根本不应该把读者传给别人
//InputSupplier等的要点是,您永远不应该直接访问
//直接发送给读者,因此您不必跟踪它是否关闭
公共输入供应商getReaderSupplier(
最终对象模板源,最终字符串编码){
返回CharStreams.join(
CharStreams.newReaderSupplier(序言),
新输入供应商(){
公共读取器getInput(){
返回delegate.getReader(templateSource,编码);
}
},
新读者供应商(结语);
}
我只回答一个问题:如何合并java.io.Reader
使用纯Java,我能够提出在InputStreams
上使用SequenceInputStream
的解决方案,这似乎是合并两个InputStreams
的更好的解决方案。有关合并输入流的信息,请参阅。
想法很简单:将读取器转换为InputStream
,合并它们并将InputStream
保存到读取器中
Reader reader1 = new StringReader("String1");
Reader reader2 = new StringReader("String2");
ReaderInputStream readInputStream1 = new ReaderInputStream(reader1, StandardCharsets.UTF_8)
ReaderInputStream readInputStream2 = new ReaderInputStream(reader2, StandardCharsets.UTF_8)
Reader merged = new InputStreamReader(new SequenceInputStream(readInputStream1,readInputStream2), StandardCharsets.UTF_8);
谢谢你,路易斯,现在我明白了InputSupplier背后的想法,可以消除我自己的无效实现。