HTTP协议
1:请求消息:客户端发给服务器端的数据
1.请求行
2.请求头
3.请求空行
4.请求体
2:响应消息:服务端发送给客户端的数据
1:响应行
2:响应头
3:响应空行
4:响应体
响应行
1.组成:协议/版本 响应状态码 状态码描述
2.响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Mon, 23 Dec 2019 08:23:00 GMT
* 状态码都是3位数字
* 分类:
* 1xx :接收消息中,但是没有接受完成
* 2xx:成功。代表:200
* 3xx: 重定向。代表:302(重定向:客户端请求服务器,服务器中有各种资源,客户端请求a资源,a资源不能完成回复客户端重新访问c)304(访问缓冲:访问过某资源,服务端回复访问本地缓冲)
* 客户端错误 404(路径没有对应的资源)405(方法不允许:没有对应的doXxx方法
* 服务端错误 500(服务器内部错误)
响应头
- 格式:头名称:值
- 常见响应头:
- Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
- Contend-disposition:服务器告诉客户端以什么样的格式打开响应体数据
1.值:in_line:默认值,在当前页面打开
2.值:attachment;filename=xxx:以附件形式打开响应体。文件下载
响应体
真实的传输对象。
-
功能:设置响应消息
1:设置响应行设置状态码:setStatus(int sc) 设置响应头:setHeader(String name, String value) 设置响应体: *步骤: 获取输出流 *字符输出流:PrintWriter getWriter() *字节输出流:ServletOutputStream getOutputStream() 使用输出流,将数据输出到客户端浏览器
1:完成重定向(资源跳转,状态码302)
* 特点:**redirect**
*地址栏发生变化
*重定向可以访问其他站点的资源
*重定向是两次请求,不能用request对象共享数据
* 转发的特点 **forward**
* 转发地址栏路径不变
* 转发只能访问当前服务器下的资源
* 转发是一次请求,可以用request对象共享数据
* 路径的写法:
2:服务器输出字符数据到浏览器
3:服务器输出字节数据到浏览器
4:验证码
//访问/demo2resp,会自动跳转到/demo3resp
//1 :设置状态码302
resp.setStatus(302);
//设置响应头location
resp.setHeader("location","/demo3resp");
可以简化为:
resp.sendRedirect("/demo3resp");
2:路径的写法:避免404
*相对路径
./当前路径
../后退一级目录
(不推荐,写的时候复杂)
*绝对路径
规则:判断定义的路径给谁使用
*客户端:需药加虚拟目录(项目的访问路径)
建议虚拟目录动态获取
String contextPath = req.getContextPath();
resp.sendRedirect(contextPath + "demo3resp");
<a> <form> 重定向。。
*给服务器使用:不需要虚拟目录
*转发路径
3:服务器输出字符数据到浏览器
*步骤:
1:获取字符输出流
2:输出数据
//设置编码
resp.setCharacterEncoding("utf-8"); //可以省略,下面的一行可以设置。
//告诉浏览器,服务器发送的消息数据及编码,建议浏览器使用。。
resp.setHeader("content-type", "text/html;charset=utf-8");
//获取字符输出流
PrintWriter pw = resp.getWriter();
//输出数据
pw.write("<h1>你好 response!<h1>");//不用刷新都可以,因为resp在请求行会关闭,流会关闭,自动刷出
**//简写
resp.setContentType("text/html;charset=utf-8");**
4:服务器输出字节数据到浏览器
//简写
resp.setContentType("text/html;charset=utf-8");
//获取字节输出流
ServletOutputStream sos = resp.getOutputStream();
//输出数据
sos.write("<h1>你好 response!<h1>".getBytes("utf-8"));//获取字节数组
5:验证码:
本质:图片
目的:防止表单注册(无限注册)
int width = 100;
int height = 40;
//创建一对象,在内存中图片(验证码图片对象)
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//美化图片
//填充背景色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.pink);//设置画笔颜色
g.fillRect(0, 0, width, height);
//画边框
g.setColor(Color.BLUE);
g.drawRect(0, 0, width - 2, height - 2);
//写验证码
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
//生成随机角标
Random ran = new Random();
int index = 0;
for(int i = 1; i <= 4 ; i++){
index = ran.nextInt(str.length());
String strs = str.charAt(index) + "";
g.drawString(strs, 20 * i , 25 );
}
//画干扰线
g.setColor(Color.GREEN);
for(int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int x2 = ran.nextInt(width);
int y2 = ran.nextInt(height);
g.drawLine(x1, y1, x2, y2);
}
//输出图片
ImageIO.write(image, "jpg", response.getOutputStream());
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
/*
分析:
点击图片和超链接都更新图片
1:绑定单击事件
2:重新设置
*/
window.onload = function () {
var img = document.getElementById("newImage");
img.onclick=function () {
//加时间戳
var date = new Date().getTime();
img.src="/demo6checkcode?" + date;
}
}
</script>
</head>
<body>
<img id="newImage" src="/demo6checkcode">
<a id="change" href=""> 看不清换一张 </a>
</body>
</html>
}