Response详解
1. 功能
设置响应消息,包括响应行、响应头、响应体的数据。
2. 设置响应行
主要是来设置状态码,使用setStatus(int sc)
方法。
3. 设置响应头
使用setHeader(String name, String value)
方法。
4. 设置响应体
获取输出流;
- 字符输出流,使用
PrintWriter getWriter()
方法; - 字节输出流,使用
ServletOutputStream getOutputStream()
方法。
- 字符输出流,使用
使用输出流,将数据输出到客户端浏览器。
5. Response的更多使用
5.1. 重定向
5.1.1. 概念
资源跳转的一种方式。
5.1.2. 使用
- 核心代码:
//重定向,访问 /responseDemo1 路径会自动跳转到 /responseDemo2 路径。
/*
//1.设置状态码为302
resp.setStatus(302);
//2.设置响应头location
resp.setHeader("location","/today/responseDemo2");
*/
//更简单的重定向,一般都使用该种方式
resp.sendRedirect("/today/responseDemo2");
请求转发是一种在服务器内部的资源跳转方式。
这里需要和请求转发区分开:请求转发的路径不会变,状态码为200,拥有共享域对象,只能在服务器内部进行跳转;重定向的路径会变,状态码为302,没有共享域对象,可跳转服务器内部和外部的资源。
5.1.3. 重定向和转发的区别
5.1.3.1. 重定向(redirect)
- 地址栏发生变化,状态码为302;
- 重定向可以访问当前服务器内部和其他站点(服务器外部)的资源;
- 重定向是两次请求,有两个request对象,不能使用request对象来共享数据;
- 路径需要加虚拟目录。
5.1.3.2. 转发(forward)
- 转发地址栏路径不变,状态码为200;
- 转发只能访问当前服务器内部的资源;
- 转发是一次请求,可以使用request对象来共享数据;
- 路径不需要加虚拟目录。
请求转发的更多解析可到文章servlet&http&request中的[请求转发]({% post_path 'JavaWEB-4.Servlet&HTTP&Request-note' %}#请求转发)查看。
5.2. 服务器输出字符数据(String)到浏览器
5.2.1. 使用步骤
- 获取字符输出流
- 输出数据
一般用于服务器输出文本信息、HTML代码块到浏览器。
5.2.2. 乱码问题
PrintWriter pw = response.getWriter();
获取的流的默认编码是ISO-8859-1;- 设置该流的默认编码;
- 告诉浏览器响应体使用的编码。
简单的形式设置编码,是在获取流之前设置,使用代码:response.setContentType("text/html;charset=utf-8");
。
5.2.3. 核心代码
package io.gitee.hek97.web.servlet;
//去掉了导包的代码
@WebServlet("/responseDemo3")
public class ResponseDemo3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取流对象之前,设置流的编码
//response.setCharacterEncoding("utf-8");该行可省略,下一行设置响应头中编码的代码会间接设置流的编码。
//告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码,这里使用的是设置响应头中编码的方法
response.setHeader("content-type","text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter pw = response.getWriter();
//2.输出数据
pw.write("你好,response");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
5.3. 服务器输出字节数据(Byte)到浏览器
5.3.1. 使用步骤
- 获取字节输出流
- 输出数据
一般用于从服务器输出图片到浏览器。
5.3.2. 核心代码
package io.gitee.hek97.web.servlet;
//省略导包代码
@WebServlet("/responseDemo4")
public class ResponseDemo4 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应消息编码
response.setHeader("content-type","text/html;charset=utf-8");
//1.获取字节输出流
ServletOutputStream sos = response.getOutputStream();
//2.输出数据
sos.write("你好".getBytes("utf-8"));
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
5.4. 练习:验证码
本质就是一张图片,为了防止恶意表单注册。
5.4.1. 使用步骤
- 在内存中生成一张图片
- 美化图片
- 输出图片
5.4.2. 核心代码
package io.gitee.hek97.web.servlet;
//去除导包代码
@WebServlet("/demo")
public class CheckCodeServlet extends HttpServlet {
@Override
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_3BYTE_BGR);
//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 ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();//获取随机数对象
for (int i = 1; i <= 4; 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);//设置画笔颜色
//画10条干扰线
for (int i = 0; i < 10; i++) {
//随机生成坐标点
int x1=ran.nextInt(width);
int x2=ran.nextInt(width);
int y1=ran.nextInt(height);
int y2=ran.nextInt(height);
//画1条干扰线
g.drawLine(x1,x2,y1,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
5.4.3. 使用代码
在网页中使用验证码,并实现点击图片切换验证码的功能。
<!--login.html-->
<!DOCTYPE html>
<html lang="en">
<script>
window.onload=function () {
//1.获取图片对象
var img =document.getElementById("checkCode");
//2.绑定单击事件
img.onclick=function () {
//加时间戳
var date = new Date().getTime();
img.src = "/today/demo?"+date;//时间戳可以防止浏览器认读取本地缓存的图片
}
}
</script>
<head>
<meta charset="UTF-8">
<title>点击图片切换验证码</title>
</head>
<body>
<img id="checkCode" src="/today/demo"/>//点击图片切换验证码
</body>
</html>
6. 相对路径和绝对路径
6.1. 相对路径
6.1.1. 概念
通过相对路径不可以确定唯一资源,如:./index.html
,一般以.开头的路径,其中的./
也可以省略。
6.1.2. 使用规则
找到当前资源和目标资源之间的相对位置关系。
常用的有
./
:当前目录,../
:上一级目录。
6.2. 绝对路径
6.2.1. 概念
通过绝对路径可以确定唯一资源,如:http://localhost/day15/responseDemo2
,因为服务器地址是一样的,所以可简化书写为:/day15/responseDemo2
,以/开头。
6.2.2. 使用规则
通过判断定义的路径是给谁使用的?
- 给客户端(浏览器)使用:需要加虚拟目录(项目的访问路径),相当于在教学楼门前叫张三,需要指明具体是那个班级的张三。
- 建议虚拟目录动态获取,一但虚拟目录发生改变可以动态获取,不用修改,使用
request.getContextPath()
方法;例如重定向推荐使用:resp.sendRedirect(req.getContextPath()+"/responseDemo2");
。
- 建议虚拟目录动态获取,一但虚拟目录发生改变可以动态获取,不用修改,使用
Html中虚拟目录的获取在之后的jsp中学习
<a>
,<form>
。
- 给服务器内部使用:不需要加虚拟目录,相当于在班级门前叫张三,直接喊就可以了。
可以判断请求将来从哪儿发出,从客户端还是服务器端内部发出,比如转发是从服务器内部发出的,不需要加虚拟目录,重定向是两次请求,由客户端发出,需要加虚拟目录。