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;
}
分享到:
相关推荐
使用`RequestDispatcher`接口的`include`方法获取JSP页面的内容。 4. 将获取到的JSP内容输出到一个`ByteArrayOutputStream`对象中。 5. 最后,将`ByteArrayOutputStream`中的内容写入到指定的HTML文件中。 #### ...
2. **处理请求并生成内容**:Servlet调用相应的JSP页面,获取动态生成的HTML内容。 3. **保存为静态页面**:将生成的HTML内容写入硬盘上的HTML文件中,形成静态页面。 4. **返回结果**:向客户端发送操作成功的消息...
由于Filter无法直接修改ServletResponse的编码,我们需要在响应内容发送前,通过`HttpServletResponseWrapper`包装原始响应对象,然后在包装类中重写`getOutputStream()`方法,返回一个自定义的`ServletOutputStream...
HttpServletResponse rep = new HttpServletResponseWrapper(response) {...}; // 将请求和包装后的响应传递给RequestDispatcher进行处理 rd.include(request, rep); // 将JSP输出的内容写入到HTML文件 pw....
### JSP实现将动态网页转换成...通过上述步骤,我们可以有效地利用JSP技术将动态内容转换为静态页面,从而实现性能优化的目标。这种方法不仅适用于论坛类应用,还可以广泛应用于各类需要频繁访问数据库的Web项目中。
8. **HTTP客户端API**:Java 7引入了`HttpURLConnection`类,Java 11引入了`HttpClient`模块,用于从Java程序中发起HTTP请求,获取网页内容。 9. **DOM和SAX解析器**:Java提供了对XML文档的解析支持,DOM解析器将...
所以在JSP容器通过Response获取输出流之前,前面的流并没有关闭,所以会造成该异常的报出。 本文解决办法: 在前面所说的网络解决办法中,使用的是一种躲避的方式解决该问题,也就是置之不理。 这里提供一个...
- **class: HttpServletResponseWrapper**:用于包装HttpServletResponse对象,允许修改响应属性。 ### 3. Filters Filter在Servlet容器中起着拦截器的作用,可以在请求到达目标资源之前或响应发送到客户端之前...