Web 的基石:HTTP协议

Web 的基石:HTTP协议

一、HTTP 是什么?

​​HTTP(超文本传输协议,HyperText Transfer Protocol)​​ 是一个用于从网络服务器传输超文本(如网页)到本地浏览器(客户端)的​​应用层协议​​。它是互联网上数据通信的基础,也是万维网(WWW)的基石。

你可以把它想象成 ​​“浏览器和服务器之间约定好的一种对话规则和语言”​​。

在这里插入图片描述

特点:​​

  1. 基于TCP协议:面向连接,安全
  2. 基于请求-响应模型的:一次请求对应一次响应
  3. HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。
    · 缺点:多次请求间不能共享数据。
    · 优点:速度快

二、HTTP请求协议

(1)请求数据格式

HTTP 请求报文结构(由三部分组成)

1.请求行 (Request Line)

​​位置​​:请求数据的第一行。

​​内容​​:包含三个核心部分:

  • ​​请求方式​​:如 GETPOSTPUTDELETE 等。
  • ​​资源路径​​:即请求的目标 URL 路径,如 /api/users。
  • ​​协议​​:使用的 HTTP 协议版本,如 HTTP/1.1。

2.请求头 (Request Headers)

​​位置​​:从第二行开始,至一个空行结束。

​​格式​​:每一行都是一个键值对,格式为 Key: Value。

请求头字段含义与示例
Host请求的主机名
User-Agent浏览器版本,例如Chrome浏览器的标识类似Mozilla/5.0... Chrome/79,IE浏览器的标识类似Mozilla/5.0 (Windows NT ...) like Gecko
Accept表示浏览器能接收的资源类型,如text/*image/*或者*/*表示所有
Accept-Language表示浏览器偏好的语言,服务器可以据此返回不同语言的网页
Accept-Encoding表示浏览器可以支持的压缩类型,例如gzipdeflate
Content-Type请求主体的数据类型
Content-Length请求主体的大小(单位:字节)

