Response对象
封装了所有响应信息并将服务器端资源数据输出到浏览器
HttpServletResponse 对象封装了向客户端发送数据、发送响应头,发送响应状态码的
方法。
1.封装了所有响应数据(获取不到,但是可以设置响应头数据,如果你不设置都会有默认值)
2.页面跳转—重定向
3.响应头作用
a)数据压缩
b)附件下载
c)验证码
响应数据格式
响应行,响应头,响应体.
响应行(状态行)
响应行的组成
响应行是http响应内容的第一行。
响应行一般数据为:HTTP/1.1 200(tomcat8.5) 或者 HTTP/1.1 200 OK(tomcat7)
响应行分为三个部分:
HTTP/1.1:协议版本
200:响应状态码
OK:对响应状态码的解释
常见的响应状态码:
1.200 OK 请求已成功,服务器通信正常。
2.302 Move temporarily 设置重定向页面跳转的动作执行。
3.304 Not Modified 从浏览器缓存中读取数据,不从服务器重新获取数据。
4.403 Forbidden 服务器已经理解请求,但是拒绝执行它。由于资源没有执行权限,导致无法执行.
5.404 Not Found 请求失败,请求所希望得到的资源未被在服务器上发现。一般是用户输错了url导致.
6.405 Method Not Allowed 请求行中指定的请求方法不存在。
例如,发送post请求,服务器没有doPost方法,就会报这个错误.
7.500 Internal Server Error 服务器发生了错误。一般服务器代码错误
response.setStatus(302);
响应头作用
Location: http:
Server:apache tomcat --服务器型号
Content-Encoding: gzip --数据压缩
Content-Length: 80 --数据长度
Content-Language: zh-cn --语言环境
Content-Type: text/html; charset=GB2312 --编码
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT --最后修改时间
Refresh: 1;url=http:
Content-Disposition: attachment; filename=aaa.zip --下载
Set-Cookie:SS=Q0=5Lb_nQ; path=/search
Expires: -1 --缓存
Cache-Control: no-cache --缓存
Pragma: no-cache --缓存
Connection: close/Keep-Alive --连接
Date: Tue, 11 Jul 2000 18:23:51 GMT --时间
常见的响应头介绍
1. location:
重定向操作:通知浏览器马上向该地址发送请求,通常和响应码 302 一起使用。
2. content-encoding:
设置当前数据的压缩格式,通知浏览器以何种压缩格式解压数据。
比如像浏览器输出一个压缩文件,可以设置这个响应头通知浏览器解压显示数据,
但是目前浏览器只支持”gzip”格式解压
3.refresh:
定时刷新跳转页面
4. content-disposition:
通知浏览器以何种方式获取数据(直接解析数据(网页,图片文本),或者以附件方式(下载文件))
5. content-type:
实体头部用于指示资源的 MIME 类型(MIME 类型:用于提示当前文件的媒体类型,)
例如:
图片——(image/png)
音频——(audio/ogg)。
它的作用与传统上 windows 上的文件扩展名相同。
我们 content-type 一般都设置为”text/html;charset=utf-8”,
其中"text/html";——设置浏览器以文本格式解析数据;
"charset=utf-8"——响应数据的编码表。
response常用API
void setHeader(String name, String value) 用给定名称和值设置响应头
response.setHeader("location", "/demo/index.html");
void setStatus(int sc) 设置此响应的状态代码
response.setStatus(302);
页面跳转—重定向
response.setHeader("location", "/demo/index.html");
response.setStatus(302);
response.sendRedirect("/demo/index.html");
页面转发与重定向区别
1.请求转发url没有发生变化,
2.请求转发跳转发生在服务器内部,重定向跳转发生在浏览器客户端
3.请求转发是服务器内部跳转,只能访问当前资源目录里面的资源;
重定向是客户端浏览器发生跳转,所以可以访问本服务器上任意位置资源
4.请求转发共享一个request和response,重定向不共享。
5.请求转发访问的是同一目录下的资源,所以访问速度快 ;
重定向可以访问本服务器上的任意位置资源,所以访问速度比较慢.
response.setHeader("refresh","3;url=http://www.baidu.com");
response.setStatus(200);
response.sendRedirect(request.getContextPath()+"/ResponseServlet");
解决服务器输出字符流中文乱码
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("<ul>");
writer.write("<li>北京</li>");
writer.write("<li>上海</li>");
writer.write("<li>广州</li>");
writer.write("</ul>");
writer.flush();
writer.close();
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("utf-8");
response.setHeader("content-type","text/html;charset=UTF-8");
或
response.setContentType("text/html;charset=UTF-8");
定时刷新
Refresh: 1;url=http:
描述:1秒以后页面跳转到http:
response.setHeader("refresh","3;url="+getServletContext().getContextPath()+"/demo.html");
页面倒计时进行跳转到某一资源页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
var count = 3;
window.onload=function(){
tick();
}
function tick(){
if(count>0){
var p = document.getElementById("one");
p.innerHTML=count--;
window.setTimeout(tick, 1000);
}
}
</script>
</head>
<body>
页面在<p id="one">3</p>秒后跳转...
</body>
</html>
response.setHeader("refresh", "3;url="+getServletContext().getContextPath()+"/demo.html");
request.getRequestDispatcher("/wait.html").forward(request, response);
Content-Encoding 数据压缩
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("content-encoding", "gzip");
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 1000; i++) {
stringBuilder.append("abcd");
}
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(response.getOutputStream());
gzipOutputStream.write(stringBuilder.toString().getBytes());
gzipOutputStream.finish();
}
以附件形式下载文件
Content-Disposition: attachment; filename=aaa.zip --下载
attachment,通知浏览器不要显示数据要以附件形式下载
filename=aaa.zip,下载的文件名字
通知浏览器不要直接显示数据,以附件形式下载数据。
默认浏览器查看数据是直接显示数据,有的资源下载网站需要下载资源数据而不是直接显示,
所以需要通过设置响应头content-disposition来通知浏览器以附件下载数据。
* 响应头:content-disposition
* 格式:attachment; filename=aaa.zip
* 作用,通知浏览器以附件下载方式下载文件
* */
//要求:通知浏览器下载这个图片
//response.setHeader("content-disposition","attachment;filename=2.jpg");
1. 创建一个页面,展示所有要被下载文件的链接。
2. 链接将要下载的文件名称,发送给服务器的 Servlet,
让 Servlet 进行处理服务器加载文件资源。
<script>
function isIE(){
var userAgent = window.navigator.userAgent.toLocaleLowerCase();
var ie10 = userAgent.indexOf("msie") > 0 ? true : false;;
var ie11 = userAgent.indexOf("rv:11.0") > 0 ? true : false;
var edge = userAgent.indexOf("edge") > 0 ? true : false;;
if (ie10 || ie11 || edge) {
return true;
}else {
return false;
}
}
window.onload = function(){
if(isIE()){
var a = document.getElementById("xx");
var href = a.href;
var encodeHref = encodeURI(href);
a.href = encodeHref;
}
}
</script>
String fileName = request.getParameter("fileName");
System.out.println(fileName);
ServletContext context = getServletContext();
String realPath = context.getRealPath("/download");
File file = new File(realPath,fileName);
response.setContentType(getServletContext().getMimeType(fileName));
String ua = request.getHeader("User-Agent");
boolean IE_LT11 = ua.contains("MSIE");
boolean IE11 = ua.contains("rv:11.0) like Gecko");
boolean Edge = ua.contains("Edge");
if (IE_LT11 || IE11 || Edge) {
fileName = URLEncoder.encode(fileName, "UTF-8");
fileName = fileName.replace("+", "%20");
}
else {
Base64.Encoder encoder = Base64.getEncoder();
fileName = encoder.encodeToString(fileName.getBytes("utf-8"));
fileName = "=?utf-8?B?" + fileName + "?=";
}
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
响应体
就是服务器输出数据给用户看,浏览器直接要显示给用户的网页数据,就是服务器输出数据
.
.
.--
验证码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="LoginServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"/></td>
</tr>
<tr>
<td>验证码:</td>
<td><input type="password" name="checkcode"/></td>
</tr>
<tr>
<td></td>
<td><img id="img" onclick="changeCheckCode(this)" src="CheckCodeServlet"/></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登录"/></td>
</tr>
</table>
<script type="text/javascript">
function changeCheckCode(imgObj) {
imgObj.src="CheckCodeServlet?time="+new Date().getTime();
}
</script>
</form>
</body>
</html>
BufferedImage image = new BufferedImage(90,30,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.fillRect(0,0,90,30);
g.setColor(Color.red);
g.drawRect(0,0,90-1,30-1);
for(int i=0;i<3;i++){
g.setColor(getRandomColor());
int x1=random.nextInt(89);
int y1 =random.nextInt(29) ;
int x2=random.nextInt(89);
int y2 =random.nextInt(29) ;
g.drawLine(x1,y1,x2,y2);
}
String checkCode= "23456789qwertyupasdfghjkzxcvbnmQWERTYUPASDFGHJKLZXCVBNM";
StringBuilder checkCodeBuilder = new StringBuilder();
for(int i=0;i<4;i++){
int index = random.nextInt(checkCode.length());
char item = checkCode.charAt(index);
checkCodeBuilder.append(item);
g.setColor(getRandomColor());
g.drawString(item+"",10+(i*20),20);
}
ImageIO.write(image,"png",response.getOutputStream());
}
/**
* 获取随机颜色
* @return Color
*/
private Color getRandomColor(){
int r=random.nextInt(256);
int g=random.nextInt(256);
int b=random.nextInt(256);
return new Color(r,g,b);
}
response.getOutputStream().write("1".getBytes());
PrintWriter p = response.getWriter();
p.print("2");
只能回应一次请求? or一个页面只能用一个输出流?
一次响应只能使用一种类型输出流,要么字符流,要么字节流。这是服务器输出数据的机制。