0

我将 Freemarker 模板加载器包装在 Spring MVC 中,如此处所述以在 html 页面中进行默认转义。

所以,我需要用我的字符串包装来自 java.io.Reader 的内容,而不是读取它,不将其转换为字符串并且不实现自己。流行的公共库中是否有类似于WrappingReader或 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;
    }

}

我使用的 CharStreams 被标记为@com.google.common.annotations.Beta。那么,是否可以在不使用 CharStreams 的情况下以更可靠的方式重写它?

4

2 回答 2

1

番石榴贡献者在这里。...好的。

@Beta并不意味着“未完全测试”或“未广泛使用”。 唯一的意思是我们不太确定我们是否准备好冻结 API。如果您正在开发库或计划稍后升级 Guava 版本,这只是一个问题。(而且,老实说,与APICharStreams一样稳定......)@Beta

你不应该一个ReaderSupplier类,它破坏了InputSupplier界面的全部意义。对于这种特殊情况,Reader您应该绕过 s ,而不是传递InputSupplier<Reader>s。在这种特殊情况下,CharStreams.newReaderSupplier(String)返回InputSupplier产生StringReaders 的 an,因此非常适合这个用例。

无论如何,我的完整实现将类似于:

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));
 }
于 2012-07-19T14:06:28.597 回答
1

我只是在回答这个问题:如何合并 java.io.Reader's。

使用纯 Java 我能够提出使用SequenceInputStreamon的解决方案InputStreams,这似乎是合并两个的更好解决方案InputStreams。有关合并 InputStreams,请参阅此 stackoverflow 问题。想法很简单:将 reader 转换为InputStreams,将它们合并并将其保存InputStreamReader.

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);
于 2019-11-21T12:10:34.317 回答