CS61B sp21fall Project02 Gitlet

news2024/11/19 7:27:10

Project02 Gitlet

  • 一、项目简介
  • 二、Git和Gitlet
    • 2.1 Git简介
    • 2.2 Gitlet简介
  • 三、框架设计
    • 3.1 Blobs
    • 3.2 Trees
    • 3.3 Commits
  • 四、.Gitlet文件结构设计
    • 4.1 .git文件架构
      • 4.1.1 重点介绍
        • index(VSCode中无法查看,会乱码)
        • objects(VSCode中无法查看,会乱码)
      • 4.1.2 其他文件大杂烩
    • 4.2 Gitlet文件架构设计
  • 五、项目文件设计
    • Repository类
      • init函数
      • add函数
      • commit函数
      • rm函数
      • log函数
      • global_log函数
      • find函数
      • status函数
      • checkout部分综合代码
      • branch函数
      • rm_branch函数
      • reset函数
      • merge函数

一、项目简介

这个项目将会带着我们一同手写实现一个Git版本管理工具,事件性和趣味性非常强,想象一下自己可以使用自己写的代码管理工具Gitlet,想想都爽。

二、Git和Gitlet

2.1 Git简介

  1. 保存整个文件目录的内容。在git中,这被称为提交(git commit + git push),而保存的内容本身被称为提交。
  2. 还原一个或多个文件的版本或整个提交。在git中,这称为签出那些文件或提交的文件。
  3. 查看备份的历史记录。在git中,您可以在称为日志的东西中查看此历史(简称开发历史,同时起到还原的作用)。
  4. 维护相关的提交序列,称为分支(branch)。
  5. 将一个分支中的更改合并到另一个分支中(简单理解就是将不同版本的代码进行合并)。
  6. 不仅支持历史版本的修改,还能支持形式上的不同实现方案(Plan A B C D)同时推进。

2.2 Gitlet简介

  1. Gitlet支持多版本多分枝开发。
  2. Gitlet不支持删除commit,这样设计的目的是尽可能保证各个历史版本的完整性。
  3. Gitlet的结构比较像树形结构,但是Gitlet仅仅支持两个parents的树形结构。
  4. GItlet更像是一个本地Git版本管理工具,将代码推送到远程分支的功能可以自己感兴趣进行添加,在我的项目实现里面我添加了这个功能,因为是Git的忠实信徒(doge)。

三、框架设计

3.1 Blobs

将代码还有文件内容保存到一个一个blobs里面,不同版本的文件只需要通过指针指向该版本对应条件下存在的文件就可以实现版本回退和更换,CS61B的助教课中的Assistant画了一幅非常生动的图:
在这里插入图片描述
这幅图就非常直观表示出了不同分支内容和blobs之间的关系,图片中红色的就是blobs,对于项目中的每一个文件,都有一个blob保存这个文件。

3.2 Trees

因为要支持多版本的文件更新,所以使用树形结构,如果仅仅使用链表只能支持单个分支的形式。
在这里插入图片描述

3.3 Commits

将元数据、日志信息(正常commit -m后面加的东西)、还有相关指针信息
在这里插入图片描述
这张图我感觉很好地展示了commit和blobs之间的关系,可以看到blobs是真正存储数据的部分,commit通过存储对于数据存储块的引用(在C语言中就是指针)来实现版本追踪,同时很大程度上节省了空间,不用每次commit都将所有的数据单独保存成一个快照。

四、.Gitlet文件结构设计

4.1 .git文件架构

这里.Gitlet的设计可以参考.git文件夹的设计,在VSCode中打开隐藏的.git文件夹查看结构:
在这里插入图片描述
借用阿里的.git文件架构介绍:
在这里插入图片描述
如果想要一个纯净的.git文件参考一下用来写init函数,可以在powershell中找一个文件夹执行git init,于是乎得到以下文件:
在这里插入图片描述

4.1.1 重点介绍

index(VSCode中无法查看,会乱码)

保存暂存区的内容,可以简单理解成一个本地的temp文件,在推送至远端或者进行快照之前可供修改的部分

objects(VSCode中无法查看,会乱码)

这个是实现的重点,包含三个内容:

  • commits:元数据,commit指针以及整体commit的维护
  • trees:各个commit版本文件的存储结构(数据结构)
  • blobs:数据块

