「这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战」
JavaWeb——HttpServletResponse对象
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。
什么是HttpServletResponse
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。HttpServletResponse是ServletResponse的子接口,功能和方法更加强大。
HttpServletResponse中的方法
根据方法的功能分类:
负责向浏览器发送数据的方法
public PrintWriter getWriter() throws IOException;
public ServletOutputStream getOutputStream() throws IOException;
负责向浏览器发送响应头的方法
public void setCharacterEncoding(String charset);//设置字符编码
public void setContentLength(int len);//设置内容长度
public void setContentLengthLong(long len);//设置内容长度长
public void setContentType(String type);//设置内容类型
public void setDateHeader(String name, long date);//设置日期标题
public void addDateHeader(String name, long date);//添加日期标题
public void setHeader(String name, String value);//设置标题
public void addHeader(String name, String value);//添加标题
public void setIntHeader(String name, int value);//设置Int标头
public void addIntHeader(String name, int value);//添加Int标头
public void setStatus(int sc);//设置状态码
HttpServletResponse的常见应用
1.向浏览器输出消息
-
使用OutputStream流
String data = "中国"; OutputStream outputStream = resp.getOutputStream();//获取OutputStream输出流 respPrintWriter out = response.getWriter();//获取PrintWriter输出流. setHeader("content-type", "text/html;charset=UTF-8");//通过设置响应头控制浏览器以UTF-8的编码显示数据, byte[] dataByteArr = data.getBytes("UTF-8");//将字符转换成字节数组,指定以UTF-8编码进行转换 outputStream.write(dataByteArr);//使用OutputStream流向客户端输出字节数组 -
使用PrintWriter
resp.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器 PrintWriter out = resp.getWriter();//获取PrintWriter输出流 out.print();
2.下载文件
思路:
- 要获取下载文件的路径
- 下载的文件名
- 设置content-disposition响应头控制浏览器能以下载的形式打开文件
- 获取下载的输入流
- 创建缓冲区buffer
- 获取OutputStream
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区数据输出到客户端
实现类:
package com.cheng.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 要获取下载文件的路径,写死
String realPath = "D:\\JavaWeb\\maven\\javaweb-01-servlet\\response\\target\\classes\\images\\fu.png";
System.out.println("下载文件的路径:"+realPath);
//2. 下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);//获得文件名,路径名最后的"\\"的下一个就是文件名
//3. 设置content-disposition响应头控制浏览器能以下载的形式打开文件
resp.setHeader("content-disposition","attachment; filename="+fileName);
//4. 获取下载的输入流
FileInputStream in = new FileInputStream(realPath);
//5. 创建缓冲区buffer
int len = 0;
byte[] buffer = new byte[1024];
//6. 获取OutputStream
ServletOutputStream out = resp.getOutputStream();
//7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区数据输出到客户端
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
//关闭资源
out.close();
in.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注册servlet
<servlet>
<servlet-name>filedown</servlet-name>
<servlet-class>com.cheng.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>filedown</servlet-name>
<url-pattern>/down</url-pattern>
</servlet-mapping>
启动测试:
下载成功
注意:如果文件名包含中文,要使用URLEncoder.encode方法进行编码(URLEncoder.encode(fileName, "字符编码")),否则会出现文件名乱码。
//例如当文件名为:鹏程.png
//第三步
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
3.Response验证码实现
实现一个八位数的验证码,并让它三秒钟刷新一次
package com.cheng.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//让浏览器每3秒自动刷新一次
resp.setHeader("refresh","3");
//在内存中创建一张空白的图片 宽 高 颜色
BufferedImage image = new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
//得到这张图片
Graphics2D g = (Graphics2D) image.getGraphics();//笔
//设置背景颜色
g.setColor(Color.white);//设置背景颜色
g.fillRect(0,0,100,25);//给图片填充
//给图片写随机数(验证码)
g.setColor(Color.BLUE);//设置笔的颜色
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,25);
//告诉浏览器这个请求用图片的方式打开
resp.setContentType("image/png");
//网站存在缓存,我们要不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器 ImageIO类,用于定位图片读和写
ImageIO.write(image,"png",resp.getOutputStream());
}
private String makeNum() {
Random random = new Random();
StringBuffer sb = new StringBuffer();
String num = random.nextInt(99999999) + ""; //返回一个大于等于0小于99999999的随机数,加个空字符串变为String类型
//这里的8-num.length()一定为0,就算不为0,下面也可以用0补足八位数
for (int i = 0; i < 8 - num.length(); i++) {
//所以保证了生成的随机数一定是八位数,
sb.append("0");
}
num = sb.toString() + num;//转化为int类型输出
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注册Servlet
<servlet>
<servlet-name>Imageservlet</servlet-name>
<servlet-class>com.cheng.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Imageservlet</servlet-name>
<url-pattern>/image</url-pattern>
</servlet-mapping>
测试结果:
4.实现重定向
重定向(Redirect)
重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令,告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。
重定向过程:web资源B收到客户端A的请求后,会通知A去访问web资源C,这个过程中URL会发生改变
测试重定向
package com.cheng.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/p1/down");//本项目的路径和定位的路径
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
分析重定向的原理:
观察浏览器的网络请求,可以看到两次Http请求
如果浏览器请求/red路径,RedirectServlet将处理此请求。由于RedirectServlet在内部又发送了重定向响应,因此,浏览器会收到302响应:当浏览器收到302响应后,它会立刻根据Location的指示请求/down路径
//所以 resp.sendRedirect("/p1/down");的原理为
resp.setHeader("Location","/p1/down");
resp.setStatus(302)//这里的302如果改为301就变为永久重定向
重定向分类:
- 临时重定向302
- 永久重定向301
区别:如果服务器发送301永久重定向响应,浏览器会缓存/red到/down这个重定向的关联,下次请求/red的时候,浏览器就直接发送/down请求了。
重定向的作用:
重定向的目的是当Web应用升级后,如果请求路径发生了变化,可以将原来的路径重定向到新路径,从而避免浏览器请求原路径找不到资源。
重定向和转发的区别
- 相同:都会实现页面的跳转
- 不同:
- 重定向时,URL地址栏会发生改变
- 转发时,URL地址栏不会改变