都广实习笔记

为什么用UUID做主键


自增id依赖存储引擎
自增主键删除之后无法复用,内存占用
分库分表问题
请求的时候id无法提前预知

面向过程和面向对象



以把大象装入冰箱为例
我们可以把这件事抽象为 开门 把大象放进去等的过程
这就是面向过程

对于面向对象
我们可以将大象和冰箱抽象为实体,并封装他们的动作,比如冰箱有开门关门的行为,我们无需关注把大象装入冰箱的细节,只需要调用相应的方法

RESTFUL风格

一种api设计的规范,全称叫资源状态转换

Artifacts表初识


溯源问题
猜测是使用Artifacts存储镜像,与Devops结合方便开发和运维的协同工作
artifacts 表通常用于管理和存储软件构建产物(Artifacts)的相关信息,是软件开发和 DevOps 流程中的核心组件之一。它的设计旨在满足以下需求:


1. 构建产物存储与管理

  • 集中存储:将构建产物(如二进制文件、依赖库、容器镜像等)的元数据和存储路径集中管理,方便查找和使用。
  • 版本控制:通过 version 字段管理构建产物的不同版本,支持版本回滚和发布管理。

2. 构建产物的可追溯性

  • 构建来源:记录构建产物的生成信息(如代码分支、提交哈希、构建时间),确保每次构建都可以追溯到具体的代码变更。
  • 构建环境:记录构建时的环境信息(如操作系统、构建工具版本、依赖包版本),便于复现构建过程。

3. 构建产物的分发与部署

  • 存储位置:通过 location 字段记录构建产物的存储路径(如 S3、NFS、本地路径),支持快速分发和部署。
  • 哈希校验:通过 hash 字段(如 MD5、SHA-256)确保构建产物在传输和存储过程中的完整性。

4. 构建产物的合规性与安全性

  • 签名验证:记录构建产物是否经过数字签名验证,确保其来源可信。
  • 安全扫描:关联安全扫描结果(如漏洞扫描报告),确保构建产物符合安全标准。

5. 构建产物的分类与搜索

  • 标签与分类:通过 tags 字段对构建产物进行分类(如 production-readytest),支持快速筛选和搜索。
  • 项目与团队:记录构建产物所属的项目或团队,便于权限管理和资源分配。

6. 支持 CI/CD 流程

  • 自动化集成:与 CI/CD 工具(如 Jenkins、GitLab CI、GitHub Actions)集成,自动记录每次构建的产物信息。
  • 发布管理:通过 status 字段(如 DraftStable)管理构建产物的发布状态,确保只有经过测试和验证的构建产物才能进入生产环境。

7. 数据分析与报告

  • 构建统计:通过分析 artifacts 表中的数据,生成构建频率、构建成功率等统计报告。
  • 依赖分析:分析构建产物之间的依赖关系,优化构建流程和资源使用。

8. 示例表结构

以下是一个典型的 artifacts 表结构设计:

字段名类型描述
idUUID构建产物的唯一标识(主键)。
nameString构建产物的名称(如应用名称)。
versionString构建产物的版本号(遵循语义化版本控制)。
typeString构建产物的类型(如 JAR、Docker 镜像、ZIP)。
sizeBigInt构建产物文件的大小(以字节为单位)。
locationString构建产物的存储路径或 URI(如 S3 路径)。
hashString构建产物的哈希值(如 SHA-256),用于校验文件完整性。
created_atTimestamp构建产物的创建时间。
updated_atTimestamp构建产物的最后更新时间。
build_timeTimestamp构建产物的生成时间。
build_sourceString触发构建的代码分支或提交哈希。
build_toolString使用的构建工具及其版本(如 Maven 3.8.4)。
statusString构建产物的状态(如 DraftStable)。
signatureBoolean构建产物是否经过数字签名验证。
tagsJSON Array自定义标签(如 production-readytest)。
projectString构建产物所属的项目名称。
teamString构建产物所属的团队或部门。

9. 典型使用场景

场景 1:构建产物存储与查询

  • 开发者通过 CI/CD 工具生成构建产物,并将其元数据存储到 artifacts 表中。
  • 运维人员通过 nameversion 查询特定构建产物,并获取其存储路径进行部署。

场景 2:版本管理与回滚

  • 通过 version 字段管理构建产物的多个版本。
  • 当生产环境出现问题时,可以快速回滚到之前的稳定版本。

场景 3:安全与合规性检查

  • 在构建产物生成后,自动进行安全扫描,并将结果存储到 artifacts 表中。
  • 只有通过安全扫描的构建产物才能被标记为 Stable 并用于生产环境。

场景 4:构建产物分发

  • 通过 location 字段获取构建产物的存储路径,并使用分发工具(如 AWS S3、Artifactory)将其分发到目标环境。

场景 5:数据分析与优化

  • 分析 artifacts 表中的数据,生成构建频率、构建成功率等报告,优化构建流程和资源使用。

10. 总结

artifacts 表的主要需求包括:

  1. 集中存储和管理构建产物。
  2. 支持构建产物的版本控制和可追溯性。
  3. 确保构建产物的合规性和安全性。
  4. 支持构建产物的分发与部署。
  5. 提供分类、搜索和统计分析功能。

通过 artifacts 表,可以实现对软件构建产物的全生命周期管理,从而提高开发效率和系统可靠性。

REST API 设计

题目:1. 目标与需求分析

主要目标

提高构建产物的可追溯性和合规性。

管理软件构建产物(如二进制文件、依赖库、容器镜像等)。

提供高效的存储、检索、分发和版本控制功能。

支持多种构建工具和开发流程(如 CI/CD)。

1. 元数据定义

构建物元数据是构建物的相关信息,主要包括以下内容:

基本属性

  • 名称:构建物的唯一标识,如 my-app.
  • 版本:遵循语义化版本控制(如 1.0.0)。
  • 类型:构建物的格式(如 JAR、Docker 镜像、ZIP)。
  • 大小:文件大小。
  • 存储位置:实际存储的路径或 URI(如 S3 路径)。
  • 哈希值:校验文件完整性(如 MD5, SHA-256)。

上下文属性

  • 构建时间:构建物的生成时间。
  • 构建来源:触发构建的代码分支、提交哈希。
  • 构建工具:使用的工具和版本(如 Maven 3.8.4)。
  • 构建环境:构建时的操作系统、依赖包版本等。

状态属性

  • 状态:如 Draft(草稿)、Stable(稳定)。
  • 签名:构建物是否被数字签名验证。
  • 安全扫描结果:漏洞扫描报告。

标签与分类

项目或团队:归属的项目名称或团队。

标签:自定义标签(如 production-ready, test)。

Artifacts 表(构建物主表)

  • id(主键,UUID)
  • name(名称)
  • version(版本)
  • type(类型)
  • size(大小)
  • location(存储路径)
  • hash(哈希值)
  • created_at(创建时间)
  • updated_at(更新时间)

Metadata 表(元数据扩展表)

  • id(主键,UUID)
  • artifact_id(外键,关联 Artifacts 表)
  • key(元数据键,如 build_tool)
  • value(元数据值,如 Maven 3.8.4)

Tags 表(标签表)

  • id(主键,UUID)
  • artifact_id(外键)
  • tag(标签值)

ScanResults 表(扫描结果表)

report(扫描报告的存储路径或 JSON 内容)

id(主键,UUID)

artifact_id(外键)

scan_tool(扫描工具名称)

result(扫描结果,如 PASS, FAIL)


1. **Artifacts API**
获取所有构建物
- **GET** `/api/artifacts`
- 查询参数
- `name`: 按名称过滤
- `version`: 按版本过滤
- `type`: 按类型过滤
- `tag`: 按标签过滤
- 响应:返回符合条件的构建物列表

获取单个构建物
- **GET** `/api/artifacts/{id}`
- 响应:返回指定ID的构建物详细信息

