2012-03-11 22 views
5

Estoy tratando de leer el resultado de FreemarkerView renderizado:lectura ServletOutputStream a cadena

View view = viewResolver.resolveViewName(viewName, locale); 
view.render(model, request, mockResponse); 

Para leer el resultado, he creado mockResponse, que encapsula el HttpServletResponse:

public class HttpServletResponseEx extends HttpServletResponseWrapper { 

    ServletOutputStream outputStream; 

    public HttpServletResponseEx(HttpServletResponse response) throws IOException { 
     super(response); 
     outputStream = new ServletOutputStreamEx(); 
    } 

    @Override 
    public ServletOutputStream getOutputStream() { 
     return outputStream; 
    } 

    @Override 
    public PrintWriter getWriter() throws IOException { 
     return new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8")); 
    } 
} 

Y también mi ServletOutputStream, que construye la cadena usando StringBuilder:

public class ServletOutputStreamEx extends ServletOutputStream { 

    StringBuilder stringBuilder; 

    public ServletOutputStreamEx() { 
     this.stringBuilder = new StringBuilder(); 
    } 

    @Override 
    public void write(int b) throws IOException { 
    } 

    @Override 
    public void write(byte b[], int off, int len) throws IOException { 
     stringBuilder.append(new String(b, "UTF-8")); 
    } 

    @Override 
    public String toString() { 
     return stringBuilder.toString(); 
    } 
} 

Con ésos puedo leer fácilmente la respuesta con el método ServletOutputStreamEx.toString.

Mi problema es que el método de escritura no se llama en el orden correcto y al final la secuencia final es mixto y no en el orden correcto. Esto es probablemente causado por la concurrencia en Freemarker, pero no tengo idea de cómo solucionarlo.

+1

Estoy seguro de que Freemarker llamará a los métodos de escritura en el orden correcto durante la etapa de reproducción, de lo contrario generaría un resultado confuso. Además, Freemarker no se ejecuta al mismo tiempo. Creo que el problema está en su implementación de 'ServletOutputStreamEx'. No ha anulado todos los métodos de escritura y sus métodos súper. No veo que llame a 'super.write (int b)', simplemente no hará nada si se llama a este método. – gigadot

+1

No estoy seguro de cuál es tu problema, pero si obtienes dos 'cadenas' como resultado de llamadas' ServletOutputStreamEx.write() 'mezcladas. usar 'StringBuffer' en lugar de' StringBuilder' arreglaría esto -despuesto a que 'StringBuffer' está sincronizado- –

+1

No estoy de acuerdo, StringBuffer es algo que debería estar en desuso (como se describe en Effective Java, 2nd Edition), y usar un StringBuilder es bueno, porque la mayoría de las veces una sola solicitud (y, por lo tanto, una respuesta única) se maneja con un hilo. –

Respuesta

4

Gracias por las respuestas: el write(int b) no se implementó, porque nunca se llama. El problema al final es la matriz de bytes, que también contiene la cadena anterior. Por lo tanto, la cadena debe crearse como String(b, off, len, "UTF-8").

Cuestiones relacionadas