利用github pages建立Serverless个人博客

利用github pages建立Serverless个人博客

概述

使用github pages,可以在github上部署静态网站。利用这个功能,可以很方便地实现个人博客的发布托管。

比如我的个人博客:Buttering’s Blog

对应代码仓库:buttering/EasyBlog: 自动将本地博客部署到github中展示

相关技术

1. 博客处理

采用go语言对md格式的博客进行处理,主要目的是处理文档中的图片,将其保存在图床,并将文档中的图片链接替换为图床链接。

2. 图床

采用github仓库直接作为图床。图片和博客存放在同一个仓库中。

3. Hexo博客框架

Hexo是一个快速、简洁且高效的博客框架,能很方便地生成静态的博客网站。采用Fluid主题。

4. CI/CD流程

采用github actions,自动实现博客上传后网站的生成和部署。

5. 更多功能

  • 使用hexo-renderer-markdown-it-plus插件,实现对latex的支持。

  • 使用giscus评论插件,利用github discussions实现博客的评论功能。

  • 使用LeanCloud实现访问统计。

  • 展示网站运行时长

实现

0. 项目框架

项目所有文章和图片都位于同一个github仓库中:

image-20240505100150836

  • .github:存放github action的配置文件
  • asset:存放处理后的博客和图片,pictures起到了图床的作用
  • publish:Hexo部署在此子目录
  • resource:存放githubPub公钥
  • tools:一些自己写的工具函数
  • UploadBlogs:实现博客处理和自动push的脚本

1. 博客预处理

对md格式的博客进行预处理,使用正则表达式提取其中的图片路径:

  • 对于本地图片,直接将其拷贝到asset/pictures目录中;
  • 对于网络图片,将其下载在asset/pictures目录中。

在pictures目录中,对文章名和图片进行了哈希处理,如图:

image-20240505100811570

博客则直接按照原文件名放在blogs目录下。

博客中图片的链接会被替换为形如 https://raw.githubusercontent.com/buttering/EasyBlogs/master/asset/pictures/bdf03a9b9bdacaaf60d1f899c0222865/74d51bfa109b4065ccb3ba37b6922bb3.png的url。

raw.githubusercontent.com 是github用来存储用户上传文件的服务地址。

