vue+springboot读取git的markdown文件并展示

前言

最近,在研究一个如何将我们git项目的MARKDOWN文档获取到,并且可以展示到界面通过检索查到,于是经过几天的摸索,成功的研究了出来

本次前端vue使用的是Markdown-it

Markdown-it 是一个用于解析和渲染 Markdown 标记语言的 JavaScript 库。
它采用模块化的设计,提供了灵活的配置选项和丰富的插件系统,使开发者可以根据自己的需要定制 Markdown 的解析和渲染过程。

使用 Markdown-it,你可以将 Markdown 文本解析为 HTML 输出,并且可以根据需要添加功能、扩展语法或修改解析行为

后端springboot使用JGit

JGit 是一个开源的 Java 实现的 Git 客户端库,它允许开发者在 Java 程序中直接操作 Git 仓库。

JGit 提供了一些核心的 API,使开发者可以使用 Java 代码来访问和操作 Git 仓库,例如创建仓库、提交变更、分支管理、标签管理、克隆远程仓库等。它提供了对 Git 分布式版本控制系统的完整支持,能够满足日常的代码版本管理需求。

但是我们这里单纯只是将其获取git的文件进行展示markdown,因此并用不上

准备工作

前端

在前端,
我使用了element-ui前端框架写页面
使用Markdown-it 进行解析markdown
使用axios连接了前后端
因此,需要安装如上依赖,指令如下:

npm i element-ui
npm i markdown-it
npm i axios

后端

因后端为springboot项目,需要安装springboot的依赖,这里不多赘述,主要是需要安装JGit的依赖

<dependency><groupId>org.eclipse.jgit</groupId><artifactId>org.eclipse.jgit</artifactId><version>5.9.0.202009080501-r</version>
</dependency>

效果演示

那么,在说如何做之前,先介绍一下我做出来的效果吧

首先,我建立了一个git仓库 ,专门用于获取到markdown文件

在这里插入图片描述

为了程序能够获取到文件,我在data文件夹下放了四个markdown文件,并且在程序指定只获取data下的markdown文件

  • 无数据时,前端界面显示如下
    在这里插入图片描述

当什么关键字都不输入,检索全部markdown文件

在这里插入图片描述
此时展示文件

此时随便点击列表的一个文件查看

在这里插入图片描述

切换另一个
在这里插入图片描述
在这里插入图片描述

以上,我们能够发现,它能够把我们的markdown的表格,图片以及表情正确的显示出来,并且样式排版也过得去,当然,这个是可以自己调整的

多提一句,我有做一个简单的检索关键字的逻辑,逻辑如下:

  1. 什么关键字不输入的时候,检索指定文件夹下所有markdown
  2. 当输入关键字,检索文件名,如果包含关键字,则把文件路径加入集合列表
  3. 当文件名不包含关键字,判断文件内容是否包含关键字,包含也把对应文件路径加入列表

前端代码逻辑

界面部分

<template><div><el-page-header content="MarkDown展示"/><el-input v-model="searchKey" placeholder="检索问题" style="position: relative;;width: 70%;left: 0%"></el-input><el-button @click="searchProblem" type="primary" plain style="margin: 10px;">检索</el-button><el-card><el-table :data="searchData" style="width: 100%;font-size: 20px; max-height: 500px; overflow-y: auto;background-color: white;"><el-table-column type="index" label="序号"></el-table-column><el-table-column label="列表项"><template slot-scope="scope"><span>{{ changePathName(scope.row )}}</span></template></el-table-column><el-table-column label="操作"><template slot-scope="scope"><div><el-button type="primary" size="medium" @click="findMarkDown(scope.row)" style="font-size: 24px;">查看</el-button></div></template></el-table-column></el-table></el-card><!-- 展示区 --><el-card style="position: relative;width: 100%;overflow-x: auto;" header="MarkDown处理文档"><div style="position: relative;"><el-card style="background-color:rgb(255, 253, 245);padding: 32px;" v-if="htmlContent"><div v-html="htmlContent" class="v-md-header"></div></el-card><el-card style="background-color:rgb(255, 253, 245);padding: 32px;" v-else><div style="position: absolute;left:46.5%;text-align: center;line-height: 0px;font-weight: bold;">请检索并查看文档</div></el-card></div></el-card></div></template>

JavaScript逻辑