这个部分在GItlet中使用了Java的面向对象编程中常用的对象序列化和对象反序列化进行

4.1.2 其他文件大杂烩

  • COMMIT_EDITMSG:commit修改的最新的相关信息

    这里输出的commit内容刚好跟我最近一次提交的信息对应:
    在这里插入图片描述

  • config:设置远程仓库地址以及远程仓库分支、本地仓库分支

在这里插入图片描述

  • HEAD:保存了本地仓库的分支指针位置,在这个仓库中是master
    在这里插入图片描述
  • ORIG_HEAD:用哈希的方法随机生成的唯一标识码
    在这里插入图片描述
  • log :保存日志信息相关内容
    • HEAD:保存所有的头部指针信息
      在这里插入图片描述
      这里的matster文件保存了所有master分支提交的信息在这里插入图片描述
    • refs:保存本地分支和远程分支对应关系
      在这里插入图片描述

4.2 Gitlet文件架构设计

  • objects 文件夹:存储commit和blob对象,数据结构是tree(使用hashcode作为文件名)
    • commits文件夹:存储每一次commit信息
    • blobs文件夹:存储数据块
  • commit 文件:用sha1编码保存对commit的引用
  • blob文件:用sha1编码·1保存对blob的引用
  • remotes 存储远端分支内容,用于远程推送
  • HEAD文件: 存储当前分支的名称,默认为master分支,在init的时候生成
  • staging 存储缓存区内容(以Stage class的形式存储blob)
  • removedStage 存储被rm的文件(以Stage class的形式存储)

五、项目文件设计

在这里插入图片描述

  • Utils文件中是用于实现生成sha1标签值、对象序列化和反序列化、使用到的数据结构、常用的IO操作的辅助函数
  • Repository中定用于初始化的时候定义Gitlet项目文件夹的架构和文件初始化。
  • Commit中定义了git中比较重要的一个类commit的应用。

tips:

  1. 序列化的时间不能由于对象的内容大小而变化。

Repository类

init函数

public void init() {
        //create a new .gitlet directory
        if (GITLET_DIR.exists()) {
            System.out.println("A Gitlet version-control system already exists in the current directory.");
            return;
        } else {
            GITLET_DIR.mkdir();
            // set the visibility of the .gitlet directory to hidden
            DosFileAttributeView fileAttributeView = Files.getFileAttributeView(GITLET_DIR.toPath(), DosFileAttributeView.class);
            try {
                fileAttributeView.setHidden(true);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //get the current time
            long time = System.currentTimeMillis();
            //change the type of the time to a string
            String timestamp = String.valueOf(time);
            //create the initial commit
            Commit initialCommit = new Commit("initial commit", null,timestamp, null);
            //set the branch to master by defult
            branch = "master";
            //create object area for commits areas
            File object = join(GITLET_DIR, "object");
            //create subdirectories for commits areas and blobs
            File commit = join(object, "commit");
            //create subdirectories for blobs areas
            File blob = join(object, "blob");
            //create head area for commits areas
            File head = join(GITLET_DIR, "HEAD");
            //init the head to master
            writeContents(head, "master");
            //create staging area for commits
            File staging = join(GITLET_DIR, "staging");
            //create the files above
            object.mkdir();
            commit.mkdir();
            blob.mkdir();
            staging.mkdir();
        }

    }
  1. 判断当前文件夹下是否存在.gitlet仓库,如果没有就新建一个,如果有就提示已经存在。
  2. 创建commit文件夹和blob文件夹,同时初始化一个initial commit对象到文件并保存到commit文件夹下
  3. 创建一个staging区域用于暂存commit的内容。

add函数

//add a copy of the files as currently exist to the stagging area
    public void add(String filename) {
        //if the current working version of the file is identical to the version in the current commit do not stage!
        //if the file does not exist at all,print an error message
        if (!join(CWD, filename).exists()) {
            System.out.println("File does not exist.");
            return;
        }
        //if the current working version of the file is identical to the version in the current commit, do not stage it
        if (join(GITLET_DIR, "object", "commit", "HEAD", filename).exists()) {
            if (join(CWD, filename).equals(join(GITLET_DIR, "object", "commit", "HEAD", filename))) {
                return;
            }
        }
        //if the file is not staged, add it to the staging area
        if (!join(GITLET_DIR, "staging", filename).exists()) {
            writeContents(join(GITLET_DIR, "staging", filename), readContentsAsString(join(CWD, filename)));
        }
        //if the file is already staged, overwrite the file in the staging area with the new version
        else {
            writeContents(join(GITLET_DIR, "staging", filename), readContentsAsString(join(CWD, filename)));
        }
    }
  1. 将指定的文件添加到暂存区中

commit函数

//commit the files in the staging area
    public void commit(String message) {
        //if no files have been staged, print an error message
        if (join(GITLET_DIR,"stageing").list().length == 1) {
            System.out.println("No changes added to the commit.");
            return;
        }
        //create a new commit object and set the parent commit
        //TODO: figure out how the blobs work
        Commit newCommit = new Commit(message, readObject(join(GITLET_DIR, "HEAD", "HEAD"), Commit.class), String.valueOf(System.currentTimeMillis()), null);
        //create a new commit file
        File commitFile = join(GITLET_DIR, "object", "commit", newCommit.getUID());
        //serialize the commit object and write it to the commit file
        writeObject(commitFile, newCommit);
        //update the head to the new commit
        writeContents(join(GITLET_DIR, "HEAD", "HEAD"), newCommit.getUID());
        //clear the staging area
        for (File file : join(GITLET_DIR, "staging").listFiles()) {
            file.delete();
        }
    }
  1. 新建一个commit对象记录当前的项目状态。

rm函数

//remove the file from the staging area
    public void rm(String filename) {
        //if the file is not staged, print an error message
        if (!join(GITLET_DIR, "staging", filename).exists()) {
            System.out.println("No reason to remove the file.");
            return;
        }
        //remove the file from the staging area
        join(GITLET_DIR, "staging", filename).delete();
    }
  1. 从暂存区中将已经添加的某个文件删除。

log函数

//print the commit history, but we only display the first parent commit links and ignore any second parent links
    public void log() {
        //get into the commit directory
        File commit = join(GITLET_DIR, "object", "commit");
        //get the current commit and deserialize it to a commit object
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD", "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //print the commit history
        while (current != null) {
            System.out.println("===");
            System.out.println("commit " + current.getUID());
            System.out.println("Date: " + current.getTimestamp());
            System.out.println(current.getMessage());
            System.out.println();
            current = current.getParent();//implement the circular of the commit messages
        }
    }
  1. 从commit文件夹下获取当前分支的commit信息并打印在控制台上面。

global_log函数

//print the commit history of all commits
    public void global_log() {
        //get the global log of all commits
        File commit = join(GITLET_DIR, "object", "commit");
        for (File file : commit.listFiles()) {
            Commit current = readObject(file, Commit.class);
            System.out.println("===");
            System.out.println("commit " + current.getUID());
            System.out.println("Date: " + current.getTimestamp());
            System.out.println(current.getMessage());
            System.out.println();
        }
    }
  • 在全局范围内打印所有的commit信息。

find函数

//find the commit with the given message
    public void find(String message) {
        //get the global log of all commits
        File commit = join(GITLET_DIR, "object", "commit");
        for (File file : commit.listFiles()) {
            Commit current = readObject(file, Commit.class);
            if (current.getMessage().equals(message)) {
                System.out.println(current.getUID());//print the commit message by line
                return;
            }
        }
    }
  • 根据文件名找到相应的commit message

status函数

//print the status of the repository
    public void status() {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //print the current branch
        System.out.println("=== Branches ===");
        System.out.println("*" + currentBranch);
        for (File file : join(GITLET_DIR, "object", "commit").listFiles()) {
            if (!file.getName().equals(currentBranch)) {
                System.out.println(file.getName());
            }
        }
        System.out.println();
        //print the staged files
        System.out.println("=== Staged Files ===");
        for (File file : join(GITLET_DIR, "staging").listFiles()) {
            System.out.println(file.getName());
        }
        System.out.println();
        //print the removed files
        System.out.println("=== Removed Files ===");
        for (File file : join(GITLET_DIR, "staging").listFiles()) {
            System.out.println(file.getName());
        }
        System.out.println();
        //print the modified files
        System.out.println("=== Modifications Not Staged For Commit ===");
        System.out.println();
        //print the untracked files
        System.out.println("=== Untracked Files ===");
        System.out.println();
    }
  • 打印当前的暂存区的状态

checkout部分综合代码

 //checkout the file from the current commit
    public void checkout(String filename) {
        //get the current commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //get the file from the current commit
        File file = join(GITLET_DIR, "object", "blob", current.getUID(), filename);
        //copy the file to the current working directory
        writeContents(join(CWD, filename), readContents(file));
    }
    //checkout the file from the commit id
    public void checkout(String commitID, String filename) {
        //get the commit from the commit id
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, commitID);
        Commit current = readObject(currentCommit, Commit.class);
        //get the file from the commit
        File file = join(GITLET_DIR, "object", "blob", current.getUID(), filename);
        //copy the file to the current working directory
        writeContents(join(CWD, filename), readContents(file));
    }
    //checkout the branch
    public void checkoutBranch(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch does not exist, print an error message
        if (!join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("No such branch exists.");
            return;
        }
        //if the branch is the current branch, print an error message
        if (currentBranch.equals(branchName)) {
            System.out.println("Already on the target branch, no need to change the branch");
            return;
        }
        //get the current commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //get the branch commit
        File branchCommit = join(commit, branchName);
        Commit branch = readObject(branchCommit, Commit.class);
        //get the files from the branch commit
        for (File file : join(GITLET_DIR, "object", "blob", branch.getUID()).listFiles()) {
            //copy the file to the current working directory
            writeContents(join(CWD, file.getName()), readContents(file));
        }
        //delete the files that are not in the branch commit
        for (File file : join(CWD).listFiles()) {
            if (!join(GITLET_DIR, "object", "blob", branch.getUID(), file.getName()).exists()) {
                file.delete();
            }
        }
        //update the head to the branch commit
        writeContents(join(GITLET_DIR, "HEAD"), branchName);
    }
  • 分支切换以及状态更新

