- 响应消息:服务器端发送给客户端的数据
1. 响应数据格式:
a. 响应行
1. 格式:协议/版本 响应状态码 状态码描述
例如:
HTTP/1.1 200 OK
2. 响应状态码:
服务器告诉客户端浏览器本次请求和响应的状态
分类:
* 1xx:服务器接收客户端消息,没有接收完成,发送1xx响应码询问客户端是否还有数据
* 2xx:
* 3xx:重定向
-- 302 资源重定向 当浏览器访问服务器资源A时,A不能处理该服务,但C资源可以处理
将C资源的访问地址随302一起发送给浏览器
-- 304 访问缓存 当浏览器访问服务器的资源,服务器该资源没改变,
客户端有缓存,则304告诉浏览器访问缓存即可
* 4xx:客户端错误
-- 404 没有该路径对应的资源
-- 405 请求方式没有对应的doXxx方法
* 5xx:服务器端错误
-- 500 服务器内部出现错误
b. 响应头
1. 格式:
响应头名称:值
2. 例如:
* Content-Type:服务器告诉客户端本次响应体的数据格式,字符集编码
-- Content-Type:text/html;charset=utf-8
* Content-disposition:服务器告诉客户端以什么格式打开响应体数据
-- in-line:默认值。在当前页面打开
-- attachment;filename=xxx:以附件形式打开响应体。常用于客户端点击后提示文件下载
c. 响应空行
d. 响应体
1. 响应体为传输的数据
-- html页面(字符串)
-- 图片(二进制)
- response对象
1. 功能:设置响应消息:
a. 设置响应行
* setStatus(int sc):设置相应状态码
b, 设置响应头
* setHeader(String name, String value)
c. 设置响应体
* 设置步骤:
1. 获取输出流:用于向响应体中输入数据
* 字符输出流:PrintWriter getWriter()
-- 输出字符数据
-- 该输出流有response创建,默认使用ISO-8859-1字符集
-- 因此在获取流对象之前设置字符集编码
response.setCharacterEncoding("字符集")
设置完成后,还需要告诉浏览器使用何种字符集解析数据,设置响应头的Content-Type属性值
response.setHeader("content-type","数据格式类型;charset=字符集")
* 字节输出流:ServletOutputStream getOutputStream()
-- 输出任意类型数据
2. 使用输出流,将数据输出到客户端浏览器
3. response提供简便的成员方法设置Content-Type属性值:
* response.setContentType("数据格式类型;charset=字符集");
2. 重定向案例:
a. 重定向也是资源转发的一种方式 -- 区别服务器内部转发
b. 重定向实现需要两步:
1. 告诉浏览器需要进行重定向 -- 设置状态码为302
response.setStatus(302);
2. 告诉浏览器重定向的目标在哪里 -- 设置响应头的location为资源的路径
response.setHeader("location","new_urlPattern")
c. 由于只需要修改new_Pattern,提供了一个简化的成员方法:sendRedirect(String urlPattren)
response.sendRedirect("new_urlPattern")
d. 重定向与转发的区别:
1. 重定向的地址栏会发生变化 -- 转发时地址栏不会发生变化
2. 重定向的可以访问服务器外的站点资源 -- 转发只能访问服务器内部资源
3. 重定向发送两次请求 -- 转发发送一次请求数据,因此可以使用request对象共享数据
- 资源路径的书写技巧
1. 书写绝对路径时:
* 为了避免虚拟路径写死,使得修改虚拟路径时需要修改大量代码
* 动态获取虚拟目录
* 使用request对象成员方法获取虚拟目录,再拼接具体资源的urlPattern
* 例如:
String contextPath = request.getContextPath();
request.sendRedirect(contextPath+"/urlPattren");
2. 书写相对路径时:
* 需要理清楚当前路径和目标资源路径的关系
* ./表示当前目录下
* ../表示上一级目录
- ServletContext对象
1. 概念:代表整个web应用,可以和程序的容器来通信
2. 获取ServletContext对象:
a. 通过request对象获取:
ServletContext sc = request.getServletContext();
b. 通过HttpServlet成员方法获取:
ServletContext sc = this.getServletContext();
c. 对于同一个web应用,不管通过哪种方式获取到的都是同一个对象
2. 功能:
a. 获取MIME对象:
1. MIME类型:在互联网中通信过程中定义的一种文件数据类
* 格式:
大类型/小类型
-- text/html
-- image/jpeg
2. 动态获取:
String getMimeType(String fileName);
-- sc.getMimeType("a.html") --> text/html
-- sc.getMimeType("a.jpeg") --> image/jpeg
b. 域对象:共享数据
1. 用于共享数据的方法:
* setAttribute
* getAttribute
* removeAttribute
2. 由于该对象代表整个web应用,该域包含整个项目,所有用户都可以共享数据
3. 该对象生命周期为:在服务器启动后创建,服务器关闭前销毁。存储过多共享数据影响性能
c. 获取文件在服务器的真实路径
1. 一个web项目将来会存在tomcat和工作空间各一份,而获取文件路径应该是工作空间而不是tomcat中路径
2. 获取路径成员方法:
* String getRealPath("在web目录的相对路径");
-- 如果在工作空间的/src/目录下,则在web应用中表示的路径为/WEB-INF/classes/目录下
-- 如果在工作空间的/web/目录下,则按照相对路径写文件名/fileName即可
-- 如果在工作空间的/web/WEB-INF/目录下,则书写相对路径/WEB-INF/fileName即可
3. 文件下载:
1. 如果资源文件能够被浏览器解析,则会直接在浏览器中打开
-- 如果连接指向图片,浏览器会直接加载图片展示,而非下载
2. 如果资源文件不能被解析,则浏览器会提示下载
-- 如果连接指向视频,浏览器解析不了,则会提示下载
3. 使用响应头,设置资源文件的打开方式:
* content-disposition:attachment;filename=xxx
4. 实现步骤:
1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
-- href的属性中需要使用?来传递参数的资源名称
-- href="/downloadServlet?filename=1.jpg"
2. 定义Servlet:
* 获取文件名称
* 使用字节流加载文件进内存
-- 用流关联文件
* 指定response的响应头
-- content-type:文件的mimeType --> sc.getMimeType(flieName)
-- content-disposition:attachment;filename=xxx
* 将数据写到response的输出流:
-- 一读一写
byte[] buff = new byte[1024 * 8];
int len = 0;
while((len = fis.read(buff)) != -1)
{
sos.write(buff,0,len);
}
fis.close();
5. 资源文件中文名乱码问题:
* 在设置content-disposition属性中的filename时,需要先使用对方浏览器的编码方式编码中文名称
* 使用自定义工具类DownLoadUtils,对请求头信息中agent浏览器信息进行判别,使用对应的编码方式编码
package cn.xxx.utils;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
* 调用工具类中的静态成员方法即可
String new_fileName = DownLoaded.getFileName(agent, fileName);