(1)概念

  • Hyper Text Transfer Protocol 超文本传输协议
  • 基于TCP/IP高级协议
  • 默认端口号80

    这两种等效 http:www.baidu.com http:www.baidu.com:80

  • 一次请求对应一次响应

  • 无状态的:每次请求之间相互独立,不能交互数据
  • 请求一个页面,里面的图片、js/html有很多HTTP请求
  • HTTP历史版本
    • 1.0 每次请求建立一次链接
    • 1.1 复用链接/缓存支持

(2)请求消息

  • 请求的消息就是一个字符串,主要分为四部分

    请求行

    请求头

  • User-Agent:浏览器版本信息,服务器可以获取浏览器类型解决兼容问题

  • Accept:告诉服务器,浏览器可以解析什么类型的格式
  • Connection: keep-alive 链接可以复用
  • Referer:告诉服务器我从哪里来(防盗链)

    请求空行

    请求体(正文)

    ``` // 请求行:请求方式 url 请求协议/版本 GET /WebDemo_war_exploded/d1.action?a=1 HTTP/1.1

// 请求头 键值对,浏览器告诉服务器一些信息 Host: localhost:8080 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9

// 请求空行

// 请求体 // GET方式没有请求体,参数在url中,长度有限制 // POST方式才有请求体,格式如下 a=1

  1. - 请求方式7
  2. - GET
  3. - POST
  4. - PUT
  5. - DELETE
  6. <a name="qcird"></a>
  7. ### (3)HttpServletRequest
  8. <a name="CAMCe"></a>
  9. #### 获取请求行
  10. - request.getQueryString():获取url中的参数

@WebServlet(“/d1”) public class Servlet2 extends HttpServlet {

  1. @Override
  2. protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
  3. super.doGet(request, resp);
  4. /**
  5. * 请求行
  6. */
  7. // http://localhost:8080/WebDemo_war_exploded/d1?a=1&b=2
  8. // GET
  9. String method = request.getMethod();
  10. // /WebDemo_war_exploded 虚拟目录
  11. String contextPath = request.getContextPath();
  12. // /d1 Servlet路径
  13. String servletPath = request.getServletPath();
  14. // a=1&b=2 get方式
  15. String queryString = request.getQueryString();
  16. // /WebDemo_war_exploded/d1 统一资源标识符
  17. String requestURI = request.getRequestURI();
  18. // http://localhost:8080/WebDemo_war_exploded/d1 统一资源定位符
  19. StringBuffer requestURL = request.getRequestURL();
  20. // HTTP/1.1
  21. String protocol = request.getProtocol();
  22. // 0:0:0:0:0:0:0:1
  23. String remoteAddr = request.getRemoteAddr();
  24. System.out.println(method);
  25. System.out.println(contextPath);
  26. System.out.println(servletPath);
  27. System.out.println(queryString);
  28. System.out.println(requestURI);
  29. System.out.println(requestURL);
  30. System.out.println(protocol);
  31. System.out.println(remoteAddr);
  32. }

}

  1. <a name="wSiZz"></a>
  2. #### 获取请求头
  3. - request.getHeaderNames();
  4. - request.getHeader(name);
  1. String header = request.getHeader("User-Agent");
  2. Enumeration<String> headerNames = request.getHeaderNames();
  3. while (headerNames.hasMoreElements()){
  4. String name = headerNames.nextElement();
  5. String value = request.getHeader(name);
  6. System.out.println(name+": "+value);
  7. }
  1. <a name="aCdG1"></a>
  2. #### 获取请求体
  3. - 请求体中的数据封装在流里面,普通键值对参数,用字符流;图片文件使用字节流
  4. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600160073106-60ba05e9-9b26-4477-a1d8-28066b7eb62a.png#align=left&display=inline&height=280&margin=%5Bobject%20Object%5D&name=image.png&originHeight=560&originWidth=1448&size=62169&status=done&style=none&width=724)
  5. - 请求体中的参数封装在一行中
  1. @Override
  2. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3. super.doPost(req, resp);
  4. BufferedReader reader = req.getReader();
  5. String params = null;
  6. // a=1&b=2
  7. while ((params = reader.readLine()) != null) {
  8. System.out.println("----"+params);
  9. }
  10. }
  1. - 获取请求参数的通用方法,GETPOST中参数都能获取到
  2. > // ?hobby=football&hobby=soccer
  3. > String[] as = req.getParameterValues("hobby");
  4. >
  5. > Map<String, String[]> parameterMap = req.getParameterMap();
  6. > Set<String> strings = parameterMap.keySet();
  7. > for (String key : strings) {
  8. > System._out_.println(key + "---" + parameterMap.get(key));
  9. > }
  10. >
  11. > Enumeration<String> parameterNames = req.getParameterNames();
  12. > while (parameterNames.hasMoreElements()){
  13. > String name = parameterNames.nextElement();
  14. > String value = req.getParameter(name);
  15. > System.out.println(name+"---"+value);
  16. > }
  17. - 中文乱码的问题
  18. > req.setCharacterEncoding("utf-8");
  19. <a name="vSvLp"></a>
  20. #### 请求转发
  21. - 特点
  22. - 转发之后,浏览器的地址栏路径没有变化
  23. - 只能转发到当前服务器的内部资源中
  24. - 转发只给服务器发送一次请求

@WebServlet(“/d3”) public class Servlet3 extends HttpServlet {

  1. @Override
  2. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3. // 转发需要注释掉这个super

// super.doGet(req, resp); System.out.println(“d3访问”); req.setAttribute(“key”,”value”); RequestDispatcher requestDispatcher = req.getRequestDispatcher(“/Servlet4”); requestDispatcher.forward(req,resp); } }

@WebServlet(“/Servlet4”) public class Servlet4 extends HttpServlet {

  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. String key = (String) request.getAttribute("key");
  3. System.out.println(key);
  4. System.out.println("doGet Servlet4");
  5. }

}

  1. - 请求转发时的共享数据
  2. > req.setAttribute("key","value");
  3. > String key = (String) request.getAttribute("key");
  4. > void removeAttribute(String name);
  5. <a name="mHKkk"></a>
  6. #### ServletContext
  7. - 代表整个Web应用,可以和程序的容器来通信
  8. - 获取ServletContext,整个项目只有一个
  9. - req.getServletContext();
  10. - this.getServletContext();
  1. @Override
  2. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3. ServletContext servletContext = req.getServletContext();
  4. ServletContext servletContext1 = this.getServletContext();
  5. // true
  6. boolean one = servletContext == servletContext1;
  7. }
  1. - 获取MIME类型
  2. - 格式:大类型/小类型 text/html
  3. - tomcat软件根目录下conf/web.xml里面储存所有MIME类型
  4. > ServletContext servletContext = req.getServletContext();<br />// image/png
  5. > String mimeType = servletContext.getMimeType("a.png");
  6. - 域对象:共享数据
  7. - 共享所有用户的数据
  1. servletContext.setAttribute("name","ss");
  2. servletContext.getAttribute("name");
  3. servletContext.removeAttribute("name");
  1. - 获取文件的真实路径
  2. - out中就是最终服务器运行的文件目录
  3. - src中的文件全部变成 WEB-INF/classes中的文件
  4. - 工作目录web变成out
  5. ![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600242011476-654dcb93-af88-4b5e-99db-19b2964ff72c.png#align=left&display=inline&height=699&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1398&originWidth=566&size=125461&status=done&style=none&width=283)
  6. > ServletContext servletContext = req.getServletContext();<br />
  7. > <br />
  8. > // web目录下的文件
  9. > // /Users/wangchun/IdeaProjects/WebDemo/out/artifacts/WebDemo_war_exploded/b.txt
  10. > String realPath1 = servletContext.getRealPath("/b.txt");
  11. > <br />
  12. > // web/WEB-INF下面的文件
  13. > // /Users/wangchun/IdeaProjects/WebDemo/out/artifacts/WebDemo_war_exploded/WEB-INF/c.txt
  14. > String realPath2 = servletContext.getRealPath("/WEB-INF/c.txt");
  15. > <br />
  16. > // 获取src下面的文件
  17. > // /Users/wangchun/IdeaProjects/WebDemo/out/artifacts/WebDemo_war_exploded/WEB-INF/classes/c.txt
  18. > String realPath3 = servletContext.getRealPath("/WEB-INF/classes/c.txt");
  19. <a name="BCviu"></a>
  20. ### (4)响应消息
  21. <a name="7jgs7"></a>
  22. #### 响应行
  23. - 协议/版本 状态码
  24. - 状态码:服务器告诉客户端浏览器本次请求和响应的状态
  25. - 1xx:服务器接受客户端消息,但没有接受完成,等待一段时间后,发送1xx状态码
  26. - 2xx:成功。200
  27. - 3xx
  28. - 重定向(302
  29. - 访问缓存(304
  30. - 4xx:客户端错误
  31. - 路径没有对应的资源(404
  32. - 请求方式没有对应的doXXX方法(405
  33. - 5xx:服务端错误
  34. - 服务器内部异常500
  35. > HTTP/1.1 200
  36. <a name="E4q5A"></a>
  37. #### 响应头
  38. - Content-Type:响应体的数据格式和编码格式
  39. - Content-Disposition:服务器告诉客户端以什么格式打开响应体,
  40. - in-line:默认值,在当前页面内打开
  41. - attachment:以附件形式形式打开响应体,文件下载
  42. > Date: Wed, 16 Sep 2020 02:54:04 GMT
  43. > Accept-Ranges: bytes
  44. > ETag: W/"368-1600221847000"
  45. > Last-Modified: Wed, 16 Sep 2020 02:04:07 GMT
  46. > Content-Type: text/html;charset=UTF-8
  47. > Content-Length: 368
  48. <a name="Okbk0"></a>
  49. #### 响应空行
  50. <a name="Pfazr"></a>
  51. #### 响应体
  52. - 传输的数据
  53. > <!DOCTYPE html>
  54. > <html lang="en">
  55. > <head>
  56. > <meta charset="UTF-8">
  57. > <title>Title</title>
  58. > </head>
  59. > <body>
  60. > <form action="/WebDemo_war_exploded/loginServlet" method="post">
  61. > 用户名:<input type="text" name="username" /> <br>
  62. > 密码:<input type="text" name="password" /> <br>
  63. > <input type="submit" value="登录">
  64. >
  65. > </form>
  66. > </body>
  67. > </html>
  68. <a name="wLrqf"></a>
  69. ### (6)HttpServletResponse
  70. <a name="ONNSX"></a>
  71. #### 重定向
  72. - 相关方法
  73. > resp.setStatus(302);
  74. > resp.setHeader("location","/WebDemo_war_exploded/servlet2");
  75. > // 等效于
  76. > resp.sendRedirect("/WebDemo_war_exploded/servlet2");
  77. > // 虚拟目录动态获取
  78. > String contextPath = req.getContextPath();
  79. > resp.sendRedirect(contextPath+"/servlet2");
  80. <br />
  81. - 当访问servlet1时,会被重定向导servlet2
  82. - 重定向不支持setAttribute传值了

@WebServlet(“/servlet1”) public class Servlet1 extends HttpServlet {

  1. @Override
  2. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3. System.out.println("Servlet1");
  4. resp.setStatus(302);
  5. resp.setHeader("location","/WebDemo_war_exploded/servlet2");
  6. // 上述两行代码等效于
  7. resp.sendRedirect("/WebDemo_war_exploded/servlet2");
  8. }

}

  1. - 转发和重定向的区别
  2. > 地址栏:转发不变,重定向变
  3. > 其他服务器资源:转发只能访问当前服务器下的资源,重定向可以访问其他服务器的资源
  4. > HTTP次数:转发是1次,重定向是2
  5. > setAttribute:转发支持传值、重定向不支持
  6. > 路径:转发需要添加虚拟路径,重定向需要添加虚拟路径
  7. <a name="EXD4l"></a>
  8. #### 相对路径和绝对路径
  9. - 相对路径
  10. > ./index.html:当前目录下的index.html
  11. > ../index.html:上一个目录下的index.html
  12. - 绝对路径
  13. > 1、给客户端使用需要加虚拟路径,例如重定向
  14. > 2、给服务器使用不需要加,例如转发
  15. <a name="TJoVT"></a>
  16. #### 响应体字符数据
  17. - 响应体会显示对应数据
  18. - 注意中文乱码的问题
  19. > resp.setContentType("text/html;charset=utf-8;");
  20. >
  21. > PrintWriter writer = resp.getWriter();
  22. > writer.write("nihao");
  1. @Override
  2. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3. System.out.println("Servlet1");
  4. // 告诉客户端使用该编码
  5. resp.setHeader("Content-type","text/html;charset=utf-8;");
  6. // 同样的方法
  7. // resp.setContentType("text/html;charset=utf-8;");
  8. PrintWriter writer = resp.getWriter();
  9. writer.write("你好");
  10. }
  1. <a name="DJvv5"></a>
  2. #### 响应体字节数据
  3. - 返回一个验证码图片
  1. int width = 100;
  2. int height = 200;
  3. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  4. Graphics graphics = image.getGraphics();
  5. graphics.setColor(Color.PINK);
  6. graphics.fillRect(0,0,width,height);
  7. graphics.setColor(Color.BLACK);
  8. graphics.drawRect(0,0,width-1,height-1);
  9. graphics.drawString("A B C D",20,25);
  10. ImageIO.write(image,"jpg",resp.getOutputStream());

```