如何在ServletResponse,HTTPServletResponse或者Filter中獲取HTTP的內容
阿新 • • 發佈:2018-12-10
由於HTTPServletResponse只提供了getWriter和getOutputStream方法,並未提供獲取報文體的方法。如果在開發時遇到相應需求,可以使用HTTPServletResponseWrapper重新構造response。具體方法如下所示,例項為spring boot的一個過濾器,該示例用於演示如何將系統的HTTPServletResponse替換為可以獲得報文內容的自定義HTTPServletResponse。
import java.io.ByteArrayOutputStream; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.WriteListener; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; @WebFilter(urlPatterns="/*" ,filterName="responseFilter") public class ResponseFilter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub ServletResponseWrapper responseWrapper=new ServletResponseWrapper((HttpServletResponse)arg1); arg2.doFilter(arg0, responseWrapper); System.out.println(((HttpServletRequest)arg0).getServletPath()); System.out.println(responseWrapper.getResponseBody()); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } public static class MonitorOutoutStream extends ServletOutputStream{ private ServletOutputStream output; private ByteArrayOutputStream copy=new ByteArrayOutputStream(); public MonitorOutoutStream(ServletOutputStream output) { super(); this.output = output; } @Override public boolean isReady() { // TODO Auto-generated method stub return output.isReady(); } @Override public void setWriteListener(WriteListener arg0) { // TODO Auto-generated method stub output.setWriteListener(arg0); } @Override public void write(int b) throws IOException { // TODO Auto-generated method stub output.write(b); copy.write(b); } @Override public void write(byte[] b) throws IOException { // TODO Auto-generated method stub output.write(b); copy.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { // TODO Auto-generated method stub output.write(b,off,len); copy.write(b,off,len); } public byte[] getWroteInfo() { return copy.toByteArray(); } @Override public void flush() throws IOException { // TODO Auto-generated method stub output.flush(); copy.close(); } @Override public void close() throws IOException { // TODO Auto-generated method stub output.close(); copy.close(); } } public static class ServletResponseWrapper extends HttpServletResponseWrapper{ private volatile MonitorOutoutStream mos; public ServletResponseWrapper(HttpServletResponse response) { super(response); // TODO Auto-generated constructor stub } @Override public ServletOutputStream getOutputStream() throws IOException { // TODO Auto-generated method stub if(mos==null){ synchronized (this) { if(mos==null){ mos = new MonitorOutoutStream(super.getOutputStream()); } } } return mos; } public String getResponseBody(){ return new String(mos.getWroteInfo()); } } }
本文通過重寫getOutputstream方法,替換原本的ServletOutputStream。重寫所有的ServletOutputStream方法。當ServletOuputStream的write被呼叫的時候,同時寫入一份到我們的copy當中,這樣來達到獲取報文的目的。
不過,就一般而言,從response獲取資訊這種需求應該是不存在的,當你發現需要用到上述程式碼時,從程式碼設計結構的角度可能有更好的解決方案。