测试解决方案!
这个解决方案实际上得到了已经在这里发布的想法(特别是来自@gyan)。
- 编写一个 Servlet 来压缩
(您也可以为此使用过滤器。例如,假设您有一个 ZipFilter。您可以映射所有 *.zip 的过滤器,并将该过滤器链接到相应的 .jsf URL 的 URLRewrite 过滤器)。
public class ZipServlet
extends HttpServlet {
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
IOException {
ZipEntry zipEntry = new ZipEntry("helloWorld.html");
ZipHttpServletResponseWrapper respWrapper = new ZipHttpServletResponseWrapper(response, zipEntry);
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/helloWorld.jsf");
dispatcher.forward(request, respWrapper);
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "inline; filename=output.zip;");
response.flushBuffer();
respWrapper.getOutputStream().close();
}
}
没什么好说的。从 Java 7 开始,您可以使用本机类来正确创建 zip 文件。应该推荐在 response.getOutputStream() 之上使用带有 ZipOutputStream 的装饰器模式。
请记住,HttpServletResponseWrapper 是一个装饰器。如果您不想直接重用目标“servlet”输出(您可以使用特技 HttpServletResponse 而不是使用 HttpServletResponseWrapper),则不应使用它。
public class ZipHttpServletResponseWrapper
extends HttpServletResponseWrapper {
private ZipEntry entry;
private ZipServletOutputStreamWrapper streamWrapper;
private ZipOutputStream outputStream;
private PrintWriter printWriter;
public ZipHttpServletResponseWrapper(HttpServletResponse response, ZipEntry entry) {
super(response);
this.entry = entry;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (streamWrapper == null) {
outputStream = new ZipOutputStream(this.getResponse().getOutputStream());
outputStream.putNextEntry(entry);
streamWrapper = new ZipServletOutputStreamWrapper(outputStream);
}
return streamWrapper;
}
@Override
public PrintWriter getWriter() throws IOException {
if (printWriter == null) {
printWriter = new PrintWriter(getOutputStream());
}
return printWriter;
}
private class ZipServletOutputStreamWrapper
extends ServletOutputStream {
private ZipOutputStream outputStream;
public ZipServletOutputStreamWrapper(ZipOutputStream outputStream) {
this.outputStream = outputStream;
}
@Override
public void close() throws IOException {
outputStream.closeEntry();
outputStream.finish();
}
@Override
public void write(int b) throws IOException {
outputStream.write(b);
}
}
}
- 现在,秘密:明智地映射!
JSF 的一些重要部分可以使用过滤器链(例如,Apache 的 myfaces 使用一些扩展来提供一些 JSF 组件)。在这种情况下,您应该在这些过滤器中指定摘要 FORWARD 和 REQUEST
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>