使用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>