Adding header in response in filter?

前端 未结 4 1598
陌清茗
陌清茗 2020-12-06 10:08

I need to add the header in each response. I am planning to do below

public class MyFilter extends OncePerRequestFilter {

    @Override
    protected void d         


        
相关标签:
4条回答
  • 2020-12-06 10:50

    This is a little late, but the below might help some So if you really wanted to append values to an existing header, or add new values to an existing header, the best way possible to write a wrapper and set the value in the wrapper.

    Then chain the response in the filter

    HttpServletResponse response = (HttpServletResponse) servletResponse;
    ByteArrayPrinter pw = new ByteArrayPrinter();
    
    // Create a wrapper
    HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) {
    
        @Override
        public void setContentType(final String type) {
            super.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        }
    
        @Override
        public PrintWriter getWriter() {
            return pw.getWriter();
        }
    
        // set the outputstream content type to JSON
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            ServletResponse response = this.getResponse();
    
            String ct = (response != null) ? response.getContentType() : null;
            if (ct != null && ct.contains(APPLICATION_XHTML)) {
                response.setContentType(ct + AppConstants.CONSTANT_COMMA + MediaType.APPLICATION_JSON_UTF8_VALUE);
            }
            return pw.getStream();
        }
    
    };
    chain.doFilter(httpRequest, wrappedResp);
    

    Here is the ByteArrayPrinter.java

    public class ByteArrayPrinter {
    
        private ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
        private PrintWriter pw = new PrintWriter(baos);
    
        private ServletOutputStream sos = new ByteArrayServletStream(baos);
    
        public PrintWriter getWriter() {
            return pw;
        }
    
        public ServletOutputStream getStream() {
            return sos;
        }
    
        byte[] toByteArray() {
            return baos.toByteArray();
        }
    }
    

    And here is the ByteArrayServletOutputStream

    public class ByteArrayServletStream extends ServletOutputStream {
    
        ByteArrayOutputStream baos;
    
        ByteArrayServletStream(ByteArrayOutputStream baos) {
            this.baos = baos;
        }
    
        @Override
        public void write(int param) throws IOException {
            baos.write(param);
        }
    
        @Override
        public boolean isReady() {
            // TODO Auto-generated method stub
            return false;
        }
    
        @Override
        public void setWriteListener(WriteListener listener) {
            // TODO Auto-generated method stub
    
        }
    
    }
    
    0 讨论(0)
  • 2020-12-06 10:54

    From The Java EE Tutorial

    A filter that modifies a response must usually capture the response before it is returned to the client. To do this, you pass a stand-in stream to the servlet that generates the response. The stand-in stream prevents the servlet from closing the original response stream when it completes and allows the filter to modify the servlet’s response.

    To pass this stand-in stream to the servlet, the filter creates a response wrapper that overrides the getWriter or getOutputStream method to return this stand-in stream. The wrapper is passed to the doFilter method of the filter chain. Wrapper methods default to calling through to the wrapped request or response object. This approach follows the well-known Wrapper or Decorator pattern described in Design Patterns,

    0 讨论(0)
  • 2020-12-06 10:57

    I use this in my project with Spring 3.0.x:

    public class MyFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException
        {
            response.addHeader("headerName", "headerValue");
            filterChain.doFilter(request, response);
        }
    }
    

    Works fine.

    0 讨论(0)
  • 2020-12-06 11:06

    After filterChain.doFilter is called it's too late to do anything with the response. At this point, the entire response was already sent to the client.

    You need to build a wrap response into your own classes, pass these wrappers into doFilter method and handle any processing in your wrappers.

    There is already a response wrapper: HttpServletResponseWrapper that you can extend. For example:

    public class MyResponseRequestWrapper extends HttpServletResponseWrapper{
        public MyResponseRequestWrapper(HttpServletResponse response) {
            super(response);
        }
    }
    

    Your filter:

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
    
        HttpServletResponse myResponse = (HttpServletResponse) response;
        MyResponseRequestWrapper responseWrapper = new MyResponseRequestWrapper(myResponse);
        responseWrapper.addHeader("Access-Control-Allow-Origin", "*");
        filterChain.doFilter(request, myResponse);
    }
    
    0 讨论(0)
提交回复
热议问题