javaWeb——Request和Response03
到了这一节我们开始学习Response。
一.Response重定向
Response的作用是设置响应消息。
1. 设置响应行
1. 格式:HTTP/1.1 200 ok
2. 设置状态码:setStatus(int sc):如果不设置会自动根据情况返回
2. 设置响应头:setHeader(String name, String value):可以自定义响应头,客户端可以收到
3. 设置响应体:
1. 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream()
2. 使用输出流,将数据输出到客户端浏览器
我们要学习一个新的概念:
重定向,即一种资源跳转的方式,前面我们讲过了转发,现在我们来比较一下二者:
- 重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据- 转发的特点:forward
4. 转发地址栏路径不变
5. 转发只能访问当前服务器下的资源
6. 转发是一次请求,可以使用request对象来共享数据
现在我们来实现一个重定向的例子来演示上面的特点:
@WebServlet("/demo")
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
System.out.println("访问了demo");
req.setAttribute("aa","bb");
resp.sendRedirect("/demo2");
System.out.println(123);
}
}
@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("访问了demo2");
System.out.println(req.getAttribute("aa"));
}
}
从结果来分析:
重定向地址栏发生了变化,且request共享的数据无法获取到,重定向两次请求可以通过F12抓包来看。上面这个例子没有体现可以访问外部资源的特点,可以将resp.sendRedirect("/demo2")改为resp.sendRedirect(“www.baidu.com”);来验证这里不做演示了,同时我们发现重定向发生在ServletDemo代码完全执行完后才发生
二.Tomcat项目中路径的写法及Response流的示例
1. 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html
* 不以/开头,以.开头路径
* 规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* ../:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost:8080/jack/responseDemo2或者/jack/responseDemo2
* 以/开头的路径
* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
* 建议虚拟目录动态获取:request.getContextPath()
* <a> , <form> 重定向...
* 给服务器使用:不需要加虚拟目录
* 请求转发时不需要
(上面两种方式在写页面超链接的时候也是适用的)
演示:
相对路径这里不展示。
绝对路径展示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--这个路径是给浏览器在使用要加上虚拟目录-->
<a href="/jack/demo2">超链接</a>
</body>
</html>
点击超链接:
下面我们来看一个Response流的示例:
SevletDemo的doGet方法代码如下:
PrintWriter writer = resp.getWriter();
writer.write("<h1>Hello World! 你好</h1>");
出现了乱码的现象:
将代码改为如下即可:
resp.setCharacterEncoding("gbk");\\(将流的字符集改为gbk与浏览器一致,浏览器一般都是gbk编码格式)
PrintWriter writer = resp.getWriter();
writer.write("<h1>Hello World! 你好</h1>");
不过上面这个方法不是很通用,比如我们的浏览器采用的字符集不是gbk我们可以使用下面的方式:
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.write("<h1>Hello World! 你好</h1>");
三.文件下载
前面我们已经讲过了ServletContext对象了,这里再拓展一下:
1. 获取MIME类型:
* MIME类型:在互联网通信过程中定义的一种文件数据类型
* 格式: 大类型/小类型 text/html image/jpeg
* 获取:String getMimeType(String file)
2. 域对象:共享数据
1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
3. 获取文件的真实(服务器)路径
1. 方法:String getRealPath(String path)
三个例子:
String b = context.getRealPath("/b.txt");//web目录下资源访问
System.out.println(b);
String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
System.out.println(c);
String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
System.out.println(a);
对1,3做个演示:
ServletContext servletContext = req.getServletContext();
String mimeType = servletContext.getMimeType("login.html");
System.out.println(mimeType);
System.out.println(servletContext.getRealPath("/login.html"));
System.out.println(servletContext.getRealPath("/WEB-INF/web.xml"));
System.out.println(servletContext.getRealPath("/WEB-INF/classes/ServletDemo"));
接下来我们要实现下载这个图片:
代码如下:
resp.setCharacterEncoding("utf-8");
ServletContext servletContext = req.getServletContext();
String mimeType = servletContext.getMimeType("a.png");
mimeType+=mimeType+";charset=utf-8";
resp.setContentType(mimeType);
resp.setHeader("content-disposition", "attachment;filename=目标.png");
ServletOutputStream outputStream = resp.getOutputStream();
InputStream inputStream = new FileInputStream(servletContext.getRealPath("/WEB-INF/classes/Image/目标.png"));
byte[] bytes = new byte[1024*200];
while(inputStream.read(bytes)!=-1){
outputStream.write(bytes);
outputStream.flush();
}
inputStream.close();
outputStream.close();
下载后图片打开后正常,但是文件名乱码了
解决办法如下,编写如下文件:
package web.servlet;
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")) {
// IE浏览器
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;
}
}
然后将resp.setHeader("content-disposition", "attachment;filename=目标.png");
改为:
String header = req.getHeader("user-agent");
String filename = DownLoadUtils.getFileName(header,"目标.png");
resp.setHeader("content-disposition", "attachment;filename="+filename);
成功解决: