JavaWeb(四)——response

接收到一个请求后,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);设置响应行的状态码
//设置响应行的状态码 302——重定向
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);//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缓冲区有大小,可以设置
// 1.设置response查询的编码表
response.setCharacterEncoding("UTF-8");
// 2.告知客户端要使用什么编码解码
response.setHeader("Content-Type", "text/html;charset=UTF-8");
//Tomcat提供了封装方法合并以上两个方法的功能
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中获取字节输出流去读文件到缓存区
这种方式有缺陷,对于浏览器可以解析的文件,浏览器会直接显示
不会提示下载
// 图片上传到浏览器
// 1.获取Servlet字节输出流——在响应时候将输出流数据刷新到response的缓存区
ServletOutputStream out = response.getOutputStream();
String path = getServletContext().getRealPath("2.jpg");
System.out.println(path);
// getServletContext()通过当前Servlet获取ServletContext对象
// getRealPath("2.jpg") 通过ServletContext对象获取文件的绝对路径
// 2.获取文件输入流读取图片数据
FileInputStream in = new FileInputStream(new File(path));
// 3.将读取的数据通过输出流存入缓存区
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>//点击后直接播放mp3
文件的下载就需要另外编写代码告诉浏览器,这些文件不要解析直接下载
需要设置响应头信息,告诉浏览器文件是用来下载的,不是显示的
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中获取字节输出流读取文件到缓存区
对于中文文件名的下载,下载文件的文件名会出错
//@WebServlet("/file") 
protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 获取要下载文件的文件名
		String parameter0 = request.getParameter("filename");// 俊逸之才.jpg 无乱码
		System.out.println("文件名: " + parameter0); //中文名会乱码
		
		byte source[] = parameter0.getBytes("iso8859-1"); //编码 
		String parameter = new String(source, "UTF-8");//解码 
		System.out.println("文件名: " + parameter);	
		// 需要告诉浏览器这个要下载文件的类型——浏览器是通过文件的MIME类型来区分类型的
		response.setContentType(getServletContext().getMimeType(parameter));
		// getServletContext().getMimeType(parameter)根据文件名获取对应的MIME类型
		// response.setContentType()设置MIME类型

		// 告诉浏览器不解析,直接以附件的形式下载
		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")) {
	// IE浏览器
	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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值