HTTP超文本传输协议基础学习

30 篇文章 0 订阅
22 篇文章 0 订阅

HTTP超文本传输协议

概念:Hyper Text Tranfer Protocol 超文本传输协议

  • 传输协议:定义了,客户端和服务器端通信是,发送数据的格式
  • 特点:
    1. 基于TCP/IP的高级协议
    2. 默认端口号:80
    3. 基于请求/响应模型的:一次请求对应一次响应
    4. 无状态:每次请求之间相互独立,不能交互数据
  • 历史版本:
    1. 每一次请求响应都会建立新的连接
    2. 复用连接

请求消息数据格式

  1. 请求行

    • 请求方式 请求url 请求协议/版本

    • GET/login.html HTTP/1.1

    • 请求方式:

      • HTTP协议中有7种请求方式,常用的有两种
        • GET:
          1. 请求参数在请求行中,在url后
          2. 请求的url长度有限制的
          3. 不是很安全
        • POST:
          1. 请求参数在请求体中
          2. 请求的url长度没有限制
          3. 相对安全
  2. 请求头:客户端浏览器告诉服务器一些信息

    1. 请求头名称:请求头值
    2. 常见的请求头:
      1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
        • 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
      2. Referer: http://localhost:8080/MyApps/login.html
        • 告诉服务器,我(当前请求)从哪里来
          • 作用:
            1. 防盗链
            2. 统计
  3. 请求空行

    1. 空行:用于分割POST请求的请求头,和请求体的。
  4. 请求体(正文)

    • 封装POST请求消息的请求参数的
  5. 字符串格式:

    POST /MyApps/ser03 HTTP/1.1
    Host: localhost:8080
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Accept-Encoding: gzip, deflate
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 12
    Origin: http://localhost:8080
    Connection: keep-alive
    Referer: http://localhost:8080/MyApps/login.html
    Cookie: Idea-4311a65=5ac6d3b1-7c53-43e0-b438-60c6c2dbe879
    Upgrade-Insecure-Requests: 1
    Sec-Fetch-Dest: document
    Sec-Fetch-Mode: navigate
    Sec-Fetch-Site: same-origin
    Sec-Fetch-User: ?1
    
    USERNAME=ads
    

响应消息数据格式

Request

  1. request对象和response对象的原理

    1. request和response对象是由服务器创建的,我们来使用它们
    2. request对象来获取请求消息,response对象用来设置响应消息
  2. request对象继承体系结构

    • ServletRequest —接口
    • ​ | 继承
    • HttpServletRequest —接口
    • ​ | 实现
    • org.apache.catalina.connector.CoyoteInputStream 类(Tomcat)
  3. request:

    1. 获取请求消息数据

      1. 获取请求行数据

        • GET /MyApps/demo01?name=qin HTTP/1.1
        • 方法:
          1. 获取请求方式:GET
            • String getMethod()
          2. 获取虚拟目录:/MyApps
            • String getContextPath()
          3. 获取Servlet路径:/demo1
            • String getServletPath()
          4. 获取get方式的请求参数:name=qin
            • String getQueryString()
          5. 获取请求的uri:/MyApps/demo1
            • String getRequestURI():/MyApps/demo1
            • StringBuffer getRequestURL():http://localhost/MyApps/demo1
            • URL:统一资源定位符:http://localhost/MyApps/demo1
            • URI:统一资源标识符(范围更大):/MyApps/demo1
          6. 获取协议以及版本 HTTP/1.1
            • String getProtocol()
          7. 获取客户机的IP地址
            • String getRemoteAddr()
      2. 获取请求头数据

        • 方法:
          • String getHeader(String name):通过请求头的名称获取请求头的值
          • Enumeration<String> getHeaderNames():获取所有的请求头名称
      3. 获取请求体数据

        • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

        • 步骤:

          1. 获取流对象

            • BufferedReader getReader():获取字符输入流,只能操作字符数据

            • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型的数据

            • regist.html

              <!DOCTYPE html>
              <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <title>注册</title>
              </head>
              <body>
                  <form action="rd5" method="post">
                      <input type="text" placeholder="请输入用户名" name="username">
                      <input type="text" placeholder="请输入密码" name="password"><br>
                      <input type="submit" value="submit">
                  </form>
              </body>
              </html>
              
            • RequestDemo5

              package com.web.request;
              
              import javax.servlet.ServletException;
              import javax.servlet.annotation.WebServlet;
              import javax.servlet.http.HttpServlet;
              import javax.servlet.http.HttpServletRequest;
              import javax.servlet.http.HttpServletResponse;
              import java.io.BufferedReader;
              import java.io.IOException;
              
              @WebServlet("/rd5")
              public class RequestDemo05 extends HttpServlet {
                  @Override
                  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              
                  }
              
                  @Override
                  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                      //获取请求消息体--请求参数
              
                      //1.获取字符流
                      BufferedReader br = request.getReader();
                      //2.读取数据
                      String line = null;
                      while ((line = br.readLine())!=null){
                          System.out.println(line);
                      }
                  }
              }  
              
              
          2. 再从流对象中拿数据

    2. 其他功能

      1. 获取请求参数通用方式(无论GET或者POST):

        1. String getParameter(String name):根据参数名称获取参数值 username=qin&password=123

        2. String getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game

        3. Enumeration<String> getParameterNames():获取所有请求的参数名称

        4. Map<String,String[]> getParameterMap():获取所有参数的map集合

        5. 中文乱码问题

          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  //post 获取请求参数
                  // 根据参数名称获取参数值
          	    //1. 设置请求request的编码
                  request.setCharacterEncoding("UTF-8");
                  String username = request.getParameter("username");
                  System.out.println(username);
                  try {
                      response.setCharacterEncoding("GBK");
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  response.getWriter().write(username);
              }
          }
          
          • get方式:Tomcat 8 已经将get方式乱码问题解决了

          • post方式:会乱码

            • 解决:在获取参数之前,设置request的编码

              //1. 设置请求request的编码
              request.setCharacterEncoding("UTF-8");
              
      2. 请求转发:一种在服务器内部的资源跳转方式

        1. 步骤:
          1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
          2. 使用RequestDispatcher对象来进行转发:RequestDispatcher.forward(ServletRequest request,ServletResponse response)
        2. 特点:
          1. 浏览器地址栏路径没有发生变化
          2. 只能访问转发到当前服务器内部资源中
          3. 有转发也是一次请求
      3. 共享数据:

        • 域对象:一个有作用范围的对象,可以在范围内共享数据
        • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
        • 方法:
          1. setAttribute(String name,Object obj):存储数据
          2. getAttitude(String name):通过键获取值
          3. void removeAttribute(String name):通过键移除键值对
      4. 获取ServletContext:

        • ServletContext getServletContext()

