Web服务器收到客户端的http请求,会针对
每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。
request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向容器输出数据,只需要找response对象就行了。
ServletRequest和ServletResponse:
请求对象和响应对象,服务器自动创建,不依赖于具体的协议,任何协议都可以用
HttpServletRequest和HttpServletresponse:
为ServletRequest和ServletResponse的子类,依赖于具体的协议,处理http协议的东西
当一个请求从远程发过来的时候,服务器接收到该请求,会针对每一个的请求分别创建request和response对象,(服务器创建的)
此时Request对象封装了客户端的所有信息,
Response对象是空的 等着我们去写
response代表了一个响应,服务端要向客户端所发送的所有的东西必须通过该对象来操作。
继承于ServletResponse
Response对象创建的时间:
当在创建Servlet对象的时候,服务器已经自动创建了Request和Response对象了
直接拿来用就可以了
Response对象代表了服务端对客户端的一个输出
应用
1.解决中文乱码
package com.heima.one;
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 ServletResponse1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//采用字节流输出数据
String s = "黑马训练营1" ;
//response.getOutputStream().write(s.getBytes()) ;
//不会出现乱码,getBytes()方法使用的是平台默认的字符集:gbk,浏览器使用的也是平台默认的编码gbk进行解码,所以不会出现乱码
//response.getOutputStream().write(s.getBytes("utf-8")) ;//乱码,因为浏览器使用的是gbk
//解决乱码问题
//第一种办法:让用户在浏览器中选择解码(不靠谱)
//第二种方式:通知浏览器采用某种编码进行解码
//response.setHeader("Content-Type", "text/html;charset=UTF-8") ;
//第三种方式:输出一个字符串
// response.getOutputStream().write("<meta http-equiv='content-type' content='text/html; charset=UTF-8'>".getBytes()) ;
// response.getOutputStream().write(s.getBytes("utf-8")) ;
//第四种方式 让服务器的编码用一种编码,通知浏览器的解码
// response.setCharacterEncoding("UTF-8") ;//服务器编码采用u8
// response.setHeader("Content-Type", "text/html;charset=UTF-8") ;//通知浏览器采用u8解码
//
// response.getOutputStream().write(s.getBytes("utf-8")) ;
//第五种方法(推荐)
response.setContentType("text/html;charset=utf-8") ;
//此句代码做了两件事情:1 设定服务器将数据编码时用的码表
// 2.通知浏览器解码用的码表
//
// response.getOutputStream().write(s.getBytes("UTF-8")) ;
//字符流输出中文
response.getWriter().write(s) ;//乱码,此处输出的时候用的编码是ISO-8859-1
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
输出数字:
package com.heima.response;
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 ServletResponse1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// response.getWriter().write(65) ;//输出A:把数字当作asca码来对待了,如果想要输出数字,把数字作为一个字符串来对待
response.getWriter().write(65 +"") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.中文文件名的文件下载
package com.heima.response;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示中文文件名文件的下载
public class ServletResponse2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取文件的路径
String path = getServletContext().getRealPath("/WEB-INF/classes/美女.jpg") ; //默认从工程路径开始
//创建输入流
InputStream is = new FileInputStream(path) ;
byte[] bs = new byte[1024] ;
int b = 0 ;
//创建输出流对象
ServletOutputStream os = response.getOutputStream() ;
//对中文进行编码
//拿到中文的文件名
String name = path.substring(path.lastIndexOf("\\") + 1, path.length()) ;
System.out.println(name);
//对中文文件名进行编码
name = URLEncoder.encode(name, "utf-8") ;
//此处是文件名,与文件的内容不一样,如果下载的不是图片,而是文本文件,那么就采取response.setContentType,则文本文件下载下来的东西就是正常的
System.out.println("编码后: " + name);
//通知浏览器以下载的方式打开文件
response.setHeader("Content-Disposition", "attachment;filename=" + name) ;
while((b = is.read(bs)) != -1){
os.write(bs,0,b) ;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3.输出验证码
l
输出随机图片(CAPTCHA图像):CompletelyAutomated Public Turing Test to Tell Computers and Humans Apart(全自动区分计算机和人类的测试)
l
相关主要类(JDK查看API)
•BufferedImage:内存图像
•Graphics:画笔
•ImageIO:输出图像
•放在html页面上<img src/>
l注意:浏览器默认会缓存图片
l
l
控制客户端不要缓存:
lresponse.addHeader("Pragma","no-cache");
lresponse.setHeader("Cache-Control","no-cache");
lresponse.setHeader("Expires","0");
l
js刷新图片
页面:
<!DOCTYPE html>
<html>
<head>
<title>1.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
</head>
<script type="text/javascript">
function change(){
var img = document.getElementById("img") ;
//加一个无意义的参数,目的就是让地址每次都发生变化
img.src = "/day09_00_httpServletResponse/servlet/ServletResponse3?t=" + new Date().getTime() ;
}
</script>
<body>
<form action="">
姓名: <input type = ""><br>
年龄: <input type = ""><br><br>
请输入验证码: <input type = "text" name = "code"> <img src = "/day09_00_httpServletResponse/servlet/ServletResponse3" id = "img"><a href = "javascript:change()">看不清楚,换一张</a>
</form>
</body>
</html>
package com.heima.response;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
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;
//import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
//输出验证码
public class ServletResponse3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//创建变量
int width = 120 ;
int height = 30 ;
//创建一个内存图像
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) ;
//创建画笔
Graphics g = image.getGraphics() ;
//指定边框的颜色
g.setColor(Color.RED) ;
//画图像的边框
g.drawRect(0, 0, width, height) ;
//填充一下矩形的背景色
//设定画笔的颜色
g.setColor(Color.YELLOW) ;
//填充矩形的背景
g.fillRect(1, 1, width-2, height-2) ;
//设置字体大小
g.setFont(new Font("幼圆",Font.BOLD + Font.ITALIC,22)) ;
//填充内容
Random r = new Random() ;
//设置画笔的颜色
g.setColor(Color.GRAY) ;
//画30条干扰线
for (int i = 0; i < 30; i++) {
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height)) ;
}
//设定画笔的颜色
g.setColor(Color.RED) ;
//随机产生4个汉字
String s = "黑马训练营北京传智播客IhavanoMoney" ;
//先将汉字转换为unicode编码
s = "\u9ED1\u9A6C\u8BAD\u7EC3\u8425\u5317\u4EAC\u4F20\u667A\u64AD\u5BA2IhavanoMoney" ;
//转换成unicode编码是为了适应不同国家的电脑都能正常显示
for (int i = 0; i < 4; i++) {
char c = s.charAt(r.nextInt(s.length())) ;
int flag = r.nextBoolean()?1:-1 ;
g.drawString(c+"", 20 + 20*i + flag*r.nextInt(5), 23 + flag * r.nextInt(5)) ;
}
// //随机产生4个数字输出到页面
// for (int i = 0; i < 4; i++) {
// int n = r.nextInt(10) ;
// //画到到图片中
// g.drawString(n+"", 20 + 20*i, 20) ;
// }
//告诉客户端不要缓存图像
response.setHeader("Expires", -1 + "") ;
response.setHeader("Cache-control", "no-cache") ;
response.setHeader("Pragma", "no-cache") ;
//将图片输出到客户端
ImageIO.write(image, "jpg", response.getOutputStream()) ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
4.定时刷新网页
package com.heima.response;
import java.io.IOException;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//定时刷新网页
public class ServletResponse4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//每隔2秒刷新自己
// response.setHeader("Refresh", "2") ;
// response.getWriter().write("aa"+ new Random().nextInt()) ;
//每隔2秒刷新到其他资源
response.setHeader("Refresh", "2;url=/day09_00_httpServletResponse/1.html") ;
response.getWriter().write("aa"+ new Random().nextInt()) ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
5.控制浏览器的缓存时间
package com.heima.response;
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 ServletResponse5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//重新打开浏览器就是从服务器中拿取数据了
response.setContentType("text/html;charset= UTF-8") ;
response.getWriter().write("大家好") ;
//控制缓存的时间 缓存10s 过了就从服务器拿取数据
response.setDateHeader("Expires", System.currentTimeMillis() + 10000) ; //时间是从1970年的1月1日0点0分0秒0毫秒开始计时
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
6.请求重定向
package com.heima.response;
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 ServletResponse6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("servletresppnse6");
//第一种方式
// response.setStatus(302) ;
// response.setHeader("Location", "/day09_00_httpServletResponse/servlet/ServletResponse5") ;
response.sendRedirect("/day09_00_httpServletResponse/servlet/ServletResponse5") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
response对象使用的细节
1.getOutputStream和getWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOuputStream、Printwriter对象。
2.getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。 会抛异常。
3.Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再
与
响应状态行和各响应头组合后输出到客户端。
4.Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用
close方法关闭该输出流对象。
注意:只有response产生的流才可以不关,如果是自己写的流要关闭
package com.heima.response;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示response对象的细节
public class ServletResponse7 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//不要在一个servlet中同时使用字符流和字节流
response.getWriter().write("林志玲") ;
response.getOutputStream().write("大家好".getBytes()) ;
//混用报错 500
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}