<script>
// 封装的axios调用后端的方法,如需要则按照自己的项目调用修改即可import {searchProblem,findMarkDownBypath} from "../ajax/api"import MarkdownIt from 'markdown-it';export default {name: "MarkDown",data() {return {searchKey: "",searchData: [], // 检索到的问题列表markdownText: '', // 加载好图片的Markdown文本markdownRenderer: null, // 解析markdown渲染器定义htmlContent: '', // 解析为html}},mounted() {this.markdownRenderer = new MarkdownIt();},methods: {// 检索文件searchProblem() {searchProblem(this.searchKey).then(res => {console.log("检索数据:",res);this.searchData = res.data.data; // 赋值检索数据,注意这里的res.data.data请根据自己实际回参更改获取参数this.markdownText = ""; // 每次检索清空markdown显示文档内容this.htmlContent = ""; // 每次检索清空markdown显示文档内容})},// 根据文件路径查找markdown文件findMarkDown(path) {console.log("path:",path);findMarkDownBypath(path).then(res => {console.log("markdown内容:",res);this.markdownText = res.data.data;this.htmlContent = this.markdownRenderer.render(this.markdownText);console.log(this.htmlContent);})},// 处理字符串,回传的参数实际为:data/学生成绩系统前端.md,将字符串进行截取changePathName(str) {if (str) {var lastIndex = str.lastIndexOf('/');var result = str.substring(lastIndex + 1);return result.replace('.md','');}return str;}}}</script>

在以上,后端传递的路径实际为:

["data/README.en.md","data/README.md","data/学生成绩系统前端.md","data/网上购药商城.md"
]

因此为了美观和直观展示,我是有做字符处理的,详情参考如何代码

此外,我后端获取到的markdown的内容实际数据为:

