HTTP详解

1. web

1.1 web相关概念

软件架构
  1. C /S:客户端/服务器端

    1. 需要安装客户端应用
  2. B/S:浏览器/服务器端

    1. 不需要安装客户端应用,对于用户来说只需要记住域名访问就可以,高效,客户端零维护
资源分类
  1. 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析

    • 如: html、css,、JavaScript
  2. 动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器,(浏览器内部含有静态资源解析引擎)

    • 如:servlet/jsp、php、asp....

1.2 web服务器软件

相关概念
  1. 服务器:安装了服务器软件的计算机 ,比如之前电脑安装了mysql软件,那么你的电脑就是一台mysql服务器,

    根据ip地址就可以让其它主机访问到你的mysql服务器,并访问到相应的数据。

    • 服务器软件:接收用户的请求,处理请求,做出响应

    • web服务器软件:接收用户的请求,处理请求,做出响应。

    • 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目,也称之为web容器

  2. 常见的java相关的web服务器软件:

    webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。

    webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。

    JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。

    Tomcat:Apache基金组织,中小型JavaEE服务器,仅支持少量的JavaEE规范servlet/jsp。开源,免费。

    JavaEE:Java语言在企业级开发中使用的技术规范的总和,一共规定了13项大的规范

Tomcat:web服务器软件
  1. 下载:http://tomcat.apache.org/

  2. 安装:解压压缩包即可,注意:安装目录建议不要有中文和空格

  3. 启动:运行startup.bat/startup.sh

  4. 停止:运行shutdown.bat/shutdown.sh

1.3 Tomcat集成IDEA

概述:

将Tomcat集成到IDEA中,并且创建JavaEE的项目,部署项目。

1.4 Servlet

概念:
  • server applet ,运行在服务器端的小程序

  • Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。

  • 将来我们自定义一个类,实现Servlet接口,复写方法。

1.5 快速入门:

  1. 创建JavaEE项目

  2. 导入依赖

    XML 复制代码
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
        </dependency>
  3. 定义一个类,实现Servlet接口

    java 复制代码
    public class ServletDemo1 extends HttpServlet
  4. 实现抽象类中的抽象方法

    java 复制代码
    public class ServletDemo1 extends HttpServlet {
    ​
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("前端发送了一个get请求");
        }
        
    }
  5. 在web.xml中配置:

    XML 复制代码
    <web-app>
        <display-name>Archetype Created Web Application</display-name>
        <servlet>
            <servlet-name>servlet</servlet-name>
            <servlet-class>com.codingfuture.ServletDemo1</servlet-class>
        </servlet>
    ​
        <servlet-mapping>
            <servlet-name>servlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    ​
    </web-app>

6.访问方式

XML 复制代码
http://localhost:8080/Test_war_exploded/ServletDemo1

1.6 Servlet3.0

  • 好处:

支持注解配置。可以不需要配置web.xml了

  • 步骤:
  1. 创建JavaEE项目

  2. 定义一个类,实现Servlet接口

  3. 重写方法

  4. 在类上使用@WebServlet注解,进行配置

代码示例:
java 复制代码
@WebServlet(urlPatterns = "/demo1")
@WebServlet(value = "/demo2")
@WebServlet(name = "/demo3")
@WebServlet("/demo4")
java 复制代码
http://localhost:8080/Http_Demo_war_exploded/servletDemo1
http://localhost:8080
/Http_Demo_war_exploded -- 虚拟路径  实际开发中我们会将虚拟路径配置成/
/servletDemo1   -- 资源路径 -- 资源路径是工作类的首字母小写
修改之后的路径是:
http://localhost:8080/servletDemo1

1.7 前端发送请求

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
​
<form action="/servletDemo1" method="post">
    <p>账户:
        <input name="username" type="text">
    </p>
    <p>
        密码: <input name="password" type="password">
    </p>
    <input type="submit" value="提交">
</form>
​
</body>
</html>
java 复制代码
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
​
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("前端发送了一个get请求");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("前端发送了一个post请求");
    }
​
}

1.8 Servlet相关配置

  1. urlpartten:Servlet访问路径

    1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})

    2. 路径定义规则:

      1. /xxx:路径匹配

      2. /xxx/xxx:多层路径,目录结构

      3. *.do: 扩展名匹配

代码示例:
java 复制代码
@WebServlet({"/d2", "/dd2", "/ddd2"})//都可以访问到
@WebServlet("/demo2/user") //多层路径
@WebServlet("/demo2/*") //通配符,  *任意字符
@WebServlet("*.do") // 任意字符.do 访问

2.0 Http

