1 响应对象
1.1.1 关于响应
响应,它表示了服务器端收到请求,同时也已经处理完成,把处理的结果告知用户。简单来说,指的就是服务器把请求的处理结果告知客户端。在B/S架构中,响应就是把结果带回浏览器。
响应对象,顾名思义就是用于在JavaWeb工程中实现上述功能的对象。
1.1.2 常用响应对象
响应对象也是是Servlet规范中定义的,它包括了协议无关的和协议相关的。
协议无关的对象标准是:ServletResponse接口
协议相关的对象标准是:HttpServletResponse接口
类结构图如下:
我们课程中涉及的响应对象都是和HTTP协议相关的。即使用的是HttpServletResponse接口的实现类。
1.2 常用方法介绍
在HttpServletResponse接口中提供了很多方法,接下来我们通过API文档,来了解一下这些方法。
常用状态码:
状态码 | 说明 |
---|---|
200 | 执行成功 |
302 | 它和307一样,都是用于重定向的状态码。只是307目前已不再使用 |
304 | 请求资源未改变,使用缓存。 |
400 | 请求错误。最常见的就是请求参数有问题 |
404 | 请求资源未找到 |
405 | 请求方式不被支持 |
500 | 服务器运行内部错误 |
状态码首位含义:
状态码 | 说明 |
---|---|
1xx | 消息 |
2xx | 成功 |
3xx | 重定向 |
4xx | 客户端错误 |
5xx | 服务器错误 |
1.3 响应对象的使用示例
1.3.1 响应-字节流输出中文问题
返回值 方法名 说明
ServletOutputStream getOutputStream() 获取响应字节输出流对象
void setContentType("text/html";charset="utf-8") 设置响应内容类型,解决中文乱码问题
package com.itheima.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; /* * 字节流响应消息
* 问题:
* String str = "字节流中文乱码问题";
* 使用字节流输出,会不会产生中文乱码?
* 答案:
* 会产生乱码
* 原因:
* String str = "字节流中文乱码问题"; 在保存时用的是IDEA创建文件使用的字符集UTF-8。
* 到浏览器上显示,chrome浏览器和ie浏览器默认的字符集是GB2312(其实就是GBK),存和取用的不是同一个码表,就会产生乱码。
*
* 引申:
* 如果产生了乱码,就是存和取用的不是同一个码表
* 解决办法:
* 把存和取的码表统一。
*/
* */ @WebServlet("/servletDemo01") public class ServletDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); //获取字节输出流对象 ServletOutputStream os = resp.getOutputStream(); //定义一个消息 String str="你好"; //通过字节流对象输出 os.write(str.getBytes("utf-8")); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
字符流响应消息
返回值 方法名 说明
PrintWriter getWriter() 获取响应字符输出流对象
void setContentType("text/html;charset=utf-8") 设置响应内容类型,解决中文乱码问题
package com.itheima.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /* * 字符流响应消息 * */ @WebServlet("/servletDemo02") public class ServletDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); //获取到字符输出流对象 PrintWriter pw = resp.getWriter(); //准备一个消息 String str="你好"; //通过字符流输出 pw.write(str); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
响应图片
1.创建字节输入流对象,关联读取的图片路径
2.通过响应对象获取字节输出流对象
3.循环读取和写出图片
package com.itheima.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; /* * 响应图片 * */ @WebServlet("/servletDemo03") public class ServletDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //通过文件的相对路径获取绝对路径 String realPath = getServletContext().getRealPath("/img/Request.png"); System.out.println(realPath); //创建字节输入流对象,关联图片路径 BufferedInputStream bis=new BufferedInputStream(new FileInputStream(realPath)); //通过响应对象获取字节输出流对象 ServletOutputStream os = resp.getOutputStream(); //循环读写操作 byte[] arr=new byte[1024]; int len; while((len=bis.read(arr))!=-1){ os.write(arr,0,len); } //释放资源 bis.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
设置缓存:
缓存:对于不经常变化的数据,我们可以设置合理缓存时间,以避免浏览器频繁请求服务器 ,以此来提高效率!
返回值 方法名 说明
void setDateHeader(String name,long time) 设置 消息头,添加缓存
package com.itheima.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; /* * 设置缓存 * */ @WebServlet("/servletDemo04") public class ServletDemo04 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String news="这是一条很火爆的新闻"; //设置缓存 1小时的缓存时间 resp.setDateHeader("Expires",System.currentTimeMillis()+1*60*60*1000); //设置编码的格式 resp.setContentType("text/html;charset=UTF-8"); //写出数据 resp.getWriter().write(news); System.out.println("aaa"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
定时刷新:过了指定时间后,页面自动进行跳转
返回值 方法名 说明
void setHeader(String name,String value) 设置消息头定时刷新
package com.itheima.Servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* * 定时刷新 * */ @WebServlet("/servletDemo05") public class ServletDemo05 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String str="您的用户名或密码有误,三秒后自动跳转到登陆页面"; resp.setContentType("text/html;charset=utf-8"); //写出数据 resp.getWriter().write(str); //定时刷新 resp.setHeader("Refresh","3,URL=/response/login.html"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
客户端的一次请求到达后,发现需要借助其他Servlet来实现功能
特点:浏览器地址栏会发生改变,两次请求,请求域对象中不能共享数据,可以重定向到其他服务器。
重定向的实现原理
设置响应状态码为302 resp.setStatus(302);
设置相应的资源路径(响应到哪里去,通过响应消息头location来指定)
resp.setHeader("location","response/responseDemo07")
响应对象重定向方法
返回值 方法名 说明
void sendRedirect(String name) 设置重定向
ResponseDemo6
package com.itheima.Servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* * 请求重定向 * */ @WebServlet("/servletDemo06") public class ServletDemo06 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("servletDemo06执行了"); //设置请求共享数据 req.setAttribute("username","张三"); //设置重定向 resp.sendRedirect(req.getContextPath()+"/servletDemo07"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
ResponseDemo7
public class ResponseDemo7 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("welcome to ResponseDemo7"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package com.itheima.Servlet; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; /* * 图片显示验证码 * */ @WebServlet("/servletDemo08") public class ServletDemo08 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int width=200; int height=35; /* * 1.创建图像内存对象 * 2.拿到画笔 * 3.设置颜色,画矩形边框 * 4.设置颜色,填充矩形 * 5.设置颜色,画干扰线 * 6.设置颜色,画验证码 * 7.把内存图像输出到浏览器上 * */ //创建内存图像 BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//参数:宽度,高度(指的都是像素),使用的格式(RGB) Graphics g=image.getGraphics();//画笔就一根 //设置颜色 g.setColor(Color.BLUE); //画边框 g.drawRect(0,0,width,height); //设置颜色 g.setColor(Color.GRAY); //填充矩形 g.fillRect(1,1,width-2,width-2); //设置颜色 g.setColor(Color.WHITE); //那随机数对象 Random r=new Random(); //话干扰线10条 for (int i = 0; i < 10; i++) { g.drawLine(r.nextInt(width),r.nextInt(height),r.nextInt(width),r.nextInt(height)); } //设置颜色 g.setColor(Color.red); //改变字体大小 Font font=new Font("宋体",Font.BOLD,30); g.setFont(font);//设置字体 //画验证码 4个 int x=35; for (int i = 0; i < 4; i++) { g.drawString(String.valueOf(10),x,25); x+=35; } //输出到浏览器上 //参数:1.内存对象。2.输出的图片格式。3.使用额输出流 ImageIO.write(image,"jpg",resp.getOutputStream()); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
6.释放资源
package com.itheima.Servlet; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; 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.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.util.Random; /* * 下载文件 * */ @WebServlet("/servletDemo09") public class ServletDemo09 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.创建字节输入流,关联 读取的文件 String realPath = getServletContext().getRealPath("/img/Request.png"); BufferedInputStream bis=new BufferedInputStream(new FileInputStream(realPath)); /* * Content-Type 消息头名称 支持的类型 * application/octet-stream 消息头参数 应用的类型为字节流 * */ //2.设置响应消息头支持的类型 resp.setHeader("Content-Type","application/octet-stream"); //3.设置响应消息头以下载方式打开资源 /* * Content-Disposition 消息头名称 处理的形式 * attachment;filename=Request.png 消息头参数 附件形式进行处理 指定下载文件的名称 * */ resp.setHeader("Content-Disposition","attachment;filename=Request.png"); //4.通过响应对象获取字节输出流对象 ServletOutputStream os = resp.getOutputStream(); //5.循环读写 byte []arr=new byte[1024]; int len; while((len= bis.read(arr))!=-1){ os.write(arr,0,len); } //6.释放资源 bis.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }