Saltar al contenido

Cómo leer y copiar el contenido del flujo de salida de la respuesta del servlet HTTP para el registro

Hola usuario de nuestro sitio, tenemos la solución a tu interrogante, continúa leyendo y la hallarás más abajo.

Solución:

Necesitas crear un Filter donde envuelves el ServletResponse argumento con una costumbre HttpServletResponseWrapper implementación en la que anula el getOutputStream() y getWriter() para devolver una costumbre ServletOutputStream implementación en la que copia los bytes escritos en el resumen base OutputStream#write(int b) método. Luego, pasas la costumbre envuelta HttpServletResponseWrapper al FilterChain#doFilter() llamar en su lugar y finalmente debería poder obtener la respuesta copiada después el la llamada.

En otras palabras, el Filter:

@WebFilter("/*")
public class ResponseLogger implements Filter 

    @Override
    public void init(FilterConfig config) throws ServletException 
        // NOOP.
    

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException 
        if (response.getCharacterEncoding() == null) 
            response.setCharacterEncoding("UTF-8"); // Or whatever default. UTF-8 is good for World Domination.
        

        HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((HttpServletResponse) response);

        try 
            chain.doFilter(request, responseCopier);
            responseCopier.flushBuffer();
         finally 
            byte[] copy = responseCopier.getCopy();
            System.out.println(new String(copy, response.getCharacterEncoding())); // Do your logging job here. This is just a basic example.
        
    

    @Override
    public void destroy() 
        // NOOP.
    


La costumbre HttpServletResponseWrapper:

public class HttpServletResponseCopier extends HttpServletResponseWrapper 

    private ServletOutputStream outputStream;
    private PrintWriter writer;
    private ServletOutputStreamCopier copier;

    public HttpServletResponseCopier(HttpServletResponse response) throws IOException 
        super(response);
    

    @Override
    public ServletOutputStream getOutputStream() throws IOException 
        if (writer != null) 
            throw new IllegalStateException("getWriter() has already been called on this response.");
        

        if (outputStream == null) 
            outputStream = getResponse().getOutputStream();
            copier = new ServletOutputStreamCopier(outputStream);
        

        return copier;
    

    @Override
    public PrintWriter getWriter() throws IOException 
        if (outputStream != null) 
            throw new IllegalStateException("getOutputStream() has already been called on this response.");
        

        if (writer == null) 
            copier = new ServletOutputStreamCopier(getResponse().getOutputStream());
            writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
        

        return writer;
    

    @Override
    public void flushBuffer() throws IOException 
        if (writer != null) 
            writer.flush();
         else if (outputStream != null) 
            copier.flush();
        
    

    public byte[] getCopy() 
        if (copier != null) 
            return copier.getCopy();
         else 
            return new byte[0];
        
    


La costumbre ServletOutputStream:

public class ServletOutputStreamCopier extends ServletOutputStream 

    private OutputStream outputStream;
    private ByteArrayOutputStream copy;

    public ServletOutputStreamCopier(OutputStream outputStream) 
        this.outputStream = outputStream;
        this.copy = new ByteArrayOutputStream(1024);
    

    @Override
    public void write(int b) throws IOException 
        outputStream.write(b);
        copy.write(b);
    

    public byte[] getCopy() 
        return copy.toByteArray();
    


La solución BalusC está bien, pero un poco desactualizada. Spring ahora tiene una función para ello. Todo lo que necesitas hacer es usar [ContentCachingResponseWrapper], que tiene método public byte[] getContentAsByteArray() .

Sugiero hacer WrapperFactory que permitirá que sea configurable, ya sea para usar ResponseWrapper predeterminado o ContentCachingResponseWrapper.

En lugar de crear HttpServletResponseWrapper personalizado, puede usar ContentCachingResponseWrapper ya que proporciona el método getContentAsByteArray ().

public void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
            FilterChain filterChain) throws IOException, ServletException 

        HttpServletRequest request = servletRequest;
        HttpServletResponse response = servletResponse;
        ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper responseWrapper =new ContentCachingResponseWrapper(response);
        try 
            super.doFilterInternal(requestWrapper, responseWrapper, filterChain);

         finally 

            byte[] responseArray=responseWrapper.getContentAsByteArray();
            String responseStr=new String(responseArray,responseWrapper.getCharacterEncoding());
            System.out.println("string"+responseStr);       
            /*It is important to copy cached reponse body back to response stream
            to see response */
            responseWrapper.copyBodyToResponse();

        

    

Aquí tienes las reseñas y valoraciones

Si para ti ha resultado útil nuestro post, nos gustaría que lo compartas con más seniors y nos ayudes a extender nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *