有时我们希望在请求输出之前对response对象进行一些额外的操作,比如从response读出相应的数据,并持久化到数据库中,最后再发往客户端,但由于response输出流对象没有Buffer功能,且只能读取一次,幸好我们可以通过继承HttpServletResponseWrapper类来达到我们的需求。下面就具本通过实现此类来完成上面提到的功能。
HttpServletResponseWrapper为我们实现对response对象的后处理提供了帮助,你只需编写一个HttpServletResponseWrapper的子类,加入自己的功能实现(修饰器模式)。那么子类化 HttpServletResponseWrapper都需要重写那些方法呢?
1、获取response对象,并将输出存放在自定义的流里面,那么关于输 出流(outputStream、writer)的操作都是需要重写的了:
1)以流的方式获取输出——重写getOutputStream() //返回一般为打印流,其底层是对ServletOutputStream引用。
2)以字符方式获取输出——重写getWriter() //直接对ServletOutputStream的引用
3)刷新流——重写flushBuffer()
4)重置流——重写reset()
然后加入新增的获取输出数据的方法就ok了。
2、定义response包装器WapperedResponse继承HttpServletResponseWrapper
上面是我们对HttpServletResponseWrapper的包装。随后我们可以编写自已一Filter来完成实现的工作。
这样在页面上调用后将会输出我们修改后的结果如上例为:jack
HttpServletResponseWrapper为我们实现对response对象的后处理提供了帮助,你只需编写一个HttpServletResponseWrapper的子类,加入自己的功能实现(修饰器模式)。那么子类化 HttpServletResponseWrapper都需要重写那些方法呢?
1、获取response对象,并将输出存放在自定义的流里面,那么关于输 出流(outputStream、writer)的操作都是需要重写的了:
1)以流的方式获取输出——重写getOutputStream() //返回一般为打印流,其底层是对ServletOutputStream引用。
2)以字符方式获取输出——重写getWriter() //直接对ServletOutputStream的引用
3)刷新流——重写flushBuffer()
4)重置流——重写reset()
然后加入新增的获取输出数据的方法就ok了。
2、定义response包装器WapperedResponse继承HttpServletResponseWrapper
public class WrapperedResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream buffer = null;
private ServletOutputStream out = null;
private PrintWriter writer = null;
public WrapperedResponse(HttpServletResponse resp) throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();// 真正存储数据的流
out = new WapperedOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
}
/**重载父类获取outputstream的方法*/
@Override
public ServletOutputStream getOutputStream() throws IOException {
return out;
}
/**重载父类获取writer的方法*/
@Override
public PrintWriter getWriter() throws UnsupportedEncodingException {
return writer;
}
/**重载父类获取flushBuffer的方法*/
@Override
public void flushBuffer() throws IOException {
if (out != null) {
out.flush();
}
if (writer != null) {
writer.flush();
}
}
@Override
public void reset() {
buffer.reset();
}
/**将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据*/
public byte[] getResponseData() throws IOException {
flushBuffer();
return buffer.toByteArray();
}
/**内部类,对ServletOutputStream进行包装*/
private class WapperedOutputStream extends ServletOutputStream {
private ByteArrayOutputStream bos = null;
public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
bos = stream;
}
@Override
public void write(int b) throws IOException {
bos.write(b);
}
@Override
public void write(byte[] b) throws IOException {
bos.write(b, 0, b.length);
}
}
}
上面是我们对HttpServletResponseWrapper的包装。随后我们可以编写自已一Filter来完成实现的工作。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("begin filter invoke!");
WrapperedResponse wrapResponse = new WrapperedResponse((HttpServletResponse)response);
chain.doFilter(request, wrapResponse);
byte[] data = wrapResponse.getResponseData();
log.info("原始数据: " + new String(data));
String tempData = new String("jack");
ServletOutputStream out = response.getOutputStream();
out.write(tempData.getBytes());
out.flush();
log.info("end filter invoke!");
}
这样在页面上调用后将会输出我们修改后的结果如上例为:jack