2.1 TCP与UDP

  • 网络分层模型

  • IP IPv4 与IPv6

  • TCP (基于连接) 打电话 电话接通 互相通话 结束挂断

    • 如何实现连接: 三次握手 传输确认 四次挥手

    • 优点:传输稳定性强,适用于对网络通讯要求较高的场景 比如传输文件,发送邮件,浏览网页等等

  • UDP (基于非连接) 写信 对方是否收到,内容是否完整,顺序是否正确

    • 优点: 速度快,但是可能产生丢包,适用于对实时性要求比较高,对少量丢包没有太大要求,如语音通话,视频直播等
  • 无状态

    • 会话技术

      • Cookie

      • Session

2.2 Http超文本传输协议

Hyper Text Transfer Protocol (http)超文本传输协议 ,定义了,客户端和服务器端通信时,发送数据的格式

特点
  1. 基于TCP/IP的高级协议,安全

  2. 默认端口号:80

  3. 基于请求/响应模型的:一次请求对应一次响应

  4. 无状态的:每次请求之间相互独立,不能交互数据

2.3 HTTPS

  • HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了 SSL/TLS 非对称加密协议进行了加密处理。

  • HTTP和HTTPS使用连接方式不同,默认端口也不一样,HTTP是80,HTTPS是443。

  • 对称加密与非对称加密(CA)

2.4 请求

请求行

请求方式 请求url 请求协议/版本 GET /login.html HTTP/1.1

请求方式:

HTTP协议有多种请求方式,常用的有2种

  • GET:

    1. 请求参数在请求行中,在url后。

    2. 请求的url长度有限制的

    3. 不太安全

  • POST:

    1. 请求参数在请求体中

    2. 请求的url长度没有限制的

    3. 相对安全

请求头

请求头:客户端浏览器告诉服务器一些信息 请求头名称: 请求头值 一种键值对形式

  • 常见的请求头:

    1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息

      • 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
  1. Referer:http://localhost/login.html

    • 告诉服务器,我(当前请求)从哪里来
  2. 演示

java 复制代码
   @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          System.out.println("前端发送了一个post请求");
          String header = req.getHeader("User-Agent");
          if (header.contains("Chrome")) {
              System.out.println("用户当前使用的是谷歌浏览器");
          }
      }
请求空行

空行,就是用于分割POST请求的请求头,和请求体的。

请求体(正文):
  • 封装POST请求消息的请求参数的

java 复制代码
username: zs
password: 123

**注意:**username=123 请求体 ,只有post请求才可以查看到,get请求是没有的,get请求参数是在url中。

请求消息数据格式:
bash 复制代码
字符串格式:
POST /login.html    HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests:1
​
username: zs
password: 123

2.5 Request

体系结构

request对象继承体系结构:

java 复制代码
ServletRequest      --  父接口
            ⬆️  
HttpServletRequest  -- 子接口      
request功能
1.获取请求行数据

GET /day02/demo1?name=zhangsan HTTP/1.1

java 复制代码
1.获取请求方式 :GET
* String getMethod()
2.获取虚拟目录:/day02
* String getContextPath()
3.获取Servlet资源路径: /demo1
* String getServletPath()
4.获取get方式请求参数:name=zhangsan
* String getQueryString()
5.获取请求URI:/day02/demo1
* String getRequestURI():        /day02/demo1
* StringBuffer getRequestURL()  :http://localhost/day02/demo1
* URI:统一资源标识符 : demo01/loginServlet    范围大        共和国
* URL:  统一资源定位符 : http://localhost/demo01/loginServlet    中华人民共和国
6.获取协议及版本:HTTP/1.1
* String getProtocol()
代码示例:
java 复制代码
System.out.println(req.getMethod());//1.获取请求方式 :GET/POST
System.out.println(req.getContextPath());//2.获取虚拟目录:
System.out.println(req.getServletPath());//3.获取Servlet资源路径: /demo3
System.out.println(req.getQueryString());//4.获取get方式请求参数:username=zs
System.out.println(req.getRequestURI());//5.URI:统一资源标识符 :/虚拟目录/demo3
System.out.println(req.getRequestURL());//6.URL:统一资源定位符http://localhost:8080/demo3
System.out.println(req.getProtocol());//7.获取协议及版本:HTTP/1.1HTTP/1.1
2.获取请求头数据
  • 方法:

    • String getHeader(String name):通过请求头的名称获取请求头的值

    • Enumeration< String > getHeaderNames():获取所有的请求头名称

代码示例:
java 复制代码
 //1.获取所有请求头的值
  Enumeration<String> headernames = request.getHeaderNames();
  //2.遍历
  while (headernames.hasMoreElements()) {
  String name = headernames.nextElement();
  //3.根据名称获取头的值
  String value = request.getHeader(name);
  System.out.println(name + "-----" + value);
  }

