1. HTTP协议:响应消息
  2. Response对象
  3. ServletContext对象

1.HTTP协议:

  1. 请求消息:客户端发送给服务端的数据

    • 数据格式:

      1. 请求行
      2. 请求头
      3. 请求空行
      4. 请求体
  2. 响应消息:服务器发送给客户端的数据

    • 数据格式:

      1. 响应行

        1. 组成:协议/版本 响应的状态码 状态码描述
        2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。

          1. 状态码都是三位数字
          2. 分类:

            1. 1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后发送1xx多状态码
            2. 2xx:成功。代表:200
            3. 3xx:重定向。代表:302(重定向),304(访问缓存)
            4. 4xx:客户端错误。

              • 代表:

                • 404(请求路径没有对应的资源)
                • 405:请求方式没有对应的doXxx方法
            5. 5xx:服务器端错误。代表:500(服务器内部出现异常)
      2. 响应头

        1. 格式:头名称: 值
        2. 常见的响应头:

          1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
          2. Content-disposition:服务器告诉客户端以什么格式打开响应体数据

            • 值:

              • in-line:默认值,在当前页面内打开
              • attachment;filename=xxx:以附件形式打开响应体。文件下载
      3. 响应空行
      4. 响应体:传输的数据
  • 响应字符串格式

2.Response对象

  • 功能:设置响应消息

    1. 设置响应行

      1. 格式:HTTP/1.1 200 ok
      2. 设置状态码:setStatus(int sc)
    2. 设置响应头:setHeader(String name, String value)

    3. 设置响应体:

      • 使用步骤:
  1. 获取输出流
  • 字符输出流:PrintWriter getWriter()
  • 字节输出流:ServletOutputStream getOutputStream()
  1. 使用输出流,将数据输出到客户端浏览器

案例:

1.完成重定向

  • 重定向:资源跳转方式

  • 代码实现

    1. package com.jie.servlet;
    2. import javax.servlet.ServletException;
    3. import javax.servlet.annotation.WebServlet;
    4. import javax.servlet.http.HttpServlet;
    5. import javax.servlet.http.HttpServletRequest;
    6. import javax.servlet.http.HttpServletResponse;
    7. import java.io.IOException;
    8. /**
    9. * 重定向
    10. */
    11. @WebServlet( "/responseDemo1")
    12. public class ResponseDemo1 extends HttpServlet {
    13. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    14. System.out.println("demo1........");
    15. //访问/responseDemo1会自动跳转到demo2资源
    16. //1.设置状态码为302
    17. response.setStatus(302);
    18. //2.设置响应头
    19. /* response.setHeader("location","/day15/responseDemo2");
    20. //简单重定向方法
    21. response.sendRedirect("/day15/responseDemo2");*/
    22. }
    23. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    24. this.doPost(request,response);
    25. }
    26. }
  • 重定向的特点:redirect

    1. 地址栏发生变化
    2. 重定向可以访问其他站点(服务器)的资源
    3. 重定向是两次请求。不能使用request对象来共享数据
  • 转发的特点:forward

    1. . 转发地址栏路径不变
    2. 转发只能访问当前服务器下的资源
    3. 转发是一次请求,可以使用request对象来共享数据
  • 路径的写法:

    1. 路径的分类:

      1. 相对路径:通过相对路径不可以确定唯一的资源

        • 如:./index.html

        • 不以/开头,以·开头

        • 规则:找到访问当前的资源和目标资源之间的相对位置关系

          • ./:当前目录

            • ../:后退一级目录
      2. 绝对路径:通过绝对路径可以确定唯一的资源

        • 如:http://localhost:8080/day15/responseDemo2 /day15/responseDemo2

        • /开头的路径

        • 规则:判断定义的路径是给谁用的?判断请求将来从哪发出

          • 给客户端浏览器使用:需要加虚拟目录(项目访问路径)

            • 建议虚拟目录动态获取:request.getContextPath()
            • <a> <form> 重定向
            • 给服务端使用:不需要加虚拟目录

              • 转发路径