​​常见示例​​:

  • Host: www.example.com;User-Agent: Mozilla/5.0...;Content-Type: application/json;Accept: */*

3.请求体 (Request Body)

​​存在性​​:通常为 ​​POST​​、​​PUT​​ 等请求所特有,​​GET​​ 请求一般没有请求体。

​​作用​​:用于存放要提交给服务器的请求参数。

​​格式​​:取决于请求头中的 Content-Type,常见的有:

  • application/json (JSON 格式);application/x-www-form-urlencoded (表单格式);multipart/form-data (带文件上传的表单格式)

4.GET与POST的区别

特性GET 请求POST 请求
语义获取数据(安全操作)提交数据(非安全操作)
参数位置URL 末尾(?key1=value1&key2=value2请求体中(Body)
数据长度限制✅ 有(URL 最大 2KB~8KB)❌ 无(实际受服务器限制)
安全性❌ 低(参数暴露在地址栏/历史记录)
http://xx.com/login?password=123
⚠️ 中(Body 不可见,但抓包可获取)
幂等性✅ 是(多次请求结果相同)❌ 否(多次提交可能产生副作用)
缓存✅ 可缓存❌ 不可缓存
书签收藏✅ 支持带参数收藏❌ 仅保存路径
TCP 数据包1 个(Header + Data 一起发送)2 个(先发 Header,服务器响应 100 Continue 后再发 Body)
SpringBoot 注解@GetMapping + @RequestParam@PostMapping + @RequestBody
典型场景搜索、页面跳转、资源下载登录、支付、文件上传、数据修改

💡 ​​黄金法则​​:
​​改变服务器状态的操作(创建/修改/删除)永远不要用 GET​​
​​敏感数据(密码/支付信息)必须用 POST + HTTPS​​

(2)请求数据获取

Web服务器(Tomcat)对HTTP协议的请求数据进行解析,并进行了封装(HttpServletRequest),在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

用代码获取请求数据

在SpringBoot里面创建一个 RequestController.java类

package com.example.springbootweb1;

import com.sun.net.httpserver.HttpServer;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RequestController {

    @RequestMapping("/request")
    public String request(HttpServletRequest request) {
        // 1.获取请求方式
        String method = request.getMethod(); // GET
        System.out.println("请求方式:" + method);

        // 2.获取请求url地址
        String url = request.getRequestURL().toString(); // http://localhost:8080/request
        System.out.println("请求url地址:" + url);

        // 获取请求uri地址
        String uri = request.getRequestURI(); // /request
        System.out.println("请求uri地址:" + uri);

        // 3.获取请求协议
        String protocol = request.getProtocol(); // HTTP/1.1
        System.out.println("请求协议:" + protocol);

        // 4.获取请求参数-name,age
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        System.out.println("name: " + name + ", age: " + age);

        // 5.获取请求头-Accept
        String accept = request.getHeader("Accept");
        System.out.println("Accept: " + accept);

        return "处理完成";
    }   
}

这段代码演示了如何使用 HttpServletRequest 对象获取HTTP请求的各种信息,包括请求方法URLURI协议版本请求参数和请求头信息

接着我们启动项目输入这段网址

http://localhost:8081/request?name=whgckjxy&age=20

访问之后我们就可以在控制台接收到数据了

在这里插入图片描述

三、HTTP相应协议

(1)响应数据格式

1.响应行 (Status Line)

​​位置​​:响应数据的第一行。

​​内容​​:包含三个关键信息:

  • ​​协议版本​​:如 HTTP/1.1
  • 状态码​​:如 200、404、500等,用于简明告知客户端请求的结果。
  • ​​状态描述​​:对状态码的简短文字说明,如 OK、Not Found。
代码说明
1xx响应中 - 临时状态码,表示请求已经接收,告诉客户端应该继续请求或者如果它已经完成则忽略它。
2xx成功 - 表示请求已经被成功接收,处理已完成。
3xx重定向 - 重定向到其他地方;让客户端再发起一次请求以完成整个处理。
4xx客户端错误 - 处理发生错误,责任在客户端。如:请求了不存在的资源、客户端未被授权、禁止访问等。
5xx服务器错误 - 处理发生错误,责任在服务端。如:程序抛出异常等。

​​示例​​:HTTP/1.1 200 OK

2.响应头 (Response Headers)

​​位置​​:从第二行开始,到第一个空行结束。

格式​​:每一行都是一个键值对(Key: Value),向客户端传递关于响应的附加信息。

​​常见头部示例​​:

  • Content-Type: text/html; charset=utf-8 (告知客户端响应体的数据类型和编码)
  • Content-Length: 1024 (告知客户端响应体的数据大小)
  • Set-Cookie: sessionId=abc123 (指示浏览器设置Cookie)
响应头字段功能说明
Content-Type表示该响应内容的类型(MIME类型),例如 text/html, application/json
Content-Length表示该响应内容的长度(单位:字节)。
Content-Encoding表示该响应内容使用的压缩算法,例如 gzip
Cache-Control指示客户端应如何缓存响应内容,例如 max-age=300 表示可以最多缓存300秒。
Set-Cookie告诉浏览器为当前页面所在的域设置Cookie。

3.响应体 (Response Body)

​​位置​​:在响应头之后的一个空行下面。
内容​​:服务器返回给客户端的​​实际数据​​。这是最主要的部分。

常见内容​​:可以是网页的HTML代码、JSON数据、XML数据、图片文件等。

(2)响应数据设置

Web服务器对HTTP协议的响应数据进行了封装(HttpServletResponse),并在调用Controller方法的时候传递给了该方法。这样,就使得程序员不必直接对协议进行操作,让Web开发更加便捷。

用代码获取请求数据

在SpringBoot里面创建一个 ResponseController.java类

package com.example.springbootweb1;

import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
public class ResponseController {

    @RequestMapping("/response")
    public void response(HttpServletResponse response) {
        //1. 设置响应状态码
        response.setStatus(401);

        //2. 设置响应头
        response.setHeader("name", "Response");

        //3. 设置响应体
        try {
            response.getWriter().write("<h1>hello response</h1>");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

接着我们启动项目输入这段网址

http://localhost:8081/response

@RestController
public class ResponseController {

    /**
     * 方式一:使用HttpServletResponse原生对象设置响应数据
     * 这是Servlet API的传统方式,需要手动处理响应状态码、头部和体
     * 
     * @param response HttpServletResponse对象,用于设置响应参数
     * @throws IOException 可能发生的IO异常
     */
    @RequestMapping("/response")
    public void response(HttpServletResponse response) throws IOException {
        // 1. 设置响应状态码:401表示未授权
        response.setStatus(401);
        
        // 2. 设置响应头:添加自定义头部信息
        response.setHeader("name", "Response");
        
        // 3. 设置响应体:向客户端返回HTML内容
        response.getWriter().write("<h1>hello response</h1>");
    }

    /**
     * 方式二:使用ResponseEntity - Spring中提供的方式
     * 这是Spring框架推荐的响应构建方式,提供链式调用和更优雅的API
     * 
     * @return ResponseEntity对象,包含完整的响应信息
     */
    @RequestMapping("/response2")
    public ResponseEntity<String> response2() {
        return ResponseEntity
                .status(401)                    // 响应状态码:设置HTTP状态为401未授权
                .header("name", "javaweb-ai")   // 响应头:添加自定义头部name=javaweb-ai
                .body("<h1>hello response</h1>"); // 响应体:设置返回的HTML内容
    }
}
① 基于HttpServletResponse封装
@RequestMapping("/response")
    public void response(HttpServletResponse response) throws IOException {
        // 1. 设置响应状态码:401表示未授权
        response.setStatus(401);
        
        // 2. 设置响应头:添加自定义头部信息
        response.setHeader("name", "Response");
        
        // 3. 设置响应体:向客户端返回HTML内容
        response.getWriter().write("<h1>hello response</h1>");
    }

在这里插入图片描述

响应体

在这里插入图片描述

② 基于ResponseEntity封装
@RequestMapping("/response2")
    public ResponseEntity<String> response2() {
        return ResponseEntity
                .status(401)                    
                // 响应状态码:设置HTTP状态为401未授权
                .header("name", "javaweb-ai")   
                // 响应头:添加自定义头部name=javaweb-ai
                .body("<h1>hello response</h1>"); 
                // 响应体:设置返回的HTML内容
    }

在这里插入图片描述

响应体

在这里插入图片描述

注意:
响应状态码和响应头如果没有特殊要求的话,通常不手动设定。服务器会根据请求处理的逻辑,自动设置响应状态码和响应头。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值