HTTP协议
请求消息:客户端给服务端的数据
-
数据格式
1. 请求行 2. 请求头 3. 请求空号 4. 请求体
响应消息:服务端发给客户端的数据
-
数据格式
1. 响应行 2. 响应头 3. 响应空号 4. 响应体
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Content-Length: 101
Date: Tue, 14 Apr 2020 02:37:40 GMT
<html>
<head>
<title>$Title$</title>
</head>
<body>
hello,123123
</body>
</html>
响应行
HTTP/1.1 200 OK
-
组成:协议/版本 响应状态 状态描述
-
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
1. 状态码都是3位数字 2. 分类: 1. 1XX:服务器接收客户端消息,没有接受完成,等待一段时间后,发送1XX状态码 2. 2XX:成功。如:200 3. 3XX:重定向。如:302(重定向) ,304(访问缓存) 4. 4XX:客户端错误。 1. 404(请求路径无对应资源) 2. 405(请求方式无对应的doXX方法) 6. 5XX:服务器错误。如500(服务器内部异常)
响应头
Content-Type: text/html;charset=utf-8
Content-Length: 101
Date: Tue, 14 Apr 2020 02:37:40 GMT
- 格式:头名称:值
- Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
- Content-disposition:服务器告诉客户端以什么格式打开响应体数据
* 值:in-line默认,在当前页面内打开
* attachment;filename=XX:以附件形式打开响应体。文件下载
响应体
<html>
<head>
<title>$Title$</title>
</head>
<body>
hello,123123
</body>
</html>
传输的数据
Reponse对象
功能:设置响应消息
设置响应行
setStatus(int sc)
设置响应头
setHeader(String name, String value)
设置响应体
- 设置输出流
- 字符输出流:PrintWriter getWriter()
- 字节输出流:ServletOutputStream getOutputStream()
- 使用输出流,将数据输出到浏览器
案例:
重定向:资源跳转的方式
@WebServlet("/responseDemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo1访问了!!");
// 访问responseDemo1自动访问responseDemo2
// 1. 设置状态码为302
response.setStatus(302);
// 2. 设置响应头Location
response.setHeader("location","/Day15/responseDemo2");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
简单实现
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo1访问了!!");
// // 访问responseDemo1自动访问responseDemo2
// // 1. 设置状态码为302
// response.setStatus(302);
// // 2. 设置响应头Location
// response.setHeader("location","/Day15/responseDemo2");
// // 简单的重定向方法
response.sendRedirect("/Day15/responseDemo2");
}
* 重定向特点:redirect
1. 重定向地址栏路径改变
2. 重定向能访问其他服务器资源
3. **重定向是两次请求**,不可以使用request共享数据
* 转发特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器资源
3. 转发是一次请求,可以使用request共享数据
* 面试题:forward 和 redirect区别
* 路径写法:
1. 分类
1. 相对路径:不可以确定唯一资源,以.开头
* 规则:访问当前资源和目标资源的相对位置关系
2. 绝对路径:可以确定唯一资源,以/开头的路径
* 规则:判断定义的路径是给谁用的?
1. 给客户端浏览器:加虚拟目录(项目的访问路径)
建议虚拟目录动态获取request.getContextPath();
<a> <from>
2. 给客户端用:不加虚拟目录 。如转发
服务器输出字符数据到浏览器
步骤
- 获取字符输出流
- 输出数据
注意
-
乱码问题
- PrintWriter pw = response.getWriter();默认获取流是ISO-8859-1
- 设置流的默认编码
- 告诉浏览器使用的编码
- 在获取流之前设置码
@WebServlet("/responseDemo3")
public class ResponseDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取流之前设置编码
// response.setCharacterEncoding("utf-8");
// 告诉浏览器,服务器发送消息的数据编码,建议使用的编码
// response.setHeader("content-type","text/html;charset=utf-8");
// 简单设置编码
response.setContentType("text/html;charset=utf-8");
// 1. 获取输出流
PrintWriter pw = response.getWriter();
// 2. 输出数据
pw.write("<h1>hello asdqqqqqqq!</h1>");
pw.write("你好!!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
服务器输出字节数据到浏览器
步骤
- 获取字节输出流
- 输出数据
@WebServlet("/responseDemo4")
public class ResponseDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置头
response.setContentType("text/html;charset=utf-8");
// 1. 获取字节流
ServletOutputStream outputStream = response.getOutputStream();
// 2. 输出数据
outputStream.write("你好".getBytes("utf-8"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
验证码案例
- 本质:图片
- 目的:放置恶意表单注册
@WebServlet("/yzms")
public class YanZhengMaServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
// 1. 创建对象,在内存中图片
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
// 2. 美化图片
// 2.1 填充背景色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.pink);// 设置画笔颜色
g.fillRect(0,0,width,height);
// 2.2 画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrsduvwxyz1234567890";
// 创建随机脚标
Random ran = new Random();
for (int i = 1; i < 5; i++) {
int index = ran.nextInt(str.length());
// 获取字符
char ch = str.charAt(index);// 随机字符
// 2.3 写验证码
g.drawString(ch+"" ,width/5*i,height/2);
}
// 2.4 画干扰线
g.setColor(Color.GREEN);
// 随机生成坐标点
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
for (int i = 0; i < 10; i++) {
int x11 = ran.nextInt(width);
int x22 = ran.nextInt(width);
int y11 = ran.nextInt(height);
int y22 = ran.nextInt(height);
g.drawLine(x11,y11,x22,y22);
}
// 3. 将图片输出到页面
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
网页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
/*
点击超链接或者图片换一张
1. 给超链接和图片绑定单击事件
2. 重新设置图片的src属性
*/
window.onload = function () {
var img = document.getElementById("1");
img.onclick = function () {
// 加时间戳
var date = new Date().getTime();
img.src = "/Day15/yzms?" + date;
}
var a = document.getElementById("2");
a.onclick = function () {
// 加时间戳
var date = new Date().getTime();
img.src = "/Day15/yzms?" + date;
}
}
</script>
</head>
<body>
<img id="1" src="/Day15/yzms" />
<a id="2" href="#">看不清换一张</a>
</body>
</html>
ServletContext对象
- 基本概念:代表整个web应用,可以和程序的容器(服务器)来通信
- 获取:
- 通过request获取
request.getServletContext();
- 通过HTTPServlet
this.getServletContext();
- 通过request获取
功能:
-
获取文件的 MIME 类型:
MIME :是一种文件数据类型 格式:大类型/小类型 text/html image/jpeg 获取:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 1. 获取文件的 MIME 类型:
MIME :是一种文件数据类型
格式:大类型/小类型 text/html image/jpeg
* 获取
2. 域对象:共享数据
3. 获取文件真实路径(服务器路径)
*
* */
//2. 通过request对象获取
ServletContext context = request.getServletContext();
//3. 定义文件名称
String filename = "a.jpg";
// 4. 获取MIME类型
String mimeType = context.getMimeType(filename);
System.out.println(mimeType);
}
-
域对象:共享数据
- setAttribute(String name,Object values)
- getAttribute(String name)
- removeAttribute(String name)
- ServletContext对象范围:所有用户,所有请求的数据
-
获取文件真实路径(服务器路径)
- 方法:
String getRealPath(String path);
- 方法:
案例 文件下载
文件下载需求:
1. 页面显示超链接
2. 点击超链接后弹出下载提示框
3. 完成图片文件下载
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取文件名称
String filename = request.getParameter("filename");
// 2. 使用字节输入流加载进内存
// 2.1 找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/image/" + filename);
// 2.2 用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//3. 设置response的响应头
// 3.1 设置响应头类型
String mimeType = servletContext.getMimeType(filename);
response.setHeader("content-type",mimeType);
//3.2 设置响应头打开方式
response.setHeader("content-disposition","attachment;filename=" + filename);
// 4. 将输入流数据写到输出流
ServletOutputStream sos = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while((len = fis.read(buff)) != -1){
sos.write(buff,0,len);
}
fis.close();
}
<a href="/Day15/image/1.jpg">图片1</a>
<a href="/Day15/image/1.avi">视频</a>
<hr>
<a href="/Day15/downloadServlet?filename=1.jpg">图片1</a>
<a href="/Day15/downloadServlet?filename=1.avi">视频</a>
<hr>
<a href="/Day15/downloadServlet?filename=九尾.jpg">图片1</a>
<a href="/Day15/downloadServlet?filename=1.avi">视频</a>