2012-03-11 3 views
5

Je suis en train de lire le résultat du rendu FreemarkerView:lecture ServletOutputStream à cordes

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

Pour lire le résultat, je l'ai créé mockResponse, qui encapsule l'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")); 
    } 
} 

Et aussi mon ServletOutputStream, qui génère la chaîne à l'aide de 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(); 
    } 
} 

Avec ceux-ci, je suis capable de lire facilement la réponse avec la méthode ServletOutputStreamEx.toString.

Mon problème est que la méthode d'écriture n'est pas appelée dans le bon ordre et à la fin la chaîne finale est mélangé et pas dans le bon ordre. Cela est probablement dû à la simultanéité dans Freemarker, mais je n'ai aucune idée de comment le résoudre.

+1

Je suis sûr que les méthodes d'écriture sont appelées dans le bon ordre par Freemarker lors de la phase de rendu, sinon cela générerait un résultat déformé. De plus, Freemarker n'est pas exécuté simultanément. Je pense que le problème est dans votre implémentation de 'ServletOutputStreamEx'. Vous n'avez pas écrasé toutes les méthodes d'écriture et les méthodes de son super. Je ne vois pas que vous appelez 'super.write (int b)', il ne fera tout simplement rien si cette méthode est appelée. – gigadot

+1

Je ne suis pas sûr de savoir quel est votre problème, mais si vous obtenez comme deux 'String's résultant de' ServletOutputStreamEx.write() 'appels mélangés ensemble. l'utilisation de 'StringBuffer' au lieu de' StringBuilder' corrigerait ceci -since 'StringBuffer' est synchronisé- –

+1

Je ne peux pas être d'accord, StringBuffer est quelque chose qui devrait être déprécié (comme décrit dans Effective Java, 2nd Edition), et en utilisant un StringBuilder est bon, car la plupart du temps une seule requête (et donc une seule réponse) est traitée avec un fil. –

Répondre

4

Merci pour les réponses: le write(int b) n'a pas été implémenté, car il n'est jamais appelé. Le problème à la fin est le tableau d'octets, qui contient également la chaîne précédente. La chaîne doit donc être créée en tant que String(b, off, len, "UTF-8").