五:HttpServletResponse对象
一、HttpServletResponse对象介绍
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。查看HttpServletResponse的API,可以看到这些相关的方法。
1.1、负责向客户端(浏览器)发送数据的相关方法
1.2、负责向客户端(浏览器)发送响应头的相关方法
1.3、负责向客户端(浏览器)发送响应状态码的相关方法
1.4、响应状态码的常量
HttpServletResponse定义了很多状态码的常量(具体可以查看Servlet的API),当需要向客户端发送响应状态码时,可以使用这些常量,避免了直接写数字,常见的状态码对应的常量:
状态码404对应的常量
状态码200对应的常量
状态码500对应的常量
二、HttpServletResponse对象常见应用
2.1、使用OutputStream流向客户端浏览器输出中文数据
使用OutputStream流输出中文注意问题:
在服务器端,数据是以哪个码表输出的,那么就要控制客户端浏览器以相应的码表打开,比如:outputStream.write("中国".getBytes("UTF-8"));使用OutputStream流向客户端浏览器输出中文,以UTF-8的编码进行输出,此时就要控制客户端浏览器以UTF-8的编码打开,否则显示的时候就会出现中文乱码,那么在服务器端如何控制客户端浏览器以以UTF-8的编码显示数据呢?可以通过设置响应头控制浏览器的行为,例如:response.setHeader("content-type", "text/html;charset=UTF-8");通过设置响应头控制浏览器以UTF-8的编码显示数据。
2.2、使用PrintWriter流向客户端浏览器输出中文数据
使用PrintWriter流输出中文注意问题:
在获取PrintWriter输出流之前首先使用"response.setCharacterEncoding(charset)"设置字符以什么样的编码输出到浏览器,如:response.setCharacterEncoding("UTF-8");设置将字符以"UTF-8"编码输出到客户端浏览器,然后再使用response.getWriter();获取PrintWriter输出流,这两个步骤不能颠倒,如下:
- 1 response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
- 2 /**
- 3 * PrintWriter out = response.getWriter();这句代码必须放在response.setCharacterEncoding("UTF-8");之后
- 4 * 否则response.setCharacterEncoding("UTF-8")这行代码的设置将无效,浏览器显示的时候还是乱码
- 5 */
- 6 PrintWriter out = response.getWriter();//获取PrintWriter输出流
注意:
1,getOutputStream()和getWriter()这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。
2,getOutputStream()返回的字节输出流对象,类型为:ServletOutputStream,直接输出字节数组中的二进制数据。
3,getWriter()方法将Servlet引擎的数据缓冲区包装成PrintWriter类型的字符输出流对象后返回,PrintWriter对象只能输出字符文本内容。
然后再使用response.setHeader("content-type", "text/html;charset=字符编码");设置响应头,控制浏览器以指定的字符编码编码进行显示,例如:
- 1 //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
- 2 response.setHeader("content-type", "text/html;charset=UTF-8");
除了可以使用response.setHeader("content-type", "text/html;charset=字符编码");设置响应头来控制浏览器以指定的字符编码编码进行显示这种方式之外,还可以用如下的方式来模拟响应头的作用
- 1 /**
- 2 * 多学一招:使用HTML语言里面的<meta>标签来控制浏览器行为,模拟通过设置响应头控制浏览器行为
- 3 *response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
- 4 * 等同于response.setHeader("content-type", "text/html;charset=UTF-8");
- 5 */
- 6 response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
2.4、文件下载
文件下载功能是web开发中经常使用到的功能,使用HttpServletResponse对象就可以实现文件的下载
文件下载功能的实现思路:
1.获取要下载的文件的绝对路径
2.获取要下载的文件名
3.设置content-disposition响应头控制浏览器以下载的形式打开文件
4.获取要下载的文件输入流
5.创建数据缓冲区
6.通过response对象获取OutputStream流
7.将FileInputStream流写入到buffer缓冲区
8.使用OutputStream将缓冲区的数据输出到客户端浏览器
- package gacl.response.study;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.URLEncoder;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * @author gacl
- * 文件下载
- */
- public class ResponseDemo02 extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- downloadFileByOutputStream(response);//下载文件,通过OutputStream流
- }
- /**
- * 下载文件,通过OutputStream流
- * @param response
- * @throws FileNotFoundException
- * @throws IOException
- */
- private void downloadFileByOutputStream(HttpServletResponse response)
- throws FileNotFoundException, IOException {
- //1.获取要下载的文件的绝对路径
- String realPath = this.getServletContext().getRealPath("/download/1.JPG");
- //2.获取要下载的文件名
- String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
- //3.设置content-disposition响应头控制浏览器以下载的形式打开文件
- response.setHeader("content-disposition", "attachment;filename="+fileName);
- //4.获取要下载的文件输入流
- InputStream in = new FileInputStream(realPath);
- int len = 0;
- //5.创建数据缓冲区
- byte[] buffer = new byte[1024];
- //6.通过response对象获取OutputStream流
- OutputStream out = response.getOutputStream();
- //7.将FileInputStream流写入到buffer缓冲区
- while ((len = in.read(buffer)) > 0) {
- //8.使用OutputStream将缓冲区的数据输出到客户端浏览器
- out.write(buffer,0,len);
- }
- in.close();
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
下载中文文件时,需要注意的地方就是中文文件名要使用URLEncoder.encode方法进行编码(URLEncoder.encode(fileName, "字符编码")),否则会出现文件名乱码。
2.5生成随机图片用作验证码
- package gacl.response.study;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.image.BufferedImage;
- import java.io.IOException;
- import java.util.Random;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * 生成随机图片,用来作为验证码
- */
- public class DrawImage extends HttpServlet {
- private static final long serialVersionUID = 3038623696184546092L;
- public static final int WIDTH = 120;//生成的图片的宽度
- public static final int HEIGHT = 30;//生成的图片的高度
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- this.doPost(request, response);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String createTypeFlag = request.getParameter("createTypeFlag");//接收客户端传递的createTypeFlag标识
- //1.在内存中创建一张图片
- BufferedImage bi = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
- //2.得到图片
- Graphics g = bi.getGraphics();
- //3.设置图片的背影色
- setBackGround(g);
- //4.设置图片的边框
- setBorder(g);
- //5.在图片上画干扰线
- drawRandomLine(g);
- //6.写在图片上随机数
- //String random = drawRandomNum((Graphics2D) g,"ch");//生成中文验证码图片
- //String random = drawRandomNum((Graphics2D) g,"nl");//生成数字和字母组合的验证码图片
- //String random = drawRandomNum((Graphics2D) g,"n");//生成纯数字的验证码图片
- //String random = drawRandomNum((Graphics2D) g,"l");//生成纯字母的验证码图片
- String random = drawRandomNum((Graphics2D) g,createTypeFlag);//根据客户端传递的createTypeFlag标识生成验证码图片
- //7.将随机数存在session中
- request.getSession().setAttribute("checkcode", random);
- //8.设置响应头通知浏览器以图片的形式打开
- response.setContentType("image/jpeg");//等同于response.setHeader("Content-Type", "image/jpeg");
- //9.设置响应头控制浏览器不要缓存
- response.setDateHeader("expries", -1);
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- //10.将图片写给浏览器
- ImageIO.write(bi, "jpg", response.getOutputStream());
- }
- /**
- * 设置图片的背景色
- * @param g
- */
- private void setBackGround(Graphics g) {
- // 设置颜色
- g.setColor(Color.WHITE);
- // 填充区域
- g.fillRect(0, 0, WIDTH, HEIGHT);
- }
- /**
- * 设置图片的边框
- * @param g
- */
- private void setBorder(Graphics g) {
- // 设置边框颜色
- g.setColor(Color.BLUE);
- // 边框区域
- g.drawRect(1, 1, WIDTH - 2, HEIGHT - 2);
- }
- /**
- * 在图片上画随机线条
- * @param g
- */
- private void drawRandomLine(Graphics g) {
- // 设置颜色
- g.setColor(Color.GREEN);
- // 设置线条个数并画线
- for (int i = 0; i < 5; i++) {
- int x1 = new Random().nextInt(WIDTH);
- int y1 = new Random().nextInt(HEIGHT);
- int x2 = new Random().nextInt(WIDTH);
- int y2 = new Random().nextInt(HEIGHT);
- g.drawLine(x1, y1, x2, y2);
- }
- }
- /**
- * 画随机字符
- * @param g
- * @param createTypeFlag
- * @return
- * String... createTypeFlag是可变参数,
- * Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理。注意:可变参数必须位于最后一项
- */
- private String drawRandomNum(Graphics2D g,String... createTypeFlag) {
- // 设置颜色
- g.setColor(Color.RED);
- // 设置字体
- g.setFont(new Font("宋体", Font.BOLD, 20));
- //数字和字母的组合
- String baseNumLetter = "0123456789ABCDEFGHJKLMNOPQRSTUVWXYZ";
- //纯数字
- String baseNum = "0123456789";
- //纯字母
- String baseLetter = "ABCDEFGHJKLMNOPQRSTUVWXYZ";
- //createTypeFlag[0]==null表示没有传递参数
- if (createTypeFlag.length > 0 && null != createTypeFlag[0]) {
- if (createTypeFlag[0].equals("ch")) {
- // 截取汉字
- return createRandomChar(g, baseChineseChar);
- }else if (createTypeFlag[0].equals("nl")) {
- // 截取数字和字母的组合
- return createRandomChar(g, baseNumLetter);
- }else if (createTypeFlag[0].equals("n")) {
- // 截取数字
- return createRandomChar(g, baseNum);
- }else if (createTypeFlag[0].equals("l")) {
- // 截取字母
- return createRandomChar(g, baseLetter);
- }
- }else {
- // 默认截取数字和字母的组合
- return createRandomChar(g, baseNumLetter);
- }
- return "";
- }
- /**
- * 创建随机字符
- * @param g
- * @param baseChar
- * @return 随机字符
- */
- private String createRandomChar(Graphics2D g,String baseChar) {
- StringBuffer sb = new StringBuffer();
- int x = 5;
- String ch ="";
- // 控制字数
- for (int i = 0; i < 4; i++) {
- // 设置字体旋转角度
- int degree = new Random().nextInt() % 30;
- ch = baseChar.charAt(new Random().nextInt(baseChar.length())) + "";
- sb.append(ch);
- // 正向角度
- g.rotate(degree * Math.PI / 180, x, 20);
- g.drawString(ch, x, 20);
- // 反向角度
- g.rotate(-degree * Math.PI / 180, x, 20);
- x += 30;
- }
- return sb.toString();
- }
- }
二、HttpServletResponse常见应用——设置响应头控制浏览器的行为
2.1、设置http响应头控制浏览器禁止缓存当前文档内容
- 1 response.setDateHeader("expries", -1);
- 2 response.setHeader("Cache-Control", "no-cache");
- 3 response.setHeader("Pragma", "no-cache");
2.2、设置http响应头控制浏览器定时刷新网页(refresh)
- 1 response.setHeader("refresh", "5");//设置refresh响应头控制浏览器每隔5秒钟刷新一次
2.3、通过response实现请求重定向
请求重定向指:一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。
应用场景:用户登陆,用户首先访问登录页面,登录成功后,就会跳转到某个页面,这个过程就是一个请求重定向的过程
实现方式:response.sendRedirect(String location),即调用response对象的sendRedirect方法实现请求重定向
sendRedirect内部的实现原理:使用response设置302状态码和设置location响应头实现重定向
2.2、使用PrintWriter流向客户端浏览器输出中文数据
使用PrintWriter流输出中文注意问题:
在获取PrintWriter输出流之前首先使用"response.setCharacterEncoding(charset)"设置字符以什么样的编码输出到浏览器,如:response.setCharacterEncoding("UTF-8");设置将字符以"UTF-8"编码输出到客户端浏览器,然后再使用response.getWriter();获取PrintWriter输出流,这两个步骤不能颠倒,如下:
- 1 response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
- 2 /**
- 3 * PrintWriter out = response.getWriter();这句代码必须放在response.setCharacterEncoding("UTF-8");之后
- 4 * 否则response.setCharacterEncoding("UTF-8")这行代码的设置将无效,浏览器显示的时候还是乱码
- 5 */
- 6 PrintWriter out = response.getWriter();//获取PrintWriter输出流
然后再使用response.setHeader("content-type", "text/html;charset=字符编码");设置响应头,控制浏览器以指定的字符编码编码进行显示,例如:
- 1 //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
- 2 response.setHeader("content-type", "text/html;charset=UTF-8");
除了可以使用response.setHeader("content-type", "text/html;charset=字符编码");设置响应头来控制浏览器以指定的字符编码编码进行显示这种方式之外,还可以用如下的方式来模拟响应头的作用
- 1 /**
- 2 * 多学一招:使用HTML语言里面的<meta>标签来控制浏览器行为,模拟通过设置响应头控制浏览器行为
- 3 *response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
- 4 * 等同于response.setHeader("content-type", "text/html;charset=UTF-8");
- 5 */
- 6 response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
四、web工程中URL地址的推荐写法
在JavaWeb开发中,只要是写URL地址,那么建议最好以/
开头,也就是使用相对路径的方式,那么这个/
到底代表什么呢?可以用如下的方式来记忆/
:如果"/"是给服务器用的,则代表当前的web工程,如果"/"是给浏览器用的,则代表webapps目录。
3.1、"/"代表当前web工程的常见应用场景
①.ServletContext.getRealPath(String path)获取资源的绝对路径
- /**
- * 1.ServletContext.getRealPath("/download/1.JPG")是用来获取服务器上的某个资源,
- * 那么这个"/"就是给服务器用的,"/"此时代表的就是web工程
- * ServletContext.getRealPath("/download/1.JPG")表示的就是读取web工程下的download文件夹中的1.JPG这个资源
- * 只要明白了"/"代表的具体含义,就可以很快写出要访问的web资源的绝对路径
- */
- this.getServletContext().getRealPath("/download/1.JPG");
②.在服务器端forward到其他页面
- /**
- * 2.forward
- * 客户端请求某个web资源,服务器跳转到另外一个web资源,这个forward也是给服务器用的,
- * 那么这个"/"就是给服务器用的,所以此时"/"代表的就是web工程
- */
- this.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
③.使用include指令或者<jsp:include>标签引入页面
- <%@include file="/jspfragments/head.jspf" %>
- <jsp:include page="/jspfragments/demo.jsp" />
此时"/"代表的都是web工程。
3.2、"/"代表webapps目录的常见应用场景
①.使用sendRedirect实现请求重定向
- response.sendRedirect("/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
服务器发送一个URL地址给浏览器,浏览器拿到URL地址之后,再去请求服务器,所以这个"/"是给浏览器使用的,此时"/"代表的就是webapps目录,/JavaWeb_HttpServletResponse_Study_20140615/index.jsp
这个地址指的就是webapps\JavaWeb_HttpServletResponse_Study_20140615\index.jsp
response.sendRedirect("/项目名称/文件夹目录/页面");
这种写法是将项目名称写死在程序中的做法,不灵活,万一哪天项目名称变了,此时就得改程序,所以推荐使用下面的灵活写法:
将
- response.sendRedirect("/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
这种写法改成
- response.sendRedirect(request.getContextPath()+"/index.jsp");
request.getContextPath()
获取到的内容就是/JavaWeb_HttpServletResponse_Study_20140615
,这样就比较灵活了,使用request.getContextPath()
代替"/项目名称",推荐使用这种方式,灵活方便!
②.使用超链接跳转
- <a href="/JavaWeb_HttpServletResponse_Study_20140615/index.jsp">跳转到首页</a>
这是客户端浏览器使用的超链接跳转,这个"/"是给浏览器使用的,此时"/"代表的就是webapps目录。
使用超链接访问web资源,绝对路径的写法推荐使用下面的写法改进:
- <a href="${pageContext.request.contextPath}/index.jsp">跳转到首页</a>
这样就可以避免在路径中出现项目的名称,使用${pageContext.request.contextPath}取代"/JavaWeb_HttpServletResponse_Study_20140615"
③.Form表单提交
- <form action="/JavaWeb_HttpServletResponse_Study_20140615/servlet/CheckServlet" method="post">
- <input type="submit" value="提交">
- </form>
这是客户端浏览器将form表单提交到服务器,所以这个"/"是给浏览器使用的,此时"/"代表的就是webapps目录。
对于form表单提交中action属性绝对路径的写法,也推荐使用如下的方式改进:
- <form action="${pageContext.request.contextPath}/servlet/CheckServlet" method="post">
- <input type="submit" value="提交">
- </form>
${pageContext.request.contextPath}得到的就是"/JavaWeb_HttpServletResponse_Study_20140615"
${pageContext.request.contextPath}的效果等同于request.getContextPath(),两者获取到的都是"/项目名称"
五:HttpServletResponse对象的更多相关文章
- HttpServletRequest对象请求转发和HttpServletResponse对象请求重定向之间的区别
HttpServletRequest对象request代表浏览器请求对象,HttpServletResponse对象代表服务器响应对象,当用浏览器访问web服务器,发出请求时,Servlet调用ser ...
- JavaWeb总结(二)—HttpServletResponse对象
Web服务器收到客户端的http请求,会针对每一次的请求,分别创建一个用于代表请求的request对象和response对象.我们要获取客户端提交的数据,只需要找request对象.要向客户端输出数据 ...
- java web学习总结(七) -------------------HttpServletResponse对象(一)
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应,那我们要 ...
- JAVAWEB学习总结 HttpServletResponse对象(一)
Web服务器收到客户端(浏览器)的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象,和代表响应的response对象. request和response对象既然代表请求和响 ...
- HttpServletResponse对象 学习
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应,那我们要 ...
- JavaWeb---总结(七)HttpServletResponse对象(一)
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象. request和response对象即然代表请求和响应,那我们 ...
- javaweb学习总结(七)——HttpServletResponse对象(一)
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应,那我们要 ...
- 三HttpServletResponse对象介绍(1)
转载自http://www.cnblogs.com/xdp-gacl/p/3789624.html Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象 ...
- java web 学习七(HttpServletResponse对象1)
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应,那我们要 ...
随机推荐
- C语言:size_t类型
size_t 的全称应该是size type,就是说"一种用来记录大小的数据类型".通常我们用sizeof(XXX)操作,这个操作所得到的结果就是size_t类型.因为size_t ...
- python使用selenium,webdriver自动下载百度网盘内容
想实现一个自动下载微信公众号分享百度网盘图片链接的爬虫,使用selenium和火狐的webdriver进行完成 1.首先根据自己的浏览器下载相应的webdriver驱动器,python中导入selen ...
- JProfiler监控java应用使用情况,故障情况分析
1.软件部署(java环境已提前准备) 服务器:centos7.4 https://download-gcdn.ej-technologies.com/jprofiler/jprofiler_linu ...
- ORM研究3 - odoo fields常用的字段属性
之前我们已经讲解了odoo ORM中的一些对字段常用的API操作方法,今天我们继续研究一下Odoo orm中字段的一些通用属性字段的使用,学会它们可以为自己创建数据映射并使用有更好的帮助. 通用字段属 ...
- 前端开发入门到进阶第三集【js和jquery的执行时间与页面加载的关系】
https://blog.csdn.net/u014179029/article/details/81603561 [原文链接]:https://www.cnblogs.com/eric-qin/p/ ...
- windows系统pycharm终端更改为git bash
引自:https://blog.csdn.net/u011519550/article/details/89855122 设置路径:file--setting--tools--terminal--ap ...
- odoo里面批量上传图片
import os import base64 def base_data_product_image(self): """ odoo里批量创建产品,并上传图片 图片为b ...
- 使用分区助手转移windows 10系统出现黑屏boot manager报错问题。
问题原因: 在使用分区助手迁移windows 10到ssd中,设置完boot管理器后,出现黑屏问题, 经过长时间的搜索,发现在迁移系统的时候,只迁移了C盘的系统,没有连同msr引导 文件一同传过去,会 ...
- js问题记录
1.aixos请求响应302重定向时无法获取返回数据, 解决方法:在请求头中添加 headers: { 'X-Requested-With': 'XMLHttpRequest' },
- netty系列之:netty架构概述
目录 简介 netty架构图 丰富的Buffer数据机构 零拷贝 统一的API 事件驱动 其他优秀的特性 总结 简介 Netty为什么这么优秀,它在JDK本身的NIO基础上又做了什么改进呢?它的架构和 ...