14_Response

回顾
  • tomcat服务器启动的时候会加载服务器中的项目,并为每个项目创建一个唯一的ServletContext对象
  • 在每个项目中有多个Servlet对象,每个Servlet对象都有一个ServletConfig对象,对应的是web.xml中的配置信息
大纲
  1. 完成文件下载
    • 实质是文件的拷贝
  2. 生成验证码(了解)
    • 了解验证码的原理
    • 到企业中,每个企业都有自己封装好的验证码代码,直接调用
    • 还有第三方机构提供的代码
HttpServletResponse
概述
  • 浏览器发送请求给服务器,服务器内核通过反射创建相应的Servlet对象
  • 同时将Http请求的参数封装到ServletRequest对象中,和创建一个默认的ServletResponse对象(有默认的返回地址,请求头等参数,可以自己修改,响应体默认是空的)
  • 学习通过HttpServletResponse修改响应行,响应头,响应体的信息
Response设置响应行的信息
  • 响应行包括(Http协议的版本,状态码,状态信息),我们只需要修改状态码
  • 设置响应行中的状态码
    • setStatus(int sc)
  • 开发中用的并不多,一般都由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("你好,世界");
  • 为了简化,j2ee工程师又设置了简化的方法
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标签直接指向静态资源,如果浏览器可以解析,则直接浏览.如果浏览器不可以解析,则下载(解析能力跟浏览器的类型有关)
    • 浏览器不能解析的文件,就提供下载功能
  • 什么情况下需要在服务器端编写文件下载代码
    • 理论上,浏览器可以解析的代码需要编写文件下载代码
    • 开发中,不确定哪些可以解析哪些不可以解析,都编写下载代码
  • 但是为了防止浏览器帮你解析,需要告诉浏览器不要解析该文件
  • 我们需要设置两个响应头,告知浏览器文件的类型和文件的打开方式
    1. 告知浏览器文件的类型:response.setContentType(文件的MIME类型)
      • 客户端通过文件的MIME类型去区别文件类型(人看后缀,客户端看MIME)
    2. 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细节点
  1. response获得的流对象不需要手动关闭,tomcat容器会帮我们关闭
  2. getWriter和getOutputStream不能同时调用
  3. 重定向后就不要往下写代码了
实现验证码功能
  • 验证码的图片是通过java代码动态生成的

你可能感兴趣的:(14_Response)