2.服务器输出字符数据到浏览器

  • 步骤:

    1. 获取字符输出流
    2. 输出数据
  • 乱码问题:

    1. PrintWriter writer = response.getWriter();获取流的默认编码是ISO-8859-1

    2. 设置该流的默认编码

    3. 告诉浏览器响应体使用的编码
      //简单的形式设置编码,在获取流之前设置 response.setContentType("text/html;charset=utf-8");

    • 乱码原理:
  • 代码实现:

  1. package com.jie.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.annotation.WebServlet;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. @WebServlet( "/responseDemo3")
  10. public class ResponseDemo3 extends HttpServlet {
  11. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. //获取流对象之前设置流的默认编码,ISO-8859-1 设置为 : GBK
  13. // response.setCharacterEncoding("utf-8");
  14. //告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
  15. // response.setHeader("content-type","text/html;charset=utf-8");
  16. //简单的形式设置编码
  17. response.setContentType("text/html;charset=utf-8");
  18. //1.获取字符输出流
  19. PrintWriter writer = response.getWriter();
  20. //2.输出数据
  21. // writer.write("<h1>Hello Response</h1>");
  22. writer.write("<h1>你好</h1>");
  23. }
  24. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  25. this.doPost(request,response);
  26. }
  27. }

3.服务器输出字节数据到浏览器

  • 步骤:

    1. 获取字节输出流
    2. 输出数据
  1. package com.jie.servlet;
  2. import javax.servlet.ServletException;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. import java.io.PrintWriter;
  10. @WebServlet( "/responseDemo4")
  11. public class ResponseDemo4 extends HttpServlet {
  12. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  13. //1.获取字节输出流
  14. ServletOutputStream sos = response.getOutputStream();
  15. //2.输出数据
  16. sos.write("hello".getBytes());
  17. }
  18. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  19. this.doPost(request,response);
  20. }
  21. }

4.验证码

  1. 本质:图片
  2. 目的:防止恶意表单注册
  1. package com.jie.servlet;
  2. import javax.imageio.ImageIO;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.awt.*;
  9. import java.awt.image.BufferedImage;
  10. import java.io.IOException;
  11. import java.util.Random;
  12. @WebServlet("/checkCodeServlet")
  13. public class CheckCodeServlet extends HttpServlet {
  14. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  15. int widih = 100;
  16. int height = 50;
  17. //1.创建一个对象,在内存中图片(验证码图片对象)
  18. BufferedImage image = new BufferedImage(widih,height,BufferedImage.TYPE_3BYTE_BGR);
  19. //2.美化图片
  20. //2.1填充背景色
  21. Graphics g = image.getGraphics();//画笔对象
  22. g.setColor(Color.pink);//设置画笔颜色
  23. g.fillRect(0,0,widih,height);
  24. //2.2画边框
  25. g.setColor(Color.blue);
  26. g.drawRect(0,0,widih-1,height-1);
  27. String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
  28. //生成随机角标
  29. Random r = new Random();
  30. for (int i1 = 1; i1 <= 4; i1++) {
  31. int i = r.nextInt(str.length());
  32. //获取字符
  33. char c = str.charAt(i);//随机字符
  34. //2.3写验证码
  35. g.drawString(c+"",widih/5*i1,height/2 );
  36. }
  37. //2.4画干扰线
  38. g.setColor(Color.green);
  39. //2.5生成随机坐标点
  40. for (int i = 0; i < 7; i++) {
  41. int x1 = r.nextInt(widih);
  42. int x2 = r.nextInt(widih);
  43. int y1 = r.nextInt(height);
  44. int y2 = r.nextInt(height);
  45. g.drawLine(x1,y1,x2,y2);
  46. }
  47. //3.将图片输出到页面展示
  48. ImageIO.write(image, "jpg", response.getOutputStream());
  49. }
  50. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  51. this.doPost(request,response);
  52. }
  53. }

