HttpServletResponse说明
基本概述
HttpServletResponse是用于将Servlet处理好的内容发送给浏览器的类,服务器通过对HttpServletResponse对象中的内容进行截取、拼接就能获得一个完整的HTTP响应信息。
参考文档:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/index.html
依据http协议里面讲过的响应协议格式,response对象的功能分为以下四种:
- 响应首行:发送状态码;
- 响应头:设置响应头信息;
- 响应体:设置响应正文;
- 重定向;
负责向客户端(浏览器)发送响应状态码的相关方法
void | setStatus(int sc) Sets the status code for this response. |
l response.setStatus(200):设置状态码;
void | sendError(int sc) Sends an error response to the client using the specified status code and clears the buffer. |
void | Sends an error response to the client using the specified status and clears the buffer. |
l response.sendError(404, “您要查找的资源不存在”):当发送错误状态码时,Tomcat会跳转到固定的错误页面去,但可以显示错误信息。
HttpServletResponse定义了很多状态码的常量(具体可以查看Servlet的API),当需要向客户端发送响应状态码时,可以使用这些常量,避免了直接写数字,常见的状态码对应的常量:
状态码404对应的常量
static int | Status code (404) indicating that the requested resource is not available. |
状态码200对应的常量
static int | Status code (200) indicating the request succeeded normally. |
状态码500对应的常量
static int | Status code (500) indicating an error inside the HTTP server which prevented it from fulfilling the request. |
负责向客户端(浏览器)发送响应头的相关方法
当Servlet向客户端发送响应消息时,由于HTTP协议的响应头字段有很多种,为此,在HttpServletResponse接口中,定义了一系列设置HTTP响应头字段的方法,如表1-1所示。
表1-1 设置响应消息头字段的方法
方法声明 | 功能描述 |
void addHeader(String name, String value) | 这两个方法都是用来设置HTTP协议的响应头字段, 其中,参数name用于指定响应头字段的名称,参数value用于指定响应头字段的值。 不同的是,addHeader()方法可以增加同名的响应头字段,而setHeader()方法则会覆盖同名的头字段 |
void setHeader(String name, String value) | |
void addIntHeader(String name, int value) | 这两个方法专门用于设置包含整数值的响应头。避免了使用addHeader()与setHeader()方法时, 需要将int类型的设置值转换为String类型的麻烦 |
void setIntHeader(String name, int value) | |
void setContentLength(int len) | 该方法用于设置响应消息的实体内容的大小,单位为字节。 对于HTTP协议来说,这个方法就是设置Content-Length响应头字段的值 |
void setContentType(String type) | 该方法用于设置Servlet输出内容的MIME类型,对于HTTP协议来说,就是设置Content-Type响应头字段的值。 例如,如果发送到客户端的内容是jpeg格式的图像数据,就需要将响应头字段的类型设置为“image/jpeg”。 需要注意的是,如果响应的内容为文本,setContentType()方法的还可以设置字符编码,如:text/html;charset=UTF-8 |
void setCharacterEncoding(String charset) | 该方法用于设置输出内容使用的字符编码,对HTTP 协议来说,就是设置Content-Type头字段中的字符集编码部分。一般不使用。 |
需要注意的是,在表1-1列举的一系列方法中,addHeader()、setHeader()、addIntHeader()、setIntHeader()方法都是用于设置各种头字段的,而setContetType() 和setCharacterEncoding()方法用于设置字符编码,这些设置字符编码的方法可以有效解决乱码问题。
负责向客户端(浏览器)发送数据的相关方法
由于在HTTP响应消息中,大量的数据都是通过响应消息体传递的,因此,ServletResponse遵循以IO流传递大量数据的设计理念。在发送响应消息体时,定义了两个与输出流相关的方法,具体如下。
1.getOutputStream()方法
l ServletOutputStream out = response.getOutputStream():获取字节流
该方法所获取的字节输出流对象为ServletOutputStream类型。由于ServletOutputStream是OutputStream的子类,它可以直接输出字节数组中的二进制数据。因此,要想输出二进制格式的响应正文,就需要使用getOutputStream()方法。比如文件下载!
2.getWriter()方法
l PrintWriter out = response.getWriter():获取字符流;
该方法所获取的字符输出流对象为PrintWriter类型。由于PrintWriter类型的对象可以直接输出字符文本内容,因此,要想输出内容全为字符文本的网页文档,需要使用getWriter()方法。
getWriter()和getOutputStream()的区别
getWriter() 用于向客户机回送字符数据
getOutputStream() 返回的对象,可以回送字符数据,也可以回送字节数据(二进制数据)
OutputStream os=response.getOutputStream();
os.write("hello,world".getBytes());
PS:通过该方法也能用getOutputStream()回送字符数据
如何选择
如果是回送字符数据,则使用 PrintWriter对象 ,效率高
如果是回送字节数据(binary date) ,则只能使用 OutputStream
注意事项
PrintWriter,OutputStream 这两个流不能同时使用
比如:
OutputStream os=response.getOutputStream();
os.write("hello,world".getBytes());
PrintWriter out=response.getWriter();
out.println("abc");
会报错:
java.lang.IllegalStateException: getOutputStream() has already been called for this response
不能同时使用PrintWriter和OutputStream的原因
结论:Web服务器在完成一次service之后会自动关闭流,并销毁当前的request和response对象,故无法同时使用两个流。
重定向
案例:
package com.pc;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet7 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
// 演示下载文件
response.setHeader("Content-Disposition", "attachment; filename=EVO_120G.jpg");
// 打开文件
// 1.获取到要下载文件的全路径
String path = this.getServletContext().getRealPath("/EVO_120G.jpg");
// 测试
System.out.println("path=" + path);
// 2.创建文件输入流
FileInputStream fis = new FileInputStream(new File(path));
// 做一个缓冲字符数组
byte buff[] = new byte[1024];
int length = 0;
// 3.指向response的输出流
OutputStream os = response.getOutputStream();
// 4.循环读出
// length表示每次实际读入的字节数
while((length = fis.read(buff)) != -1){
os.write(buff, 0, length);
}
// 关闭
os.close();
fis.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
----------参考《韩顺平.细说Servlet》