接收到一个请求后,Tomcat会创建一个request和response对象作为doGet/doPost方法的参数
request表示客户端请求的信息
response表示服务器响应的信息
在doGet方法内调用response.getWrite().write("xxx")来给response对象写入数据,
这些数据存放在response缓冲区
Tomcat会取出这些数据与自身信息组成成一个完整的响应信息反馈给客户端
所以response对象可以设置Http响应的响应行,响应头和响应体
response设置响应信息
响应行:HTTP/1.1 200 OK 成功响应的响应行
response.setStatus(int i);设置响应行的状态码
response.setStatus(302);
往响应头添加自定义参数
response.addDateHeader(name, new Date().getTime());添加响应头时间类型数据(以key:value的形式)
response.addIntHeader(name, int);添加响应头int类型数据(以key:value的形式)
response.addHeader(name, str);添加响应头string类型数据(常用),中文有乱码
response.addDateHeader("date", new Date().getTime());
response.addIntHeader("age", 23);
response.addHeader("name", java.net.URLEncoder.encode("张三", "utf-8"));
重定向
设置响应头已有的参数
response.setHeader(String name,String value)
重定向需要设置一个302的状态码,同时设置响应头Location参数值
response.setStatus(302);
response.setHeader("Location", "/MyServlet/response");
重定向代码封装后:
response.sendRedirect("/MyServlet/response");
重定向:客户端发送请求到服务器,服务器响应给客户端另一个请求资源地址
客户端去请求另一个资源
重定向需要两次请求
重定向后地址栏地址会发生改变
重定向可以访问外部网站
性能弱于请求转发
定时刷新
设置响应行中参数实现定时刷新
response.setHeader("refresh", "5;url=http://www.baidu.com");
获取请求行参数referer,可以实现防盗链功能
referer : http://localhost:8080/MyServlet/
响应出现中文乱码
response.setHeader("content-Type","text/html;charset=UTF-8");
设置响应体内容
response.getOutputStream();获取字节输出流对象
response.getWriter()获取字符输出流PrintWrite对象
调用输出流对象的write方法向响应对象response的缓冲区中写入数据
两个流对象不能同时调用,会报错
response的流不需要手动关闭,Tomcat容器会关闭
Tomcat会将缓存区的内容封装成http响应返回给浏览器
将数据写入缓冲区中时,会去ISO-8859-1编码表中查询对应的编码存入缓存区的数据,如果没有就显示?号
浏览器接收到响应后,解析响应获取数据,根据自身默认的编码去查询,然后将结果显示在页面上
所以response的乱码多是浏览器编码与Tomcat编码不一致导致的
只需要在response存入数据之前修改查询的编码表,然后更换浏览器要解码的编码表即可
response缓冲区有大小,可以设置
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "text/html;charset=UTF-8");
response.setContentType("text/html;charset=UTF-8");
自定义数据响应到浏览器上
设置浏览器的解析编码response.setContentType
response.getWriter().write()获取字符流并写入数据到缓存区
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("this is a servlet! 你好!");
}
浏览器的上传与下载
1.获取字节输入流读取本地文件
2.从response中获取字节输出流去读文件到缓存区
这种方式有缺陷,对于浏览器可以解析的文件,浏览器会直接显示
不会提示下载
ServletOutputStream out = response.getOutputStream();
String path = getServletContext().getRealPath("2.jpg");
System.out.println(path);
FileInputStream in = new FileInputStream(new File(path));
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) > 0) {
out.write(b, 0, len);
}
in.close();
out.close();
点击浏览器文件,对于不能解析的文件就提示下载,反之就是显示文件
浏览器默认显示jpg和txt,IE默认下载mp3文件
其他浏览器对mp3文件是默认播放
<a href="1.jpg">1.txt</a>
<a href="2.jpg">2.jpg</a>
<a href="3.mp3">3.mp3</a>
文件的下载就需要另外编写代码告诉浏览器,这些文件不要解析直接下载
需要设置响应头信息,告诉浏览器文件是用来下载的,不是显示的
Tomcat的conf文件夹中web.xml中配置了缺省的servlet和MIME的类型映射
<body>
<font size="24px">实现上传下载代码</font><br/>
<a href="file?filename=2.jpg">2.jpg</a>
<a href="file?filename=2.mp3">2.mp3</a>
<a href="file?filename=俊逸之才.jpg">俊逸之才.jpg</a>
</body>
上传/下载改进
1.获取要下载文件的文件名
2.通过ServletContext对象的getMimeType方法来获取要下载文件的MIME类型
浏览器是通过MIME类型来区分文件的
this.getServletContext().getMimeType(parameter)
3.告诉浏览器下载文件的MIME类型
response.setContentType(MIME类型)
4.通过Content-Disposition响应头参数告诉浏览器不要解析文件直接下载
response.setHeader("Content-Disposition", "attachment;filename=" + parameter);
5.根据文件名获取在本机的绝对地址
6.获取字节输入流读取文件
7.从response中获取字节输出流读取文件到缓存区
对于中文文件名的下载,下载文件的文件名会出错
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String parameter0 = request.getParameter("filename");
System.out.println("文件名: " + parameter0);
byte source[] = parameter0.getBytes("iso8859-1");
String parameter = new String(source, "UTF-8");
System.out.println("文件名: " + parameter);
response.setContentType(getServletContext().getMimeType(parameter));
response.setHeader("Content-Disposition", "attachment;filename=" + parameter);
String path = getServletContext().getRealPath(parameter);
InputStream inputStream = new FileInputStream(path);
ServletOutputStream outputStream = response.getOutputStream();
int len = 0;
byte[] b = new byte[1024];
while ((len = inputStream.read(b)) > 0) {
outputStream.write(b, 0, len);
}
inputStream.close();
outputStream.close();
}
以上代码对于中文名称的资源出现乱码,可以下载,但是下载的文件名为空
f12查看浏览器响应头信息可知
Content-Disposition:attachment;filename=????.jpg
因为转码后的parameter没有编码,而浏览器会对名称解码所导致的
不同的浏览器有对应的不同的编码方式
request.getHeader("User-Agent");获取浏览器信息
根据不同的浏览器对文件名进行编码String filenameEncoder;
将编码后的文件传递给响应头
response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoder);
String agent = request.getHeader("User-Agent");
String filenameEncoder = "";
if (agent.contains("MSIE")) {
filenameEncoder = URLEncoder.encode(parameter, "utf-8");
filenameEncoder = filenameEncoder.replace("+", " ");
} else if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
filenameEncoder = "?utf-8?B?" + base64Encoder.encode(parameter.getBytes("utf-8")) + "?=";
} else {
filenameEncoder = URLEncoder.encode(parameter, "utf-8");
}
response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoder);