GET和POST请求的本质区别是什么?

GET和POST请求的本质区别是什么?

前言

最近在公司实习工作的同时了解研究了下TCP/IP协议,对之前面试时的问题:GET和POST有何区别?对之前我一个相对标准的答案产生了怀疑。

提示:以下是本篇文章正文内容,以后的文章我会尽量标准点

一、我的答案

GET和POST有何区别?

  • GET在浏览器回退时候无害,而POST会再次提交请求。
  • GET产生的URL地址可以被BookMark,而POST不可以
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置
  • GET请求只能进行url编码,而POST支持多种编码方式
  • GET请求参数会被完整保留在浏览器历史记录中,而POST中的参数不会被保留
  • GET请求在URL中传送的参数长度是有限的,而POST没有
  • 对参数的数据类型,GET只接受ASCLL字符,而POST没有限制
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
  • GET参数通过URL传递,POST放在Request body中
    当时回答的可能没这么多,但是有其中两三条,此答案应该算是“标准答案”----如果不深入的话

二、简单介绍下GET和POST

在介绍GET和POST之前我们首先来了解一下HTTP——超文本传输协议(HTTP)的设计目的是保证客户端与服务器之间的通信。
HTTP 的工作方式是客户端与服务器之间的请求-应答协议。
web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。
举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。

在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。
GET - 从指定的资源请求数据。
POST - 向指定的资源提交要被处理的数据。

然后我们分别来使用一下GET和POST

建立项目

我们使用的软件是IDEA
首先 File -> New -> Project
在这里插入图片描述
点击Maven
选中 Create from archetype
选中找到第二个尾部是webapp
用Maven管理
然后按照图中设置
文件目录设置
next
在这里插入图片描述
Finish

右键main 选择new -> Directory
在这里插入图片描述

新建Java和resources
在这里插入图片描述
在pom.xml中引入Spring模块

 <!--    spring-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>
    <!--    spring-web-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.7.RELEASE</version>
    </dependency>

在这里插入图片描述
新建视图解析器
在resources右键 New -> XML Configuration File ->Spring Config
名字命名为 springmvc.xml (个人习惯)
在这里插入图片描述
由于本次主要目的不是新建一个Spring项目,所以视图解析器中内容直接给出

<?xml version="1.0" encoding="UTF-8"?>
<!--视图解析器-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--设置自动扫描的包-->
    <context:component-scan base-package="com.test.getpost.handler"></context:component-scan>
    <!--    配置视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--        前缀-->
        <property name="prefix" value="/WEB-INF/views/"></property>
        <!--        后缀-->
        <property name="suffix" value=".jsp"></property>

    </bean>
    <!--配置处理静态资源-->
    <mvc:default-servlet-handler/>
    <!-- 配置了处理静态资源之后,Handler的方法上的@RequestMapping失效,   -->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

视图解析器截图
在webapp/WEB-INF目录中找到web.xml,没有的话就新建一个
在这里插入图片描述
同样的直接给出内容:

<?xml version="1.0" encoding="UTF-8"?>
<!--前端控制器-->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
  <!--    使用Spring的过滤器解决POST请求中文乱码问题-->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceRequestEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>forceResponseEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


  <!--  配置前端控制器 DispatcherServlet-->
  <servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>

      <param-name>contextConfigLocation</param-name>
      <!--        SpringMVC配置文件的路径-->
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <!--   配置映射的请求地址,设置为 / -->
    <!--        此处【/】 只处理除.jsp以外的文件-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>


</web-app>

我们测试一下,
如图在目录中新建一个控制器目录——handler,新建一个testHandler.java
在这里插入图片描述
写入代码

@Controller
public class testHandler {
    @RequestMapping("/hello")
    public String testHelloWorld(){
        System.out.println("Hello SpringMVC!");
        return "success";
    }
}

在index.jsp中新建一个超链接,同时在WEB-INF中新建一个文件views/success.jsp
在这里插入图片描述
在这里插入图片描述

配好tomcat服务器(过程略,有空写一个操作步骤,鸽~),运行

在这里插入图片描述

点击超链接
在这里插入图片描述
项目搞定了

下面我们就来看看GET和POST方式,为了方便我们都使用From
先随意新建两个实体类,代码
在这里插入图片描述

package com.test.getpost.beans;
//员工
public class Employee {
    private Integer Id; //id
    private String Last_Name; //姓名
    private String Email; //邮箱
    private Department Dept; //部门

//    无参构造器
    public Employee(){
        super();
    }
//有参数构造器
    public Employee(Integer id, String last_Name, String email, Department dept) {
        super();
        Id = id;
        Last_Name = last_Name;
        Email = email;
        Dept = dept;
    }

    public Integer getId() {
        return Id;
    }

    public void setId(Integer id) {
        Id = id;
    }

    public String getLast_Name() {
        return Last_Name;
    }

    public void setLast_Name(String last_Name) {
        Last_Name = last_Name;
    }

    public String getEmail() {
        return Email;
    }

    public void setEmail(String email) {
        Email = email;
    }

    public Department getDept() {
        return Dept;
    }

