项目总监必看:如何利用Git深度统计团队代码贡献?多语言实践教程揭秘!

news2025/1/15 6:42:27

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁
🦄 博客首页——猫头虎的博客🎐
🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐
🌊 《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大小厂~💐

🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

文章目录

  • 使用Git命令统计代码提交情况:全面解析与多语言实现 🚀
    • 🌟 引言
    • 🚀 正文
      • 1. Git命令行工具的深度探索
      • 1.2. 使用Git命令统计提交情况
        • 1.2.1 统计提交次数
        • 1.2.2 统计新增和删除行数
        • 1.1 基于bash的统计脚本
      • 2. Java实现统计功能
        • 2.1 JGit 代码管理仓库特别案例
        • 2.2 GitLab 仓库
      • 3. Python实现
      • 4. Go语言实现
    • 🔥 总结
    • 📚 参考资料
  • 原创声明

使用Git命令统计代码提交情况:全面解析与多语言实现 🚀

在这里插入图片描述

🐯 摘要:你好,我是猫头虎博主!最近在搜索引擎上发现,关于"如何使用Git命令统计代码提交情况"的搜索量暴涨。很多小伙伴都希望通过Git深入了解他们的代码统计数据。因此,我决定写一篇文章,不仅使用传统的bash脚本方式,还会用Java、Python、Go三种热门编程语言来实现。让我们开始吧!

🌟 引言

Git是每个开发者的好帮手。但是,除了基本的提交和克隆,你真的了解Git的深层功能吗?本文将带你深入了解如何使用Git命令和多种编程语言统计代码提交情况。

🚀 正文

在这里插入图片描述

1. Git命令行工具的深度探索

在这里插入图片描述

Git命令行工具不仅可以用于代码的提交、拉取和推送,还提供了许多其他功能,如查看提交历史、比较版本差异等。其中,git log命令就可以帮助我们统计代码提交情况。

1.2. 使用Git命令统计提交情况

1.2.1 统计提交次数

通过git shortlog命令,我们可以轻松统计每个人的提交次数:

git shortlog -s -n
1.2.2 统计新增和删除行数

要统计每个人的新增和删除行数,我们可以使用以下命令:

git log --numstat --pretty="%aN" | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("新增行数: %d, 删除行数: %d\n", plus, minus)}'
1.1 基于bash的统计脚本

首先,我们使用bash脚本来实现代码统计功能。

#!/bin/bash

echo "统计代码提交情况:"

# 获取所有贡献者列表
authors=$(git log --format='%aN' | sort -u)

for author in $authors; do
    echo "----------------------------------------"
    echo "作者:$author"

    # 统计提交次数
    commit_count=$(git shortlog -s -n --author="$author" | awk '{print $1}')
    echo "提交次数:$commit_count"

    # 统计新增和删除行数
    line_stat=$(git log --numstat --pretty="%aN" --author="$author" | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("%d %d", plus, minus)}')
    IFS=' ' read -ra stats <<< "$line_stat"
    echo "新增行数:${stats[0]}"
    echo "删除行数:${stats[1]}"
done

这个脚本首先获取所有的贡献者列表,然后对每个贡献者分别统计他们的提交次数、新增行数和删除行数。

你可以将这个脚本保存为git_stats.sh,然后在项目目录中运行它来获取统计信息。确保你的脚本有执行权限(你可以使用chmod +x git_stats.sh来给它添加执行权限)。

2. Java实现统计功能

Java提供了ProcessBuilder来帮助我们执行和控制进程。我们可以利用这个特性来运行Git命令,并解析输出。

在这里插入图片描述

以下是一个简单的Java实现思路:

使用ProcessBuilder调用Git命令:Java可以通过ProcessBuilder类来执行外部命令。你可以用它来运行Git命令,获取提交日志。

解析Git日志:git log命令可以输出提交日志,你可以结合–pretty=format:选项来自定义日志格式,便于后续解析。

统计信息:解析Git日志后,你可以统计每个人的提交次数、新增行数、删除行数等信息。

以下是一个简化的示例:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

public class GitStats {

    public static void main(String[] args) throws Exception {
        String repoPath = "/path/to/your/repo"; // 项目目录
        String since = "2023-01-01";  // 开始时间
        String until = "2023-12-31";  // 结束时间

        ProcessBuilder processBuilder = new ProcessBuilder(
            "git", "log", "--since=" + since, "--until=" + until, "--shortstat", "--pretty=format:%aN"
        );
        processBuilder.directory(new java.io.File(repoPath));
        Process process = processBuilder.start();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        Map<String, Integer> commitsCount = new HashMap<>();
        Map<String, Integer> insertionsCount = new HashMap<>();
        Map<String, Integer> deletionsCount = new HashMap<>();

        String line;
        String currentAuthor = null;
        while ((line = reader.readLine()) != null) {
            if (!line.isEmpty()) {
                if (!line.startsWith(" ")) {
                    currentAuthor = line;
                    commitsCount.put(currentAuthor, commitsCount.getOrDefault(currentAuthor, 0) + 1);
                } else {
                    String[] stats = line.trim().split(",");
                    for (String stat : stats) {
                        stat = stat.trim();
                        if (stat.endsWith("insertions(+)")) {
                            int count = Integer.parseInt(stat.split(" ")[0]);
                            insertionsCount.put(currentAuthor, insertionsCount.getOrDefault(currentAuthor, 0) + count);
                        } else if (stat.endsWith("deletions(-)")) {
                            int count = Integer.parseInt(stat.split(" ")[0]);
                            deletionsCount.put(currentAuthor, deletionsCount.getOrDefault(currentAuthor, 0) + count);
                        }
                    }
                }
            }
        }

        for (String author : commitsCount.keySet()) {
            System.out.println("Author: " + author);
            System.out.println("Commits: " + commitsCount.get(author));
            System.out.println("Insertions: " + insertionsCount.getOrDefault(author, 0));
            System.out.println("Deletions: " + deletionsCount.getOrDefault(author, 0));
            System.out.println("-------------");
        }
    }
}

2.1 JGit 代码管理仓库特别案例

JGit 是一个轻量级的、完全用 Java 编写的 Git 库。它是 Eclipse 项目的一部分,用于为 Java 开发者提供一个本地的 Git 实现。JGit 提供了一套 API,允许开发者在 Java 代码中直接与 Git 仓库进行交互,而不需要依赖命令行的 Git。

使用 JGit,你可以轻松地从 Java 程序中访问和操作 Git 仓库。以下是一个简单的示例,该示例展示了如何使用 JGit 统计给定日期范围内的代码提交情况:

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.util.io.DisabledOutputStream;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GitStats {

    public static void main(String[] args) throws Exception {
        File repoDir = new File("/path/to/your/git/repo/.git"); // 替换为你的 Git 仓库路径
        Repository repo = new FileRepositoryBuilder().setGitDir(repoDir).build();

        Map<String, UserStats> statsMap = new HashMap<>();

        try (Git git = new Git(repo) ) {
            Iterable<RevCommit> commits = git.log().call();

            for (RevCommit commit : commits) {
                if (commit.getAuthorIdent().getWhen().after(/* your start date */) &&
                    commit.getAuthorIdent().getWhen().before(/* your end date */)) {

                    String author = commit.getAuthorIdent().getName();
                    UserStats userStats = statsMap.getOrDefault(author, new UserStats());

                    userStats.commitCount++;
                    
                    try (DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE)) {
                        diffFormatter.setRepository(repo);
                        List<DiffEntry> diffs = diffFormatter.scan(commit.getParent(0), commit);
                        for (DiffEntry diff : diffs) {
                            userStats.addedLines += diff.getInsertions();
                            userStats.deletedLines += diff.getDeletions();
                        }
                    }
                    statsMap.put(author, userStats);
                }
            }
        }

        for (Map.Entry<String, UserStats> entry : statsMap.entrySet()) {
            System.out.println("Author: " + entry.getKey());
            System.out.println("Commits: " + entry.getValue().commitCount);
            System.out.println("Added lines: " + entry.getValue().addedLines);
            System.out.println("Deleted lines: " + entry.getValue().deletedLines);
        }
    }

    static class UserStats {
        int commitCount;
        int addedLines;
        int deletedLines;
    }
}