getHeader 介绍,判断客户端是哪个浏览器

java 复制代码
//获取请求头数据  user - agent
String agent = req.getHeader("user-agent");//不区分大小写
//判断浏览器版本
if (agent.contains("Chrome")) {
      //处理兼容性问题
    System.out.println("谷歌浏览器");
} else if (agent.contains("Firefox")) {
    System.out.println("火狐浏览器");
}
3.获取请求参数:

演示:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
​
<form action="/servletDemo2" method="post">
    <p>账户:
        <input name="username" type="text">
    </p>
    <p>
        密码: <input name="password" type="password">
    </p>
    <p>
        <input type="checkbox" name="hobby" value="coding"> coding
        <input type="checkbox" name="hobby" value="football"> football
        <input type="checkbox" name="hobby" value="basketball"> basketball
    </p>
    <input type="submit" value="注册">
</form>
​
</body>
</html>
  1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数

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

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

    • 中文乱码问题:

      • get方式:tomcat8 已经将get方式乱码问题解决了

      • post方式:会乱码

        解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");​

java 复制代码
 /**
 * 获取请求参数通用方式
 */
​
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决post乱码问题 get请求中英文都可以
        //req.setCharacterEncoding("utf-8");
      
        System.out.println("前端发送了一个post请求");
        //1.根据参数名称获取参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
       //2.根据参数名称获取参数值的数组 //String[] getParameterValues(String name)
        String[] hobbys = req.getParameterValues("hobby");
        for (String hobby : hobbys) {
            System.out.println(hobby);
        }
    }
}
4.请求转发(考点)

请求转发:一种在服务器内部的资源跳转方式

  1. 步骤:

    1. 通过request对象获取请求转发器对象:

      RequestDispatcher getRequestDispatcher(String path)

    2. 使用RequestDispatcher对象来进行转发:

      forward(ServletRequest request, ServletResponse response)

  2. 特点:

    1. 浏览器地址栏路径不发生变化

    2. 只能转发到当前服务器内部资源中。

    3. 转发是一次请求

5. 共享数据
  • 域对象:一个有作用范围的对象,可以在范围内共享数据

  • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

  • 方法:

    1. void setAttribute(String name,Object obj):存储数据

    2. Object getAttitude(String name):通过键获取值

    3. void removeAttribute(String name):通过键移除键值对

代码示例:
java 复制代码
/**
 * 请求转发:一种在服务器内部的资源跳转方式
 * 服务器内部资源跳转
 * 从一个Servlet跳转到另一个Servlet中
 * 这里是servletDemo1 跳转到servletDemo2中
 */
​
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String usernameValue = req.getParameter("username");
        // request 域
        req.setAttribute("username", usernameValue);
        // 请求转发
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servletDemo2");
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("/http://www.baidu.com");
        requestDispatcher.forward(req, resp);
    }    
}
​
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object usernameValue = req.getAttribute("username");
        System.out.println(usernameValue);
​
    }
}
  • session域(多次请求,会话期间)

    java 复制代码
    @WebServlet("/servletDemo1")
    public class ServletDemo1 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String usernameValue = req.getParameter("username");
            // session 域
            HttpSession session = req.getSession();
            session.setAttribute("username", usernameValue);
          
           try {
                Thread.sleep(5000);
                // 除此此外,浏览器主动关闭,session域中的数据也会销毁
                session.removeAttribute("username");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    ​
    @WebServlet("/servletDemo2")
    public class ServletDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            HttpSession session = req.getSession();
            Object username = session.getAttribute("username");
            System.out.println(username);
    ​
        }
    }

获取ServletContext(Application域)

Servlet三大域对象: request、session、ServletContext。

ServletContext就是三大域对象之一。

  1. ServletContext是一个全局的储存信息的空间,在服务器启动时创建,在服务器关闭时销毁,

    • 一个JavaWeb应用只创建一个ServletContext对象,

    • 作用范围:所有的用户都可以取得此信息,此信息在整个服务器上被保留。

    • 属性范围值:只要设置一次,则所有的网页窗口都可以取得数据。

    • 方法:

      java 复制代码
      ServletContext servletContext = req.getServletContext(); 
      ServletContext servletContext = this.getServletContext();
      servletContext.setAttribute("username","zhangsan");
  2. request,一个用户可有多个。

    • reques:表示一个请求,只要发出一个请求就会创建一个request,它的作用域:仅在当前请求中有效。

    • 用处:常用于服务器间同一请求不同页面之间的参数传递

    • 方法:request.setAttribute();

  3. session,一个用户一个。

    • 会话:用户打开浏览器会话开始,直到关闭浏览器会话才会结束。一次会话期间只会创建一个session对象。

    • 用处:常用于web开发中的登陆验证界面(当用户登录成功后浏览器分配其一个session键值对)。

    • 方法:session.setAttribute();

