回顾
- tomcat服务器启动的时候会加载服务器中的项目,并为每个项目创建一个唯一的ServletContext对象
- 在每个项目中有多个Servlet对象,每个Servlet对象都有一个ServletConfig对象,对应的是web.xml中的配置信息
大纲
- 完成文件下载
- 生成验证码(了解)
- 了解验证码的原理
- 到企业中,每个企业都有自己封装好的验证码代码,直接调用
- 还有第三方机构提供的代码
HttpServletResponse
概述
- 浏览器发送请求给服务器,服务器内核通过反射创建相应的Servlet对象
- 同时将Http请求的参数封装到ServletRequest对象中,和创建一个默认的ServletResponse对象(有默认的返回地址,请求头等参数,可以自己修改,响应体默认是空的)
- 学习通过HttpServletResponse修改响应行,响应头,响应体的信息
Response设置响应行的信息
- 响应行包括(Http协议的版本,状态码,状态信息),我们只需要修改状态码
- 设置响应行中的状态码
- 开发中用的并不多,一般都由tomcat自动生成对应的状态码
Response设置响应头
- 一般开发中用: serHeader(String name, String value)一个就够了
- 设置响应头的方式有:
addHeader(String name, String value)
addIntHeader(String name, int value)
addDateHeader(String name, long date)
setHeader(String name, String value)
setDateHeader(String name, long date)
setIntHeader(String name, int value)
- 其中,add表示添加,set表示设置
- 虽然添加或者设置的时候有int和long值,但是通过抓包工具,响应头的数据最终还是转为字符串
- add方法中一般只用addHeader
- 如果添加了两次相同的头,则会把两次的内容连在一起
- setHeader可以设置不存在的头,多次设置只会保留最新修改的,不会重叠
- 真正的开发当中,一般只用setHeader
重定向
- 浏览器访问Servlet1没有找到相应的资源,Servlet1告诉浏览器需要到Servlet2中找,然后浏览器拿到消息后再去连接Servlet2
- 你找我借钱,我没有,不过我可以告诉你谁有,你找他借
- 重定向特点:访问服务器2次或多次,浏览器的地址栏会发生改变
- 重定向:
- 状态码:302
- 响应头:location代表重定向地址
httpServletResponse.setStatus(302);
httpServletResponse.setHeader("Location","/webProjectName/ServletName");
- 上面代码中很多都是重复的,j2ee封装了一个更方便的方法: sendRedirect(url)
httpServletResponse.sendRedirect("/url");
定时刷新
//设置定时刷新头
httpServletResponse.setHeader("refresh","5;url=http://www.xxx.com");//时间是秒
使用js完成页面定时跳转
设置响应体
- 响应体设置文本,获取字符流,通过write(String str)方法可以将字符流设置到response缓冲区中
- 随后tomcat会将response缓冲区中的内容封装成http响应返回给浏览器
PrintWriter writer = response.getWriter();
writer.write("hello world");
- 关于编码问题:如果我们写的是中文,则在浏览器端会显示乱码.
- 因为我们写的时候默认是卸载response的缓冲区,在封装成http响应的时候,中文会经过编码转为对应的二进制,编码过程,tomcat用的码表是:ISO8859-1(西欧码表)
- 解决:修改编码用的码表(utf-8),通知response要用哪张码表(在获取writer之前设置码表)
- 客户端大部分默认的编码是本地的编码格式,如window系统默认是gbk
- 为了让客户端默认用我们编码时用的码表解码,我们可以把编码格式加到http响应头中:Content-Type
response.setCharacterEncoding("utf-8");
responst.setHeader("Content-Type","text/html;charset=UTF-8");//character也可以
PrintWriter writer = response.getWriter();
writer.write("你好,世界");
- 在开发中,一般只要写responst.setHeader("Content-Type","text/html;character=UTF-8")就可以,response自动把缓冲区的编码也改为utf-8(但是要了解,底层设置两部分,一是设置编码时的码表,二是告知浏览器用什么码表解码)
responst.setHeader("Content-Type","text/html;charset=UTF-8");//character也可以,但是服务端还是要定义编码,用charset就不用
PrintWriter writer = response.getWriter();
writer.write("你好,世界");
responst.setContentType("text/html;charset=UTF-8");//character也可以,但是服务端还是要定义编码,用charset就不用
PrintWriter writer = response.getWriter();
writer.write("你好,世界");
response的outputStream
- response.getWriter()只适合于文本类型的传输,如果需要传输图片,电影等类型,则不适合,需要用到IO操作
- 服务器向客户端写字节:
ServletOutputStrean getOutputStream()
//InputStream is = this.getClass().getClassLoader().getResourceAsStream(path);//类加载器只能加载src下的资源,我们的资源放在WEB-INF中,只能用FileInputStream手动创建输入流
- 通过该方法获得字节流,通过该字节流write(byte[] bytes)可以向response缓冲区写入字节
- 再由tomcat服务器将字节内容组成Http响应返回给浏览器
- 文件上传和文件下载用的路径都是绝对路径
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = getServletContext().getRealPath("WEB-INF/img/timg.jpg");
//InputStream is = this.getClass().getClassLoader().getResourceAsStream(path);
FileInputStream fis = new FileInputStream(path);
ServletOutputStream os = response.getOutputStream();
byte[] arr = new byte[1024];
int length = 0;
while((length=fis.read(arr))>0) {
os.write(arr,0,length);
}
fis.close();
}
文件下载基本代码
- 文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端
- 什么情况下会文件下载
- 通过a标签直接指向静态资源,如果浏览器可以解析,则直接浏览.如果浏览器不可以解析,则下载(解析能力跟浏览器的类型有关)
- 浏览器不能解析的文件,就提供下载功能
- 什么情况下需要在服务器端编写文件下载代码
- 理论上,浏览器可以解析的代码需要编写文件下载代码
- 开发中,不确定哪些可以解析哪些不可以解析,都编写下载代码
- 但是为了防止浏览器帮你解析,需要告诉浏览器不要解析该文件
- 我们需要设置两个响应头,告知浏览器文件的类型和文件的打开方式
- 告知浏览器文件的类型:response.setContentType(文件的MIME类型)
- 客户端通过文件的MIME类型去区别文件类型(人看后缀,客户端看MIME)
- 2)告示浏览器文件的打开方式是下载
- response.setHeader("Content-Disposition","attachment;filename=文件名称");
- 下载的文件名有中文名,浏览器解析不了,页面在下载时会出现中文乱码或不能显示文件名的情况
- 原因是不同的浏览器默认对下载文件的编码方式不同,ie是UTF-8编码方式,而火狐 浏览器是Base64编码方式
- 所里这里需要解决浏览器兼容性问题,解决浏览器兼容性问题的首要任务是要辨别访问者是ie还是火狐(其他)
- 通过Http请求体中的一个属性可以辨别
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
repsonse细节点
- response获得的流对象不需要手动关闭,tomcat容器会帮我们关闭
- getWriter和getOutputStream不能同时调用
- 重定向后就不要往下写代码了
实现验证码功能