WEB开发中,可能会遇到这样的需求,统一修改页面的某类标签。一种办法是直接修改返回的html页面,但这样的做法太粗糙且无复用性。另一种办法是在控制层修改http的响应内容,那么如何在java代码中获取、修改并返回正确的内容呢。又或者我们只是单纯地想更深入地了解httpServletResponse,请看以下内容。
首先,关于http,我们接触最多的两个接口是HttpServletRequest和HttpServletResponse。记住,它们都是接口。
apache官方文档(http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletResponse.html)是这样描述HttpServletResponse接口的:
扩展于servletResponse接口,在发送响应时提供http定制服务,比如它包含了访问http消息头和cookies的方法。
ServletResponse
servlet容器创建ServletResponse对象并且将其作为参数传递给servlet的服务方法(doGet, doPost等).
通过调用getOutputStream()返回的ServletOutputStream对象实现二进制数据发送。而字符数据的发送,则通过调用getWriter()返回的PrintWriter对象实现。
而已知的HttpServletResponse实现类为HttpServletResponseWrapper
该类可按照开发者意愿被继承,用以适配servlet响应。该类实现了Wrapper或Decorator模式,方法默认按封装的响应对象访问调用。
由此可见,核心部分在于ServletOutputStream对象的处理,也就是HttpServletResponseWrapper如何适配servlet。
public abstract class ServletOutputStream ServletOutputStream extends java.io.OutputStream
提供了发送二进制数据到客户端的输出流。一个servletoutputstream对象通常通过ServletResponse.getOutputStream()方法取回。
我们看到这是一个servlet容器实现的抽象类,它的子类必须实现java.io.OutputStream.write(int)方法。这句很关键,可以说是本次手动实现响应处理的突破口。
总的思路是,利用HttpServletResponseWrapper封装HttpServletResponse,使 HttpServletResponse采用我们自己定义的输入流(OutputStream)。这样,我们就可以通过这个OutputStream得到 目标jsp页面内容。
public void getContent(ServletRequest req, ServletResponse resp,) throws IOException, ServletException{
ByteArrayOutputStream os =new ByteArrayOutputStream();
HttpServletResponseWrapper response = new HttpServletResponseWrapper((HttpServletResponse) resp, os);
//刷新response的输出流, 在某些情况下, 如果不刷新的话, 会导致部分信息还在缓存中, 而没有写入os中
response.flush();
String html = new String(os.toByteArray(), "UTF-8");
resp.getWriter().print(html);
resp.setContentLength(html.getBytes("UTF-8").length);
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().flush();
}
public class HttpServletResponseWrapper extends
javax.servlet.http.HttpServletResponseWrapper implements Serializable {
private static final long serialVersionUID = -6723255025479924073L;
public HttpServletResponseWrapper(HttpServletResponse response,
OutputStream outputStream) {
super(response);
statusCode = 200;
this.servletOutputStream = new ServletOutputStreamWrapper(outputStream);
}
public ServletOutputStream getOutputStream() {
return servletOutputStream;
}
public void setStatus(int code) {
statusCode = code;
super.setStatus(code);
}
public void sendError(int i, String string) throws IOException {
statusCode = i;
super.sendError(i, string);
}
public void sendError(int i) throws IOException {
statusCode = i;
super.sendError(i);
}
public void sendRedirect(String string) throws IOException {
statusCode = 302;
super.sendRedirect(string);
}
public void setStatus(int code, String msg) {
statusCode = code;
super.setStatus(code);
}
public int getStatus() {
return statusCode;
}
public void setContentLength(int length) {
contentLength = length;
super.setContentLength(length);
}
public int getContentLength() {
return contentLength;
}
public void setContentType(String type) {
contentType = type;
super.setContentType(type);
}
public String getContentType() {
return contentType;
}
public PrintWriter getWriter() throws IOException {
if (writer == null)
writer = new PrintWriter(new OutputStreamWriter(
servletOutputStream, getCharacterEncoding()), true);
return writer;
}
public void addHeader(String name, String value) {
String header[] = { name, value };
headers.add(header);
super.addHeader(name, value);
}
public void setHeader(String name, String value) {
addHeader(name, value);
}
public Collection<String[]> getHeaders() {
return headers;
}
public void addCookie(Cookie cookie) {
cookies.add(cookie);
super.addCookie(cookie);
}
public Collection<Cookie> getCookies() {
return cookies;
}
public void flushBuffer() throws IOException {
flush();
super.flushBuffer();
}
public void reset() {
super.reset();
cookies.clear();
headers.clear();
statusCode = 200;
contentType = null;
contentLength = 0;
}
public void resetBuffer() {
super.resetBuffer();
}
public void flush() throws IOException {
if (writer != null)
writer.flush();
servletOutputStream.flush();
}
public String encodeRedirectUrl(String s) {
return super.encodeRedirectURL(s);
}
public String encodeUrl(String s) {
return super.encodeURL(s);
}
private int statusCode;
private int contentLength;
private String contentType;
private final List<String[]> headers = new ArrayList<String[]>();
private final List<Cookie> cookies = new ArrayList<Cookie>();
private ServletOutputStream servletOutputStream;
private PrintWriter writer;
}
public class ServletOutputStreamWrapper extends ServletOutputStream {
public ServletOutputStreamWrapper(OutputStream stream) {
this.stream = stream;
}
public void write(int b) throws IOException {
stream.write(b);
}
public void write(byte b[]) throws IOException {
stream.write(b);
}
public void write(byte b[], int off, int len) throws IOException {
stream.write(b, off, len);
}
private OutputStream stream;
}
分享到:
相关推荐
源代码 博文链接:https://msj.iteye.com/blog/179663
javax.servlet.http.HttpServletResponseWrapper.class javax/servlet/resources/web-app_2_2.dtd javax/servlet/resources/j2ee_1_4.xsd javax/servlet/resources/j2ee_web_services_client_1_1.xsd javax/servlet/...
所以在JSP容器通过Response获取输出流之前,前面的流并没有关闭,所以会造成该异常的报出。 本文解决办法: 在前面所说的网络解决办法中,使用的是一种躲避的方式解决该问题,也就是置之不理。 这里提供一个...
Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. -------------------------------------------------------------------------------- G ...
HttpServletResponseWrapper HttpSession HttpSessionActivationListener HttpSessionAttributeListener HttpSessionBindingEvent HttpSessionBindingListener HttpSessionContext HttpSessionEvent ...
javax.servlet.http.HttpServletResponseWrapper javax.servlet.http.HttpSessionBindingListener javax.servlet.http.HttpSessionAttributeListener javax.servlet.http.HttpSessionActivationListener