HttpServletResponse对象
一、HttpServletResponse对象介绍
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。查看HttpServletResponse的API,可以看到这些相关的方法。
1.1、负责向客户端(浏览器)发送数据的相关方法
1.2、负责向客户端(浏览器)发送响应头的相关方法
1.3、负责向客户端(浏览器)发送响应状态码的相关方法
1.4、响应状态码的常量
HttpServletResponse定义了很多状态码的常量(具体可以查看Servlet的API),当需要向客户端发送响应状态码时,可以使用这些常量,避免了直接写数字,常见的状态码对应的常量:
状态码404对应的常量
状态码200对应的常量
状态码500对应的常量
二、HttpServletResponse对象常见应用
2.1、Response输出方法
PrintWriter getWriter()
获得字符流,通过字符流的write(String s)方法可以将字符串设置到response缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。
注意:虽然response对象的getOutSream()和getWriter()方法都可以发送响应消息体,但是他们之间相互排斥,不可以同时使用,否则会发生异常。
2.2、Response乱码问题
乱码发生的原因:
计算机中的数据都是以二进制进行存储的,因此传输文本时,就会发生字节和字符之间的转换。字符与字节之间的转换需要查码表完成,将字符转换为字节的过程叫做编码,将字节转换为字符的过程叫做解码。如果编码和解码使用的码表不一致,就会发生乱码。这就是乱码发生的根本原因
①、response缓冲区的默认编码是iso8859-1,此码表中没有中文。所以需要更改response的编码方式:
②、通过更改response的编码方式为UTF-8,任然无法解决乱码问题,因为发送端服务端虽然改变了编码方式为UTF-8,但是接收端浏览器端仍然使用GB2312编码方式解码,还是无法还原正常的中文,因此还需要告知浏览器端使用UTF-8编码去解码。
上面通过调用两个方式分别改变服务端对于Response的编码方式以及浏览器的解码方式为同样的UTF-8编码来解决编码方式不一样发生乱码的问题。
response.setContentType("text/html;charset=UTF-8")
这个方法包含了上面的两个方法的调用,因此在实际的开发中,只需要调用一个response.setContentType("text/html;charset=UTF-8")
方法即可。
2.3、中文文件下载
示例:文件下载 注意:下载中文文件时,需要注意的地方就是中文文件名要使用URLEncoder.encode方法进行编码:URLEncoder.encode(fileName, "字符编码"),否则会出现文件名乱码。
ResponseDemo02.java
package com.lovo.study;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo02 extends HttpServlet {
private static final long serialVersionUID = 1L;
public ResponseDemo02() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取要下载文件的绝对路劲
String realPath = this.getServletContext().getRealPath("/downloads/美女.jpg");
//获取要下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//设置content-disposition响应头控制浏览器以下载的形式打开文件,
//中文文件名要使用URLEncoder.encode方法进行编码,否则会出现文件名乱码
response.setHeader("Content-disposition",
"attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
InputStream in = new FileInputStream(realPath);
int len = 0;
byte [] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
while((len = in.read(buffer)) > 0){
out.write(buffer,0,len);
}
in.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
三、HttpServletResponse常见应用——设置响应头控制浏览器的行为
3.1、设置http响应头控制浏览器禁止缓存当前文档内容
response.setDateHeader("expries", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
3.2、设置http响应头控制浏览器定时刷新网页(refresh)
response.setHeader("refresh", "5");//设置refresh响应头控制浏览器每隔5秒钟刷新一次
3.3、通过response实现请求重定向
请求重定向:一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。
实现方式:response.sendRedirect(String location),即调用response对象的sendRedirect方法实现请求重定向
sendRedirect内部的实现原理:使用response设置302状态码和设置location响应头实现重定向
package com.lovo.study;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo03 extends HttpServlet {
private static final long serialVersionUID = 1L;
public ResponseDemo03() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* 1.调用sendRedirect方法实现请求重定向,
* sendRedirect方法内部调用了
* response.setHeader("Location", "/request_form.jsp");
* response.setStatus(HttpServletResponse.SC_FOUND);//设置302状态码,等同于response.setStatus(302);
*/
response.sendRedirect("/request_form.jsp");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.4、重定向与转发的区别
1)转发是服务器行为,重定向是客户端行为。 为什么这样说呢,这就要看两个动作的工作流程:
转发过程:客户浏览器发送http请求——web服务器接受此请求——调用内部的一个方法在容器内部完成请求处理和转发动作——将目标资源发送给客户;
在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。
在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
重定向过程:客户浏览器发送http请求——web服务器接受后发送302状态码响应及对应新的location给客户浏览器——客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址——服务器根据此请求寻找资源并发送给客户。
在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。
2).对信息的传输不一样
重定向,其实是两次request
第一次,客户端request A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失。
请求转发是服务器内部把对一个request/response的处理权,移交给另外一个
对于客户端而言,它只知道自己最早请求的那个A,而不知道中间的B,甚至C、D。传输的信息不会丢失。
3).对于路径的认知不一样
请求转发是服务器端的动作,所以当转发路径如:
request.getRequestDispatcher("/RequestDemo07").forward(request, response);
路径前的绝对路径"/",会被认为是当前工程的根目录,也就是说,如果当前路径是:
http://localhost:8080/ServletDemo/RequestDemo06
那么根据上面的跳转就会跳转到
http://localhost:8080/ServletDemo/RequestDemo07
而重定向,如下面的路径: response.sendRedirect("/RequestDemo07");
如果当前路径是: http://localhost:8080/ServletDemo/RequestDemo06
就会跳转到: http://localhost:8080/RequestDemo07
四、web工程中URL地址的推荐写法
在JavaWeb开发中,只要是写URL地址,那么建议最好以"/"开头,也就是使用绝对路径的方式,那么这个"/"到底代表什么呢? 可以用如下的方式来记忆"/":如果"/"是给服务器用的,则代表当前的web工程,如果"/"是给浏览器用的,则代表webapps目录。
4.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工程。
4.2、"/"代表webapps目录的常见应用场景
①.使用sendRedirect实现请求重定向
response.sendRedirect("/index.jsp");
服务器发送一个URL地址给浏览器,浏览器拿到URL地址之后,再去请求服务器,所以这个"/"是给浏览器使用的,此时"/"代表的就是webapps目录,也就是上面的路径实际是:
http://localhost:8080/index.jsp
这样的路径肯定不不正确的,所以要正常访问需要改为:
response.sendRedirect("/SerlvetDemo(工程名)/index.jsp");
这种写法是将项目名称写死在程序中的做法,不灵活,万一哪天项目名称变了,此时就得改程序,所以推荐使用下面的灵活写法:
response.sendRedirect(request.getContextPath()+"/index.jsp");
request.getContextPath()获取到的内容就是"/ServletDemo",这样就比较灵活了,使用request.getContextPath()代替"/项目名称",推荐使用这种方式,灵活方便!
②.使用超链接跳转
<a href="/ServletDemo/index.jsp">跳转到首页</a>
这是客户端浏览器使用的超链接跳转,这个"/"是给浏览器使用的,此时"/"代表的就是webapps目录。
使用超链接访问web资源,绝对路径的写法推荐使用下面的写法改进:
<a href="${pageContext.request.contextPath}/index.jsp">跳转到首页</a>
③.Form表单提交 ④.js脚本和css样式文件的引用 处理方案等同于超链接
案例:生成随机图片
package com.lovo.study;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
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 ResponseDemo04 extends HttpServlet {
private static final long serialVersionUID = 1L;
public ResponseDemo04() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("refresh", "5");
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D)image.getGraphics();
//先设置画笔颜色然后画背景颜色
g.setColor(Color.WHITE);
g.fillRect(0, 0, 80, 20);
//设置画笔颜色画数字
g.setColor(Color.BLUE);
//设置字体
g.setFont(new Font(null, Font.BOLD, 20));
//生产随机数
int [] nums = {0,1,2,3,4,5,6,7,8,9};
String str = "";
for(int i=0; i<6; i++){
int n = (int)Math.floor(Math.random() * 10);
str += n;
}
//画字符串
g.drawString(str, 0, 20);
//设置响应头以图片方式打开
response.setContentType("image/jpeg");
//设置响应头清除缓存
response.setDateHeader("expries", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
//6.将图片写给浏览器
ImageIO.write(image, "jpg", response.getOutputStream());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Comments