1. 程式人生 > >使用Filter獲取伺服器響應內容(字串)

使用Filter獲取伺服器響應內容(字串)

spring mvc架構的web應用中,spring框架將資料model渲染至jsp頁面並將最終結果輸出到客戶端,model和jsp模板可以由程式定義,但是頁面渲染及結果輸出過程是由spring封裝,對程式設計師來說是不可控的。想要取得輸出的內容有一種方法就是自定義ServletOutputStream物件,在資料寫入至目標流同時寫入我們自定義的位元組流,通過位元組流便可取得輸出內容。程式碼如下:

public class CustomServletOutputStream extends ServletOutputStream {

    private OutputStream outputStream;

    private ByteArrayOutputStream byteArrayOutputStream;

    public CustomServletOutputStream(OutputStream outputStream){

        this.outputStream=outputStream;

        byteArrayOutputStream=new ByteArrayOutputStream();

    }

    @Override

    public boolean isReady() {

        return false;

    }

    @Override

    public void setWriteListener(WriteListener writeListener) {

    }

    @Override

    public void write(int b) throws IOException {

        outputStream.write(b);

        byteArrayOutputStream.write(b);

    }

    public byte[] getCopy(){

        return byteArrayOutputStream.toByteArray();

    }

}

自定義response類為獲取位元組流資料提供介面

public class CustomHttpServletResponse extends HttpServletResponseWrapper {

    private ServletOutputStream outputStream;

    private PrintWriter writer;

    private CustomServletOutputStream cout;

    /**

     * Constructs a response adaptor wrapping the given response.

     *

     * @throws IllegalArgumentException

     *          if the response is null

     */

    public CustomHttpServletResponse(HttpServletResponse response) {

        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();

            cout = new CustomServletOutputStream(outputStream);

        }

        return cout;

    }

    @Override

    public PrintWriter getWriter() throws IOException {

        if (outputStream != null) {

            throw new IllegalStateException("getOutputStream() has already been called on this response.");

        }

        if (writer == null) {

            cout = new CustomServletOutputStream(getResponse().getOutputStream());

            writer = new PrintWriter(new OutputStreamWriter(cout, getResponse().getCharacterEncoding()), true);

        }

        return writer;

    }

    @Override

    public void flushBuffer() throws IOException {

        if (writer != null) {

            writer.flush();

        } else if (outputStream != null) {

            cout.flush();

        }

    }

    public byte[] getCopy() {

        if (cout != null) {

            return cout.getCopy();

        } else {

            return new byte[0];

        }

    }

}

Filter類

public class LXCFFilter implements Filter {

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws      IOException, ServletException {

        HttpServletRequest hrequest=(HttpServletRequest)request;

        CustomHttpServletResponse cresponse=new CustomHttpServletResponse((HttpServletResponse)response);

        chain.doFilter(request,cresponse);

//      cresponse.flushBuffer();

        byte[] data=cresponse.getCopy();

        String htmStr=new String(data,response.getCharacterEncoding());

        //do something

        }

    @Override

    public void destroy() {

    }

}

在web.xml中新增filter

    <filter>

        <filter-name>lxcfFilter</filter-name>

        <filter-class>com.gtan.lxcf.common.LXCFFilter</filter-class>

    </filter>

    <filter-mapping>

        <filter-name>lxcfFilter</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>