创建构建物
- **POST** `/api/artifacts`
- 请求体:
```json
{
"name": "my-app",
"version": "1.0.0",
"type": "JAR",
"size": 1024,
"location": "s3://bucket/path/to/artifact",
"hash": "sha256:abc123..."
}
```
- 响应:返回新创建的构建物信息

更新构建物
- **PUT** `/api/artifacts/{id}`
- 请求体:
```json
{
"name": "my-app",
"version": "1.1.0",
"type": "JAR",
"size": 2048,
"location": "s3://bucket/path/to/artifact",
"hash": "sha256:def456..."
}
```
- 响应:返回更新后的构建物信息

删除构建物
- **DELETE** `/api/artifacts/{id}`
- 响应:204 No Content

2. **Metadata API**

# 获取构建物的元数据
- **GET** `/api/artifacts/{artifact_id}/metadata`
- 响应:返回指定构建物的所有元数据

# 添加/更新元数据
- **POST** `/api/artifacts/{artifact_id}/metadata`
- 请求体:
```json
{
"key": "build_tool",
"value": "Maven 3.8.4"
}
```
- 响应:返回添加/更新后的元数据

# 删除元数据
- **DELETE** `/api/artifacts/{artifact_id}/metadata/{key}`
- 响应:204 No Content

3. **Tags API**

# 获取构建物的标签
- **GET** `/api/artifacts/{artifact_id}/tags`
- 响应:返回指定构建物的所有标签

# 添加标签
- **POST** `/api/artifacts/{artifact_id}/tags`
- 请求体:
```json
{
"tag": "production-ready"
}
```
- 响应:返回添加后的标签

# 删除标签
- **DELETE** `/api/artifacts/{artifact_id}/tags/{tag}`
- 响应:204 No Content

4. **ScanResults API**

# 获取构建物的扫描结果
- **GET** `/api/artifacts/{artifact_id}/scan-results`
- 响应:返回指定构建物的所有扫描结果

# 添加扫描结果
- **POST** `/api/artifacts/{artifact_id}/scan-results`
- 请求体:
```json
{
"scan_tool": "SonarQube",
"result": "PASS",
"report": "s3://bucket/path/to/report"
}
```
- 响应:返回添加后的扫描结果

# 删除扫描结果
- **DELETE** `/api/artifacts/{artifact_id}/scan-results/{scan_result_id}`
- 响应:204 No Content

5. **Search API**

# 综合搜索
- **GET** `/api/search`
- 查询参数:
- `query`: 综合搜索关键词(名称、版本、标签等)
- `type`: 按类型过滤
- `status`: 按状态过滤(如 Draft, Stable)
- 响应:返回符合条件的构建物列表及其相关元数据、标签和扫描结果

6. **Versioning API**

# 获取构建物的所有版本
- **GET** `/api/artifacts/{name}/versions`
- 响应:返回指定名称的所有版本构建物

# 获取特定版本的构建物
- **GET** `/api/artifacts/{name}/versions/{version}`
- 响应:返回指定名称和版本的构建物

7. **Security API**

# 签名验证
- **POST** `/api/artifacts/{id}/verify-signature`
- 请求体:
```json
{
"signature": "base64-encoded-signature"
}
```
- 响应:返回验证结果(如 `valid` 或 `invalid`)

8. **Audit API**

# 获取构建物的审计日志
- **GET** `/api/artifacts/{id}/audit-logs`
- 响应:返回指定构建物的所有操作日志

9. **Bulk Operations API**

# 批量删除构建物
- **POST** `/api/artifacts/bulk-delete`
- 请求体:
```json
{
"ids": ["uuid1", "uuid2", "uuid3"]
}
```
- 响应:204 No Content

# 批量添加标签
- **POST** `/api/artifacts/bulk-tag`
- 请求体:
```json
{
"ids": ["uuid1", "uuid2", "uuid3"],
"tag": "production-ready"
}
```
- 响应:返回操作结果

10. **Health Check API**

# 健康检查
- **GET** `/api/health`
- 响应:返回服务状态(如 `{"status": "UP"}`)

ServiceWorker和WebWorker初识

特性Service WorkerWeb Worker
设计目标网络代理、离线缓存、推送通知后台计算、避免阻塞主线程
生命周期独立于页面,事件驱动依赖于页面,手动启动与终止
通信机制事件监听、postMessage、BroadcastChannelpostMessage 和 onmessage
访问权限网络请求、缓存、推送通知复杂计算,不能访问 DOM
典型场景PWA、离线应用、推送通知数据分析、图像处理、并行计算

dockerfile和docker-compose

dockerfile作为一个文本文件,包含一系列指令,用于定义构建一个docker镜像,例如设置工作目录,复制镜像之类的

docker-compose是通过yaml文件定义多个服务,网络和卷,例如指定端口,定义数据卷
Dockerfile 和 docker-compose 的区别

特性Dockerfiledocker-compose
作用定义单个镜像的构建过程定义和运行多容器应用
文件格式文本文件,包含一系列指令YAML 文件,定义服务、网络和卷
使用场景构建自定义镜像编排多容器应用
依赖关系依赖 Docker 引擎构建镜像依赖 Docker 引擎和 docker-compose 工具
典型命令docker build -t <image_name> .docker-compose up

IDEA lombok 失效问题

常见lombok失效可以考虑:
1.idea设置问题
在settings->Build,Execution,Deployment->Annotation Processors打开Enable annotation processing
2.查看maven依赖
是否导入了lombok的依赖包,以及版本问题
3.idea插件问题
查看是否安装了lombok插件,在settings中下载


昨天遇到maven编译之后target中有生成的getter和setter,但使用Application启动之后生成代码消失

问题锁定在idea的.idea文件夹中的complier.xml中,因为在pom文件的build->plugin->configuration->annotationProcessorPaths->path中没有指定lombok的版本,导致idea无法找到lombok的jar包,编译出错。


Builder标签

Buider标签用来生成建造者模式的构造器,使得传参更加灵活
例如

User user = User.builder()
.id(1L)
.name("John")
.age(30)
.build();

建造者模式

建造者模式(Builder Pattern) 是一种创建型设计模式,旨在将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。建造者模式通过一步步构建对象,最终返回一个完整的对象。


建造者模式的核心思想

  1. 分离构建过程
  • 将对象的构建过程分解为多个步骤,每个步骤负责构建对象的一部分。
  • 通过一个建造者(Builder)类来管理这些步骤。
  1. 灵活创建对象
  • 客户端可以通过调用建造者的方法,逐步设置对象的属性。
  • 最终通过一个 build() 方法返回完整的对象。
  1. 支持不可变对象
  • 建造者模式非常适合创建不可变对象(即对象创建后不能被修改),因为对象的属性可以在构建过程中一次性设置。

建造者模式的结构

建造者模式通常包含以下角色:

  1. 产品(Product)
  • 最终要构建的复杂对象。
  1. 抽象建造者(Builder)
  • 定义构建产品的各个步骤的接口。
  1. 具体建造者(Concrete Builder)
  • 实现抽象建造者的接口,完成产品的具体构建过程。
  1. 指挥者(Director)
  • 负责调用建造者的方法,按照一定的顺序构建产品。
  1. 客户端(Client)
  • 使用建造者模式创建对象。

建造者模式的实现

以下是一个简单的建造者模式实现示例:

1. 产品类(Product)

public class Computer {
    private String cpu;
    private String ram;
    private String storage;

    // 私有构造函数,只能通过建造者创建对象
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
    }

    // Getter 方法
    public String getCpu() {
        return cpu;
    }

    public String getRam() {
        return ram;
    }

    public String getStorage() {
        return storage;
    }

    @Override
    public String toString() {
        return "Computer(cpu=" + cpu + ", ram=" + ram + ", storage=" + storage + ")";
    }

    // 建造者类
    public static class Builder {
        private String cpu;
        private String ram;
        private String storage;

        // 设置 CPU
        public Builder setCpu(String cpu) {
            this.cpu = cpu;
            return this;
        }

        // 设置 RAM
        public Builder setRam(String ram) {
            this.ram = ram;
            return this;
        }

        // 设置存储
        public Builder setStorage(String storage) {
            this.storage = storage;
            return this;
        }

        // 构建 Computer 对象
        public Computer build() {
            return new Computer(this);
        }
    }
}

2. 客户端使用

public class Client {
    public static void main(String[] args) {
        // 使用建造者模式创建 Computer 对象
        Computer computer = new Computer.Builder()
            .setCpu("Intel i7")
            .setRam("16GB")
            .setStorage("512GB SSD")
            .build();

        System.out.println(computer);
        // 输出: Computer(cpu=Intel i7, ram=16GB, storage=512GB SSD)
    }
}

建造者模式的优点

  1. 分离构建过程
  • 将对象的构建过程与表示分离,使得构建过程更加清晰和灵活。
  1. 支持复杂对象的创建
  • 适合创建具有多个属性的复杂对象。
  1. 支持不可变对象
  • 可以在构建过程中一次性设置所有属性,适合创建不可变对象。
  1. 代码可读性高
  • 使用链式调用,代码更加简洁和易读。

建造者模式的缺点

  1. 代码量增加
  • 需要额外编写建造者类,增加了代码量。
  1. 适用范围有限
  • 适用于创建复杂对象,如果对象属性较少,使用建造者模式可能会显得冗余。

Lombok 中的 @Builder 注解

Lombok 提供了 @Builder 注解,可以自动生成建造者模式的代码,简化开发。

示例

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class Computer {
    private String cpu;
    private String ram;
    private String storage;
}

使用方式

public class Client {
    public static void main(String[] args) {
        Computer computer = Computer.builder()
            .cpu("Intel i7")
            .ram("16GB")
            .storage("512GB SSD")
            .build();

        System.out.println(computer);
        // 输出: Computer(cpu=Intel i7, ram=16GB, storage=512GB SSD)
    }
}

总结

  • 建造者模式 是一种创建型设计模式,用于分离复杂对象的构建过程与其表示。
  • 它通过一步步构建对象,最终返回一个完整的对象,适合创建复杂对象和不可变对象。
  • Lombok 的 @Builder 注解可以自动生成建造者模式的代码,简化开发。

关于自定义异常和封装响应体

之前看鱼皮是双层封装,估计没有学到精髓,但是今天有关静态方法不把util包分出来,而是直接集成在请求体中,另外一些状态码应该使用spring的HttpStatusCode。

package io.duguang.zack.response;

import lombok.Builder;
import lombok.ToString;
import org.springframework.http.HttpStatus;

@Builder
@ToString
public class ApiResponse<T> {
    private int code;       // 状态码
    private String message; // 消息
    private T data;         // 数据

    // 全参构造函数
    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }
    // 成功响应
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase(), data);
    }

    // 成功响应(自定义消息)
    public static <T> ApiResponse<T> success(String message, T data) {
        return new ApiResponse<>(HttpStatus.OK.value(), message, data);
    }


    // 失败响应(自定义消息)
    public static <T> ApiResponse<T> error( String message) {
        return new ApiResponse<>(HttpStatus.BAD_REQUEST.value(), message, null);
    }

    // 失败响应(默认状态码)
    public static <T> ApiResponse<T> error() {
        return new ApiResponse<>(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null);
    }
}

关于HttpsStatus

1xx 信息,表示临时响应并需要请求者继续执行操作
2xx 成功,操作被成功接收并处理
3xx 表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向
4xx 客户端错误,请求包含语法错误或无法完成请求
5xx 这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错


工厂模式

什么是工厂模式

将创建对象的具体过程隔离起来,从而达到更高的灵活性,工厂模式分为三类:
简单工厂模式
工厂方法模式
抽象工厂模式


简单工厂

简单工厂就是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低耦合

但是有缺点,不符合开放封闭,每次增加新的产品要修改工厂类。

abstract class BMW {
	public BMW(){}
}
 