branch函数

//Description: Creates a new branch with the given name, and points it at the current head commit. A branch is nothing more than a name for a reference (a SHA-1 identifier) to a commit node. This command does NOT immediately switch to the newly created branch (just as in real Git). Before you ever call branch, your code should be running with a default branch called “master”.
    public void branch(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch already exists, print an error message
        if (join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("A branch with that name already exists.");
            return;
        }
        //create a new branch commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        Commit newBranch = new Commit(current.getMessage(), current, String.valueOf(System.currentTimeMillis()), null);
        //create a new branch commit file
        File branchCommit = join(commit, branchName);
        //serialize the branch commit object and write it to the branch commit file
        writeObject(branchCommit, newBranch);
    }
  • 创建一个新的branch

rm_branch函数

//remove the branch
    public void rm_branch(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch does not exist, print an error message
        if (!join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("A branch with that name does not exist.");
            return;
        }
        //if the branch is the current branch, print an error message
        if (currentBranch.equals(branchName)) {
            System.out.println("Cannot remove the current branch.");
            return;
        }
        //remove the branch
        join(GITLET_DIR, "object", "commit", branchName).delete();
    }
  • 删除一个分支

reset函数

//reset the commit header to the given commit
    public void reset(String commitID) {
        //get the commit from the commit id
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, commitID);
        Commit current = readObject(currentCommit, Commit.class);
        //get the files from the commit
        for (File file : join(GITLET_DIR, "object", "blob", current.getUID()).listFiles()) {
            //copy the file to the current working directory
            writeContents(join(CWD, file.getName()), readContents(file));
        }
        //delete the files that are not in the commit
        for (File file : join(CWD).listFiles()) {
            if (!join(GITLET_DIR, "object", "blob", current.getUID(), file.getName()).exists()) {
                file.delete();
            }
        }
        //update the head to the commit
        writeContents(join(GITLET_DIR, "HEAD"), commitID);
    }

merge函数

