3

为了这是我需要发生的事情:

请求blah.com/test

  1. ServletFilter A - 创建配置文件,然后调用chain.doFilter
  2. ServletFilter B(被跳过,因为 url 模式不匹配)
  3. Servlet - 更改配置文件,repsonse.setStatus&response.addHeader("Location", target)
  4. ServletFilter A - 应该根据配置文件创建一个 cookie

实际发生了什么:

  1. ServletFilter A - 创建配置文件,然后调用chain.doFilter
  2. ServletFilter B(被跳过,因为 url 模式不匹配)
  3. Servlet - 更改配置文件,repsonse.setStatus&response.addHeader("Location", target)
  4. 重定向已提交,ServletFilter A 未完成任务

我认为这可能与您可以在 ServletFilter 配置中设置的调度程序值有关。

有任何想法吗?

4

2 回答 2

4

我认为响应在到达时会做出ServletFilter A承诺Step 4。一旦响应提交,即标头被写入客户端,您将无法进行需要添加标头的操作。添加cookies之类的操作。

如果您希望在Step 4尝试包装HttpServletResponse并返回自定义输出流之前不提交响应,该输出流缓冲数据直到它到达step 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();
    }

}
}
于 2012-06-14T05:31:50.773 回答
1

它工作正常。无论如何,重要的是要注意,以防缓冲的响应大小小于 8KB,除非您在调用之前刷新响应,否则它将不起作用getWrapperBytes()

这是由于 servlet-api 内部实现。

于 2012-08-16T14:19:03.920 回答