三大域对象在使用上一样,只是三者作用域范围大小不一样。从小到到范围依次是:request < session < ServletContext

代码示例:
java 复制代码
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
​
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String usernameValue = req.getParameter("username");
        //ServletContext
        ServletContext servletContext = req.getServletContext();
        servletContext.setAttribute("username", usernameValue);
    }
}
​
java 复制代码
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        Object username = servletContext.getAttribute("username");
        System.out.println(username);
    }
}

2.6 Response

响应消息

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

    • 数据格式:

      • 请求行

      • 请求头

      • 请求空行

      • 请求体

  2. 响应消息:服务器端发送给客户端的数据

    • 数据格式:

      • 响应行

      • 响应头

      • 响应空行

      • 响应体

    1. 响应行

      1. 组成:协议/版本 响应状态码 状态码描述

        HTTP/1.1 200 OK

      2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。

        1. 状态码都是3位数字

        2. 分类:

          1xx:试探性请求,服务器接收客户端消息,没接受完成,等待一段时间后,发送1xx状态码

          100: 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分

          2xx:成功。代表:200 服务器已经成功处理了请求

          3xx:重定向。代表:302(重定向),304(访问缓存)

          4xx:客户端错误。

          代表:

          404(请求路径没有对应的资源)

          405:比如请求方式 没有对应的doXxx方法

          5xx:服务器端错误。代表:500(服务器内部出现异常) ,比如运算错误

    2. 响应头:

      1. 格式:

        java 复制代码
        头名称 : 值 
      2. 常见的响应头:

        java 复制代码
        /*  Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式 
        /*  text/html;charset=utf-8
    3. 响应空行

    4. 响应体

      传输给前端的数据

      响应字符串格式

java 复制代码
HTTP/1.1 200 OK             
Content-Type: text/html;charset=UTF-8 
Content-Length: 101 字节个数
Date: Thu, 17 Sep 2020 02:59:05 GMT
Location: /servletB
​
我是response
java 复制代码
@WebServlet("/servletDemo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            // resp.setCharacterEncoding("utf-8");
            // Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
            // text/html;charset=utf-8
            resp.setContentType("text/html;charset=utf-8");
            int i = 5 / 0;
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
            resp.getWriter().println("<h1>服务器正在维护。。。see you later</h1>");
        }
    }
}

2.7 重定向

  1. 重定向:资源跳转的方式

    代码实现:

    1. 设置状态码为302

      response.setStatus(302);

    2. 设置响应头location

      response.setHeader("location","/responseServlet02");

    3. 简单的重定向方法

      response.sendRedirect("/responseServlet02");

    代码示例:

java 复制代码
/**
 * @author Petrel
 */
@WebServlet("/responseServlet01")
public class ResponseServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问了responseServlet01");
        // 访问 /responseServlet01  会跳转到 /responseServlet02资源
        // 方法一
        // 1.设置状态码为302
        // resp.setStatus(302);
        // 2.置响应头location
        // resp.setHeader("location", "/responseServlet02");
        // 方法二
        // 3.简单的重定向方法
        // resp.sendRedirect("/responseServlet02");
        // resp.sendRedirect("http://www.baidu.com");
    }
}
​
@WebServlet("/responseServlet02")
public class ResponseServlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问了responseServlet02");
    }
}
forward 和 redirect 区别
  1. 重定向的特点:redirect

    1. 地址栏发生变化

    2. 重定向可以访问其它站点(服务器)的资源

    3. 重定向是两次请求。不能使用request对象来共享数据

  2. 转发的特点:forward

    1. 转发地址栏路径不变

    2. 转发只能访问当前服务器下的资源

    3. 转发是一次请求,可以使用request对象来共享数据

  3. 注意

    不能使用重定向来访问request域中的数据

相关推荐
‍。。。31 分钟前
使用Rust实现http/https正向代理
http·https·rust
龙哥说跨境33 分钟前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
懒大王就是我1 小时前
C语言网络编程 -- TCP/iP协议
c语言·网络·tcp/ip
Elaine2023911 小时前
06 网络编程基础
java·网络
海绵波波1072 小时前
Webserver(4.3)TCP通信实现
服务器·网络·tcp/ip
热爱跑步的恒川5 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
云飞云共享云桌面6 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
音徽编程8 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
幺零九零零9 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
23zhgjx-NanKon10 小时前
华为eNSP:QinQ
网络·安全·华为