# search_markdown_data#### Description
用于检索markdown的数据来源#### Software Architecture
Software architecture description#### Installation1.  xxxx
2.  xxxx
3.  xxxx#### Instructions1.  xxxx
2.  xxxx
3.  xxxx#### Contribution1.  Fork the repository
2.  Create Feat_xxx branch
3.  Commit your code
4.  Create Pull Request#### Gitee Feature1.  You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2.  Gitee blog [blog.gitee.com](https://blog.gitee.com)
3.  Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4.  The most valuable open source project [GVP](https://gitee.com/gvp)
5.  The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6.  The most popular members  [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

我的代码中,使用markdown-it创建渲染器,将如上数据转换为:

<h1>search_markdown_data</h1>
<h4>Description</h4>
<p>用于检索markdown的数据来源</p>
<h4>Software Architecture</h4>
<p>Software architecture description</p>
<h4>Installation</h4>
<ol>
<li>xxxx</li>
<li>xxxx</li>
<li>xxxx</li>
</ol>
<h4>Instructions</h4>
<ol>
<li>xxxx</li>
<li>xxxx</li>
<li>xxxx</li>
</ol>
<h4>Contribution</h4>
<ol>
<li>Fork the repository</li>
<li>Create Feat_xxx branch</li>
<li>Commit your code</li>
<li>Create Pull Request</li>
</ol>
<h4>Gitee Feature</h4>
<ol>
<li>You can use Readme_XXX.md to support different languages, such as Readme_en.md, Readme_zh.md</li>
<li>Gitee blog <a href="https://blog.gitee.com">blog.gitee.com</a></li>
<li>Explore open source project <a href="https://gitee.com/explore">https://gitee.com/explore</a></li>
<li>The most valuable open source project <a href="https://gitee.com/gvp">GVP</a></li>
<li>The manual of Gitee <a href="https://gitee.com/help">https://gitee.com/help</a></li>
<li>The most popular members  <a href="https://gitee.com/gitee-stars/">https://gitee.com/gitee-stars/</a></li>
</ol>

实际为html的数据,因此,我们就可以在界面使用vue的v-html展示markdown的内容

css样式

以上我们知道它会将数据转为html的数据,因此,就可以使用css样式调整,以下为我的css样式,供参考:

h1 {color: #ff0000;}p {font-size: 16px;line-height: 1.5;}.v-md-header {text-align: left !important;}table {border-collapse: collapse;width: 100%;}th, td {border: 1px solid black;padding: 8px;}th {background-color: #f2f2f2; /* 设置表头的背景颜色 */}tr:nth-child(even) {background-color: #dddddd; /* 设置偶数行的背景颜色 */}tr:hover {background-color: #f5f5f5; /* 设置鼠标悬停时的背景颜色 */}h1,h2,h3,h4,h5{border-bottom: 1px #d8d6d6 solid;}img{width: 80%;}

后端代码逻辑

先说下我的查询的方法,JGIT我尝试了很久,都只能通过先克隆到本地,再读取的方式,于是放弃了研究如何使用JGIT在线读取文件的方式,也许后面我可能研究的出来。

同样,为了保证每次都是最新的文档,我采用了判断是否已经克隆下来了,如果克隆了则更新代码,没有克隆则克隆,来保证每次都是最新代码

在正式执行前,我们需要先定义好需要的参数

// 解析markdown图片正则private static final String MARKDOWN_IMAGE_PATTERN = "(!\\[[^\\]]*\\])\\(([^\\)]+)\\)";
// 需要克隆git到本机的路径private final String LOCAL_PATH = "E:\\git\\markdown";
// 需要获取markdown的git链接private final String GIT_PATH = "https://gitee.com/spring-in-huangxian-county/search_markdown_data.git";
// 需要获取的git分支private final String GIT_BRANCH = "master";
// 需要抓取的Git内指定文件夹的markdownprivate final String MARK_DOWN_PATH = "data";
// 当前后端项目的位置,该目的是为了能够找到正确的文件路径private final String PROJECT_PATH = "F:\\gitee\\search_markdown_end";

查询

controller层

    @GetMapping("/searchProblem")public ResultVO<List<String>> searchMarkdown(@RequestParam("searchKey") String searchKey)throws Exception {// 获取Git仓库中的Markdown文档列表try {List<String> markdownFiles = new MarkDownService().getGitDataFilePath();List<String> results = new ArrayList<>();if (StringUtils.isEmpty(searchKey)) {results.addAll(markdownFiles);} else {for (String path:markdownFiles) {// 如果标题包含检索关键字加入列表if (path.contains(searchKey)) {results.add(path);} else {// 判断具体内容是否包含关键字,是则加入列表if (new MarkDownService().isContainSearchKeyForContent(searchKey,path)) {results.add(path);}}}}return new ResultVO<>(0,"OK",results);}catch (Exception e) {return new ResultVO<>(1,e.getMessage());}}

ResultVO为封装的响应体,如有兴趣可参考我之前文章
MarkDownService为service层文件名

service层

克隆和拉取git的方式读取文件,获取文件路径

    // 克隆和拉取git的方式读取文件public List<String> getGitDataFilePath() throws Exception {File localPath = new File(LOCAL_PATH);String remoteUrl = GIT_PATH;String branchName =GIT_BRANCH; // 或者其他分支名称String folderPath = MARK_DOWN_PATH; // data文件夹的路径List<String> markDownFilePathList = new ArrayList<>();Repository repository;if (localPath.exists()) {repository = openLocalRepository(localPath);pullLatestChanges(repository);} else {repository = cloneRepository(localPath, remoteUrl);}try (Git git = new Git(repository)) {Iterable<RevCommit> commits = git.log().add(repository.resolve(branchName)).call();RevCommit commit = commits.iterator().next();try (RevWalk revWalk = new RevWalk(repository)) {RevTree tree = revWalk.parseTree(commit.getTree());try (TreeWalk treeWalk = new TreeWalk(repository)) {treeWalk.addTree(tree);treeWalk.setRecursive(true);while (treeWalk.next()) {if (treeWalk.getPathString().startsWith(folderPath) && treeWalk.getPathString().endsWith(".md")) {System.out.println("Found markdown file: " + treeWalk.getPathString());// 这里可以根据需要进行具体的处理,比如读取文件内容等markDownFilePathList.add(treeWalk.getPathString());}}}}} catch (IOException | GitAPIException e) {e.printStackTrace();}return markDownFilePathList;}

打开本地git

    // 打开本地git项目private Repository openLocalRepository(File localPath) throws IOException {System.out.println("Opening existing repository...");Git git = Git.open(localPath);return git.getRepository();}

克隆代码

    // 克隆gitprivate Repository cloneRepository(File localPath, String remoteUrl) throws GitAPIException {System.out.println("Cloning repository...");Git git = Git.cloneRepository().setURI(remoteUrl).setDirectory(localPath).call();return git.getRepository();}

拉取最新代码

    //拉取git最新代码private void pullLatestChanges(Repository repository) throws GitAPIException {System.out.println("Pulling latest changes...");Git git = new Git(repository);PullCommand pull = git.pull().setTimeout(30);pull.call();}

检查文件内容是否包含关键字

    /*** @param searchKey 检索关键字* @param path markdown文本路径* @desc 通过关键字和路径找到指定markdown文件是否内容包含关键字* */public Boolean isContainSearchKeyForContent(String searchKey,String path) {Boolean containFlag = false;String content ="";try {content =  findMarkDownBypathNoWithImage(path);}catch (Exception e) {System.out.println("获取markdown文本失败:"+e.getMessage());}if (content.contains(searchKey)) {containFlag = true;}return containFlag;}

要判断文件内容是否包含关键字,不需要将文件图片进行解析,直接获取文件内容

    public String findMarkDownBypathNoWithImage(String filePath) throws Exception{String localPath = LOCAL_PATH;String markDownContent = "";if (filePath.endsWith(".md")) {File markdownFile = new File(localPath, filePath);try (Scanner scanner = new Scanner(markdownFile)) {StringBuilder contentBuilder = new StringBuilder();while (scanner.hasNextLine()) {contentBuilder.append(scanner.nextLine()).append("\n");}markDownContent = contentBuilder.toString();System.out.println("Markdown file content:\n" + markDownContent);} catch (IOException e) {throw new Exception(e.getMessage());}}return markDownContent;}

根据路径获取文件

以下为会解析图片的方式进行获取文件

controller层

    @GetMapping("findMarkDownBypath")public ResultVO<String> findMarkDownBypath(@RequestParam("path")String path) throws Exception {try {return new ResultVO<>(new MarkDownService().findMarkDownBypathWithImage(path));}catch (Exception e) {return new ResultVO<>(1,e.getMessage());}}

service层

    public String findMarkDownBypathWithImage(String filePath) throws Exception{String localPath = LOCAL_PATH;String markDownContent = "";if (filePath.endsWith(".md")) {File markdownFile = new File(localPath, filePath);try (Scanner scanner = new Scanner(markdownFile)) {StringBuilder contentBuilder = new StringBuilder();while (scanner.hasNextLine()) {contentBuilder.append(scanner.nextLine()).append("\n");}String markdownContent = contentBuilder.toString();markDownContent = loadImages(markdownContent,filePath);// 在这里得到了具体的markdown文件内容System.out.println("Markdown file content:\n" + markdownContent);} catch (IOException e) {throw new Exception(e.getMessage());}}return markDownContent;}

解析图片

    public  String loadImages(String markdownContent, String markdownFilePath) {Pattern pattern = Pattern.compile(MARKDOWN_IMAGE_PATTERN);Matcher matcher = pattern.matcher(markdownContent);String localPath = LOCAL_PATH;StringBuffer sb = new StringBuffer();while (matcher.find()) {String originalImageTag = matcher.group(0);String altText = matcher.group(1);String imagePath = matcher.group(2);try {String absoluteImagePath = getAbsoluteImagePath(imagePath, markdownFilePath);absoluteImagePath = absoluteImagePath.replace(PROJECT_PATH,localPath);String imageData = loadImage(absoluteImagePath);String transformedImageTag = "![Image](" + imageData + ")";matcher.appendReplacement(sb, transformedImageTag);} catch (IOException e) {// 图像加载出错,可以根据实际需求进行处理e.printStackTrace();}}matcher.appendTail(sb);return sb.toString();}
    public static String loadImage(String imagePath) throws IOException {File imageFile = new File(imagePath);// 读取图像文件的字节数组byte[] imageData = FileUtils.readFileToByteArray(imageFile);// 将字节数组转换为Base64编码字符串String base64ImageData = java.util.Base64.getEncoder().encodeToString(imageData);return "data:image/png;base64," + base64ImageData;}
    public static String getAbsoluteImagePath(String imagePath, String markdownFilePath) {File markdownFile = new File(markdownFilePath);String markdownDirectory = markdownFile.getParent();String absoluteImagePath = new File(markdownDirectory, imagePath).getAbsolutePath();return absoluteImagePath;}

依赖

为了防止出现依赖可能缺失的情况,可参考我的项目的maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><modelVersion>4.0.0</modelVersion><groupId>org.hxc.common</groupId><artifactId>CommonBack</artifactId><version>1.0</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><mysql.version>5.1.47</mysql.version><druid.version>1.1.16</druid.version><log4j2.version>2.17.0</log4j2.version><mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.2.2.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version><optional>true</optional></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.8</version></dependency>
<!--        swagger--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version><exclusions><exclusion><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId></exclusion><exclusion><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>1.5.21</version></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>1.5.21</version></dependency><!--        swagger的ui--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.9</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.5</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.spring.boot.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!-- pagehelper --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.5</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.15.0</version></dependency><!--    文件处理--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><!--   POI excel处理依赖     --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.9</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.9</version></dependency><!--   工具类     --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.3.8</version></dependency>
<!--        <dependency>-->
<!--            <groupId>org.eclipse.jgit</groupId>-->
<!--            <artifactId>org.eclipse.jgit</artifactId>-->
<!--            <version>4.4.1.201607150455-r</version>-->
<!--        </dependency>--><dependency><groupId>org.eclipse.jgit</groupId><artifactId>org.eclipse.jgit</artifactId><version>5.9.0.202009080501-r</version></dependency></dependencies><build><finalName>common_end</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.1.0</version><configuration><archive><manifest><addClasspath>true</addClasspath><mainClass>com.hxc.common.MarkDownApplication</mainClass><classpathPrefix>libs/</classpathPrefix></manifest></archive></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>3.1.0</version><executions><execution><id>copy-dependencies</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/libs</outputDirectory></configuration></execution></executions></plugin><!--跳过junit--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><skip>true</skip></configuration></plugin></plugins></build></project>

git

以下为我实现读取git的markdown的项目,可供参考

前端

后端

结语

以上为我实现vue+springboot读取git的markdown文件并展示的过程

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

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

相关文章

Cache学习(3):Cache地址映射(直接映射缓存组相连缓存全相连缓存)

1 Cache的与存储地址的映射 以一个Cache Size 为 128 Bytes 并且Cache Line是 16 Bytes的Cache为例。首先把这个Cache想象成一个数组&#xff0c;数组总共8个元素&#xff0c;每个元素大小是 16 Bytes&#xff0c;如下图&#xff1a; 现在考虑一个问题&#xff0c;CPU从0x0654…

城市生命线丨桥梁结构健康监测系统的作用

在城市建设当中&#xff0c;有非常多的城市基本建设&#xff0c;建设当中&#xff0c;桥梁作为不可忽视的一环&#xff0c;也需要有很多桥梁建设的智能监测系统&#xff0c;在这个桥梁结构健康监测系统中&#xff0c;桥梁的各个数值都能被监测得到。 WITBEE万宾使用城市生命线智…

高并发内存池

1.什么是内存池 内存池动态内存分配与管理技术&#xff0c;对于程序员来说&#xff0c;通常情况下&#xff0c;动态申请内存需要使用new,delete,malloc,free这些API来申请&#xff0c;这样导致的后果是&#xff0c;当程序长时间运行之后&#xff0c;由于程序运行时所申请的内存…

探索 Rollup:简化你的前端构建流程

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Linux 命令vim(编辑器)

(一)vim编辑器的介绍 vim是文件编辑器&#xff0c;是vi的升级版本&#xff0c;兼容vi的所有指令&#xff0c;同时做了优化和延伸。vim有多种模式&#xff0c;其中常用的模式有命令模式、插入模式、末行模式&#xff1a;。 (二)vim编辑器基本操作 1 进入vim编辑文件 1 vim …

排序算法:归并排序、快速排序、堆排序

归并排序 要将一个数组排序&#xff0c;可以先将它分成两半分别排序&#xff0c;然后再将结果合并&#xff08;归并&#xff09;起来。这里的分成的两半&#xff0c;每部分可以使用其他排序算法&#xff0c;也可以仍然使用归并排序&#xff08;递归&#xff09;。 我看《算法》…

电源的纹波

电源纹波的产生 我们常见的电源有线性电源和开关电源&#xff0c;它们输出的直流电压是由交流电压经整流、滤波、稳压后得到的。由于滤波不干净&#xff0c;直流电平之上就会附着包含周期性与随机性成分的杂波信号&#xff0c;这就产生了纹波。 在额定输出电压、电流的情况下…

leetCode 1080.根到叶路径上的不足节点 + 递归 + 图解

给你二叉树的根节点 root 和一个整数 limit &#xff0c;请你同时删除树中所有 不足节点 &#xff0c;并返回最终二叉树的根节点。假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit&#xff0c;则该节点被称之为 不足节点 &#xff0c;需要被删除…

SQL Injection (Blind)`

SQL Injection (Blind) SQL Injection (Blind) SQL盲注&#xff0c;是一种特殊类型的SQL注入攻击&#xff0c;它的特点是无法直接从页面上看到注入语句的执行结果。在这种情况下&#xff0c;需要利用一些方法进行判断或者尝试&#xff0c;这个过程称之为盲注。 盲注的主要形式有…

Python之内置函数和模块

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

基于单片机的可升降助眠婴儿床(论文+源码)

1.系统设计 本课题为基于单片机的可升降助眠婴儿床系统&#xff0c;在设计目标上确定如下&#xff1a; 1. 可以实现婴儿床的升降&#xff0c;摇床功能控制&#xff1b; 2. 具有音乐播放功能&#xff0c;并且有多首曲目&#xff1b; 3. 用户可以通过按键或者红外遥控&#x…

Runloop解析

RunLoop 前言 ​ 本文介绍RunLoop的概念&#xff0c;并使用swift和Objective-C来描述RunLoop机制。 简介 ​ RunLoop——运行循环&#xff08;死循环&#xff09;&#xff0c;它提供了一个事件循环机制在程序运行过程中处理各种事件&#xff0c;例如用户交互、网络请求、定…

Xshell连接VMware虚拟机中的CentOS

Xshell连接VMware虚拟机中的CentOShttps://www.cnblogs.com/niuben/p/13157291.html 步骤&#xff1a; 1. 检查Linux虚拟机的网络连接模式&#xff0c;确保它是NAT模式。&#xff08;由于只在本机进行连接&#xff0c;所以没有选择桥接模式。当然&#xff0c;桥接模式的配置会…

利用ngrok实现内网穿透(全网最详细教程)

准备工具&#xff1a; 1、phpstudy 用于在本地搭建网站 2、ngrok 用于将自己的本地端口暴露到公网上&#xff0c;从而实现内网穿透 文章开始前给大家分享一个学习人工智能的网站&#xff0c;通俗易懂&#xff0c;风趣幽默 人工智能https://www.captainbed.cn/myon/ ~~~~~…

【教学类-06-12】20231126 (一)二位数 如何让加减乘除题目从小到大排序(以1-20之间加法为例,做正序排列用)

结果展示 优化后 优化前 背景需求&#xff1a; 生成列表 单独抽取显示题目排序方法 存在问题: 我希望 00 01 02……这样排序&#xff0c;但是实际上&#xff0c;除了第一个加数会从小到大排序&#xff0c;第二个被加数的第十位数和个位数都会从小到大排序&#xff0c;也就是…

提示工程-Prompt Engineering

提示工程 提示工程 1、概述 Prompt Engineering&#xff1a; 提示工程 通过自然语言&#xff08;英语、汉语等&#xff09;来给AI下达指示&#xff0c;从而让AI完成你指定给他的工作的过程都可以称之为提示工程。&#xff08;面向自然语言编程&#xff09; 提示词要素 指令&…

Spring Web MVC

目录 一.简介 二.建立连接&#xff08;客户端和服务器&#xff09; 三.请求 1.传递单个参数 2.传递多个参数 3.对象 4.数组/集合 5.JSON 6.URL参数 7.上传文件 8.获取cookie和session &#xff08;1&#xff09;获取cookie &#xff08;2&#xff09;获取session …

4D Gaussian Splatting:用于实时的动态场景渲染

Wu G, Yi T, Fang J, et al. 4d gaussian splatting for real-time dynamic scene rendering[J]. arXiv preprint arXiv:2310.08528, 2023. 更多参考资料如下&#xff1a; 文章总结&#xff1a;4D Gaussian Splatting for Real-Time Dynamic Scene Rendering&#xff1b;疑难问…

C#,《小白学程序》第二十一课:大数的减法(BigInteger Subtract)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// </summary> p…

python中模块的创建及引用(import as,import,from)

模块&#xff08;module&#xff09;简介&#xff1a; 1.模块化&#xff0c;模块化指将一个完整的程序分解为一个一个的小模块&#xff0c; 通过将模块组合&#xff0c;来搭建出一个完整的程序 2.不采用模块化就是统一将所有的代码编写到一个文件中&#xff0c;采用 模块化就是…