如何合并java.io.Reader';s或包装读取器';什么内容?

如何合并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

我在SpringMVC中包装Freemarker模板加载器,如前所述,在html页面中有默认转义

所以,我需要用我的字符串包装java.io.Reader中的内容,而不是读取它,也不是将它转换为字符串,也不是实现我自己。在流行的公共库中是否有类似于或com.google.common.io.MultiReader(非公共)的类

我的实施:

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背后的想法,可以消除我自己的无效实现。