注意:

  1. 替换 /path/to/your/git/repo/.git 为你的 Git 仓库的路径。
  2. 设置你的开始和结束日期在 commit.getAuthorIdent().getWhen().after(/* your start date */)commit.getAuthorIdent().getWhen().before(/* your end date */)

这个脚本统计了在指定日期范围内每个作者的提交次数,新增行数和删除行数。你可以根据需要进行进一步的修改和优化。

2.2 GitLab 仓库

要获取 GitLab 上指定日期范围内每个作者的提交次数、新增行数和删除行数,你需要首先获取每个提交的详细信息,然后解析每个提交的差异以获取新增和删除的行数。

下面是一个示例,使用 Java 和 GitLab API 来获取这些统计信息:

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class GitLabDetailedStats {

    private static final String GITLAB_URL = "https://gitlab.example.com";
    private static final String PRIVATE_TOKEN = "YOUR_PRIVATE_TOKEN";

    public static void main(String[] args) throws Exception {
        String projectId = "your_project_id"; // 替换为你的项目 ID
        String sinceDate = "2023-01-01"; // 开始日期
        String untilDate = "2023-12-31"; // 结束日期

        Map<String, UserStats> statsMap = new HashMap<>();

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet commitsRequest = new HttpGet(GITLAB_URL + "/api/v4/projects/" + projectId + "/repository/commits?since=" + sinceDate + "&until=" + untilDate);
            commitsRequest.setHeader("PRIVATE-TOKEN", PRIVATE_TOKEN);

            try (CloseableHttpResponse response = httpClient.execute(commitsRequest)) {
                String responseBody = EntityUtils.toString(response.getEntity());
                JSONArray commitsArray = new JSONArray(responseBody);

                for (int i = 0; i < commitsArray.length(); i++) {
                    JSONObject commit = commitsArray.getJSONObject(i);
                    String commitId = commit.getString("id");
                    String authorName = commit.getJSONObject("author").getString("name");

                    UserStats userStats = statsMap.getOrDefault(authorName, new UserStats());

                    HttpGet diffRequest = new HttpGet(GITLAB_URL + "/api/v4/projects/" + projectId + "/repository/commits/" + commitId + "/diff");
                    diffRequest.setHeader("PRIVATE-TOKEN", PRIVATE_TOKEN);
                    try (CloseableHttpResponse diffResponse = httpClient.execute(diffRequest)) {
                        String diffResponseString = EntityUtils.toString(diffResponse.getEntity());
                        JSONArray diffArray = new JSONArray(diffResponseString);
                        for (int j = 0; j < diffArray.length(); j++) {
                            JSONObject diff = diffArray.getJSONObject(j);
                            userStats.addedLines += diff.getInt("additions");
                            userStats.deletedLines += diff.getInt("deletions");
                        }
                    }

                    userStats.commitCount++;
                    statsMap.put(authorName, userStats);
                }
            }
        }

        for (Map.Entry<String, UserStats> entry : statsMap.entrySet()) {
            System.out.println("Author: " + entry.getKey());
            System.out.println("Commits: " + entry.getValue().commitCount);
            System.out.println("Added lines: " + entry.getValue().addedLines);
            System.out.println("Deleted lines: " + entry.getValue().deletedLines);
        }
    }

    static class UserStats {
        int commitCount;
        int addedLines;
        int deletedLines;
    }
}

注意:

  1. 替换 GITLAB_URLPRIVATE_TOKEN 和其他相关配置为你的实际值。
  2. 这个脚本可能会发出大量的 HTTP 请求,特别是当你有很多提交时。为了避免 GitLab API 的速率限制,你可能需要在请求之间添加适当的延迟或考虑其他优化策略。

3. Python实现

Python也可以轻松地调用子进程。我们可以使用subprocess模块来实现。

以下是使用Python实现统计Git代码提交情况的完整代码:

import subprocess

