1 HttpServletResponse概述
在创建Servlet时会覆盖service()方法,或doGet()/doPost()。这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的response的类型是ServletResponse,
而doGet/doPost方法的response的类型是HttpServletResponse,
HttpServletResponse是ServletResponse的子接口,功能和方法更加强大。
1.1 response的运行流程
1.2通过抓包工具抓取Http响应
(之前写过)
因为response代表响应,所以可以通过该对象分别设置Http响应的响应行,响应头和响应体:
2通过response设置响应行
1)设置响应行的状态码(int sc)
例:建一个web项目,建一个servlet
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置状态码 response.setStatus(302); }
3通过response设置响应头
3.1
1)设置响应头 setHeader(String name, String value)
2)添加响应头addHeader(String name, String value)
例:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //添加响应头 response.addHeader("name", "zhangsan"); }
其他方法:
addIntHeader(String name, int value)
addDateHeader(String name, long date)
setDateHeader(String name, long date)
setIntHeader(String name, int value)
3.2设置定时刷新的头
response.setHeader("refresh", "5;url=http://www.baidu.com");
用js方式:
建一个index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>Insert title here 恭喜你注册成功,5秒后跳转,如不跳转点击 这里
4重定向
4.1重定向需要
状态码:302
响应头:location 代表重定向地址
4.2特点
1)访问服务器两次
2)地址栏会发生变化
例:建两个servlet:Servlet01, Servlet02
package com.zyx.demo01;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 Servlet01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("Servlet01"); //重定向到Servlet02 //1.设置响应行状态码 response.setStatus(302); //2.设置响应头的Location response.setHeader("Location", "/20190109WEB/Servlet02"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
访问http://localhost:8080/20190109WEB/Servlet01
实际不用这些,比较麻烦,用sendRedirect()方法
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("Servlet01"); //重定向到Servlet02 response.sendRedirect("/20190109WEB/Servlet02"); }
5通过response设置响应体
5.1响应体设置文本
PrintWriter getWriter()
获得字符流,通过字符流的write(String s)方法可以将字符串设置到response缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览 器端。
5.2关于设置中文的乱码问题
response.getWriter().write("中国");
修改:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置response缓冲区码表 response.setCharacterEncoding("utf-8"); //告知客户端用什么码表解码 response.setHeader("Content-Type", "text/html;charset=utf-8"); response.getWriter().write("中国"); }
比较麻烦,不用这种方式。用方法解决:
//解决响应时中文乱码问题response.setContentType("text/html;charset=utf-8");
5.3响应头设置字节
方法:ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。
字节能解析就解析。不能解析就下载。
例:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取Servlet字节输出流 ServletOutputStream out=response.getOutputStream(); //获取服务器上的图片(绝对路径) String realpath=getServletContext().getRealPath("download/pic.jpg"); //获取数据源 FileInputStream in=new FileInputStream(realpath); //开始复制 int len=0; byte[] bytes=new byte[1024]; while((len=in.read(bytes))!=-1){ out.write(bytes,0,len); } //释放资源 in.close(); }
改成b.zip就是下载(因为无法解析)
5.4文件下载
文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端。
所以文件下载需要IO技术将服务器端的文件使用InputStream读取到,
再使用ServletOutputStream写到response缓冲区中。
例:
建一个download.jsp
提供下载,需要设置两个响应头,告知浏览器文件的类型和文件的打开方式:
1)告知浏览器文件的类型:response.setContentType(文件的MIME类型);
用ServletContext对象的getMimeType()方法获取MIME类型
2)告示浏览器文件的打开方式是下载:
response.setHeader("Content-Disposition","attachment;filename=文件名称");
把文件名改成中文
这里也改了:
打断点查看一下:
用debug模式(服务器上右键---Debug)查看
解决方式:
filename = new String(filename.getBytes("ISO8859-1"), "utf-8");
但是,没有名字
这是因为如果下载中文文件,页面在下载时会出现中文乱码或不能显示文件名的情况,
原因是不同的浏览器默认对下载文件的编码方式不同,ie是UTF-8编码方式,而火狐浏览器是Base64编码方式。所里这里需要解决浏览器兼容性问题。
解决浏览器兼容性问题的首要任务是要辨别访问者是ie还是火狐(其他),通过Http请求体中的一个属性可以辨别(代码不用记,直接复制)。
完整代码:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取要下载的文件名称 String filename = request.getParameter("filename"); // 解决request对象中get方式中文乱码 filename = new String(filename.getBytes("ISO8859-1"), "utf-8"); // 获取User-Agent(哪个浏览器) String agent = request.getHeader("User-Agent"); // 根据不同浏览器对文件进行不同编码 String filenameEncoder = ""; if (agent.contains("MSIE")) { // IE浏览器 filenameEncoder = URLEncoder.encode(filename, "utf-8"); filenameEncoder = filenameEncoder.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filenameEncoder = URLEncoder.encode(filename, "utf-8"); } // 告知客户端浏览器该文件的MIME类型 String filemime = getServletContext().getMimeType(filename); response.setContentType(filemime); // 告示浏览器文件的打开方式是下载 response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoder); // 这里原来是filename,改成filenameEncoder // 获取文件在服务器上的绝对路径 String realpath = getServletContext().getRealPath("download/" + filename); // 获取文件输入流(数据源) FileInputStream fis = new FileInputStream(realpath); // 获得输出流(目的地) ServletOutputStream out = response.getOutputStream(); // 文件复制 int len = 0; byte[] bytes = new byte[1024]; while ((len = fis.read(bytes)) != -1) { out.write(bytes, 0, len); } // 释放资源 fis.close(); }
5.5验证码
1)将写好的验证码成生图片Servlet文件 CheckImgServlet复制到项目中
2)验证码数据new_words.txt放在WEB-INF里(为了外部访问不到)
3)配置web.xml
4)建一个register.jsp
文件目录如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>Insert title here
每点击图片一次,就换一张图片。
6 response细节点
1)response获得的流不需要手动关闭,web容器(tomcat容器)会关闭
2)getWriter和getOutputStream不能同时调用
3)重定向语句一般作为终结代码
因为都跳走了,下面的代码不会执行了。
重点总结:
1设置响应行:
设置状态码setStatus
2添加响应头:addHeader
3设置响应头: 1)定时刷新的头response.setHeader("refresh", "5;url=完整网址");
2)用js方式实现
4重定向(用方法)sendRedirect
5字符流:解决响应时中文乱码问题(用方法)
response.setContentType("text/html;charset=utf-8");
6字节流两个例子:
文件下载:就是文件复制的基础上,加上下载方式和解决中文乱码和编码解析等问题
验证码:注意拷贝过来servlet后,配置web.xml。图片点击更新因为缓存问题,加一个毫秒值做为参数