没有使用过滤器和ByteArrayOutputStream写入响应

时间:2014-08-19 19:23:52

标签: java jsp servlets stream servlet-filters

我有以下过滤器:

@WebFilter( filterName = "myfilter" )
public class WebCacheFilter implements Filter {
    @Override
    public void init( FilterConfig filterConfig ) {}

    @EJB
    AppExceptionLogger logger;

    @Override
    public void doFilter( ServletRequest req, ServletResponse res, final FilterChain chain )
    throws IOException, ServletException {
        final HttpServletRequest request = ( HttpServletRequest )req;
        final HttpServletResponse response = ( HttpServletResponse )res;
        execute( new StreamAction<ByteArrayOutputStream>() {
            @Override
            public void doAction( ByteArrayOutputStream stream ) throws Exception {
                chain.doFilter( request, new ProxiedServletResponse( response, stream ) );
                response.getOutputStream()
                    .write( stream.toByteArray() );
            }
        } );
    }

    @Override
    public void destroy() {}

    private void execute( StreamAction<ByteArrayOutputStream> action ) throws IOException {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            action.doAction( stream );
        } catch ( Exception e ) {
            logger.logInternal( e );
        } finally {
            stream.close();
        }
    }
}

在web.xml中作为

的mappend
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <filter-mapping>
        <filter-name>myfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

ProxiedServletResponse类来自此处:https://github.com/FagnerMartinsBrack/Servlet-GZIP-Compression/blob/95f4bac01e5037ea403f502819d3e74f66ef1ad0/src/main/java/com/fagnerbrack/servlet/gzip/proxy/ProxiedServletResponse.java

以下是test.jsp文件内容:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Página de teste</title>
    <!-- Descrição do sistema -->
    <meta name="description" content="">
    <!-- Ajusta o conteúdo de acordo com o tamanho da tela em aparelhos mobile -->
    <meta name="viewport" content="width=device-width">
  </head>
  <body>
    test page
  </body>
</html>

当我尝试访问\webapp\test.jsp文件时,浏览器不会打印任何内容。似乎response.getOutputStream().write( stream.toByteArray() );部分无效。那是为什么?

注意:如果您尝试访问/static/js/jquery.js之类的javascript文件,则会正确加载。只加载JSP文件。

注2:baos.toByteArray()部分,ByteArrayOutputStream的长度为0,用于JSP文件(!!!)

1 个答案:

答案 0 :(得分:2)

JSP写入getWriter(),而不是getOutputStream()。在getWriter()中,您将ByteArrayInputStream包裹在PrintWriter中。 PrintWriter有一个8K字符缓冲区。 JSP明显小于8K字符。在获得书面flush()之前,您永远不会PrintWriter byte[]的缓冲区,因此它永远不会写入包裹的ByteArrayInputStream

你需要冲洗婊子。取代

chain.doFilter(request, new ProxiedServletResponse(response, stream));
response.getOutputStream().write(stream.toByteArray());

通过

HttpServletResponse proxiedResponse = new ProxiedServletResponse(response, stream);
chain.doFilter(request, proxiedResponse);
proxiedResponse.flushBuffer();
response.getOutputStream().write(stream.toByteArray());