def git_stats(repo_path):
    # 获取所有贡献者
    cmd_authors = ["git", "log", "--format='%aN'", "--no-merges"]
    authors_output = subprocess.Popen(cmd_authors, cwd=repo_path, stdout=subprocess.PIPE).communicate()[0].decode()
    unique_authors = set(authors_output.splitlines())

    stats = {}

    for author in unique_authors:
        # 统计每个贡献者的提交次数
        cmd_commits = ["git", "shortlog", "-s", "-n", "--author=" + author]
        commits_output = subprocess.Popen(cmd_commits, cwd=repo_path, stdout=subprocess.PIPE).communicate()[0].decode()
        commit_count = int(commits_output.strip().split()[0])

        # 统计每个贡献者的新增和删除行数
        cmd_lines = ["git", "log", "--numstat", "--author=" + author, "--pretty=tformat:", "--no-merges"]
        lines_output = subprocess.Popen(cmd_lines, cwd=repo_path, stdout=subprocess.PIPE).communicate()[0].decode()

        added, deleted = 0, 0
        for line in lines_output.splitlines():
            if '\t' in line:
                a, d, _ = line.split('\t')
                added += int(a)
                deleted += int(d)

        stats[author] = {"commits": commit_count, "added": added, "deleted": deleted}

    return stats

if __name__ == "__main__":
    repo = "/path/to/repo"  # 修改为你的仓库路径
    statistics = git_stats(repo)

    for author, data in statistics.items():
        print(f"Author: {author}")
        print(f"Commits: {data['commits']}")
        print(f"Added lines: {data['added']}")
        print(f"Deleted lines: {data['deleted']}")
        print("-------------------------")

这段代码首先会获取仓库中所有的贡献者,然后对每个贡献者分别统计他们的提交次数、新增行数和删除行数。

为了运行这段代码,你需要确保你的Python环境已经设置好,并且你的机器上已经安装了Git命令行工具。

4. Go语言实现

Go语言也提供了调用子进程的功能,我们可以使用os/exec包来实现。

demo:

package main

import (
	"os/exec"
	"fmt"
)

func GitStats(repoPath string) {
	cmd := exec.Command("git", "shortlog", "-s", "-n")
	cmd.Dir = repoPath
	out, err := cmd.Output()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(out))
}

func main() {
	GitStats("/path/to/repo")
}

以下是使用Go语言实现统计Git代码提交情况的完整代码:

package main

import (
	"os/exec"
	"fmt"
	"strings"
)

func GitStats(repoPath string) {
    // 获取所有贡献者
	cmdAuthors := exec.Command("git", "log", "--format=%aN", "--no-merges")
	cmdAuthors.Dir = repoPath
	authorsOutput, err := cmdAuthors.Output()
	if err != nil {
		fmt.Println(err)
		return
	}
	uniqueAuthors := removeDuplicates(strings.Split(string(authorsOutput), "\n"))

	stats := make(map[string]map[string]int)

	for _, author := range uniqueAuthors {
		// 统计每个贡献者的提交次数
		cmdCommits := exec.Command("git", "shortlog", "-s", "-n", "--author=" + author)
		cmdCommits.Dir = repoPath
		commitsOutput, err := cmdCommits.Output()
		if err != nil {
			fmt.Println(err)
			return
		}
		commitCount, _ := strconv.Atoi(strings.TrimSpace(strings.Split(string(commitsOutput), "\t")[0]))

		// 统计每个贡献者的新增和删除行数
		cmdLines := exec.Command("git", "log", "--numstat", "--author=" + author, "--pretty=tformat:", "--no-merges")
		cmdLines.Dir = repoPath
		linesOutput, err := cmdLines.Output()
		if err != nil {
			fmt.Println(err)
			return
		}

		added, deleted := 0, 0
		for _, line := range strings.Split(string(linesOutput), "\n") {
			if strings.Contains(line, "\t") {
				parts := strings.Split(line, "\t")
				add, _ := strconv.Atoi(parts[0])
				del, _ := strconv.Atoi(parts[1])
				added += add
				deleted += del
			}
		}

		stats[author] = map[string]int{"commits": commitCount, "added": added, "deleted": deleted}
	}

	for author, data := range stats {
		fmt.Println("Author:", author)
		fmt.Println("Commits:", data["commits"])
		fmt.Println("Added lines:", data["added"])
		fmt.Println("Deleted lines:", data["deleted"])
		fmt.Println("-------------------------")
	}
}

func removeDuplicates(elements []string) []string {
    encountered := map[string]bool{}
    result := []string{}

    for v := range elements {
        if encountered[elements[v]] == true {
        } else {
            encountered[elements[v]] = true
            result = append(result, elements[v])
        }
    }

    return result
}