html中添加验证码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script>
  7. /*
  8. 分析:
  9. 点击超链接或图片,需要换一张
  10. 1.给超链接和图片绑定单机事件
  11. 2.重新设置图片src属性值
  12. */
  13. window.onload = function () {
  14. //1.给超链接和图片绑定单机事件
  15. var img = document.getElementById("checkCode");
  16. img.onclick = function () {
  17. //加时间戳,防止缓存只重复一张
  18. var date = new Date().getTime();
  19. img.src = "/day15/checkCodeServlet?"+date;
  20. }
  21. var a = document.getElementById("change");
  22. a.onclick = function () {
  23. }
  24. }
  25. </script>
  26. </head>
  27. <body>
  28. <img id="checkCode" src="/day15/checkCodeServlet">
  29. <a id="change" href="">看不清,换一张</a>
  30. </body>
  31. </html>

3.ServletContext对象

  1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信

  2. 获取:

    1. 通过request对象获取

      • request.getServletContext();
    2. 通过HttpServlet获取

      • this.getServletCOntext();
  3. 功能:

    1. 获取MIME类型:

      • MIME类型:在互联网通信过程中定义的一种文件数据类型

        • 格式:大类型/小类型 text/html image/jpeg
      • 获取:

        • String getMimeType(String file)
    2. 域对象:共享数据

      1. setAttribute(String name,Object obj)
      2. getAttribute(String name)
      3. removeAttritube(String nme)
      • ServletContext对象范围:所有用户所有请求的数据
    3. 获取文件的真实路径(服务器路径)

      1. 方法:String getRealPath(String path)

        1. String realPath = context.getRealPath("/b.txt");//web目录下资源访问
        2. String c = context.getRealPath("/WEB-INF/c.txt");//web-inf// 目录下资源访问
        3. String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下资源 访问

案例

  • 文件下载需求:

    1. 页面显示超链接
    2. 点击超链接后弹出下载提示框
    3. 完成图片文件下载
  • 分析:

    1. 超链接指向的资源如果能被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框,不满足需求
    2. 任何资源都必须弹出下载提示框
    3. 使用响应头设置资源的打开方式

      • content-disposition:attachment;filename=xxx
  • 步骤:

    1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
    2. 定义Servlet

      1. 获取文件的名称
      2. 使用字节输入流加载文件进内存content-disposition:attachment;filename=xxx
      3. 指定response响应头
      4. 将数据写出到response输出流即可 ```java package com.jie.downLoad;

import javax.servlet.ServletContext; 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.FileInputStream; import java.io.IOException;

@WebServlet(“/downLoadServlet”) public class DownLoadServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  1. //1.获取请求参数,文件名称
  2. String filename = request.getParameter("filename");
  3. //2.使用字节输入流加载进内存
  4. //2.1找到服务器路径
  5. ServletContext context = this.getServletContext();
  6. String realPath = context.getRealPath("/img/" + filename);
  7. //2.2用字节流关联
  8. FileInputStream fis = new FileInputStream(realPath);
  9. //3.设置response的响应头
  10. //3.1设置MIME类型content-type
  11. String mimeType = context.getMimeType(filename);
  12. response.setHeader("content-type",mimeType);
  13. //3.2设置打开方式content-disposition
  14. response.setHeader("content-disposition","attachment;filename="+filename);
  15. //4.将输入流的数据写出到输出流
  16. ServletOutputStream sos = response.getOutputStream();
  17. byte[] bytes = new byte[1024*8];
  18. int len = 0;
  19. while ((len=fis.read(bytes))!=-1){
  20. sos.write(bytes,0,len);
  21. }
  22. fis.close();
  23. }
  24. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  25. this.doPost(request,response);
  26. }

}

  1. 解决中文名显示错误问题
  2. ```java
  3. package cn.itcast.utils;
  4. import sun.misc.BASE64Encoder;
  5. import java.io.UnsupportedEncodingException;
  6. import java.net.URLEncoder;
  7. public class DownLoadUtils {
  8. public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
  9. if (agent.contains("MSIE")) {
  10. // IE浏览器
  11. filename = URLEncoder.encode(filename, "utf-8");
  12. filename = filename.replace("+", " ");
  13. } else if (agent.contains("Firefox")) {
  14. // 火狐浏览器
  15. BASE64Encoder base64Encoder = new BASE64Encoder();
  16. filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
  17. } else {
  18. // 其它浏览器
  19. filename = URLEncoder.encode(filename, "utf-8");
  20. }
  21. return filename;
  22. }
  23. }