小案例:用户登录

  • 用户登录案例需求:

    1. 编写login.html登录页面
      1. username&password 两个输入框
    2. 使用Druid数据库连接池技术,操作mysql,day14数据库中user表
    3. 使用jdbcTemplate技术封装JDBC
    4. 登录成功跳转到SuccessServlet展示:登录成功!
    5. 登录失败跳转到FailServlet展示:登录失败,用户名或密码错误
  • 分析

  • 开发步骤:

    1. 创建项目,导入html页面,配置文件,jar包

    2. 创建数据库环境

      create database	day14;
      use day14;
      create table User(
      	id int primary key auto_increment not null,
      	username varchar(32),
      	pwd varchar(32)
      )
      
    3. 创建包cn.domain,创建类User

      package cn.domain;
      
      
      /**
       * 用户的实体类
       */
      public class User {
          private String id;
          private String username;
          private String password;
      
      
          public String getId() {
              return id;
          }
      
          public void setId(String id) {
              this.id = id;
          }
      
          public String getUsername() {
              return username;
          }
      
          public void setUsername(String username) {
              this.username = username;
          }
      
          public String getPassword() {
              return password;
          }
      
          public void setPassword(String password) {
              this.password = password;
          }
      
          @Override
          public String toString() {
              return "User{" +
                      "id='" + id + '\'' +
                      ", username='" + username + '\'' +
                      ", password='" + password + '\'' +
                      '}';
          }
      }
      
      
    4. 创建包cn.op,创建UserOp,

      package cn.util;
      
      import com.alibaba.druid.pool.DruidDataSourceFactory;
      
      import javax.sql.DataSource;
      import java.io.IOException;
      import java.io.InputStream;
      import java.sql.Connection;
      import java.sql.SQLException;
      import java.util.Properties;
      
      /**
       * JDBC工具类 使用Durid连接池
       */
      public class JDBCUtils {
          private static DataSource ds;
      
          static {
              try {
              //1.加载配置文件
              Properties pro = new Properties();
              //使用ClassLoader加载配置文件,获取字节码输入流
              InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druif.properties");
              pro.load(is);//字节码输入
      
              //2.初始化连接池对象
                  ds = DruidDataSourceFactory.createDataSource(pro);
              } catch (IOException e) {
                  e.printStackTrace();
              } catch (Exception e) {
                  e.printStackTrace();
              }
      
      
          }
      
          /**
           * 获取连接池对象
           */
          public   static DataSource getDataSource(){
              return ds;
          }
      
          /**
           * 获取连接Connection对象
           */
          public static Connection getConnectyion() throws SQLException {
              return ds.getConnection();
      
          }
      
      }
      
      
    5. 创建包cn.op,创建类UserOp,提供login方法

      package cn.op;
      
      
      import cn.domain.User;
      import cn.util.JDBCUtils;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.dao.DataAccessException;
      import org.springframework.jdbc.core.BeanPropertyRowMapper;
      import org.springframework.jdbc.core.JdbcTemplate;
      
      /**
       * 操作数据库中User表的类
       */
      
      public class UserOp {
      
          //声明JDBCTemplate对象用来共用
          private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
          /**
           * 登录方法
           * @param loginUser 只有用户名和密码
           * @return  包含用户全部数据
           */
          public User login(User loginUser){
              try {
                  //1.编写sql
                  String sql = "select * from user where username = ? and pwd = ?;";
                  //2.调用query方法
                  User user = template.queryForObject(sql,
                          new BeanPropertyRowMapper<User>(User.class),
                          loginUser.getUsername(), loginUser.getPwd());
      
                  return user;
              } catch (DataAccessException e) {
                  e.printStackTrace();//记录日志
              }
              return null;
          }
          
      
      
      }
      
    6. 编写cn.web.servlet.LoginServlet类

      package cn.myweb.servlet;
      
      import cn.domain.User;
      import cn.op.UserOp;
      
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      
      @WebServlet("/loginServlet")
      public class LoginServlet extends HttpServlet {
      
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              try {
                  //1.设置编码
                  req.setCharacterEncoding("utf-8");
                  //2.获取请求参数
                  String u = req.getParameter("username");
                  String p = req.getParameter("password");
                  //3.封装User对象
                  User logier = new User();
                  logier.setUsername(u);
                  logier.setPwd(p);
                  //调用UserOp的login方法
                  System.out.println(logier);
                  System.out.println("要进入");
                  UserOp op = new UserOp();
                  System.out.println("进入后");
                  User user = op.login(logier);
      
                  //5.判断user
                  if(user==null){
                      //登录失败
                      req.getRequestDispatcher("/failServlet").forward(req,resp);
                  }else{
                      //登录成功
                      //存储数据
                      req.setAttribute("user",user);
                      //转发/重定向
                      req.getRequestDispatcher("/successServlet").forward(req,resp);
                  }
              } catch (ServletException | IOException e) {
                  e.printStackTrace();
              }
      
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              this.doGet(req,resp);
          }
      }
      
      
    7. login.html中form表单的action路径的写法

      • 虚拟目录+Servlet的资源路径

      • <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>登录</title>
        </head>
        <body>
            <form action="/day14_2/loginServlet" method="post">
                <input type="text" name="username">
                <input type="password" name="pwd">
                <input type="submit" value="submit">
            </form>
        <!--    <a href="rd4">lianjie</a>-->
        </body>
        </html>
        
    8. BeanUtils工具类,完成数据封装

      • 用于封装JavaBean的

        1. JavaBean:标准的java类

          1. 要求:
            1. 类必须被public修饰
            2. 必须提供空参的构造器
            3. 成员变量必须使用private修饰
            4. 提供公用setter和getter方法
          2. 功能:封装数据
        2. 概念:

          • 成员变量:
          • 属性:setter和getter方法截取后的产物
            • 例如:getUsername() --> Username --> username
        3. 方法:

          1. setProperty()

          2. getProperty()

          3. populate(Object obj,Map map):将map集合的键值对信息,封装到对应的JavaBean对象中

            package cn.myweb.servlet;
            
            import cn.domain.User;
            import cn.op.UserOp;
            import com.mchange.v2.beans.BeansUtils;
            import com.mchange.v2.codegen.bean.BeangenUtils;
            import org.apache.commons.beanutils.BeanUtils;
            
            
            import javax.servlet.ServletException;
            import javax.servlet.annotation.WebServlet;
            import javax.servlet.http.HttpServlet;
            import javax.servlet.http.HttpServletRequest;
            import javax.servlet.http.HttpServletResponse;
            import java.io.IOException;
            import java.lang.reflect.InvocationTargetException;
            import java.util.Map;
            
            @WebServlet("/loginServlet")
            public class LoginServlet extends HttpServlet {
            
                @Override
                protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                    try {
                        //1.设置编码
                        req.setCharacterEncoding("utf-8");
            //            //2.获取请求参数
            //            String u = req.getParameter("username");
            //            String p = req.getParameter("password");
            //            //3.封装User对象
            //            User logier = new User();
            //            logier.setUsername(u);
            //            logier.setPwd(p);
            
                        //2.获取所有请求参数
                        Map<String, String[]> map = req.getParameterMap();
                        //3.创建User对象
                        System.out.println("mima---"+map.get("password")[0]);;
                        User loginer = new User();
                        //3.2 使用BeanUtils封装
                        try {
                            BeanUtils.populate(loginer,map);//记住要用阿帕奇的不然会报错,把map里面的数据封装到User里面了
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                        //调用UserOp的login方法
                        System.out.println(loginer);
                        System.out.println("要进入");
                        UserOp op = new UserOp();
                        System.out.println("进入后");
                        User user = op.login(loginer);
            
                        //5.判断user
                        if(user==null){
                            //登录失败
                            req.getRequestDispatcher("/failServlet").forward(req,resp);
                        }else{
                            //登录成功
                            //存储数据
                            req.setAttribute("user",user);
                            //转发/重定向
                            req.getRequestDispatcher("/successServlet").forward(req,resp);
                        }
                    } catch (ServletException | IOException e) {
                        e.printStackTrace();
                    }
            
                }
            
                @Override
                protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                    this.doGet(req,resp);
                }
            }
            
            

(“user”,user);
//转发/重定向
req.getRequestDispatcher("/successServlet").forward(req,resp);
}
} catch (ServletException | IOException e) {
e.printStackTrace();
}

             }
         
             @Override
             protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                 this.doGet(req,resp);
             }
         }
         
         ```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立乱来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值