    public void setDept(Department dept) {
        Dept = dept;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "Id=" + Id +
                ", Last_Name='" + Last_Name + '\'' +
                ", Email='" + Email + '\'' +
                ", Dept=" + Dept +
                '}';
    }
}

package com.test.getpost.beans;
//部门
public class Department {
    private Integer Id;
    private String Dept_Name;

    public Integer getId() {
        return Id;
    }

    public void setId(Integer id) {
        Id = id;
    }

    public String getDept_Name() {
        return Dept_Name;
    }

    public void setDept_Name(String dept_Name) {
        Dept_Name = dept_Name;
    }

    @Override
    public String toString() {
        return "Department{" +
                "Id=" + Id +
                ", Dept_Name='" + Dept_Name + '\'' +
                '}';
    }
}

1.GET方式

在index.jsp上新建一个表单,
在这里插入图片描述

<form action="${pageContext.request.contextPath}/testPOJO" method="get">
    员工工号:<input type="text" name="Id"><br>
    员工姓名:<input type="text" name="Last_Name"><br>
    员工邮箱:<input type="text" name="Email"><br>
    部门编号:<input type="text" name="Dept.Id"><br>
    部门名称:<input type="text" name="Dept.Dept_Name"><br>
    <input type="submit" value="Test POJO">
</form>

在testHandler中添加代码
在这里插入图片描述

@RequestMapping("/testPOJO")
    public String testPOJO(Employee employee) {
        System.out.println("信息:" + employee);
        return "success";
    }

运行:
在这里插入图片描述
点击提交Test POJO
在这里插入图片描述

2.POST方式

将index.jsp中的from代码中的method="get"改为method=“post”
在这里插入图片描述
再次运行
在这里插入图片描述

单独的从导航栏上来看,我们之前的回答好像是没有毛病,但是我们如果更加深层次的扒一扒,我们把GET和POST本质拿出来看看。

本文重点

首先我们应该明确一点GET和POST本质没有区别,上面也说了,GET和POST是HTTP协议中的两种发送请求的方法。 HTTP是什么?
HTTP是基于TCP/IP的关于数据在万维网中如何通信的协议。HTTP的底层是TCP/IP,所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接,GET和POST能做的事情完全一样,你要给GET加上request
body,给POST带上url参数,技术上是完全可以的。 那么上述答案中的两者区别是怎么回事呢?
在万维网的世界中,HTTP协议像是一种规则,给TCP运输数据设置了好几个服务类别,有GET、POST、PUT、DELETE等等,HTTP规定,当执行GET时候,要给设置GET标签,就是上述例子中的method=“get”,而且要求把传送的数据放在URL中,方便记录。而POST请求,就需要设置method=“post”,并且不需要显示数据在url中。当然,如果你是好事者,你可以在用GET的时候,把数据不放到url中,也可以在使用POST时候,把数据显示到url中(具体操作:自行百度,我懒 ~ ~)
HTTP只是一个准则,TCP才是GET和POST怎么实现的基本,但是我们只看到HTTP对GET和POST参数的传送渠道(url还是request
body)提出了要求。 那么最开始我们说的关于参数有限又是怎么来的呢?
在万维网中,不同的浏览器:发起http请求和服务器:接受http请求,就是不同的运输公司,虽然原则上url可以无限的放资源数据。数据量太大对浏览器和服务器都是很大的负担和风险,所以需要限制单次数量节约资源和减低风险。业界不成文规定,(大多数)浏览器通常都会限制url长度在2K字节,(大多数)服务器最多处理64K的url,超过的部分,看着办吧。。。。
同时如果你用了GET在request body中偷偷藏了数据,不同的服务器的处理方式也是不同的,有些服务器会帮你读出数据,有的服务器会忽略,所以,上面的一种假想型操作我不想尝试。
好了,现在我们得出结论,GET和POST本质上就是TCP链接没区别,但是由于HTTP规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。还没完!!!

然后接下来才是我想说的也是看到wx中某个博主猿某某说的:

很多地方都不会说到
GET和POST有一个重大区别:

GET产生一个TCP数据包
POST产生两个TCP数据包

长一点的解释:

  • 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
  • 而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 返回数据。(有点像 3次握手 那个东西,没事可以看看,有些面试为了提升自己面试B格会问问这个问题,我暂时还没遇到过,嘿嘿)
    也就是说,GET只需要跑一趟就把货送到了,而POST需要跑两趟,首先先过去和服务器说一声,我要来送货,你准备一下,然后回头把货送回去。

因为POST需要两步,时间上消耗的多一些,看起来好像GET比POST更有效,因此Yahoo团队有推荐使用GET代替POST来优化网站,但是这是一个巨大的坑,why?

  1. GET和POST都有自己的语义,不能随便混用
  2. 据研究,在网络环境好的情况下,发一次包和发两次包基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
  3. 并不是所有的浏览器都会在POST中发送两次包,Fixfox就只发送一次。

总结

以上就是今天讲述的内容,最近也是了解了相关方面的知识做个分享,为以后面试或者项目设计带来思路。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Biver__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值