从spring MVC角度理解HTTP协议及Request-Response模式

什么是HTTP协议?HTTP协议(HyperText Transfer Protocol,超文本传输协议)是一种通信规则,它定义了客户端(如浏览器、手机APP) 和服务器 之间如何交换信息,是用于在万维网(WWW)中传输数据的应用层协议,它定义了客户端与服务器之间如何通信、如何请求资源如网页、图片、视频,以及如何响应请求,是互联网信息交互的通用语言。

一、HTTP协议的核心定位:应用层的通信规则在TCP/IP协议栈(互联网的基础通信框架)中,HTTP属于应用层协议,其底层依赖传输层的TCP协议提供可靠的数据传输通道。TCP负责把数据安全送到对方,确保数据不丢失、不混乱,HTTP负责定义数据的格式和交互逻辑。

二、 HTTP的核心特点 :1. 无状态HTTP协议本身不记录"前后请求的关联"------服务器不会记住上一次给这个客户端发了什么,每次请求都是独立的、全新的。 例如:你第一次访问某购物网站,服务器不知道你是谁;第二次点击"加入购物车",若没有Cookie或Token(用于身份标识的技术),服务器依然不认识你。 2. 请求-响应模式(Request-Response)通信必须由客户端主动发起,服务器只能"被动响应",不会主动向客户端发送数据。流程固定为: 客户端发送请求 → 服务器处理请求 → 服务器返回响应3. 可扩展HTTP允许通过头部字段扩展功能,比如用Accept-Encoding: gzip告诉服务器我支持压缩数据。 4. 媒体无关HTTP可传输任意类型的数据(只要客户端和服务器约定好格式,包括网页、图片、视频、JSON数据等。

三、HTTP的核心交互流程:请求与响应 一次完整的HTTP通信,本质是客户端发请求、服务器回响应的过程,两者都有固定的格式。

  1. HTTP 请求(客户端→服务器)

请求由 3 部分组成:请求行、请求头部、请求体(可选)。

请求头部:辅助信息,如Host(指定服务器域名)、Cookie(携带客户端的身份信息,如登录状态)、Content-Type(POST 请求时,说明请求体的数据格式,如application/json)。

请求体:仅 POST/PUT 等请求有,用于传递数据(如登录时的 "用户名 + 密码"、上传的文件内容)。请求行:核心信息,决定 "要做什么"。请求方法:常用有GET(获取资源,如打开网页)、POST(提交数据,如登录、上传表单)、PUT(修改资源)、DELETE(删除资源)。

程序如何接收前端网页的数据?第一种方式:通过GET、POST等请求。

这种方式首先就要在方法上加上注解@RequestMapping并给定路径("v1/car/add")而要给客户端反馈还得加上@ResponseBody注解。同时用户在输入网址的时候要按照以下格式:localhost:+(本地的port)+路径+?+给定参数赋值

java 复制代码
@Controller
public class CarController {
    @RequestMapping("v1/car/add")
    @ResponseBody
    public String add(String brand,String color,int price)
    {
        System.out.println("品牌是:"+brand+"颜色是"+color+"价格是"+price);
        return "add";
    }
}

localhost:8080/v1/car/add?brand=tsl&color=black&price=100000

这种方式属于后端,需要注意一定要先启动程序,然后再输入网址,顺序不能反,如果有修改代码,也一定要重新运行程序。

第二种方式:通过.html文件获取。

所有的.html文件都属于静态资源,所以应该在resources中的static里面创建。完成创建后里面会有个<body>的标签,在<body>内即可编辑页面。比如想拿到车辆的brand、color、price等信息并添加,先设置好路径并告诉它方法是post(post就是添加的作用)然后用<input>标签就可以让用户输入,并给placeholder提示。在打开网页的时候一定要确保后端的代码仍然处于运行状态。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/v1/car/add" method="post">
    <input type="text" name="brand" placeholder="请输入品牌">
    <input type="text" name="color" placeholder="请输入颜色">
    <input type="text" name="price" placeholder="请输入价格">
    <input type="submit" value="添加车辆">
</form>
</body>
</html>

这就通过用.html完成了新增车辆的功能,但这属于前端的处理方式,不再做过多的讨论。

这里只有三个参数需要给,但实际中可能会有很多参数,而一旦只要有一个字母打错了就可能导致整个程序没法收到客户端的请求。那么就可以将客户端提供的数据先保存到一个AddCarDTO类中并定义必要的参数,加上tostring/get/set方法,这个DTO类可以放到一个pojo包里面,那么程序就会根据这个类来得到客户端输入的数据。

java 复制代码
    @RequestMapping("/v1/car/add2")
    @ResponseBody
    public String add2(AddCarDTO addCarDTO)
    {
        System.out.println(addCarDTO);
        return "add";
    }

localhost:8080/v1/car/add2

localhost:8080/v1/car/add2?brand=byd&color=white&price=300000

可以看到,分别给了没值和有值的,就算不输入必要的信息,它也会给默认值而不会获取失败,这样既能方便用户输入,也减少了输入错误的可能。

接下来在当前工程实现一个功能:BMI身体质量指数测试 BMIController。客户端将用户的 身高height和 体重weight 传递给服务端,服务端接收参数并计算用户的身体健康指数。计算公式:bmi = 体重kg/(身高m*身高)<18.5 偏瘦 <24 正常 <27 微胖 >=27 该减肥了

先在pojo里面创建一个BmiDTO类,接收网页数据时就是用这个类,同时加上get/set/tostring方法。然后在Controller中创建BMIController类,用于计算bmi,属于后端的业务。根据接收的BmiDTO类的对象,获取其中的高度和重量,完成计算后根据bmi所在的范围给客户端反馈。

java 复制代码
public class BmiDTO {
    private double weight;
    private double height;

    @Override
    public String toString() {
        return "BmiDTO{" +
                "weight=" + weight +
                ", height=" + height +
                '}';
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }
}
java 复制代码
@Controller
public class BMIController {

    @RequestMapping("/v1/bmi/func")
    @ResponseBody
    public String func(BmiDTO bmi)
    {
        double high=bmi.getHeight();
        double weight=bmi.getWeight();
        double res=weight/(high*high);
        if(res<18.5)
            return "偏瘦";
        else if(res<24)
            return "正常";
        else if(res<27)
            return "微胖";
        else
            return "该减肥了";
    }
}
  1. HTTP 响应(服务器→客户端)

响应同样由 3 部分组成:状态行、响应头部、响应体(可选)。

状态行:核心是状态码,用数字表示请求的处理结果(常见状态码如下表)。

响应头部:辅助信息,如Content-Type(标识响应体的类型)、Set-Cookie(服务器向客户端写入 Cookie,如登录后的身份令牌)、Cache-Control(控制资源的缓存策略,如 "缓存 1 小时")。

响应体:服务器返回的实际数据,如 HTML 网页、JSON 数据、图片二进制流等(若状态码是 404,响应体可能是 "404 页面找不到" 的提示内容)。

常见 HTTP 状态码分类

状态码以 "第一位数字" 区分含义,核心常用码如下:

1xx(信息性):临时响应,告知客户端 "请求已收到,正在处理"(极少用,如100 Continue)。

2xx(成功):请求已正常处理,最常用:

200 OK:通用成功(如网页加载、API 调用成功);

201 Created:资源创建成功(如 POST 请求新增用户、上传文件成功)。

3xx(重定向):请求需要进一步操作(客户端需跳转):

301 Moved Permanently:永久重定向(如旧域名跳转新域名,搜索引擎会更新地址);

302 Found:临时重定向(如登录后跳转首页,下次访问仍走原地址);

304 Not Modified:缓存命中(客户端本地有最新缓存,无需重新下载资源)。

4xx(客户端错误):请求本身有问题,服务器无法处理:

400 Bad Request:请求参数错误(如 JSON 格式错误、必填字段缺失);

401 Unauthorized:未授权(需要登录或令牌失效);

403 Forbidden:权限不足(已登录,但无操作权限,如普通用户删管理员数据);

404 Not Found:资源不存在(如访问不存在的网页、API 路径错误)。

5xx(服务器错误):服务器处理请求时出错(客户端无错):

500 Internal Server Error:通用服务器错误(如代码 bug、数据库连接失败);

502 Bad Gateway:网关错误(服务器作为网关时,上游服务器无响应,如反向代理后端挂了);

503 Service Unavailable:服务暂时不可用(如服务器维护、负载过高);

504 Gateway Timeout:网关超时(上游服务器响应太慢,网关等不及)。

在浏览器中输入www.360buy.com打开的却是京东页面

背后核心是域名重定向机制,对应的 HTTP 状态码主要是 3xx 系列重定向状态码,最常见的是 301 永久重定向 或 302 临时重定向,其中京东对该域名的配置更可能是 301 永久重定向。

为什么会跳转?------ 域名历史与重定向逻辑

360buy.com 本身是京东早期使用的域名(京东曾用名 "360buy 京东"),后来为了品牌统一,将主域名切换为 jd.com。为了避免老用户因记忆旧域名无法访问,京东会通过服务器配置,让所有访问 www.360buy.com 的请求自动跳转到 www.jd.com(或京东主站其他地址),这个过程就是 "HTTP 重定向"。

核心状态码:301 和 302 的区别

重定向的核心是通过 HTTP 响应头中的 Location 字段指定新地址,同时用 3xx 状态码 告诉浏览器 "该地址已变更,请访问新地址"。其中京东对 360buy.com 的配置更可能是 301 永久重定向

四、HTTP与HTTPS的核心区别

我们常说的 "HTTP 不安全",本质是它传输数据时不加密,数据在网络中可能被拦截、篡改(如 "中间人攻击")。而 HTTPS(HTTP Secure)是 "HTTP+SSL/TLS 加密协议" 的组合,解决了安全问题:

HTTP 协议(HyperText Transfer Protocol,超文本传输协议)和 HTTPS 协议(HyperText Transfer Protocol Secure,超文本传输安全协议)是互联网中用于客户端(如浏览器)与服务器之间数据传输的核心协议,二者的核心区别在于安全性,但在传输原理、端口、应用场景等维度也存在显著差异。以下从 7 个关键维度进行详细对比,并补充核心原理说明:

1.安全性:明文 vs 加密(核心区别)

HTTP 的安全隐患:HTTP 传输的数据是 "明文"------ 比如在网页上输入的账号密码、支付信息,会以 "原始文本" 的形式在网络中传输。如果数据被 "中间人"(如黑客通过公共 WiFi 拦截、路由器劫持)捕获,可直接读取内容,甚至篡改数据,完全无安全保障。

HTTPS 的安全机制:HTTPS 通过SSL/TLS 协议解决了 HTTP 的安全问题,核心依赖两种加密技术和证书验证,混合加密(对称加密 + 非对称加密),通过 TLS/SSL 协议对 HTTP 协议的传输过程进行加密和认证,从而解决 HTTP 协议原生存在的明文传输、身份不可信、数据易篡改三大安全问题。

服务器需安装权威 CA 机构颁发的证书,证书中包含服务器的公钥和身份信息。客户端(浏览器)会验证证书的合法性 ------ 若证书无效,浏览器会弹出 "不安全" 警告,避免用户连接到伪装的钓鱼网站。

  1. 传输流程:简单 vs 多握手步骤

HTTP 传输流程:客户端通过 TCP 协议与服务器的 80 端口建立连接;客户端发送 HTTP 请求;服务器返回 HTTP 响应;连接关闭(或保持长连接)。整个过程无额外安全步骤,流程简单。

HTTPS 传输流程:在 HTTP 流程基础上,增加了SSL/TLS 握手阶段(约 3-4 次 TCP 交互):客户端与服务器的 443 端口建立 TCP 连接;SSL/TLS 握手:客户端发送 "支持的加密算法列表""随机数 A";服务器返回 "选定的加密算法""随机数 B""服务器 SSL 证书";客户端验证证书合法性,生成 "预主密钥",用服务器公钥加密后发送给服务器;客户端和服务器分别用 "随机数 A + 随机数 B + 预主密钥" 生成相同的 "对称加密密钥";后续的 HTTP 请求 / 响应,均用 "对称加密密钥" 加密后传输;连接关闭(或保持长连接)。握手阶段是 HTTPS 比 HTTP 慢的主要原因,但现代浏览器和服务器会通过会话复用等技术减少重复握手,降低性能损耗。

在网络通信中优先使用https,它从根本上解决了 HTTP 协议的安全缺陷,能保护数据传输的完整性、机密性和身份真实性,同时满足现代网络环境对安全、合规和用户信任的核心需求。

相关推荐
程序员江鸟14 小时前
Java面试实战系列【JVM篇】- JVM内存结构与运行时数据区详解(共享区域)
java·jvm·面试
努力也学不会java14 小时前
【设计模式】三大原则 单一职责原则、开放-封闭原则、依赖倒转原则
java·设计模式·依赖倒置原则·开闭原则·单一职责原则
冬天vs不冷14 小时前
Java基础(十):关键字static详解
java·开发语言
小蒜学长14 小时前
基于Django的论坛系统设计与实现(代码+数据库+LW)
java·spring boot·后端·python·django
是小崔啊14 小时前
极客学院-从零开始学架构
java·架构
一只叫煤球的猫14 小时前
Java泛型类型擦除:从诞生讲到原理,全文深度解析
java·后端·面试
是三好14 小时前
单例模式(Singleton Pattern)
java·开发语言·算法·单例模式
Sagittarius_A*16 小时前
Maven + JUnit:Java单元测试的坚实组合
java·后端·单元测试·maven
毕设源码-郭学长17 小时前
【开题答辩全过程】以 基于SpringBoot的流浪猫狗领养系统为例,包含答辩的问题和答案
java·spring boot·后端