HTTP之Response:接上一篇博文HTTP协议详细.
本文目录
一.设置Response对象
响应消息数据格式:
- 响应行
- 响应头
- 响应空行
- 响应体
Response对象功能:设置响应消息
1.设置响应行
响应行格式:
协议/版本信息 响应状态码 状态码描述
HTTP/1.1 200 ok
我们可以进行响应状态码的设置,告诉浏览器本次请求和响应的一个状态。像请求重定向中,响应状态码为304,告诉浏览器这是一次重定向操作。响应状态码设置的方法:
void setStatus(int var1);
设置了状态码,参数是设置状态码的整数值。
响应行中的状态描述信息直接与状态码相关,而HTTP版本由服务器确定。正常情况下,Web服务器会默认产生一个状态码为200的状态行。
2.设置响应头
设置响应头的方法:
void setHeader(String name, String value);
参数是设置的响应头名称,和对应的值。
3.设置响应体
使用输出流,将数据输出到客户端浏览器。使用步骤:
1.获取输出流
PrintWriter getWriter();
字符输出流ServletOutputStream getOutputStream();
就是一个字节输出流
2.调用输出流中的方法,写入数据
二.Response重定向
重定向,也叫请求重定向,也是一种资源跳转的方式。如下图:
当客户端访问Servlet1时 ,由于在Servlet1中设置了请求重定向到Servlet2,因此,浏览器在收到Servlet1的响应消息后,立刻向Servlet2发送请求。Servlet2对请求处理完毕后,再将响应消息回送给客户端。
forward(转发)和 redirect(重定向)的区别:常见面试题
redirect重定向的特点:
- 1.地址栏发生变化
- 2.重定向可以访问其他站点(服务器)的资源
- 3.重定向是两次请求。不能使用request对象来共享数据
forward转发的特点:
- 1.转发地址栏路径不变
- 2.转发只能访问当前服务器下的资源
- 3.转发是一次请求,可以使用request对象来共享数据
重定向代码实现
需求:访问/ResponseDemo1,会自动跳转到/ResponseDemo2资源
//设置重定向方式1
//1.设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/Response/ResponseDemo2");
//设置重定向方式2:推荐的简单方式
response.sendRedirect(contextPath+"/ResponseDemo2");
ResponseDemo1.java
/**
* 请求重定向
* 需求:访问/ResponseDemo1,会自动跳转到/ResponseDemo2资源
*/
@WebServlet(name = "ResponseDemo1", urlPatterns = "/ResponseDemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Demo1请求重定向...");
//设置重定向方式1
//1.设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/Response/ResponseDemo2");
//共享一个请求域数据:验证重定向是否可以共享请求域的数据
request.setAttribute("msg","hello");
//动态获取虚拟目录
String contextPath = request.getContextPath();
//设置重定向方式2:推荐的简单方式
response.sendRedirect(contextPath+"/ResponseDemo2");
//重定向可以指向外部的资源
//response.sendRedirect("https://www.baidu.com");
}
}
ResponseDemo2.java
@WebServlet(name = "ResponseDemo2", urlPatterns = "/ResponseDemo2")
public class ResponseDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Demo2......");
//获取共享数据
Object msg = request.getAttribute("msg");
System.out.println(msg);
}
}
浏览器访问ResponseDemo1结果:
自动跳转到ResponseDemo2
控制台打印:
获取共享数据的结果为null,可以证明重定向是两次请求,不能使用request对象来共享数据。
三.相对路径和绝对路径
资源路径分类:相对路径和绝对路径。
1.相对路径:通过相对路径不可以确定唯一资源,因为不知道相对谁确定的。
如:./index.html
,一般不 /
开头,以.开头路径都是相对路径。
确定相对路径的规则:要找到当前资源和目标资源之间的相对位置关系。
目录表示:
./:当前目录
…/:后退一级目录
…/…/:以此类推,后退多级目录。
例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>相对路径</h1>
<h1>找到当前资源和目标资源之间的相对位置关系</h1>
<P>
当前资源:location.html
访问路径:http://localhost/dong/location.html
</P>
<P>
目标资源:ResponseDemo2
访问路径:http://localhost/dong/ResponseDemo2
</P>
<!-- ResponseDemo2与location.html处在同一目录下,
目标资源相对于location.html路径就是: ./responseDemo2
相对路径可以省略./
-->
<a href="./responseDemo2">responseDemo2</a>
<a href="responseDemo2">responseDemo2</a>
</body>
</html>
2.绝对路径:通过绝对路径可以确定唯一资源
如:http://localhost/dong/ResponseDemo2和/dong/responseDemo2
,都是绝对路径。
一般以 /
开头路径都是绝对路径。
确定相对路径的规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出。
2.1 给客户端浏览器使用:需要加虚拟目录(项目的访问路径),如/dong
/ResponseDemo2
- 建议虚拟目录动态获取:
request.getContextPath()
- 常用场景,
<a> , <form>
标签, 重定向路径使用
2.2 给服务器使用:不需要加虚拟目录,如/ResponseDemo2
- 常用场景,请求转发路径
例子
<h1>绝对路径</h1>
<a href="/dong/ResponseDemo2">responseDemo2</a>
四.Response输出数据
就是设置响应体的内容。使用输出流,将数据输出到客户端浏览器。
1.服务器输出字符数据到浏览器
实现步骤:
- 1.获取字符输出流
- 2.调用流中的方法,写入数据
注意乱码问题:
PrintWriter pw = response.getWriter();
获取的流的默认编码是ISO-8859-1- 设置该流的默认编码为UTF-8(GBK也可以,要与浏览器请求编码格式一致)。
- 设置响应头
content-type
:告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
//简单的形式,设置响应体编码,必须在获取流之前设置
response.setContentType("text/html;charset=utf-8");
代码实现
/**
* Response输出数据
*/
@WebServlet(name = "ResponseDemo4", urlPatterns = "/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//解决输出中文乱码
//设置response编码方式1
//1.获取流对象之前,设置流的默认编码:ISO-8859-1 设置为:UTF-8(GBK也可以,要与浏览器请求编码格式一致)
response.setCharacterEncoding("UTF-8");
//2.设置响应头:告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
response.setHeader("content-type","text/html;charset=UTF-8");
//设置response编码方式2:推荐简单形式设置编码,里面封装上面2步
response.setContentType("text/html;charset=UTF-8");
//输出数据
//1.获取字符输出流
PrintWriter pw = response.getWriter();
//2.调用方法,写入数据
pw.write("<h1>你好呀,response...</h1>");
}
}
浏览器访问ResponseDemo4
2.服务器输出字节数据到浏览器
实现步骤:
- 1.获取字符输出流
- 2.调用流中的方法,写入数据
也需要统一编码格式,避免中文数据乱码
response.setContentType("text/html;charset=UTF-8");
代码实现
/**
* Response输出数据
*/
@WebServlet(name = "ResponseDemo5", urlPatterns = "/ResponseDemo5")
public class ResponseDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//解决Response输出中文乱码
response.setContentType("text/html;charset=UTF-8");
//1.获取字节输出流
ServletOutputStream os = response.getOutputStream();
//2.调用方法,写入数据
os.write("你好,我是董小帅..".getBytes("utf-8"));
}
}
浏览器访问ResponseDemo5
五.Response验证码案例
验证码的本质是一张图片,目的是为了防止恶意表单注册。
恶意表单注册:像注册账号,这些数据都会存储在数据库中,如果恶意无限循环注册,用不了多久数据库就会崩溃。
随机不重复的验证码有效限制了这样的恶意行为,并且现在验证码越来越高级了。
制作验证码一般有两种方式:
- 静态图片验证码:需要有大量图片,不推荐,始终是有限的,并且可能重复出现。
- 动态生成验证码:在程序中动态随机生成,推荐。
现在使用java动态生成如下一张简单的验证码图片。
需求:在网页上显示一张验证码图片,点击超链接或者图片,需要换一张验证码图片。
实际开发中,一般是修改现存的美观好看的验证码代码,逻辑是一致的。
实现步骤
服务器端编写Servlet资源
- 1.创建一对象,在内存中图片(验证码图片对象)
- 2.美化图片
- 3.将图片输出到页面展示
代码实现:
@WebServlet(name = "CheckCodeServlet", urlPatterns = "/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
Random random = new Random();
for (int i = 1; i <= 4; i++) {
//生成随机角标
int index = random.nextInt(str.length());
//获取字符
char ch = str.charAt(index);
//2.3 写出验证码
g.drawString(ch+"",width/5*i,height/2);
}
//2.4 画干扰线
g.setColor(Color.GREEN);
//随机生成坐标点
for (int i = 0; i < 10; i++) {//画10条干扰线
int x1 = random.nextInt(width);
int x2 = random.nextInt(width);
int y1 = random.nextInt(height);
int y2 = random.nextInt(height);
//画线
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示,使用字节输出流
ImageIO.write(image,"jpg",response.getOutputStream());
}
}
前端页面代码:
验证码功能分析:点击超链接或者图片,需要换一张
- 给超链接和图片绑定单击事件
- 重新设置图片的src属性值
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码案例</title>
</head>
<body>
<img id="checkCode" src="CheckCodeServlet" alt="换一张"/>
<a id="change" href="#">看不清,换一张?</a>
<script type="text/javascript">
//1.获取图片和超链接对象
var img = document.getElementById("checkCode");
var change = document.getElementById("change");
//2.绑定单击事件
img.onclick = function () {
//加时间戳
var time = new Date().getTime();
//设置img资源路径src
img.src = "CheckCodeServlet?"+time;
};
change.onclick = function () {
//加时间戳
var time = new Date().getTime();
//设置img资源路径src
img.src = "CheckCodeServlet?"+time;
};
</script>
</body>
</html>
案例效果:
简单验证码例子,到这HTTP之Response对象细节结束,学无止境,每天都要全力以赴!
推荐阅读:
欢迎点赞评论,指出不足,笔者由衷感谢哦!~