//merge the branch with the current branch
    public void merge(String branchName) {
        //get the current branch
        File head = join(GITLET_DIR, "HEAD");
        String currentBranch = readContentsAsString(head);
        //if the branch does not exist, print an error message
        if (!join(GITLET_DIR, "object", "commit", branchName).exists()) {
            System.out.println("A branch with that name does not exist.");
            return;
        }
        //if the branch is the current branch, print an error message
        if (currentBranch.equals(branchName)) {
            System.out.println("Cannot merge a branch with itself.");
            return;
        }
        //get the current commit
        File commit = join(GITLET_DIR, "object", "commit");
        File currentCommit = join(commit, readContentsAsString(join(GITLET_DIR, "HEAD")));
        Commit current = readObject(currentCommit, Commit.class);
        //get the branch commit
        File branchCommit = join(commit, branchName);
        Commit branch = readObject(branchCommit, Commit.class);
        //get the split point commit
        Commit splitPoint = findSplitPoint(current, branch);
        //get the files from the split point commit
        for (File file : join(GITLET_DIR, "object", "blob", splitPoint.getUID()).listFiles()) {
            //copy the file to the current working directory
            writeContents(join(CWD, file.getName()), readContents(file));
        }
        //get the files from the branch commit
        for (File file : join(GITLET_DIR, "object", "blob", branch.getUID()).listFiles()) {
            //if the file is not in the split point commit, copy the file to the current working directory
            if (!join(GITLET_DIR, "object", "blob", splitPoint.getUID(), file.getName()).exists()) {
                writeContents(join(CWD, file.getName()), readContents(file));
            }
        }
        //get the files from the current commit
        for (File file : join(GITLET_DIR, "object", "blob", current.getUID()).listFiles()) {
            //if the file is not in the split point commit, copy the file to the current working directory
            if (!join(GITLET_DIR, "object", "blob", splitPoint.getUID(), file.getName()).exists()) {
                writeContents(join(CWD, file.getName()), readContents(file));
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1610209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【汇编语言】初识汇编

【汇编语言】初识汇编 文章目录 【汇编语言】初识汇编前言由机器语言到汇编语言机器语言与机器指令汇编语言与汇编指令汇编语言程序示例 计算机组成指令和数据的表示计算机的存储单元计算机的总线 内存读写与地址空间CPU对存储器的读写内存地址空间 总结 前言 为什么要学习汇编…

精通MongoDB聚合操作API:深入探索高级技巧与实践

MongoDB 聚合操作API提供了强大的数据处理能力,能够对数据进行筛选、变换、分组、统计等复杂操作。本文介绍了MongoDB的基本用法和高级用法,高级用法涵盖了setWindowFields、merge、facet、expr、accumulator窗口函数、结果合并、多面聚合、查询表达式在…

动态库静态库linux

动态库静态库 静态库 静态库必须包含在可执行文件里,整个都要包含 缺点:消耗系统大,每个使用静态库的程序都要复制静态库(浪费内存) 影响使用场景: 在静态库内存小的时候,可以用来提升速度 制…

Linux(CentOS7)离线使用安装盘部署Telnet

# [pdf在线免费转word文档](https://orcc.online/pdf) https://orcc.online/pdf 挂载镜像CentOS-7-x86_64-DVD-1810.iso到/mnt下(其他位置也行),命令如下: mount /dev/sr0 /mnt 安装包默认在Packages目录下,需要安装…

【QT进阶】Qt Web混合编程之CMake VS2019编译并使用QCefView(图文并茂超详细版本)

往期回顾 【QT进阶】Qt Web混合编程之CEF、QCefView简单介绍-CSDN博客 【QT进阶】Qt Web混合编程之VS2019 CEF的编译与使用(图文并茂超详细介绍)-CSDN博客【QT进阶】Qt Web混合编程之QWebEngineView基本用法-CSDN博客【QT进阶】Qt Web混合编程之VS2019 C…

AI生图美学在淘宝的实践应用

本文介绍了如何制定和应用美学标准来评估和改善人工智能生成的图像质量,特别是在电商领域的应用,主要分为制定美学标准、训练美学模型、应用美学模型、升级淘宝风格模型四个步骤。 美学的定义与分析 图像质量标准:现代设计框架下,…

类和对象【二】this指针,构造函数和成员初始化列表【超详细】

文章目录 this指针this指针的定义this指针的“工作”原理this指针的作用this指针的特点 构造函数构造函数的定义构造函数的作用构造函数的特点构造函数的调用方式括号法无参构造或者全缺省构造需要传参才能调用的构造函数 隐式类型转换法是只传一个参数就能调用的构造函数是要传…

HCIE-Shell实验1

要求: 判断当前磁盘剩余空间是否有20G,如果小于20G,则将报警邮件发送给管理员,每天检查一次磁盘剩余空间。判断web服务是否运行(1、査看进程的方式判断该程序是否运行,2、通过查看端口的方式判断该程序是否运行)&…

大模型应用开发基础

AGI 时代,AI 无处不在,形成新的社会分层: AI 使用者,使用别人开发的 AI 产品AI 产品开发者,设计和开发 AI 产品基础模型相关,训练基础大模型,或为大模型提供基础设施 越向下层,重要…

Leetcode-168.Excel表列名称

题目描述 给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称。 例如: A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...示例 1: 输入:columnNumber 1 输出:"A"…

ROS2学习笔记(一) 基本概念

1. Node 节点 节点: 完成具体功能的模块 相关命令 #运行命令 ros2 run <package_name> <executable_name>#当前节点查询查询 ros2 node list#重映射 Remapping ros2 run <package_name> <executable_name> --ros-args --remap __node:<node_na…

揭开ChatGPT面纱(一):准备工作(搭建开发环境运行OpenAI Demo)

文章目录 序言&#xff1a;探索人工智能的新篇章一、搭建开发环境二、编写并运行demo1.代码2.解析3.执行结果 本博客的gitlab仓库&#xff1a;地址&#xff0c;本博客对应01文件夹。 序言&#xff1a;探索人工智能的新篇章 随着人工智能技术的飞速发展&#xff0c;ChatGPT作为…

虚拟ip地址怎么弄到手机上

在当下的社会&#xff0c;手机已经变得至关重要&#xff0c;它融入了我们的日常生活&#xff0c;无论是上网冲浪、社交互动&#xff0c;还是工作学习&#xff0c;都离不开它。但有时候&#xff0c;由于某些限制&#xff0c;我们可能无法充分享受网络带来的便利。这时&#xff0…

《苍穹外卖》Day02部分知识点记录

一、属性的拷贝以及密码的加密 使用org.springframework.beans中的BeanUtils.copyProperties()方法时&#xff0c;二者的属性名必须要一致。 /*** 新增员工* param employeeDTO*/Overridepublic void save(EmployeeDTO employeeDTO) {Employee employee new Employee();// 对…

spring webflux 小结

一、WebFlux 简介 WebFlux 是 Spring Framework5.0 中引入的一种新的反应式Web框架。通过Reactor项目实现Reactive Streams规范&#xff0c;完全异步和非阻塞框架。本身不会加快程序执行速度&#xff0c;但在高并发情况下借助异步IO能够以少量而稳定的线程处理更高的吞吐&…

COIN++: Neural Compression Across Modalities 论文阅读笔记

1. 论文基本信息 发布于&#xff1a; TMLR 2022 2. 创新点 使用元学习将编码时间减少了两个数量级以上&#xff0c;将编码共享结构进行编码&#xff0c;并对该网络应用调制来编码实例特定信息。量化和熵编码调制。虽然我们的方法在压缩和速度方面都大大超过了 COIN&#xff0…

Navicat导入sql文件图文教程

本文使用的MySQL工具为:Navicat.默认已经连接数据库!! 步骤: 1.右键自己的数据库,选择新建数据库. 2.输入数据库名称&#xff0c;字符集选择“utf8”&#xff0c;排序规则选择“ utf8_general_ci”,确定. 3.双击新建好的“数据库”。右键点击“运行SQL文件”。 4.选择本地的s…

Linux上的uname

2024年4月19日&#xff0c;周五上午 这是我第一篇用CSDN上的markdown编辑器写的博客&#xff0c;感觉还不错 uname 是一个常用的命令行工具&#xff0c;uname 的全称是 “Unix Name”&#xff0c;它是一个 Unix 和类 Unix 操作系统上的命令行工具&#xff0c;用于获取操作系统相…

同旺科技 USB TO SPI / I2C适配器读写24LC256--页写

所需设备&#xff1a; 1、USB 转 SPI I2C 适配器&#xff1b;内附链接 2、24LC256芯片 适应于同旺科技 USB TO SPI / I2C适配器升级版、专业版&#xff1b; 从00地址开始写入64个字节&#xff0c;然后再将64个字节读回&#xff1b; 页写时序&#xff1a; 读时序&#xff1a…

【不看后悔】AGI时代,这些工具真的能让你收入翻倍!

引言 在数字化浪潮中&#xff0c;AIGC已经成为不可或缺的一部分 无论你是一名内容创作者&#xff0c;还是简单的社交媒体用户&#xff0c;免费的AI工具都能在多个层面助你一臂之力。这些工具涵盖从文本创作到图像设计&#xff0c;再到视频制作等多个方面&#xff0c;不仅可以…