func main() {
	GitStats("/path/to/repo")
}

这段Go代码首先获取仓库中所有的贡献者,然后对每个贡献者分别统计他们的提交次数、新增行数和删除行数。你可以将这段代码保存为git_stats.go,然后使用go run git_stats.go命令运行它。确保你已经设置好Go环境并安装了Git命令行工具。

🔥 总结

不同的编程语言提供了各自的方法来调用子进程,这使得我们可以灵活地使用Git命令来统计代码提交情况。无论你是bash、Java、Python还是Go开发者,都可以根据自己的需求选择合适的方法。

📚 参考资料

  • Git官方文档
  • Java ProcessBuilder官方文档
  • Python subprocess官方文档
  • Go os/exec官方文档

感谢大家阅读,如果有任何问题或建议,欢迎留言交流!🐱🐅🚀🌟🔥📚

在这里插入图片描述

原创声明

======= ·

  • 原创作者: 猫头虎

作者wx: [ libin9iOak ]

学习复习

本文为原创文章,版权归作者所有。未经许可,禁止转载、复制或引用。

作者保证信息真实可靠,但不对准确性和完整性承担责任

未经许可,禁止商业用途。

如有疑问或建议,请联系作者。

感谢您的支持与尊重。

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

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

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

相关文章

AP5193 DC-DC降压恒流驱动器 大功率宽电压LED驱动IC

产品描述 AP5193是一款PWM工作模式,高效率、简单、内置功率MOS管&#xff0c;适用于4.5-100V输入的高精度降压LED恒流驱动芯片。电流2.5A。AP5193可实现线性调光和PWM调光&#xff0c;线性调光脚有效电压范围0.55-2.6V.AP5193 工作频率可以通过RT 外部电阻编程来设定&#xff…

ffprobe命令

查看一个音频文件&#xff0c;在终端命令行输入一下命令 ffprobe video/audio.m4a 可以看到audio.m4a这个文件的所有信息。 Duration&#xff1a;音频总时长&#xff1a;开始播放时间&#xff1a;比特率 Stream&#xff1a;说明是一个音频流&#xff0c;编码格式是aac&…

珠宝饰品商家为什么要做微信小程序开发

珠宝饰品商家为什么要做微信小程序开发&#xff1f; 随着互联网的发展&#xff0c;微信小程序作为一种新型的应用形态&#xff0c;正逐渐成为商家们关注的热点。对于珠宝饰品商家来说&#xff0c;开发微信小程序具有以下几个方面的优势&#xff1a; 一、获取更多流量 微信小程…

浅谈霍尔传感器在电子设备中的应用

安科瑞虞佳豪壹捌柒陆壹伍玖玖零玖叁 0摘 要&#xff1a;本文介绍了霍尔传感器的原理、应用和发展情况&#xff0c;详细讨论了其在电子设备中的应用。霍尔传感器在电子设备中具有高精度、高灵敏度、高稳定性等特点&#xff0c;可以应用于磁场测量、位置检测、电流检测等多个领…

zookeeper入门篇之分布式锁

文章目录 前言非公平锁公平锁 前言 上一篇说过&#xff0c;zookeeper是一个类似文件系统的数据结构&#xff0c;每个节点都可以看做是一个文件目录&#xff0c;也就是说&#xff0c;我们所创建的节点是唯一的&#xff0c;那么分布式锁的原理就是基于这个来的。 代码仓库&…

196、管理 RabbitMQ 的用户

开启Rabbitmq的一些命令&#xff1a; 小黑窗输入&#xff1a; rabbitmq-plugins enable rabbitmq_management 启动控制台插件&#xff0c; 就是启动登录rabbitmq控制台的页面&#xff0c;rabbitmq_management 代表了RabbitMQ的管理界面。 rabbitmq-server 启动rabbitMQ服务器…

NoSQL Redis

NoSQL Redis 1、数据库1.1关系型数据库1.2非关系型数据库1.3关系型和非关系型区别 2、非关系型数据库应用场景3、存储结构4、redis4.1redis概述4.2Redis 优点4.3Redis为什么这么快&#xff1f; 5、部署redis6、redis基础操作 1、数据库 1.1关系型数据库 关系型数据库是一个结…

房地产行业如何有效进行软文推广?

