Java 响应正在提交,doFilter链已断开

Java 响应正在提交,doFilter链已断开,java,servlets,redirect,servlet-filters,Java,Servlets,Redirect,Servlet Filters,为了做到这一点,我需要: 请求访问blah.com/test ServletFilter A-创建配置文件,然后调用chain.doFilter ServletFilter B(由于url模式不匹配而被跳过) Servlet-更改配置文件,repsonse.setStatus&response.addHeader(“位置”,目标) ServletFilter A-应基于配置文件创建cookie 实际发生的情况: ServletFilter A-创建配置文件,然后调用chain.doFilter

为了做到这一点,我需要:

请求访问
blah.com/test

  • ServletFilter A-创建配置文件,然后调用
    chain.doFilter
  • ServletFilter B(由于url模式不匹配而被跳过)
  • Servlet-更改配置文件,
    repsonse.setStatus
    &
    response.addHeader(“位置”,目标)
  • ServletFilter A-应基于配置文件创建cookie
  • 实际发生的情况:

  • ServletFilter A-创建配置文件,然后调用
    chain.doFilter
  • ServletFilter B(由于url模式不匹配而被跳过)
  • Servlet-更改配置文件,
    repsonse.setStatus
    &
    response.addHeader(“位置”,目标)
  • 重定向已提交,ServletFilter A未完成任务
  • 我认为这可能与您可以在ServletFilter配置中设置的dispatcher值有关


    有什么想法吗?

    我认为在
    步骤4
    中,当响应到达
    ServletFilter A
    时,响应就被提交了。一旦响应被提交,即头被写入客户端,您就不能执行需要添加头的操作。添加cookie之类的操作

    如果希望在
    步骤4
    之前不提交响应,请尝试包装
    HttpServletResponse
    并返回自定义输出流,该流缓冲数据直到到达
    步骤4
    ,然后提交响应

    以下是示例代码:

    public class ResponseBufferFilter implements Filter
    {
    public void init(FilterConfig filterConfig) throws ServletException
    {
    }
    
    public void doFilter(ServletRequest request, ServletResponse response, 
       FilterChain filterChain) throws IOException, ServletException
    {
        HttpServletResponse httpResponse = (HttpServletResponse)response;
        BufferResponseWrapper wrapper = new BufferResponseWrapper(httpResponse);
        filterChain.doFilter(request, resposneWrapper);
        response.getOutputStream().write(wrapper .getWrapperBytes());
    }
    
    public void destroy()
    {
    }
    
    private final class BufferResponseWrapper extends HttpServletResponseWrapper
    {
    
        MyServletOutputStream stream = new MyServletOutputStream();
    
        public BufferResponseWrapper(HttpServletResponse httpServletResponse)
        {
            super(httpServletResponse);
        }
    
        public ServletOutputStream getOutputStream() throws IOException
        {
            return stream;
        }
    
        public PrintWriter getWriter() throws IOException
        {
            return new PrintWriter(stream);
        }
    
        public byte[] getWrapperBytes()
        {
            return stream.getBytes();
        }
    }
    
    private final class MyServletOutputStream extends ServletOutputStream
    {
        private ByteArrayOutputStream out = new ByteArrayOutputStream();
    
        public void write(int b) throws IOException
        {
            out.write(b);
        }
    
        public byte[] getBytes()
        {
            return out.toByteArray();
        }
    
    }
    }
    

    它很好用。无论如何,需要注意的是,为了防止缓冲响应大小小于8KB,除非在调用
    getWrapperBytes()
    之前刷新响应,否则它将无法工作


    这是由于servlet api内部实现造成的。

    然后在
    response.getOutputStream()之后写入(wrapper.getWrapperBytes())我应该能够将cookies写入响应?或者在此之前?您应该在写入实际响应之前这样做。您的解决方案在没有响应有效负载的情况下运行良好。但是,当有一具尸体的时候,它就破裂了。我需要一只手。谢谢。这会将整个响应缓存到内存中,这可能是不可取的。这是另一个对我有效的解决方案