public class BMW320 extends BMW {
	public BMW320() {
		System.out.println("制造-->BMW320");
	}
}
public class BMW523 extends BMW{
	public BMW523(){
		System.out.println("制造-->BMW523");
	}
}

public class Factory {
	public BMW createBMW(int type) {
		switch (type) {
		
		case 320:
			return new BMW320();
 
		case 523:
			return new BMW523();
 
		default:
			break;
		}
		return null;
	}
}

public class Customer {
	public static void main(String[] args) {
		Factory factory = new Factory();
		BMW bmw320 = factory.createBMW(320);
		BMW bmw523 = factory.createBMW(523);
	}
}

工厂方法模式

相比于简单工厂,工厂方法模式将工厂和产品进行了抽象,这就符合了开放封闭原则
但仍然有缺点,每增加一个产品呢都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统类的依赖

abstract class BMW {
	public BMW(){}
}
public class BMW320 extends BMW {
	public BMW320() {
		System.out.println("制造-->BMW320");
	}
}
public class BMW523 extends BMW{
	public BMW523(){
		System.out.println("制造-->BMW523");
	}
}


interface FactoryBMW {
	BMW createBMW();
}
 
public class FactoryBMW320 implements FactoryBMW{
 
	@Override
	public BMW320 createBMW() {
		return new BMW320();
	}
 
}
public class FactoryBMW523 implements FactoryBMW {
	@Override
	public BMW523 createBMW() {
		return new BMW523();
	}
}


public class Customer {
	public static void main(String[] args) {
		FactoryBMW320 factoryBMW320 = new FactoryBMW320();
		BMW320 bmw320 = factoryBMW320.createBMW();
 
		FactoryBMW523 factoryBMW523 = new FactoryBMW523();
		BMW523 bmw523 = factoryBMW523.createBMW();
	}
}

抽象工厂模式

抽象工厂模式仍然有抽象类,不同于工厂方法模式一个抽象工厂对应一个抽象产品,抽象工厂一个抽象工厂可以对应多个抽象产品。

抽象工厂模式主要用于生产相关对象的家族,当一个产品族需要被设计在一起工作时,通过抽象工厂模式可以保证客户端始终只使用同一个产品族中的对象。

//发动机以及型号  
public interface Engine {}  
 
public class EngineA implements Engine{  
    public EngineA(){  
        System.out.println("制造-->EngineA");  
    }  
}  
public class EngineB implements Engine{  
    public EngineB(){  
        System.out.println("制造-->EngineB");  
    }  
}  
 
 
//空调以及型号  
public interface Aircondition {} 
 
public class AirconditionA implements Aircondition{  
    public AirconditionA(){  
        System.out.println("制造-->AirconditionA");  
    }  
}  
public class AirconditionB implements Aircondition{  
    public AirconditionB(){  
        System.out.println("制造-->AirconditionB");  
    }  
} 


//创建工厂的接口  
public interface AbstractFactory {  
    //制造发动机
    public Engine createEngine();
    //制造空调 
    public Aircondition createAircondition(); 
}  
 
//为宝马320系列生产配件  
public class FactoryBMW320 implements AbstractFactory{     
    @Override  
    public Engine createEngine() {    
        return new EngineA();  
    }  
    @Override  
    public Aircondition createAircondition() {  
        return new AirconditionA();  
    }  
}  
//宝马523系列
public class FactoryBMW523 implements AbstractFactory {  
     @Override  
    public Engine createEngine() {    
        return new EngineB();  
    }  
    @Override  
    public Aircondition createAircondition() {  
        return new AirconditionB();  
    }  
} 


public class Customer {  
    public static void main(String[] args){  
        //生产宝马320系列配件
        FactoryBMW320 factoryBMW320 = new FactoryBMW320();  
        factoryBMW320.createEngine();
        factoryBMW320.createAircondition();
          
        //生产宝马523系列配件  
        FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
        factoryBMW523.createEngine();
        factoryBMW523.createAircondition();
    }  
}

SpringBoot接口访问不到问题

包问题
启动类与conroller包同级
注解问题
启动类配置componnetscan,扫描controller
路径问题!!!