对于房地产行业来说&#xff0c;软文营销是常见的营销方式&#xff0c;也有不少地产行业来找媒介盒子进行软文推广&#xff0c;和传统的硬广相比&#xff0c;软文成本更低&#xff0c;而且效果是持续性的&#xff0c;那么房地产行业如何有效进行软文推广呢&#xff1f;接下来就…

Stable Diffusion生成图片

画质 masterpiece,best quality,illustration,extremely detail CG unity 8k wallpaper,ultra-detailed,depth of field 杰作&#xff0c;最佳质量&#xff0c;插图&#xff0c;极度详细的8K壁纸&#xff0c;超高详细度&#xff0c;景深 画风 Chinese ink painting,water color…

一文弄懂 if __name__ == “__main__“:(洒洒水啦!)

本篇文章是博主在AI、无人机、强化学习等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在AI学…

C#练习题-构造函数

文章目录 前言题目习题1运行示例 习题2运行示例 参考答案习题1习题2 其他文章 前言 本篇文章的题目为C#的基础练习题&#xff0c;构造函数部分。做这些习题之前&#xff0c;你需要确保已经学习了构造函数的知识。 本篇文章可以用来在学完构造函数后加深印象&#xff0c;也可以…

在JavaScript中,什么是生成器函数(generator function)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 生成器函数概述⭐ 生成器函数的作用⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域…

嵌入式开发系统中的加密性能:第1部分

嵌入式系统上的密码学基础密码术是处理数据的艺术和科学&#xff0c;因此外部团体在没有任何秘密的情况下就无法撤消或模仿该操作。它启用了高级功能&#xff0c;例如&#xff1a; 存储和传输期间信息的机密性 用户身份验证 接收/检索的信息的完整性 不可否认交易的 有效性…

美女制服扮演建模法-UMLChina建模知识竞赛第4赛季第13轮

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 只要最先答对前3题&#xff0c;即可获得本轮优胜。第4题为附加题&#xff0c;对错不影响优胜者…

2023年中国家用路由器市场发展概况分析:家用路由器线上市场整体销量为1050.6万台[图]

在疫情过后的第一个半年度&#xff0c;已经连续三年规模下滑幅度超过15%的家用路由器行业&#xff0c;终于迎来一丝回暖迹象。2023年上半年&#xff0c;我国家用路由器线上市场整体销量为1051万台&#xff0c;同比下降5.5%&#xff0c;下降幅度开始收窄&#xff0c;销售额为24.…

为什么短视频离不开美颜SDK?短视频领域的秘密武器

在当今的社交媒体时代&#xff0c;短视频已经成为了人们获取信息、娱乐和社交的重要方式。无论是抖音、快手&#xff0c;还是Instagram、TikTok&#xff0c;短视频都以其独特的魅力吸引着数亿用户。而在这些短视频的背后&#xff0c;有一款名为“美摄美颜SDK”的秘密武器&#…

【Leetcode】 51. N 皇后

按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。 每一种…

iOS App上架全流程及相关处理

iOS app上架总体流程&#xff1a; 一、IOS上架整个流程 1、申请开发者账号 2、创建APP ID及申请证书 3、itunes connect 创建APP 4、打包 上传APP 5、提交APP&#xff0c;上线成功 1、申请开发者账号 苹果开发者账号主要分为三种&#xff1a;个人账号、公司账号、企业账…

导致 JVM 内存泄露的 ThreadLocal 详解

为什么要有 ThreadLocal 当我们在学习JDBC时获取数据库连接时&#xff0c;每次CRUD的时候都需要再一次的获取连接对象&#xff0c;并把我们的sql交给连接对象实现操作。 在实际的工作中&#xff0c;我们不会每次执行 SQL 语句时临时去建立连接&#xff0c;而是会借助数据库连接…

Android用户登录与数据存储:从权限请求到内外部存储的完整实践【完整实践步骤、外部存储、内部存储】

步骤 1: 登录页面布局 在 MainActivity 中实现用户登录功能&#xff0c;首先创建一个布局文件 activity_main.xml 包含用户名和密码的输入字段以及登录按钮。 <!-- activity_main.xml --> <LinearLayoutxmlns:android"http://schemas.android.com/apk/res/andr…