package mainimport ("EasyBlogs/tools""fmt""github.com/go-git/go-git/v5""github.com/go-git/go-git/v5/plumbing/object""github.com/go-git/go-git/v5/plumbing/transport/ssh""io""log""net/http""net/url""os""path""path/filepath""regexp""strings""time"
)type markdownPicture struct {isUrl             boolsourcePicturePath stringstart             int // md中源图片路径的起始偏移量end               inthashName          string // 均将包含后缀的文件名进行hash,且后拼接上原有后缀名targetUrl         string // 修改后在github仓库中的url
}type Blog struct {name          stringhashName      stringpictures      []markdownPicturedirectoryPath string // 源文件文件夹路径legal         bool   // 成功通过解析
}var (BLOG_PATH      stringPICTURE_PATH   stringREPOSITORY_URL string
)func getBlogList(path string) (blogsList []Blog) {blogsList = make([]Blog, 0, 10)fileList, err := os.ReadDir(path)if err != nil {panic(err)}for _, file := range fileList {if !file.IsDir() && filepath.Ext(file.Name()) == ".md" {fileName := file.Name()blogsList = append(blogsList, Blog{fileName, tools.Hash(fileName), nil, path, false})}}return
}func extractPicture(blog *Blog) {isUrl := func(path string) bool {return strings.HasPrefix(path, `http://`) || strings.HasPrefix(path, `https://`)}content, err := os.ReadFile(filepath.Join(blog.directoryPath, blog.name))if err != nil {println(err)return}re, _ := regexp.Compile(`!\[.*?]\((.*?)\)`)matches := re.FindAllSubmatchIndex(content, -1)for _, match := range matches {start := match[2]end := match[3]picturePath := string(content[start:end])var pictureName stringif isUrl(picturePath) {u, err := url.Parse(picturePath)if err != nil {println("解析图片url:", picturePath, " 失败")continue}pictureName = path.Base(u.Path)} else if filepath.IsAbs(picturePath) {pictureName = filepath.Base(picturePath)} else { // 相对路径的本地文件picturePath = filepath.Join(blog.directoryPath, picturePath)pictureName = filepath.Base(picturePath)}hashName := tools.Hash(pictureName) + path.Ext(pictureName)blog.pictures = append(blog.pictures,markdownPicture{isUrl(picturePath),picturePath,start,end,hashName,REPOSITORY_URL + "/" + blog.hashName + "/" + hashName,},)}blog.legal = true
}func copyBlog(blog *Blog) {fmt.Println("拷贝博客:“" + blog.name + "”")blogTargetPath := filepath.Join(BLOG_PATH, blog.name)pictureTargetPath := filepath.Join(PICTURE_PATH, blog.hashName)if _, err := os.Stat(blogTargetPath); !os.IsNotExist(err) {println("文章“" + blog.name + "”已经存在")blog.legal = falsereturn}if err := os.Mkdir(pictureTargetPath, 0777); err != nil {println("为博客“" + blog.name + "”创建对应picture文件夹失败")blog.legal = falsereturn}content, _ := os.ReadFile(filepath.Join(blog.directoryPath, blog.name))offset := 0for _, picture := range blog.pictures {start := picture.start + offsetend := picture.end + offsetcontent = append(content[:start], append([]byte(picture.targetUrl), content[end:]...)...)offset += len(picture.targetUrl) - (end - start)}err := os.WriteFile(blogTargetPath, content, 0644)if err != nil {println("复制文件“" + blog.name + "”错误")blog.legal = false}}func copyPicture(blog Blog) {pictureTargetPath := filepath.Join(PICTURE_PATH, blog.hashName)for _, picture := range blog.pictures {fmt.Println("导入图片:“" + picture.sourcePicturePath + "”")var sourceFile interface{}if picture.isUrl {for i := 0; i < 5; i++ {response, err := http.Get(picture.sourcePicturePath)if err == nil && response.StatusCode == http.StatusOK {sourceFile = response.Bodybreak}time.Sleep(50 * time.Millisecond)}if sourceFile == nil {println("下载图片“" + picture.sourcePicturePath + "”失败")continue}} else {file, err := os.Open(picture.sourcePicturePath)if err != nil {println("打开图片“" + picture.sourcePicturePath + "”失败")continue}sourceFile = file}destinationFile, _ := os.Create(filepath.Join(pictureTargetPath, picture.hashName))_, err := io.Copy(destinationFile, sourceFile.(io.Reader))if err != nil {println("复制图片“" + picture.sourcePicturePath + "”失败")}}
}func gitOperate(blogList []Blog) {if len(blogList) == 0 {return}repositoryPath, _ := filepath.Abs(".")r, err := git.PlainOpen(repositoryPath)if err != nil {println("打开仓库失败")return}w, err := r.Worktree()if err != nil {println("打开仓库失败")println(err.Error())return}_, err = w.Add("./asset")if err != nil {println("向仓库添加文件失败")println(err.Error())return}status, _ := w.Status()println("git 状态:")println(status.String())nameList := tools.Map(blogList, func(blog Blog) string {return blog.name})var summary stringif len(nameList) == 1 {summary = fmt.Sprintf("提交文件 [%s]", blogList[0].name)} else {summary = fmt.Sprintf("提交 %d 个博客\n"+"\n"+"文件列表: [%s]",len(blogList),strings.Join(nameList, ", "),)}commit, err := w.Commit(summary, &git.CommitOptions{Author: &object.Signature{Name: "Wang",When: time.Now(),},})obj, _ := r.CommitObject(commit)fmt.Println("提交文件:")fmt.Println(obj.String())// user必须是"git"。。。困扰了半天,最后查issue发现的。真够郁闷的。privateKey, err := ssh.NewPublicKeysFromFile("git", "./resource/githubPublicKey", "")if err != nil {println(err.Error())}for i := 0; i < 3; i++ {err = r.Push(&git.PushOptions{RemoteName: "origin",RemoteURL:  `git@github.com:buttering/EasyBlogs.git`,Auth:       privateKey,Progress:   os.Stdout,})if err == nil {break}println("第 %d 次上传失败")}if err != nil {println("重试次数已达上限,上传失败")return}fmt.Println("提交成功!")
}func init() {path, _ := filepath.Abs(".")BLOG_PATH = filepath.Join(path, "asset", "blogs")PICTURE_PATH = filepath.Join(path, "asset", "pictures")REPOSITORY_URL = `https://raw.githubusercontent.com/buttering/EasyBlogs/master/asset/pictures`
}func main() {filePath := "E:/desktop/blog"//yamlPath := "./asset/blogs-list.yaml"blogList := getBlogList(filePath)for i := range blogList {extractPicture(&blogList[i])copyBlog(&blogList[i])copyPicture(blogList[i])}if len(blogList) == 0 {return}// 改用github page进行博客部署,不需要额外记录博客信息//yamlOperate(yamlPath, blogList)//dbOperate(blogList)gitOperate(blogList)}

2. 引入Hexo框架

Hexo框架的使用方式很简单,只需使用Hexo CLI建立基本框架,而后将博客和相关资源移入指定文件夹,然后运行Hexo服务器即可。这里为实现Serverless,后两部交由github action实现。

安装Hexo并初始化站点

保证电脑中安装了Node.js。Hexo的部署目录为publish。

npm install -g hexo-cli
nexo init publish
cd publish
npm install

执行后,Hexo会自动在publish目录建立一个空白站点,目录如下:

.
├── _config.yml
├── package.json
├── scaffolds
├── source
|   └── _posts
└── themes
  • _config.yml:站点的配置文件
  • _posts:Hexo会自动将其中的文档转化为静态资源
  • themes:主题文件夹
安装fluid主题

初始的Hexo站点已经很完善了,但是为了更加个性化,安装了fluid主题:配置指南 | Hexo Fluid 用户手册 (fluid-dev.com)

# 仍是在publish目录
npm install --save hexo-theme-fluid

然后在博客目录下创建 _config.fluid.yml,将主题的 _config.yml(位于publish\themes\fluid_config.yml)内容复制进去。这个_config.fluid.yml是主题的覆盖配置,之后要自定义主题,只需修改其中的内容即可。

修改publish下的_config.yml如下:

theme: fluid  # 指定主题
language: zh-CN  # 指定语言,会影响主题显示的语言,按需修改

最后创建主题的关于页

hexo new page about
测试博客

自此,一个本地的博客网站即搭建成功,可以尝试手动将文档移入_post文件夹,而后在命令行内的 publish 文件夹下运行 hexo ghexo s ,就可以在浏览器看到博客。

最后记得使用hexo clean 清空生成的文件,避免影响到后面的部署。

3. github actions配置

在预处理函数的最后一步,实现了git的自动提交和推送。在成功向github推送后,就轮到github action实现博客网站的自动部署了。

配置github仓库

首先将本地的git仓库上传至github,且设置为公开。

进入github 项目的设置页面开启page功能。设置SourceGitHub Actions

image-20240505163116047

编写actions脚本文件

回到本地,在项目根目录创建 .github/workflows/xxx.yml 文件。

这里需要一些github actions的知识,简单地说 Actions 就是在设定的时机触发创建一个虚拟云环境,然后执行一连串动作,从而实现自动部署的功能。

可以直接复制以下内容:

name: Deploy Github# 在master分支发生push事件时触发。
on:push:branches:- masterworkflow_dispatch:jobs:build:runs-on: ubuntu-lateststeps:- name: 检出仓库uses: actions/checkout@v4- name: Install pandocrun: |cd /tmpwget -c https://github.com/jgm/pandoc/releases/download/2.14.0.3/pandoc-2.14.0.3-1-amd64.debsudo dpkg -i pandoc-2.14.0.3-1-amd64.deb- name: 安装Node.js 18uses: actions/setup-node@v4with:node-version: '18'- name: Cache NPM dependenciesuses: actions/cache@v4with:path: node_moduleskey: ${{ runner.OS }}-npm-cacherestore-keys: |${{ runner.OS }}-npm-cache- name: 安装相关依赖working-directory: publishrun: |npm install --silent --no-fundnpm un hexo-renderer-marked --savenpm i hexo-renderer-markdown-it-plus --save- name: 复制博客文件run: |cd publishrm -rf source/_postsmkdir source/_postscp -rf ../asset/blogs/* ./source/_posts/- name: 构建网站working-directory: publishrun: npm run build- name: Upload Pages artifactuses: actions/upload-pages-artifact@v3with:path: ./publish/publicdeploy:needs: buildpermissions:pages: writeid-token: writeenvironment:name: github-pagesurl: ${{ steps.deployment.outputs.page_url }}runs-on: ubuntu-lateststeps:- name: Deploy to GitHub Pagesid: deploymentuses: actions/deploy-pages@v4

github 工作流在完成了环境的初始化后,会自动将位于 asset/blog 中的博客文件复制到 publish/source/_post 目录内。而后的构建步骤,工作流就会利用 _post 目录中的博客文件生成网站。

修改配置

编辑 _config.yml,将 url: 更改为 <你的 GitHub 用户名>.github.io/<repository 的名字>

提交并自动部署

在提交前,记得编辑.gitignore文件:

/resource/githubPublicKey
/publish/node_modules/
/publish/public/

在之后的每次提交,都会触发actions流程,生成站点。部署完成后,前往 https://<你的 GitHub 用户名>.github.io/<repository 的名字> 查看站点。

4. 开启latex功能

hexo默认的渲染器不支持复杂的数学公式。

Latex的渲染分为前端渲染和后端渲染两种方法,这里选择后端渲染,需要更换渲染器(已经在actions脚本中完成了)。

npm un hexo-renderer-marked --save
npm i hexo-renderer-markdown-it-plus --save

修改 _config.fluid.yml

post:math:enable: truespecific: falseengine: katex

使用hexo-renderer-markdown-it-plus插件进行latex渲染时,如果使用mathjax,一些不完全符合md语法的标题会渲染失败(如一级标题前没有空行),因此要将引擎改为katex。

可以参考配置指南 | Hexo Fluid 用户手册 (fluid-dev.com) 和 CHENXCHEN/hexo-renderer-markdown-it-plus

5. 实现评论功能

使用 Giscus插件,且基于 GitHub Discussion实现评论功能。

开启 GitHub Discussion

进入github仓库->Settings->General->Features,勾选 Discussions

image-20240505170039793

安装 Github Apps

点击链接GitHub Apps - giscus ,为本仓库安装应用。

image-20240505170017470

可以到 giscus仓库 检查自己的仓库是否满足giscus要求的条件。

image-20240505170207236

配置插件

由于使用了fluid主题,因此只需修改配置文件即可开启评论。

修改 _config.fluid.yml

  comments:enable: true# 指定的插件,需要同时设置对应插件的必要参数# The specified plugin needs to set the necessary parameters at the same time# Options: utterances | disqus | gitalk | valine | waline | changyan | livere | remark42 | twikoo | cusdis | giscus | discusstype: giscus# Giscus
# 基于 GitHub Discussions,类似于 Utterances
# Based on GitHub Discussions, similar to Utterances
# See: https://giscus.app/
giscus:repo: buttering/EasyBlogrepo-id: category: Announcementscategory-id: theme-light: lighttheme-dark: darkmapping: titlereactions-enabled: 1emit-metadata: 0input-position: bottomlang: zh-CN

在配置基于 Github Discussions 的博客评论系统时(例如 giscus),往往需要获取 repo 的 repo-id, category-id 等属性,因此这里介绍一种获取这些信息的方法

首先打开以下 Github Docs 地址:Github Docs Explorer,然后授权 Github 账户,并输入以下内容

{repository(owner: "userName", name: "repoName") {iddiscussionCategories (first: 5) {nodes {nameid}}}
}
  • userName 换成具体的 Github 用户名;
  • repoName 换成保存评论数据的 Repo 名称。

点击运行按钮,即可得到形如 "id": "R_kgDOKjFfn1"DIC_kwdOJPFfnc4CU9... 就是我们需要的 repoIdcategoryId

因为网站中文章的url是直接使用文章名进行定位的,如 https://buttering.github.io/EasyBlog/2022/10/15/使用plotly离线模式报错UnicodeEncodeError:gbk codec can't encode character in position的解决方法/,如果 mapping: 的值设为 pathname 或者 url,其在 github discussions中出现的标题,中文会被base64字符代替,严重影响观感,设为 title 可以解决这个问题。

6. 实现访问统计

参考Hexo-fluid主题设置统计博客阅读量与评论 - 贾明晖的博客 (minghuijia.cn)

到LeanCloud注册一个免费账户,创建一个开发板应用后,再创建一个Class(依次点击数据存储->结构化存储->创建Class),权限给到最大。

然后在设置->应用凭证里找到AppID与AppKey。

修改 _config.fluid.yml

# 网页访问统计
# Analysis of website visitors
web_analytics:  # 网页访问统计enable: true# LeanCloud 计数统计,可用于 PV UV 展示,如果 `web_analytics: enable` 没有开启,PV UV 展示只会查询不会增加leancloud:app_id: xxxapp_key: xxx# REST API 服务器地址,国际版不填server_url:# 统计页面时获取路径的属性path: window.location.pathname# 开启后不统计本地路径( localhost 与 127.0.0.1 )ignore_local: falsefooter:# 展示网站的 PV、UV 统计数statistics:enable: true

7. 网站运行时长

参考Fluid 页脚增加网站运行时长 - Hexo Theme Fluid (fluid-dev.com)

修改 _config.fluid.yml

footer:content: '<a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a><i class="iconfont icon-love"></i><a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a><div style="font-size: 0.85rem"><span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span><script src="/js/duration.js"></script></div>'

content 前三行是 Fluid 原有的页脚内容,建议不要删除,可稍作修改,保留 Fluid 的超链接,用于向更多人推广主题。

新增的div标签用于实现功能。duration.js 包含的是功能代码,我们在博客目录的 source/js 下创建 duration.js (如果没有js目录,创建即可),

如果直接创建source/js/duration.js 是无效的

针对fluid 1.9.7: 需要将 content<script src="/js/duration.js"> 这行改为 <script src="<项目根目录名>/js/duration.js">,如 <script src="/EasyBlog/js/duration.js"></script>

js文件内容如下:

!(function() {/** 计时起始时间,自行修改 **/var start = new Date("2020/01/01 00:00:00");function update() {var now = new Date();now.setTime(now.getTime()+250);days = (now - start) / 1000 / 60 / 60 / 24;dnum = Math.floor(days);hours = (now - start) / 1000 / 60 / 60 - (24 * dnum);hnum = Math.floor(hours);if(String(hnum).length === 1 ){hnum = "0" + hnum;}minutes = (now - start) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);mnum = Math.floor(minutes);if(String(mnum).length === 1 ){mnum = "0" + mnum;}seconds = (now - start) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);snum = Math.round(seconds);if(String(snum).length === 1 ){snum = "0" + snum;}document.getElementById("timeDate").innerHTML = "本站安全运行&nbsp"+dnum+"&nbsp天";document.getElementById("times").innerHTML = hnum + "&nbsp小时&nbsp" + mnum + "&nbsp分&nbsp" + snum + "&nbsp秒";}update();setInterval(update, 1000);
})();

start 的时间改为自己的时间即可。

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

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

相关文章

Ubuntu20.4部署Cuda12.4

准备Ubuntu20.4 VM 安装Cuda12.4 1.进入如下界面安装安装Cuda12.4版本&#xff1a; CUDA Toolkit 12.4 Update 1 Downloads | NVIDIA Developerhttps://developer.nvidia.com/cuda-downloads?target_osLinux&target_archx86_64&DistributionUbuntu&target_vers…

图像分割各种算子算法-可直接使用(Canny、Roberts、Sobel)

Canny算子&#xff1a; import numpy as np import cv2 as cv from matplotlib import pyplot as pltimg cv.imread("../test_1_1.png") edges cv.Canny(img, 100, 200)plt.subplot(121),plt.imshow(img,cmap gray) plt.title(Original Image), plt.xticks([]), …

TC3xx MTU概述(1)

目录 1.MTU基本功能 2.MBIST 3.小结 1.MTU基本功能 在TC3xx中&#xff0c;MTU(Memory Unit Test)被用来管理控制芯片内部各种RAM的测试、初始化和数据完整性检查。 既然MTU主要是管理和控制&#xff0c;那干活的想必另有他人。所以在该平台中&#xff0c;我们可以看到SRAM…

(Java)心得:LeetCode——19.删除链表的倒数第 N 个节点

一、原题 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&…

C++ 指针 参数 静态 常 友元与组合概念

一 类类型作为函数参数 1 类类型作参数类型的三种方式 1&#xff09; 对象本身作为参数 由于C采用传值的方式传递参数&#xff0c;因此使用对象本身参数时&#xff0c;形参是实参的一个拷贝。在这种情况下&#xff0c;最好显式地为类定义一个拷贝构造函数&#xff0c;以免出…

图论专题训练

leecode 547 并查集 class Solution { public:int findCircleNum(vector<vector<int>>& isConnected) {ini();int len isConnected.size();for(int i0;i<len;i){for(int j0;j<len;j)if(isConnected[i][j]){unio(i,j);}}int ans 0;for(int i0;i<len;…

面试集中营—Redis面试题

一、Redis的线程模型 Redis是基于非阻塞的IO复用模型&#xff0c;内部使用文件事件处理器&#xff08;file event handler&#xff09;&#xff0c;这个文件事件处理器是单线程的&#xff0c;所以Redis才叫做单线程的模型&#xff0c;它采用IO多路复用机制同时监听多个socket&a…

Obsidian/Typora设置图床

在obsidian中默认图片是保存在本地的&#xff0c;但是在要导出文档上传到网上时&#xff0c;由于图片保存在本地&#xff0c;会出现无法加载图片的问题。 这里引用的一段话&#xff1a; 这里使用picgo-core和gitee实现图床功能&#xff0c; 参考1&#xff1a; Ubuntu下PicGO配…

【半个月我拿下了软考证】软件设计师高频考点--系统化教学-关系模式

&#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件设计师考点暴击 ⭐&#x1f170;️进入狂砍分⭐ ⭐软件设计师高频考点文档&#xff0c; ⭐软件设计师高频考点专栏 ⭐软件设计师高频考点⭐ &#x1f3b6;&#xff08;A) 考点1,关系模式 考点&#xff1a; 三个模式相…

AI算法-高数5-线性代数1-基本概念、向量

线性代数&#xff1a;主要研究1、张量>CV计算机视觉 2、研究张量的线性关系。 深度学习的表现之所以能够超过传统的机器学习算法离不开神经网络&#xff0c;然而神经网络最基本的数据结构就是向量和矩阵&#xff0c;神经网络的输入是向量&#xff0c;然后通过每个矩阵对向量…

Calendar 366 II for Mac v2.15.5激活版:智能日历管理软件

在繁忙的工作和生活中&#xff0c;如何高效管理日程成为了许多人的难题。Calendar 366 II for Mac&#xff0c;作为一款全方位的日历管理软件&#xff0c;以其独特的功能和优秀的用户体验&#xff0c;成为您的日程好帮手。 Calendar 366 II for Mac支持多种视图模式&#xff0c…

【Android学习】简单的登录页面和业务逻辑实现

实现功能 1 登录页&#xff1a;密码登录和验证码登录 2 忘记密码页&#xff1a;修改密码 3 页面基础逻辑 java代码 基础页面 XML login_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.and…

2-6 任务 猜数小游戏(单次版)

本任务要求编写一个猜数小游戏&#xff08;单次版&#xff09;&#xff0c;游戏规则是计算机产生一个0到100之间的随机整数&#xff0c;用户通过输入猜测的数字进行猜测&#xff0c;根据猜测情况给出提示&#xff0c;直到猜对为止。编程思路是利用while循环和多分支结构实现永真…

DELL T630服务器iDRAC分辨率调整办法

对于Dell T630服务器的iDRAC分辨率调整&#xff0c;您需要登录到iDRAC的Web界面。以下是详细的步骤&#xff1a; 登录iDRAC&#xff1a;在浏览器中输入iDRAC的IP地址&#xff0c;然后使用用户名&#xff08;通常是“root”&#xff09;和密码登录。 导航到虚拟控制台&#xff…

MyBatis——在WEB中使用MyBatis(MVC架构模式)

一、在 Web 应用中使用 MyBatis 项目目录结构 pojo package org.qiu.bank.pojo;/*** 账户类&#xff0c;封装账户数据* author 秋玄* version 1.0* package org.qiu.bank.pojo* date 2022-09-27-20:31* since 1.0*/ public class Account {private Long id;private String …

数据分析的统计推断

数据分析的统计推断 前言一、提出问题二、统计归纳方法三、统计推断四、统计推断步骤如何进行统计推断统计推断的基本问题点估计区间估计总体方差已知总体方差未知 假设检验假设检验的假设显著性水平 五、检验统计量常见的检验统计量 六、检验方法七、拒绝域八、假设检验步骤九…

报告!Golang冲上来啦!

今天又来讲Go语言&#xff0c;根据全球知名的编程语言排行榜TIOBE在4月份公布的最新的编程语言排名&#xff0c;令人瞩目的是&#xff0c;Go语言已经跃升至历史最高位&#xff0c;位列排行榜第七名&#xff0c;并且Go语言是前十榜单中最年轻的编程语言。这一成绩不仅彰显了Go语…

鲁教版六年级数学上册-笔记

文章目录 第一章 丰富的图形世界1 生活中的立体图形2 展开和折叠3 截一个几何体4 从三个方向看物体的形状 第二章 有理数及其运算1 有理数2 数轴3 绝对值4 有理数的加法5 有理数的减法6 有理数的加减混合运算7 有理数的乘法8 有理数的除法9 有理数的乘方10 科学计数法11 有理数…

CentOS7 安装 Kamailio

https://www.kamailio.org/wiki/packages/rpms 官方文档说 yum -y install yum-utils yum-config-manager --add-repo https://rpm.kamailio.org/centos/kamailio.repo 但目前这样其实行不通 需要这样做&#xff1a; yum install --disablerepokamailio --enablerepokamai…

Oracle 删除表中的列

Oracle 删除表中的列 CONN SCOTT/TIGER DROP TABLE T1; create table t1 as select * from emp; insert into t1 select * from t1; / / --到6000行&#xff0c;构造一个实验用大表T1。 COMMIT; select EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS from dba_extents where SEGMENT_…