yml文件里context-path一定注意,如果配置的有,映射路径里就不要再写!!!
访问的时候要记的加上!!!


Http细节

Http协议

全称超文本协议,用于从万维网服务器传输超文本到本地浏览器的传送协议

http是应用层协议,基于TCP/IP通信协议来传送数据,其中HTTP1.0,HTTP1.1,HTTP1.1,HTTP2.0均为TCP实现,HTTP3.0基于UDP实现。


Http协议工作过程

特点是一发一收,一问一答

多发一收:例如上传大文件
一发多收:看直播时,一个词条可以得到多个视频源
多发多收:串流(steam link,moonlight)

HTTP请求和响应格式

请求

响应

http报文为什么要存在空行

防止粘包问题(在基于TCP的网络通信协议中,发送方连续发送的多个数据包被合并为一个大的数据包,导致接收方无法正确区分每个数据包的边界,这种现象称为“粘包”)


HTTP请求的URL

一个http请求的url包括协议类型,访问资源的凭证,服务器地址,端口好,资源层级unix文件路径,文件名,查询字符串,片段标识符。


HTTP请求方法

GET没有请求体

GET和POST的区别

使用习惯上,GET常用来获取数据,POST常用来上传数据
传参的形式上,GET 使用query string传参,POST使用body传参
GET可以被缓存

GET请求URL长度的误解
GET请求长度有限制冰不在协议本身,而是浏览器的支持长度

POST比GET更安全的误解
安全问题取决于加密算法,和query string或body无关

GET只能传输文本数据的误解
GET也可以传输二进制数据,可以使用urlencode转码放在url里


请求包头

HOST:服务器主机的地址和端口
Content-Length:body数据长度,长度单位字节
Content-Type:body的数据格式
application/x-www-form-urlencode 这是form表单的提交数据格式,此时body的格式类似于query string
multipart/form-data 也是form表单,通常用于HTML提交图片或文件
application/json json格式

特性x-www-form-urlencodedform-data
数据格式键值对,URL 编码多部分格式,原始数据
适用场景简单文本数据提交复杂数据提交,支持文件上传
性能高效,适合小数据量较低,适合大数据量或文件传输
文件上传不支持支持
请求头Content-Type: application/x-www-form-urlencodedContent-Type: multipart/form-data


User-Agent 表示浏览器或者操作系统的属性
Refer 指页面从哪个页面跳转过来

Cookie
浏览器的本地存储,但是存储在本机硬盘,其中存储键值对的字符串,用;分割。
cookie的数据可以通过js写入,也可以是服务器返回的Set-cookie字段。

响应报头

Content-Type
text/html text/css application/javascrpt application/json


请求路径 /**,取出**做参数问题

当我们需要http请求中的形如/demo/demo1/…这样的路径做参数时,可以使用HttpServletRequest这个包

@PutMapping("/upload/**")
    public ResponseEntity<Map<String, String>> uploadFilePut(HttpServletRequest request, @RequestBody byte[] fileContent) {
        Map<String, String> response = new HashMap<>();
        try {
            // 获取请求路径
            String path = request.getRequestURI().replace("/files/upload/", "");

            // 解析路径
            PathInfo pathInfo = parsePath(path);

            // 创建上传目录(如果不存在)
            Path targetDir = Paths.get(uploadDir, pathInfo.getGroupId(), pathInfo.getArtifactId(), pathInfo.getVersion());
            if (!Files.exists(targetDir)) {
                Files.createDirectories(targetDir);
            }

            // 保存文件
            Path filePath = targetDir.resolve(pathInfo.getFilename());
            Files.write(filePath, fileContent);

            response.put("message", "文件上传成功");
            response.put("filePath", filePath.toString());
            return ResponseEntity.ok(response);
        } catch (IOException e) {
            response.put("error", "文件上传失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        } catch (IllegalArgumentException e) {
            response.put("error", "路径解析失败: " + e.getMessage());
            return ResponseEntity.badRequest().body(response);
        }
    }
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