<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>云升的小窝</title><description>此心安处是吾乡</description><link>https://blog-yunsheng.cn/</link><language>zh_CN</language><item><title>解决腾讯云服务器无法连接GitHub</title><link>https://blog-yunsheng.cn/posts/projects/operations/%E8%A7%A3%E5%86%B3%E8%85%BE%E8%AE%AF%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%97%A0%E6%B3%95%E8%BF%9E%E6%8E%A5github/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/projects/operations/%E8%A7%A3%E5%86%B3%E8%85%BE%E8%AE%AF%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%97%A0%E6%B3%95%E8%BF%9E%E6%8E%A5github/</guid><description>解决腾讯云服务器在国内访问 GitHub 时经常遇到连接超时或无法解析的问题。</description><pubDate>Sat, 11 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;问题描述&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;腾讯云服务器在国内访问 GitHub 时经常遇到连接超时或无法解析的问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决思路&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过手动修改 &lt;code&gt;hosts&lt;/code&gt; 文件，将 GitHub 域名解析到可用的 IP 地址。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;操作步骤&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;第一步：查询可用 IP 地址&lt;/h3&gt;
&lt;p&gt;访问 &lt;a href=&quot;https://www.ip138.com/&quot;&gt;IP 地址查询网站&lt;/a&gt;，查询以下域名的 DNS 解析地址：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;github.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;raw.githubusercontent.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;建议&lt;/strong&gt;：优先选择美国节点的 IP 地址，新加坡节点可能存在问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;第二步：目前获取到的可用 IP&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;域名&lt;/th&gt;
&lt;th&gt;IP 地址&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;github.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;140.82.116.3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;raw.githubusercontent.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;185.199.108.133&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;第三步：修改 hosts 文件&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 编辑 hosts 文件
sudo vim /etc/hosts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加以下内容：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;140.82.116.3 github.com
185.199.108.133 raw.githubusercontent.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;第四步：验证连接&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;ping github.com
ssh -T git@github.com
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如遇连接问题，可定期更新 &lt;code&gt;hosts&lt;/code&gt; 文件中的 IP 地址&lt;/li&gt;
&lt;li&gt;若使用代理或 VPN，请确保配置正确&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>无</title><link>https://blog-yunsheng.cn/posts/archives/summary/20250418/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/summary/20250418/</guid><description>今日离职了。</description><pubDate>Fri, 18 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;自4月1号通知我裁员后，今天就是我在公司的最后一天了。&lt;/p&gt;
&lt;p&gt;去年1月我曾在一家游戏公司做后端开发实习，当时有一个社招进入的和我一起培训的男生，他告诉我他去年工作被裁员后到这里来的，当时还有些诧异怎么只待了一年就被优化，没想到同样的事情在一年后发生到我身上。&lt;/p&gt;
&lt;p&gt;说起来，当时看中现在的公司规模更大，所以最后放弃了那家游戏公司，选择了现在的一家电商公司是否是个错误呢？从3月开始在这里实习起，7月毕业后正式入职到现在，部门裁员了50%的人……几乎每月身边的同事都在离开，我周围的同事几乎都离职了，我还常常自嘲自己是同事杀手，这都是在我实际来之前完全没有预见的。&lt;/p&gt;
&lt;p&gt;其实和公司的同事相处都很融洽，可能作为程序员的大家都比较单纯吧，我也很喜欢这儿的大家，只是部门的经营状况实在太差，业务在不断地大幅下滑，像餐补一类的福利也在去年底就砍掉了，当时就对公司的发展状况有了一个比较清晰的感受，也早早有了预期，所以在单独通知我裁员的时候我的心里几乎一点实感都没有，不过当晚在打电话告诉父母的时候还是有些难过。&lt;/p&gt;
&lt;p&gt;都说实践是最好的学习方式，在刚毕业时我还是完全的前端小白，因为在学校里一直都学习的后端（其实后端也没学得多好:D），没想到毕业后找到的却是前端工作。&lt;/p&gt;
&lt;p&gt;其实在短短的一年里真的进步了很多，最终也独立地完成了很多项目的相当多工作上的内容，只是可惜处在了一个不是那么好的时代。&lt;/p&gt;
&lt;p&gt;我自己是相当热爱计算机的，毕竟从小就有接触，甚至中学时代就在管理班级的多媒体计算机，大学也自己填报了计算机专业，我不是天赋型选手，但是在班里专业成绩也还算不错，当时想着自己以后一定要以此为工作，创造一些有趣的事物来。如今我还是热爱计算机，并且热情不减，但是我却不想以此为工作了，我想象中为自己的爱好而工作不是这样子的，大概以后我还会自己去学习去实现一些东西，比如前段时间我还开始在自学Unity游戏开发，但是这些以后都可能不再会是我的职业了。&lt;/p&gt;
&lt;p&gt;叽里咕噜也不知道记了些什么，就这样吧。&lt;/p&gt;
</content:encoded></item><item><title>Waline的使用</title><link>https://blog-yunsheng.cn/posts/archives/frontend/waline/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/frontend/waline/</guid><description>简单记录一下Fuwari主题中Waline评论模块的使用</description><pubDate>Thu, 17 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;1. 部署 Waline 服务端&lt;/h2&gt;
&lt;p&gt;先照着&lt;a href=&quot;https://waline.js.org/guide/get-started/&quot;&gt;Waline官方文档&lt;/a&gt;把 &lt;code&gt;Waline&lt;/code&gt; 项目给部署了，就完全照着操作就行了，官方文档写的很详细，我觉得没必要再重复写一次。一直照着操作到绑定域名为止，暂时没有必要绑定域名，如果有进行加速使国内可以访问的需求时再绑定域名（之后会写如何加速）。&lt;/p&gt;
&lt;p&gt;记住部署好的 &lt;code&gt;Waline&lt;/code&gt; 项目的 &lt;code&gt;Domains&lt;/code&gt;，有需要的话可以先用我的做测试，已做国内加速，域名注册的话选有首年优惠的就行，大概10块钱左右，但是续费很贵，所以到期后我会更换新域名，所以还是需要你自己注册一个自己域名。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image.png&quot; alt=&quot;alt text&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;2. 配置前端&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;src/config.ts&lt;/code&gt; 中的 &lt;code&gt;walineConfig&lt;/code&gt; 配置项里添入自己部署的 &lt;code&gt;Waline&lt;/code&gt; 项目的域名。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-1.png&quot; alt=&quot;alt text&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;3. 启用评论功能&lt;/h2&gt;
&lt;p&gt;然后在要启用评论系统的文章 &lt;code&gt;Front-matter&lt;/code&gt; 中加入 &lt;code&gt;comments: true&lt;/code&gt; 就可以单独对文章启用 &lt;code&gt;Waline&lt;/code&gt; 评论了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-3.png&quot; alt=&quot;alt text&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;4. 管理员与管理面板&lt;/h2&gt;
&lt;p&gt;首个注册的账号会是管理员，管理面板在 &lt;code&gt;example.yourdomain.com/ui&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;5. 国内访问加速&lt;/h2&gt;
&lt;p&gt;如果你使用 &lt;code&gt;Vercel&lt;/code&gt; 部署 &lt;code&gt;Waline&lt;/code&gt;，国内用户可能无法直接访问评论系统。需要加速的同学可以参考：&lt;a href=&quot;https://blog-yunsheng.cn/posts/old-post/vercel-cloudflare-twikoo/&quot;&gt;这篇文章&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;如有疑问，欢迎留言交流！&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>鼠标点击爆炸特效美化</title><link>https://blog-yunsheng.cn/posts/archives/frontend/astro/beautify/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/frontend/astro/beautify/</guid><description>简单的鼠标点击爆炸特效。</description><pubDate>Fri, 11 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;继续处理博客的升级工作，决定把旧框架下的鼠标点击爆炸特效移植过来。这是在之前的 Hexo 博客中使用过的功能，链接是&lt;a href=&quot;https://blog-yunsheng.cn/posts/old-post/hexo-beautify/&quot;&gt;hexo 博客美化&lt;/a&gt;。这个特效让页面点击时出现彩色粒子爆炸。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog-yunsheng.cn/utils/fireworks.min.js&quot;&gt;使用的文件&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;接下来，在 &lt;code&gt;Layout&lt;/code&gt; 文件的 &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; 标签内添加必要的元素。过程很顺利，我把代码保存为一个单独的 JS 文件，然后引入它。具体的添加部分是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;canvas
  id=&quot;fireworks&quot;
  style=&quot;position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 32767&quot;
&amp;gt;&amp;lt;/canvas&amp;gt;
&amp;lt;script
  type=&quot;text/javascript&quot;
  src=&quot;https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js&quot;
&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;/utils/fireworks.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;要让该JS能在线上（生产环境）被访问，必须把它放到 &lt;code&gt;Astro&lt;/code&gt; 项目的 &lt;code&gt;public&lt;/code&gt; 目录下。&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>快速上手 Google Tag Manager (GTM) 与 Microsoft Clarity 集成教程</title><link>https://blog-yunsheng.cn/posts/archives/frontend/tracking/clarity/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/frontend/tracking/clarity/</guid><description>Clarity - 微软大哥的永久免费的用户行为分析工具。</description><pubDate>Fri, 11 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;在网站分析和用户行为追踪中，Google Tag Manager (GTM) 是一个强大的工具，可以帮助我们轻松管理各种追踪代码。而 Microsoft Clarity 则是一款优秀的用户行为分析工具，能够提供热图、会话录制等功能。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;一、创建 Google Tag Manager (GTM) 账号和容器&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;访问 GTM 官网&lt;/strong&gt;&lt;br /&gt;
打开 &lt;a href=&quot;https://tagmanager.google.com/&quot;&gt;GTM 官网&lt;/a&gt;，使用你的 Google 账号登录。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建账号和容器&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点击“创建账号”，填写账号名称（通常是公司或项目名）。&lt;/li&gt;
&lt;li&gt;创建一个新的“容器”，选择“网页”类型，并输入网站域名。&lt;/li&gt;
&lt;li&gt;完成设置后，GTM 会生成两段代码，用于嵌入到你的网站中。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;二、将 GTM 代码嵌入网站&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;获取 GTM 代码&lt;/strong&gt;&lt;br /&gt;
创建容器后，GTM 会提供两段代码：一段放在 &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; 标签内，另一段放在 &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; 标签内。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;嵌入代码到项目&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;找到项目的主布局文件（通常是 &lt;code&gt;Layout&lt;/code&gt; 文件）。&lt;/li&gt;
&lt;li&gt;将第一段代码粘贴到 &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; 标签的最前面。&lt;/li&gt;
&lt;li&gt;将第二段代码粘贴到 &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; 标签的最前面。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;解决 TypeScript 报错（可选）&lt;/strong&gt;&lt;br /&gt;
如果你的项目使用 TypeScript (ts)，可能会在 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 标签处报错。解决方法是给 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 标签加上 &lt;code&gt;type=&quot;text/javascript&quot;&lt;/code&gt; 属性，例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
  // GTM 代码内容
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;发布并测试&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;代码嵌入完成后，部署你的网站。&lt;/li&gt;
&lt;li&gt;使用浏览器开发者工具或 GTM Preview 模式测试，确保代码正常运行，无报错。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;三、通过 GTM 集成 Microsoft Clarity&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;访问 Microsoft Clarity 官网&lt;/strong&gt;&lt;br /&gt;
打开 &lt;a href=&quot;https://clarity.microsoft.com/&quot;&gt;Clarity 官网&lt;/a&gt;，使用 Microsoft 账号登录。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建新项目&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点击“新建项目”，填写项目名称和网站 URL。&lt;/li&gt;
&lt;li&gt;选择“在第三方平台上安装”，然后选择“Google Tag Manager (GTM)”作为集成方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;连接 GTM 项目&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clarity 会生成一段代码或指引你完成连接。&lt;/li&gt;
&lt;li&gt;在 GTM 界面中，创建一个新的“标签”，选择“自定义 HTML 标签”，将 Clarity 提供的代码粘贴进去。&lt;/li&gt;
&lt;li&gt;设置触发器为“所有页面”，确保代码在每个页面加载时触发。&lt;/li&gt;
&lt;li&gt;保存并发布 GTM 容器。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;四、等待数据同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;完成以上步骤后，通常需要等待几个小时（视网站流量而定），Clarity 才会开始显示数据。&lt;/li&gt;
&lt;li&gt;登录 Clarity 仪表板，查看热图、会话录制等用户行为数据，确保一切正常。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;五、总结与注意事项&lt;/h2&gt;
&lt;p&gt;通过以上步骤，你已经成功将 GTM 集成到网站，并通过 GTM 连接了 Microsoft Clarity，用于用户行为分析。以下是一些注意事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确保 GTM 代码正确嵌入，避免因位置错误导致追踪失败。&lt;/li&gt;
&lt;li&gt;定期检查 GTM 和 Clarity 的数据，确保没有异常。&lt;/li&gt;
&lt;li&gt;如果网站有多个子域名或复杂结构，可能需要额外配置 GTM 容器。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>搜索引擎活用手册</title><link>https://blog-yunsheng.cn/posts/resources/search-engine/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/resources/search-engine/</guid><description>其实主要就是写如何干掉CSDN。</description><pubDate>Thu, 12 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;一直苦于像牛皮癣一样到处都是的 CSDN 文章，现在似乎连必应都被这个二流网站给铺满了，于是开始好好研究如何正确使用搜索引擎，过滤掉那些不需要的信息。&lt;/p&gt;
&lt;h2&gt;过滤信息&lt;/h2&gt;
&lt;p&gt;首先，让我们来干掉该死的 CSDN 吧。&lt;/p&gt;
&lt;p&gt;根据网络上给出的方法，可以在搜索框加上&lt;code&gt;-site:csdn.net&lt;/code&gt;，这样会过滤掉&lt;code&gt;csdn.net&lt;/code&gt;网站的搜索结果。&lt;/p&gt;
&lt;p&gt;但是这样似乎需要写的东西太长了，很麻烦，可以直接去掉&lt;code&gt;site&lt;/code&gt;，写&lt;code&gt;-csdn.net&lt;/code&gt;，虽然在必应上仍然有些漏网之鱼，但是总的来说依然是生效的。&lt;/p&gt;
&lt;p&gt;似乎每次都要输入一次&lt;code&gt;-csdn.net&lt;/code&gt;也有点麻烦，如果能每次搜索的时候都自动添加上这个关键词，那是不是更方便呢？&lt;/p&gt;
&lt;p&gt;我们可以打开 EDGE 中的设置面板，在&quot;管理搜索引擎&quot;选项中，可以添加上一个地址栏搜索引擎，其中的搜索地址为：&lt;code&gt;https://cn.bing.com/search?q=%s+-site:csdn.net&lt;/code&gt;，其他两项&quot;搜索引擎&quot;和&quot;快捷方式&quot;都可以自行随意设置。&lt;/p&gt;
&lt;p&gt;同样，用这个方法也可以过滤掉一些不需要的信息，例如我们搜索一个电子游戏，但是和一部电影重名了，也可以&lt;code&gt;-movie&lt;/code&gt;或是&lt;code&gt;-&lt;/code&gt;多余的搜索结果中出现的关键词来过滤掉对应的搜索结果。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;如果需要在特点的网站上进行搜索的话，将&lt;code&gt;-site&lt;/code&gt;前的&lt;code&gt;-&lt;/code&gt;去掉即可，例如：&lt;code&gt;Vue教程 site:github.com&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;现在我们成功干掉了 CSDN，接下来顺势学习一下搜索引擎的更多技巧吧。&lt;/p&gt;
&lt;h2&gt;精确搜索&lt;/h2&gt;
&lt;p&gt;如果要进行精确搜索，可以将搜索的参数加上&lt;code&gt;&quot;&quot;&lt;/code&gt;，当没有引号时，搜索的是以任意顺序包含关键词的内容，而加上引号后，将会把引号内的参数作为一个整体进行精确搜索。&lt;/p&gt;
&lt;p&gt;不过目前实际应用中需要用到精确搜索的场景比较少，了解即可。&lt;/p&gt;
&lt;h2&gt;填充模糊信息&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;*&lt;/code&gt;可以填充关键词间的模糊信息。&lt;/p&gt;
&lt;h2&gt;文档搜索&lt;/h2&gt;
&lt;p&gt;使用&lt;code&gt;filetype&lt;/code&gt;可以搜索指定文档格式的资料，例如:&lt;code&gt;filetype:pdf 区块链报告&lt;/code&gt;，这样搜索出来的结果都是 pdf 格式的资料。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;一般而言，以上的技巧就足够应付实际应用中的大部分场景了。&lt;/p&gt;
</content:encoded></item><item><title>Vue2开发学习笔记</title><link>https://blog-yunsheng.cn/posts/archives/old-post/vue2-simple/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/vue2-simple/</guid><description>Vue2的一些学习笔记，包括安装、自定义组件、Vuex、Vue Router等内容。</description><pubDate>Sat, 13 Apr 2024 21:31:01 GMT</pubDate><content:encoded>&lt;p&gt;好想直接学最新的 vue3……&lt;/p&gt;
&lt;p&gt;最近听到一首挺好听的歌，《若月亮没来》。&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;没啥用的一篇文章，以后自己的这些东西都会改为放到&lt;a href=&quot;https://tecdoc-yunsheng.cn/&quot;&gt;另一个网站里&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;vue2 安装&lt;/h2&gt;
&lt;p&gt;vue2 的 CLI 与 vue3 的 CLI 有所不同，应参照&lt;a href=&quot;https://cli.vuejs.org/#getting-started&quot;&gt;该文档&lt;/a&gt;进行安装&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安装 Vue CLI&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -g @vue/cli
# or
yarn global add @vue/cli
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;创建项目&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vue create my-project
# or
vue ui
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;启动项目&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm run serve
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Vue 自定义组件&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src\components\product-item\product-item.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;product-item&quot;&amp;gt;
    &amp;lt;img :src=&quot;products.img&quot; alt=&quot;商品&quot; /&amp;gt;
    &amp;lt;div class=&quot;title&quot;&amp;gt;{{ products.title }}&amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;price&quot;&amp;gt;
      &amp;lt;div class=&quot;current-price&quot;&amp;gt;{{ products.currentPrice }}&amp;lt;/div&amp;gt;
      &amp;lt;div class=&quot;original-price&quot;&amp;gt;{{ products.originalPrice }}&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
  export default {
    props: {
      products: {
        type: Object,
        default: () =&amp;gt; ({
          img: &quot;&quot;,
          title: &quot;&quot;,
          currentPrice: &quot;&quot;,
          originalPrice: &quot;&quot;,
        }),
      },
    },
  };
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src\App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;layout-default&quot;&amp;gt;
      &amp;lt;topNavigation /&amp;gt;
      &amp;lt;div class=&quot;list&quot;&amp;gt;
        &amp;lt;Product
          v-for=&quot;(product, index) in products&quot;
          :key=&quot;index&quot;
          :products=&quot;product&quot;
        &amp;gt;&amp;lt;/Product&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
  import Product from &quot;@/components/product-item/product-item.vue&quot;;
  import topNavigation from &quot;@/components/top-navigation/top-navigation.vue&quot;;
  import { mapState } from &quot;vuex&quot;;

  export default {
    components: {
      Product,
      topNavigation,
    },
    computed: {
      ...mapState({
        products: (state) =&amp;gt; state.shop.products,
      }),
    },
  };
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;slot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 Vue 中，&lt;code&gt;slot&lt;/code&gt;是一种分发内容的机制，允许我们将组件的一部分内容插入到组件的模板中。这种方式使得我们可以编写可复用的组件，而不需要在每次使用时都写重复的内容。&lt;/p&gt;
&lt;p&gt;例如，如果有一个自定义的&lt;code&gt;&amp;lt;my-button&amp;gt;&lt;/code&gt;组件，我们可能想在不同的地方使用不同的文本。这就可以通过&lt;code&gt;slot&lt;/code&gt;来实现：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- my-button组件的模板 --&amp;gt;
&amp;lt;button&amp;gt;
  &amp;lt;slot&amp;gt;默认按钮文本&amp;lt;/slot&amp;gt;
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用这个组件时，可以这样做：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;my-button&amp;gt; 点击我 &amp;lt;/my-button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样&lt;code&gt;&amp;lt;my-button&amp;gt;&lt;/code&gt;组件里的&lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt;标签就会被替换为“点击我”，而不是默认的“默认按钮文本”。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;slot&lt;/code&gt;还可以有名字，这样你就可以定义多个插槽，让父组件决定哪些内容放在哪里。例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- my-layout组件的模板 --&amp;gt;
&amp;lt;div&amp;gt;
  &amp;lt;header&amp;gt;
    &amp;lt;slot name=&quot;header&quot;&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/header&amp;gt;
  &amp;lt;main&amp;gt;
    &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/main&amp;gt;
  &amp;lt;footer&amp;gt;
    &amp;lt;slot name=&quot;footer&quot;&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/footer&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在使用时：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;my-layout&amp;gt;
  &amp;lt;template v-slot:header&amp;gt;
    &amp;lt;h1&amp;gt;这是标题&amp;lt;/h1&amp;gt;
  &amp;lt;/template&amp;gt;

  &amp;lt;p&amp;gt;这是主体内容&amp;lt;/p&amp;gt;

  &amp;lt;template v-slot:footer&amp;gt;
    &amp;lt;p&amp;gt;这是页脚信息&amp;lt;/p&amp;gt;
  &amp;lt;/template&amp;gt;
&amp;lt;/my-layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样，&lt;code&gt;my-layout&lt;/code&gt;组件就会在相应的位置显示“这是标题”、“这是主体内容”和“这是页脚信息”。&lt;/p&gt;
&lt;p&gt;总之，&lt;code&gt;slot&lt;/code&gt;是 Vue 中一种非常有用的特性，用于创建灵活且可复用的组件。&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://v3.vuex.vuejs.org/zh/&quot;&gt;Vuex 的使用&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;使用常量存储静态数据&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src\constants\constants.js
import {
  productImageUrl1,
  productImageUrl2,
  productImageUrl3,
  productImageUrl4,
} from &quot;@/constants/image&quot;;

export const SHOP_PRODUCTS_DATA = [
  {
    img: productImageUrl1,
    title: &quot;AC/DC North American Tour T-shirt&quot;,
    currentPrice: &quot;$25.90&quot;,
    originalPrice: &quot;$37.50&quot;,
  },
  {
    img: productImageUrl2,
    title: &quot;Brown Janis Joplin Printed HoodedLight Trailer  S...&quot;,
    currentPrice: &quot;$19.90&quot;,
    originalPrice: &quot;&quot;,
  },
];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;关于 image.js 的示例:&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import productImage1 from &quot;@/assets/img/image 1.png&quot;;
export const productImageUrl1 = productImage1;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Vuex 的引入&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建 store 文件夹，在 store 文件夹下创建 module 文件夹和 index.js 文件，在 module 文件夹中创建 module.js 文件.&lt;/li&gt;
&lt;li&gt;在 module.js 文件中创建 state,mutations,actions,getters 对象。&lt;/li&gt;
&lt;li&gt;在 index.js 中创建 store 对象，在 main.js 中引入 store 对象，在 main.js 中挂载 store 对象&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;// src\store\modules\shop.js
import { SHOP_PRODUCTS_DATA } from &quot;@/constants/constants&quot;;

export default {
  state: {
    products: SHOP_PRODUCTS_DATA,
  },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// src\store\index.js
import Vue from &quot;vue&quot;;
import Vuex from &quot;vuex&quot;;
import shopProducts from &quot;@/store/modules/shop&quot;;

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    shop: shopProducts,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// src\main.js
import Vue from &quot;vue&quot;;
import App from &quot;./App.vue&quot;;
import store from &quot;@/store/index&quot;;

Vue.config.productionTip = false;

new Vue({
  store,
  render: (h) =&amp;gt; h(App),
}).$mount(&quot;#app&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;在主模块中引入 Vuex&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
  import Product from &quot;@/components/product-item/product-item.vue&quot;;
  import { mapState } from &quot;vuex&quot;;

  export default {
    components: {
      Product,
    },
    computed: {
      ...mapState({
        products: (state) =&amp;gt; state.shop.products,
      }),
    },
  };
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;a href=&quot;https://v3.router.vuejs.org/zh/&quot;&gt;vue-router 的使用&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;vue-router 安装&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;npm install vue-router@version
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;vue-router 结构目录&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;src
&lt;ul&gt;
&lt;li&gt;router
&lt;ul&gt;
&lt;li&gt;index.js&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;路由配置&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// src\router\index.js
import Vue from &quot;vue&quot;;
import Router from &quot;vue-router&quot;;
Vue.use(Router);

// 路由规则
const routes = [
  {
    path: &quot;/&quot;,
    component: () =&amp;gt; import(&quot;../page/ShoppingList.vue&quot;),
  },
  {
    path: &quot;/PDP&quot;,
    component: () =&amp;gt; import(&quot;../page/PDP.vue&quot;),
  },
  {
    path: &quot;/ShoppingCart&quot;,
    component: () =&amp;gt; import(&quot;../page/ShoppingCart.vue&quot;),
  },
  {
    path: &quot;*&quot;,
    ridirect: &quot;/&quot;,
  },
];

// 路由器
const router = new Router({
  routes,
  mode: &quot;hash&quot;, // history
});

export default router;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;路由模式：如果需要去掉 URL 中的 &quot;#&quot; ，需要在创建 &lt;code&gt;VueRouter&lt;/code&gt; 实例时设置 &lt;code&gt;mode&lt;/code&gt; 为 &lt;code&gt;history&lt;/code&gt; 。&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src\main.js
import router from &quot;./router/index&quot;;

new Vue({
  router, // new
  render: (h) =&amp;gt; h(App),
}).$mount(&quot;#app&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;路由使用&lt;/h3&gt;
&lt;p&gt;对于动态导航，可以这样使用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- 在组件模板中 --&amp;gt;
&amp;lt;router-link to=&quot;/&quot;&amp;gt;Home&amp;lt;/router-link&amp;gt;
&amp;lt;router-view&amp;gt;
&amp;lt;/router-view&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者在 JavaScript 中：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;this.$router.push(&quot;/&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;router-link&lt;/code&gt;内的属性值：&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- replace 不保留历史记录 --&amp;gt;
&amp;lt;!-- tag 改变标签 --&amp;gt;
&amp;lt;!-- target 改变链接打开方式 --&amp;gt;
&amp;lt;router-link to=&quot;/&quot; replace tag=&quot;div&quot; target=&quot;_blank&quot;&amp;gt;Home&amp;lt;/router-link&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;路由传参&lt;/h3&gt;
&lt;p&gt;在本项目中，要实现跳转到 PDP 页面，需要将商品 ID 传过去。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;动态匹配路由跳转时路由规则的修改&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const routes = [
  {
    path: &quot;/pdp/:id&quot;,
    name: &quot;pdp&quot;,
    component: () =&amp;gt; import(&quot;../page/PDP.vue&quot;),
  },
];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加上 name 属性后，就可以在 &lt;code&gt;&amp;lt;router-link&amp;gt;&lt;/code&gt; 中进行动态匹配了：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;router-link :to=&quot;{ name: &apos;pdp&apos;, params: { id: products.id } }&quot;&amp;gt;&amp;lt;/router-link&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里进行路由跳转时，会动态匹配 &lt;code&gt;name=pdp&lt;/code&gt; 的路由规则，并把 &lt;code&gt;params&lt;/code&gt; 参数传过去。&lt;/p&gt;
&lt;h3&gt;获取路由中传递过来的参数&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;首先注入 &lt;code&gt;$route&lt;/code&gt; 对象，使得组件可以直接访问 &lt;code&gt;vue-router&lt;/code&gt; 中的 &lt;code&gt;$route&lt;/code&gt; 实例，从而获取当前路由的信息。&lt;/li&gt;
&lt;li&gt;之后定义一个属性来获取路由参数。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
  export default {
      // ...
      inject: [&apos;$route&apos;],
      // ...
      data() {
          return {
              getIdFromRoute: this.$route.params.id,
          }
      }
      // 另外一种使用computed的方法:
      computed: {
          getIdFromRoute() {
            return this.$route.params.id
          }
      }
  }
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过一个自定义的属性来取到当前的商品信息，然后就可以在组件中直接使用。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;!-- 使用示例 --&amp;gt;
  &amp;lt;img :src=&quot;currentProduct.img&quot; /&amp;gt;
  &amp;lt;div&amp;gt;{{ currentProduct.title }}&amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
  export default {
    // ...
    computed: {
      currentProduct() {
        return this.products.find(
          (product) =&amp;gt; product.id === this.getIdFromRoute
        );
      },
    },
    // ...
  };
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;在 &lt;code&gt;main.js&lt;/code&gt; 中注入 &lt;code&gt;VueRouter&lt;/code&gt; 的标准流程：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 Vue 应用中，&lt;code&gt;$router&lt;/code&gt; 和 &lt;code&gt;$route&lt;/code&gt; 对象是通过 &lt;code&gt;Vue Router&lt;/code&gt; 插件自动注入到每个 &lt;code&gt;Vue&lt;/code&gt; 实例（包括组件实例）中的。当在 &lt;code&gt;main.js&lt;/code&gt; 文件中创建并使用 &lt;code&gt;VueRouter&lt;/code&gt; 实例，并将其作为选项传递给 &lt;code&gt;Vue&lt;/code&gt; 构造器时，&lt;code&gt;Vue&lt;/code&gt; 将会自动处理注入过程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 导入 Vue 和 VueRouter
import Vue from &quot;vue&quot;;
import VueRouter from &quot;vue-router&quot;;
import App from &quot;./App.vue&quot;; // 你的主组件
import Home from &quot;./components/Home.vue&quot;; // 示例组件
import About from &quot;./components/About.vue&quot;; // 示例组件

// 创建 VueRouter 实例
const router = new VueRouter({
  routes: [
    { path: &quot;/&quot;, component: Home },
    { path: &quot;/about&quot;, component: About },
    //另一种写法： component: () =&amp;gt; import(&quot;@/components/HelloWorld.vue&quot;)
  ],
});

// 注册 VueRouter 插件并注入 $router
Vue.use(VueRouter);

// 创建并挂载 Vue 根实例，传入 router
new Vue({
  router, // 这里是关键，传入 router 实例
  render: (h) =&amp;gt; h(App),
}).$mount(&quot;#app&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在这个例子中，&lt;code&gt;Vue.use(VueRouter)&lt;/code&gt; 是注册插件的必要步骤，然后在创建 &lt;code&gt;Vue&lt;/code&gt; 根实例时，通过 &lt;code&gt;router&lt;/code&gt; 选项将路由器实例传递给 Vue。这使得 &lt;code&gt;$router&lt;/code&gt; 可以在任何组件中通过 &lt;code&gt;this&lt;/code&gt; 访问。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 在任何组件中，你都可以使用 $router
export default {
  methods: {
    navigateToAbout() {
      this.$router.push(&quot;/about&quot;);
    },
  },
};
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Swiper11在Vue2项目中的使用</title><link>https://blog-yunsheng.cn/posts/archives/old-post/swiper11-vue2/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/swiper11-vue2/</guid><description>swiper11在vue2项目中的使用记录，有一些坑，好在爬出来了。</description><pubDate>Wed, 10 Apr 2024 19:37:05 GMT</pubDate><content:encoded>&lt;p&gt;今年《天国：拯救 2》就要发售了，明年还有《GTA6》，期待( •̀ ω •́ )✧。&lt;/p&gt;
&lt;h2&gt;swiper11 在 vue2 项目中的使用&lt;/h2&gt;
&lt;p&gt;因为公司使用的仍然是 vue2，所以被迫在 vue2 项目下进行 swiper11 的使用，而 swiper 的中文文档是有很多坑的，英文文档是基于 vue3 的，所以记录以下自己在 vue2 下使用 swiper11 的爬坑过程（￣︶￣）↗ 　。&lt;/p&gt;
&lt;p&gt;虽然 swiper 中文网有很多坑，但是还是把&lt;a href=&quot;https://swiper.com.cn/&quot;&gt;中文文档&lt;/a&gt;和&lt;a href=&quot;https://swiperjs.com/&quot;&gt;官方文档&lt;/a&gt;都贴出来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;尝试过 swiper7 版本，引入方式跟之后的版本很不一样，本文仅适用于 7 之后的版本。&lt;em&gt;安装 swiper7 及以前的版本采用我的方法的话会报错，无法使用。&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install swiper
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;导入包&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;正确的引入方式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
  import Swiper from &quot;swiper&quot;;
  import &quot;swiper/swiper-bundle.css&quot;;
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;使用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;直接 copy 文档中的代码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;swiper-demo&quot;&amp;gt;
    &amp;lt;div class=&quot;swiper&quot;&amp;gt;
      &amp;lt;div class=&quot;swiper-wrapper&quot;&amp;gt;
        &amp;lt;div class=&quot;swiper-slide&quot;&amp;gt;
          &amp;lt;img src=&quot;./assets/imges/1.png&quot; alt=&quot;img-1&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;swiper-slide&quot;&amp;gt;
          &amp;lt;img src=&quot;./assets/imges/2.png&quot; alt=&quot;img-1&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;swiper-slide&quot;&amp;gt;
          &amp;lt;img src=&quot;./assets/imges/3.png&quot; alt=&quot;img-1&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;!-- If we need pagination --&amp;gt;
      &amp;lt;div class=&quot;swiper-pagination&quot;&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;!-- If we need navigation buttons --&amp;gt;
      &amp;lt;div class=&quot;swiper-button-prev&quot;&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div class=&quot;swiper-button-next&quot;&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;!-- If we need scrollbar --&amp;gt;
      &amp;lt;div class=&quot;swiper-scrollbar&quot;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
  export default {
    mounted() {
      new Swiper(&quot;.swiper&quot;, {
        // Optional parameters
        loop: true,
        // If we need pagination
        pagination: {
          el: &quot;.swiper-pagination&quot;,
        },
        // Navigation arrows
        navigation: {
          nextEl: &quot;.swiper-button-next&quot;,
          prevEl: &quot;.swiper-button-prev&quot;,
        },
        // And if we need scrollbar
        scrollbar: {
          el: &quot;.swiper-scrollbar&quot;,
        },
      });
    },
  };
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;到这里其实轮播图已经能正常显示了，关于 css 样式自行设置，这就是官方文档给出的使用方式，但是如果自己接着进行一下操作，马上就能发现问题。&lt;/p&gt;
&lt;p&gt;如果自己操作一下的话，一定马上就能发现，分页器没有显示、左右导航键按了没反应，如果再尝试着加入&lt;code&gt;auto: true&lt;/code&gt;的话，更会发现这个自动轮播功能根本就没有生效！&lt;/p&gt;
&lt;p&gt;在网上找了很多，但都是老版本 swiper 或是 vue3 的，反正横竖不能解决问题，最后在查 swiper 的包时，终于发现了在其中有个&lt;code&gt;modules&lt;/code&gt;文件夹，打开后马上恍然大悟，原来相关的模块都在这个文件夹里，要再引入！&lt;/p&gt;
&lt;p&gt;那么接下来就简单了，正确的引入方式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;
  import Swiper from &quot;swiper&quot;;
  import { Autoplay, Pagination } from &quot;swiper/modules&quot;;
  import &quot;swiper/swiper-bundle.css&quot;;
  Swiper.use([Autoplay, Pagination]);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中我只用了&lt;code&gt;autoplay&lt;/code&gt;和&lt;code&gt;pagination&lt;/code&gt;两个模块，需要什么再引入什么即可，再测试功能已能正常实现了。&lt;/p&gt;
&lt;h2&gt;图片的自适应问题&lt;/h2&gt;
&lt;p&gt;在写 banner 图时，发现一个问题，轮播图中使用的图片大小不同，会出现撑起的容器高度不一致，没法对其的情况，如果简单地采用明确的宽高(px 单位)，又无法自适应多种设备。&lt;/p&gt;
&lt;p&gt;在网上找到了合适的教程，原理是使用 vw 解决，现简单的总结下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;理解 vw 单位，即将视窗宽度分为 100 份，每份即为 1vw；&lt;/li&gt;
&lt;li&gt;width 正常设置为 100%，然后设置&lt;code&gt;height: 需要图片的高度 / 设备宽度 * 100&lt;/code&gt;，例如我需要的正常图片高度为 624px，设备宽度为 768px，那么&lt;code&gt;height: 624 / 750 * 100&lt;/code&gt;，即可得到需要的高度；&lt;/li&gt;
&lt;li&gt;接下来使用到&lt;code&gt;object-fit: cover&lt;/code&gt;，关于 object-fit，可以参考&lt;a href=&quot;https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fit&quot;&gt;MDN&lt;/a&gt;；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/echolun/p/11354416.html&quot;&gt;参考地址&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Erlang语言基础学习笔记</title><link>https://blog-yunsheng.cn/posts/archives/old-post/erlang/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/erlang/</guid><description>在某游戏公司岗前培训（其实就是自学）期间的学习笔记，Erlang是一个函数式编程语言，一般用于高并发情况下，初上手时不适应，但熟悉一天后写起来还蛮有意思的。</description><pubDate>Wed, 17 Jan 2024 16:33:26 GMT</pubDate><content:encoded>&lt;h1&gt;Erlang语言基础学习笔记&lt;/h1&gt;
&lt;h2&gt;常用的一些语法&lt;/h2&gt;
&lt;h3&gt;API类（及其实现）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;%%%-------------------------------------------------------------------
%%% lists:max()
max([H|T]) -&amp;gt; max(T, H).
max([H|T], Max) when H &amp;gt; Max -&amp;gt; max(T, H);
max([_|T], Max)              -&amp;gt; max(T, Max);
max([],    Max)              -&amp;gt; Max.
%%%-------------------------------------------------------------------
%%% lists:min()
min([H|T]) -&amp;gt; min(T, H).
min([H|T], Min) when H &amp;lt; Min -&amp;gt; min(T, H);
min([_|T], Min)              -&amp;gt; min(T, Min);
min([],    Min)              -&amp;gt; Min. 
%%%-------------------------------------------------------------------
%%% lists:sum()
sum(L)          -&amp;gt; sum(L, 0).
sum([H|T], Sum) -&amp;gt; sum(T, Sum + H);
sum([], Sum)    -&amp;gt; Sum.
%%%-------------------------------------------------------------------
%%% lists:reverse()
reverse(List) -&amp;gt;
    reverse(List, []).
reverse([], Acc) -&amp;gt;
    Acc;
reverse([Head | Tail], Acc) -&amp;gt;
    reverse(Tail, [Head | Acc]).
%%%-------------------------------------------------------------------
%%% lists:member(Elem, List) 存在返回true,不存在返回false
member(_, []) -&amp;gt; false;
member(Element, [Element | _]) -&amp;gt; true;
member(Element, [_ | Tail]) -&amp;gt; member(Element, Tail).
%%%-------------------------------------------------------------------
%%% ++
concatenate_lists(List1, List2) -&amp;gt;
    case List1 of
        [] -&amp;gt;
            List2;
        [Head | Tail] -&amp;gt;
            [Head | concatenate_lists(Tail, List2)]
    end.
%%%-------------------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;算术表达式&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;操作符&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;参数类型&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;+ X&lt;/td&gt;
&lt;td&gt;+ X&lt;/td&gt;
&lt;td&gt;数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;- X&lt;/td&gt;
&lt;td&gt;- X&lt;/td&gt;
&lt;td&gt;数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X * Y&lt;/td&gt;
&lt;td&gt;X * Y&lt;/td&gt;
&lt;td&gt;数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X / Y&lt;/td&gt;
&lt;td&gt;X / Y （浮点除法）&lt;/td&gt;
&lt;td&gt;数字&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X div Y&lt;/td&gt;
&lt;td&gt;X被Y整除&lt;/td&gt;
&lt;td&gt;整数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X rem Y&lt;/td&gt;
&lt;td&gt;X除以Y的整数余数&lt;/td&gt;
&lt;td&gt;整数&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;练习题总结&lt;/h2&gt;
&lt;h3&gt;元组，列表相关练习题&lt;/h3&gt;
&lt;h4&gt;遍历方式与累加器&lt;/h4&gt;
&lt;p&gt;对于列表的遍历，用尾递归，结合累加器，进行数据存储，示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test([H | T], Acc) -&amp;gt;
	test(T, [H | Acc]).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中，H是列表的头元素，T是H以后的列表，&lt;code&gt;[H | Acc]&lt;/code&gt;为通过头插的形式把H插入到Acc头部。&lt;/p&gt;
&lt;h4&gt;终止遍历条件&lt;/h4&gt;
&lt;p&gt;要终止对列表的遍历非常简单：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test([], Acc) -&amp;gt;
    Acc;
%% 以下为遍历
test([H | T], Acc) -&amp;gt;
	test(T, [H | Acc]).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里的意思是，当传入的第一个参数，列表为空时，输出Acc。&lt;/p&gt;
&lt;h4&gt;简化调用API&lt;/h4&gt;
&lt;p&gt;继续上面，我们的累加器是自己设置的，实际用户调用的时候不需要设置Acc，所有调用接口可以简化：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-export([test/1]).

test(List) -&amp;gt;
    test(List, []).

test([], Acc) -&amp;gt;
    lists:reverse(Acc);
%% 以下为遍历
test([H | T], Acc) -&amp;gt;
	test(T, [H | Acc]).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一个简单的遍历列表并把每个元素加到累加器中的功能就写好了，如果需要的话可以用&lt;code&gt;lists:reverse()&lt;/code&gt;将Acc进行反转。&lt;/p&gt;
&lt;h4&gt;索引的控制&lt;/h4&gt;
&lt;p&gt;一般情况下，在调用函数的时候就进行索引的比较与控制：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$$$ 计算数字列表或元组索引N到M的和

%% API
-export([get_sum/3]).

get_sum(List, N, M) -&amp;gt;
    get_sum(List, N, M, 1, []).

get_sum([], _, _, _, Acc) -&amp;gt;
    lists:sum(Acc);
get_sum([H | T], N, M, Index, Acc) when (Index =&amp;lt; M) and (Index &amp;gt;= N)-&amp;gt;
    get_sum(T, N, M, Index + 1, [H | Acc]);
get_sum([_ | T], N, M, Index, Acc) -&amp;gt;
    get_sum(T, N, M, Index + 1, Acc).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中，我们在调用&lt;code&gt;get_sum&lt;/code&gt;函数的时候，就对要传入其中的&lt;code&gt;Index&lt;/code&gt;参数进行了控制，并用关卡机制对&lt;code&gt;Index&lt;/code&gt;进行了检查，使其能够完成题目的要求。&lt;/p&gt;
&lt;p&gt;关于索引控制的经典例题：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%%% 替换元组或列表中指定位置的元素，新元素作为参数和列表或元组一起传入函数内

%% API
-export([replaceIdx/3]).

replaceIdx(List, Index, Val) -&amp;gt;
    replaceIdx(List, Index, Val, 1, []).

%% 列表空后反转累加器。
replaceIdx([], _, _, _, Acc) -&amp;gt;
    lists:reverse(Acc);

%% 到达替换位置的处理：把Val放到累计器的头部
replaceIdx([_ | Rest], Index, Val, Index, Acc) -&amp;gt;
%%    io:format(&quot;[~p]~n&quot;, [[Val | Acc]]),
    replaceIdx(Rest, Index, Val, Index + 1, [Val | Acc]);

%% 未到达指定位置：把头元素放到累加器的头部。
replaceIdx([Element | Rest], Index, Val, CurrentIndex, Acc) -&amp;gt;
%%    io:format(&quot;[~p]~n&quot;, [[Element | Acc]]),
    replaceIdx(Rest, Index, Val, CurrentIndex + 1, [Element | Acc]).
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;case与if表达式&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;%%% 对数字列表中的奇数进行求和，后除以3的商得值为A，并将偶数求和后除以3的余数得值为B，然后求A+B结果，输出A、B、A+B

%% API
-export([get_res/1]).

%% 求和
get_sum([]) -&amp;gt; 0;
get_sum([H | T]) -&amp;gt; H + get_sum(T).

%% 求偶数和
get_even_sum([], Acc) -&amp;gt; Acc;
get_even_sum([H | T], Acc) -&amp;gt;
    %% 这里的case用来做一种类似if的判断，如果`H rem 2 = 0`说明是偶数，就把H加到累加器中。
    case H rem 2 of
        0 -&amp;gt; get_even_sum(T, Acc + H);
        _ -&amp;gt; get_even_sum(T, Acc)
    end.

%% 求值
get_res([H | T]) -&amp;gt;
    A = get_sum([H | T]) div 3,
    B = q5:get_even_sum([H | T], 0) rem 3,
    {A, B, A + B}.
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;%%% 查找元素在元组或列表中的位置

%% API
-export([get_index/3]).

get_index([], _, _) -&amp;gt; 0; %% 不会用到的参数用_传入即可。
get_index([H | T], N, Index) when (Index =&amp;lt; T) -&amp;gt;
    if
        (H == N) -&amp;gt;
            Index;
        true -&amp;gt;
            get_index(T, N, Index + 1)
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;%%% 移除元组或列表中指定位置的元素

%% API
-export([remove/2]).

remove(List, Position) -&amp;gt;
    case Position of
        1 -&amp;gt;
            [H | T] = List,
            T;
        N when N &amp;gt; 1 -&amp;gt;
            [H | T] = List,
            [H | remove(T, N - 1)]
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;列表推导&lt;/h4&gt;
&lt;p&gt;[ F(X) || X &amp;lt;- L]标记的意思是“由F(X)组成的列表（X从列表L中提取）”。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%%% 对数字列表或元组，输出所有偶数乘以它在此列表或元组中的偶数位数

%% API
-export([evens_mul/1]).

evens_mul(List) -&amp;gt;
    Even = evens(List, [], 1),
    [H * Idx || {H, Idx} &amp;lt;- Even].

evens([], Even, _) -&amp;gt;
    Even;
%% 先拿到偶数与坐标
evens([H | T], Even, Idx) -&amp;gt;
    if
        H rem 2 == 0 -&amp;gt;
            evens(T, [{H, Idx} | Even], Idx + 1);
        true -&amp;gt;
            evens(T, Even, Idx)
    end.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;冒泡排序&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;%%% 使用冒泡排序对列表进行排序

%% API
-export([bubble_sort/1]).

%% 取列表头作为最大值和
bubble_sort(List) -&amp;gt;
    bubble_sort(List, length(List)).

bubble_sort(List, 0) -&amp;gt; List; % 当迭代次数为 0 时，排序完成
bubble_sort(List, N) -&amp;gt;
    SortedList = bubble_pass(List, N), % 对列表进行下一趟冒泡,一个元素到达最终位置
    bubble_sort(SortedList, N - 1). % 递归的进行下一趟冒泡

bubble_pass([X, Y | Rest], N) when X &amp;gt; Y -&amp;gt;
    [Y | bubble_pass([X | Rest], N - 1)]; % 如果 X &amp;gt; Y 就交换他们
bubble_pass([X | Rest], N) -&amp;gt;
    [X | bubble_pass(Rest, N - 1)]; % 否则位置保持不变
bubble_pass([], _) -&amp;gt; [].
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;列表更方便的匹配方式&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;%%% 对一个字符串按指定符字劈分

%% API
-export([split/2]).

split(String, [C | _]) -&amp;gt;
    split_head(String, C, []).
split_tail([], _, RAcc) -&amp;gt;
    lists:reverse(RAcc);
split_tail([H | T], Seps, RAcc) -&amp;gt;
    split_tail(T, Seps, [H | RAcc]).
split_head([Seps | T], Seps, FAcc) -&amp;gt;
    [lists:reverse(FAcc), split_tail(T, Seps, [])];
split_head([H | T], Seps, FAcc) -&amp;gt;
    split_head(T, Seps, [H | FAcc]).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中&lt;code&gt;split_head([Seps | T], Seps, FAcc)&lt;/code&gt;为在传参，条件判断的时候就进行了匹配，更方便好用。&lt;/p&gt;
&lt;h4&gt;列表的链式反应&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;%%% 对相同类型的数据进行拼接

%% API
-export([merge_lists/2, merge_tuples/2, merge_binary/2]).

%% 列表拼接
merge_lists([], List2) -&amp;gt; List2;
merge_lists([Head | Tail], List2) -&amp;gt;
    [Head | merge_lists(Tail, List2)].

%% 元组拼接
merge_tuples(Tuple1, Tuple2) -&amp;gt;
    TupleList1 = tuple_to_list(Tuple1),
    TupleList2 = tuple_to_list(Tuple2),
    Tuples = merge_lists(TupleList1, TupleList2),
    list_to_tuple(Tuples).

%% 二进制拼接
merge_binary(Binary1, Binary2) -&amp;gt;
    BinaryList1 = binary_to_list(Binary1),
    BinaryList2 = binary_to_list(Binary2),
    BinaryList = merge_lists(BinaryList1, BinaryList2),
    list_to_binary(BinaryList).

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;[Head | merge_lists(Tail, List2)]&lt;/code&gt;为链式反应，不断把每次递归的头结点依次塞到该列表内。&lt;/p&gt;
&lt;h3&gt;字符串相关练习题&lt;/h3&gt;
&lt;h4&gt;回文题&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;%%% 检查一个字符串是否是回文

%% API
-export([check/1]).

check(String) -&amp;gt;
    Middle = (length(String) div 2) + (length(String) rem 2),
    split_string(String, Middle, 1, []).
split_string([_ | T], Index, Index, Acc) -&amp;gt;
    check_equal(lists:reverse(Acc), split_string_right(T, []));
split_string([H | T], Index, CIndex, Acc) -&amp;gt;
    split_string(T, Index, CIndex + 1, [H | Acc]).
split_string_right([], Acc) -&amp;gt;
    Acc;
split_string_right([H | T], Acc) -&amp;gt;
    split_string_right(T, [H | Acc]).
check_equal(List, List) -&amp;gt;
    true;
check_equal(_, _) -&amp;gt;
    false.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;多层嵌套&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;%%% 查找一个字符串中的最长单词

%% API
-export([check_max_length/1]).

%% 经过测试，空格是32
check_max_length(String) -&amp;gt;
    check_max_length(String, 32, 0, 0).
check_max_length([], _, Length, Max) -&amp;gt;
    check_max(Length, Max);
check_max_length([Seps | T], Seps, Length, Max) -&amp;gt;
    check_max_length(T, Seps, 0, check_max(Length, Max));
check_max_length([_ | T], Seps, Length, Max) -&amp;gt;
    check_max_length(T, Seps, Length + 1, Max).
check_max(Length1, Length2) -&amp;gt;
    if
        Length1 &amp;gt; Length2 -&amp;gt;
            Length1;
        true -&amp;gt;
            Length2
    end.
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Web3.0与区块链简单调研</title><link>https://blog-yunsheng.cn/posts/archives/old-post/web3/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/web3/</guid><description>关于Web3.0的简单调研。</description><pubDate>Wed, 13 Dec 2023 14:57:33 GMT</pubDate><content:encoded>&lt;h1&gt;Web1.0、Web2.0、Web3.0简述&lt;/h1&gt;
&lt;h2&gt;关于 Web 1.0 、Web 2.0 、Web 3.0 不同点:&lt;/h2&gt;
&lt;p&gt;Web 1.0 是用户&lt;strong&gt;读取互联网&lt;/strong&gt;，Web 2.0 是用户&lt;strong&gt;写入互联网&lt;/strong&gt;，Web3 是用户&lt;strong&gt;生活在互联网&lt;/strong&gt;。&lt;/p&gt;
&lt;h3&gt;Web1.0简述&lt;/h3&gt;
&lt;p&gt;Web 1.0：第一代互联网，静态互联网；&lt;/p&gt;
&lt;p&gt;Web 1.0 的核心为：&lt;strong&gt;平台创造、平台所有、平台控制、平台受益&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;代表：静态网页、传统报刊、Yahoo&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;所谓的Web1.0，从&lt;strong&gt;用户角度&lt;/strong&gt;来看，就是由平台单方面向用户输送信息，而用户仅具备&lt;strong&gt;只读&lt;/strong&gt;权利，平台输送什么信息，用户就看什么信息。&lt;em&gt;&lt;strong&gt;即我的这个博客也就是Web1.0&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Web2.0简述&lt;/h3&gt;
&lt;p&gt;Web 2.0：第二代互联网，交互式互联网；&lt;/p&gt;
&lt;p&gt;Web 2.0 的核心为：&lt;strong&gt;用户创造、平台所有、平台控制、平台受益&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;代表：微博、Facebook&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Web 2.0也是目前网络上最主要的形式，在Web2.0上，平台只需提供一个基础设施及环境，但&lt;strong&gt;平台创造的内容占比较小&lt;/strong&gt;，且&lt;strong&gt;鼓励用户自我创作&lt;/strong&gt;。在整个创作的环境、发布的平台、读者的阅读等，都将由平台掌握。&lt;/p&gt;
&lt;p&gt;从用户角度来看 Web2.0，用户观看了其他用户在平台所创造的内容及收益，于是自己也想创造新的内容，这是&lt;strong&gt;创造者数量激增&lt;/strong&gt;的原因。用户在&lt;strong&gt;遵守平台规则&lt;/strong&gt;的同时，获得内容带来的&lt;strong&gt;收益&lt;/strong&gt;，同时对自己的账户及内容有极大的自主&lt;strong&gt;控制权&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这无疑是平台为用户营造了一种虚假 Web3.0 的情况，因为无论是&lt;strong&gt;归属权&lt;/strong&gt;、&lt;strong&gt;管理权&lt;/strong&gt;还是&lt;strong&gt;利益分配&lt;/strong&gt;，看似都在用户手中，实则均为平台说了算。&lt;/p&gt;
&lt;h3&gt;Web3.0简述&lt;/h3&gt;
&lt;p&gt;Web 3.0：第三代互联网，协议互联网；&lt;/p&gt;
&lt;p&gt;Web 3.0 的核心为：&lt;strong&gt;用户创造、用户所有、用户控制、协议分配利益&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;代表：区块链、元宇宙、NFT&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在 Web 3.0 中，&lt;strong&gt;用户所创造的数字内容，归属权明确为用户所有，控制管理权明确由用户所有，其所创造的价值，根据用户与他人签订的协议进行分配。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Web3.0的特征&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Web3.0是分布式的&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;（1）它不是集中式的，就没有单一的公司可以控制它；&lt;/p&gt;
&lt;p&gt;（2）任何一种服务都有多家提供商，通过分布式协议连起来，用户可以极小的成本，从一个提供商转移到另一个服务商。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;这里有个疑问，Web3.0真的能在中国的环境里成长吗？换句话说我国会允许Web3.0存在吗？&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Web3.0利用区块链的协议创造与自动执行的技术，即通过&lt;strong&gt;智能合约&lt;/strong&gt;，权利与价值的分配协议可以不通过第三方，即得到高效、准确、可信的执行，并且全过程可审计。用一句通俗易懂的话来说，就是“&lt;strong&gt;没有中间商赚差价&lt;/strong&gt;”。但区块链只是手段，目的是&lt;strong&gt;实现用户数字资产权益的确认和保护&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Web3.0的核心特色是去中心化，用户的行为生成的一系列数据构成的资源库，并不是由某一个中心化的平台或媒体所掌握，而是大众共同拥有所有权和使用权。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;区块链&lt;/h1&gt;
&lt;h2&gt;区块链简述&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;区块链本质上是一个去中心化数据库&lt;/strong&gt;。是一种分布式数据存储，点对点传输，共识机制，加密算法等计算机技术的新型应用模式。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;举例：&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;比如说小明找大康借一百块钱，但大康怕他赖账，于是就找来村长做公证，并记录下这笔账，这个就叫&lt;strong&gt;中心化&lt;/strong&gt;。但如果，你不找村长，直接拿个喇叭在村里大喊“我大康借给小明一百块钱！请大家记在账本里”，这个就叫&lt;strong&gt;去中心化&lt;/strong&gt;。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;以前村长德高望重，掌握全村的账本，大家都把钱存在他这里，这是过去大家对中心化的信任。现在，大家都担心村长会偷偷挪用大家的钱，怎么办呢？ 于是大家就给每个人都发了一本账本，任何人之间转账都通过大喇叭发布消息，收到消息后，每个人都在自家的账本上记下这笔交易，这就叫去中心化。有了分布式账本，即使老孔或老周家的账本丢了也没关系，因为老朱、老杨等其他家都有账本。&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;区块链特点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;去中心化&lt;/li&gt;
&lt;li&gt;开放性&lt;/li&gt;
&lt;li&gt;安全&lt;/li&gt;
&lt;li&gt;不可篡改&lt;/li&gt;
&lt;li&gt;匿名性&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h1&gt;其他&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/508466425&quot;&gt;什么是Web3？和区块链的关系是什么？ - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.sohu.com/a/742326427_121124362&quot;&gt;区块链白皮书（2023）问世，Web3.0助力网络空间安全_发展_数字_创新 (sohu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://new.qq.com/rain/a/20231204A01IJJ00&quot;&gt;Web3.0出海：日本区块链行业监管政策介绍_腾讯新闻 (qq.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/461804396&quot;&gt;粗谈区块链与Web3.0 - 知乎 (zhihu.com)&lt;/a&gt;：关于以太坊部分很有趣，对于区块链讲解很易懂。&lt;/p&gt;
&lt;p&gt;个人对于何为赋值的新理解：将虚拟货币送给我的朋友，当然了现在它是没有任何价值的，因为我没有对其赋予任何价值。如果哪一天我公布说谁拥有这个虚拟货币，可以来找我领取10W人民币，那么瞬间，它的价值就是10W人民币。&lt;strong&gt;即一个产品是否真的能转化为真实的价值。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.36kr.com/p/1538266122446341&quot;&gt;什么是Web3，为什么币圈的人都开始谈Web3了？-36氪 (36kr.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E4%BB%A5%E5%A4%AA%E5%9D%8A&quot;&gt;以太坊 - 维基百科，自由的百科全书 (wikipedia.org)&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;参考资料&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/451172211&quot;&gt;一文读懂&quot;什么是 Web 3.0 ？&quot; - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.ruanyifeng.com/blog/2021/12/web3.html&quot;&gt;为什么 Web3 与区块链有关 - 阮一峰的网络日志 (ruanyifeng.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/346493198&quot;&gt;区块链是什么通俗解释 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://finance.sina.com.cn/blockchain/roll/2022-06-28/doc-imizmscu9080046.shtml&quot;&gt;Web3.0与区块链有何不同？现在处于哪个阶段？|区块链_新浪财经_新浪网 (sina.com.cn)&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Vercel+CloudFlare实现近零成本Twikoo评论系统CDN加速</title><link>https://blog-yunsheng.cn/posts/archives/old-post/vercel-cloudflare-twikoo/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/vercel-cloudflare-twikoo/</guid><description>6块钱一年的奶茶（域名）钱，加一两个小时的宝贵时间，同样也可用于网站加速等等。</description><pubDate>Thu, 23 Nov 2023 09:54:03 GMT</pubDate><content:encoded>&lt;h2&gt;问题分析&lt;/h2&gt;
&lt;p&gt;可以通过Vercel对Twikoo评论系统服务进行免费的部署，但因为&lt;code&gt;*.vercel.app&lt;/code&gt;因某种不可抗力在国内无法访问，所以用到了CloudFlare的免费CDN服务，来实现对评论系统的加速，实现国内网络环境也能访问的效果。&lt;/p&gt;
&lt;h2&gt;前置工作&lt;/h2&gt;
&lt;p&gt;已在Vercel成功部署Twikoo。&lt;/p&gt;
&lt;p&gt;CloudFlare账户。&lt;/p&gt;
&lt;p&gt;至少4块钱。&lt;/p&gt;
&lt;h2&gt;解决过程&lt;/h2&gt;
&lt;p&gt;成本一共6元钱——在腾讯云随便注册一个便宜的域名。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;腾讯云控制台&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在域名DNS解析里选快速添加解析，输入Vercel中项目的Domains地址，例如&lt;code&gt;*.vercel.app&lt;/code&gt;，快速添加解析记录。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Vercel&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;进入Domains界面下，添加刚注册域名的域名，选择第三项，添加。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;CloudFlare&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;点击&lt;code&gt;add site&lt;/code&gt;输入自己的域名，一直下一步。&lt;/p&gt;
&lt;p&gt;按照CloudFlare提示更换nameservers，具体为在腾讯云控制台，进入我的域名，选择修改DNS服务器，将CloudFlare提供的DNS服务器添加上去。&lt;/p&gt;
&lt;p&gt;等待一段时间即可。&lt;/p&gt;
&lt;h2&gt;后记&lt;/h2&gt;
&lt;p&gt;因为免费的CloudFlare服务，其服务器在中国以外，实际上并不稳定，但是已经比原本一定不能访问到要强很多了，偶尔评论系统连接出现问题属正常现象。&lt;/p&gt;
&lt;p&gt;关于&lt;a href=&quot;https://blog-yunsheng.cn/2023/11/21/CDN%E8%AE%BF%E9%97%AE%E5%BC%82%E5%B8%B8%E4%B9%8B%E9%87%8D%E5%AE%9A%E5%90%91%E6%AC%A1%E6%95%B0%E8%BF%87%E5%A4%9A/&quot;&gt;CDN访问异常之重定向次数过多&lt;/a&gt;的问题，在我的上一篇文章里有写过了，遇到问题的伙伴可以看看，希望能有所帮助。&lt;/p&gt;
</content:encoded></item><item><title>CDN访问异常之重定向次数过多</title><link>https://blog-yunsheng.cn/posts/archives/old-post/cdn-redirect-exception/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/cdn-redirect-exception/</guid><description>为博客开启CDN后访问出现重定向次数过多异常的解决。</description><pubDate>Thu, 21 Sep 2023 15:53:37 GMT</pubDate><content:encoded>&lt;h2&gt;问题原因&lt;/h2&gt;
&lt;p&gt;源站开启了HTTP重定向至HTTPS的功能，并且CDN控制台上配置的回源端口为80。在这种情况下，由于CDN回源端口为80，客户端无论是通过HTTP还是HTTPS访问CDN加速域名时，CDN在回源的时候都是使用HTTP请求源站，此时会触发源站的HTTPS强制跳转逻辑，然后源站会要求CDN重新发送一个HTTPS的请求，但是CDN回源的时候仍然会发送HTTP回源请求，然后再进行跳转，以此类推，就会出现反复重定向问题，最终导致出现报错。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231121155518294.png&quot; alt=&quot;image-20231121155518294&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;可见无限301重定向的情况&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;解决方法&lt;/h2&gt;
&lt;p&gt;查了一下相关资料，CloudFlare导致的重定向次数过多可以通过将“SSL/TLS 加密模式”设置为完全（Strict）解决。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231121160250278.png&quot; alt=&quot;image-20231121160250278&quot; /&gt;&lt;/p&gt;
&lt;p&gt;其他产品的CDN可以通过将回源端口设置为443来解决，CDN回源时会以HTTPS协议请求源站，就不会触发源站的强制跳转逻辑。&lt;/p&gt;
&lt;p&gt;另一种方法是将协议跟随回源设置为“跟随”。设置为跟随以后，源站发起HTTPS重定向以后，CDN回源协议跟随为HTTPS回源。&lt;/p&gt;
&lt;h2&gt;经验总结&lt;/h2&gt;
&lt;p&gt;自行用F12控制台分析网络连接情况，定位问题，然后查找相关资料。&lt;/p&gt;
</content:encoded></item><item><title>计算机开发综合知识总结（偏Java方向）</title><link>https://blog-yunsheng.cn/posts/archives/old-post/comprehensive-java/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/comprehensive-java/</guid><description>计算机开发综合知识总结，包括操作系统、数据结构、计算机网络、数据库、编程等，好累…………┭┮﹏┭┮</description><pubDate>Thu, 24 Aug 2023 02:44:45 GMT</pubDate><content:encoded>&lt;h1&gt;数据结构&lt;/h1&gt;
&lt;h2&gt;列表&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;数组&lt;/li&gt;
&lt;li&gt;链表&lt;/li&gt;
&lt;li&gt;队列，栈&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;树&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;二叉树&lt;/li&gt;
&lt;li&gt;搜索树&lt;/li&gt;
&lt;li&gt;堆/优先队列&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;push(1);push(3);push(2);pop();pop();pop();
栈：2; 3; 1
队列：1; 3; 2
优先队列：1; 2; 3
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;图&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;无向图&lt;/li&gt;
&lt;li&gt;有向图&lt;/li&gt;
&lt;li&gt;有向无环图&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;图的算法&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;深度优先遍历&lt;/li&gt;
&lt;li&gt;广度优先遍历&lt;/li&gt;
&lt;li&gt;拓扑排序&lt;/li&gt;
&lt;li&gt;最短路径/最小生成树&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java集合类型&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;image-20231029171954123-1698571199741-1.png&quot; alt=&quot;image-20231029171954123&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;ArrayList和LinkedList的区别&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;都是线性表的结构，他们都是List接口，但是实现不同，ArrayList是数组实现，LinkedList是链表实现。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;HashMap和Hashtable的区别&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hashtable是Java 1的遗留产物；&lt;/p&gt;
&lt;p&gt;Hashtable不允许null；&lt;/p&gt;
&lt;p&gt;Hashtable线程安全，因为所有危险函数都加了synchronized（一种同步锁），会让开销变得很大；&lt;/p&gt;
&lt;p&gt;HashMap更快，想要线程安全用ConcurrentHashMap。&lt;/p&gt;
&lt;h2&gt;二叉树&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;前序遍历
&lt;ul&gt;
&lt;li&gt;先遍历树根&lt;/li&gt;
&lt;li&gt;前序遍历左子树&lt;/li&gt;
&lt;li&gt;前线遍历右子树&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;中序遍历
&lt;ul&gt;
&lt;li&gt;中序遍历左子树&lt;/li&gt;
&lt;li&gt;遍历树根&lt;/li&gt;
&lt;li&gt;中序遍历右子树&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;后序遍历
&lt;ul&gt;
&lt;li&gt;后序遍历左子树&lt;/li&gt;
&lt;li&gt;后序遍历右子树&lt;/li&gt;
&lt;li&gt;遍历树根&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;二叉树的性质&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;非空二叉树上第k层上至多有$2^{k-1}$个结点（k&amp;gt;=1）&lt;/li&gt;
&lt;li&gt;高度为h的二叉树至多有$2^h-1$个结点（h&amp;gt;=1）
&lt;ul&gt;
&lt;li&gt;满二叉树：高度为h的有$2^h-1$个结点（h&amp;gt;=1）的二叉树&lt;/li&gt;
&lt;li&gt;满二叉树：每一层有$2^{k-1}$个结点&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;非空二叉树上的叶节点数等于度为2的结点数加1，即$n_0$=$n_2$+1
&lt;ul&gt;
&lt;li&gt;设度为0，1，2的结点个数分别为$n_0,n_1,n_2$，结点总数$n=n_0+n_1+n_2$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;具有n个（n&amp;gt;0）结点的完全二叉树的高度为$log_2(n+1)$（n向上取整）或$log_2n+1$（n向下取整）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;根据前序中序构造二叉树&lt;/h3&gt;
&lt;p&gt;前序：树根 + （左子树 + 右子树）&lt;/p&gt;
&lt;p&gt;中序：（左子树） + 树根 + （右子树）&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;递归思想，不停找树根，定左右子树，即可构造出二叉树！&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;二叉查找树和中序遍历&lt;/h4&gt;
&lt;p&gt;因为二叉查找树每一个左子树都比根小，每一个右子树都比根大，所以它的中序遍历序列是从小到大的。&lt;/p&gt;
&lt;h3&gt;B/B+树&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/a519640026/article/details/106940115&quot;&gt;一文彻底搞懂MySQL基础：B树和B+树的区别_mysql b树和b+树的区别-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;m阶B/B+树&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个非叶子节点（除根外）至多有m个儿子，至少有[m/2]个儿子&lt;/li&gt;
&lt;li&gt;根节点（如果不是叶子）至少有两个儿子&lt;/li&gt;
&lt;li&gt;所有叶子节点在同一层&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;B/B+树的区别&lt;/h4&gt;
&lt;p&gt;B树的值可以出现在非叶子节点上，B+树真正有用的东西全在叶子节点上，它的根和非叶子节点作用在于帮助找到这个真正的数值所在的地方。&lt;/p&gt;
&lt;h4&gt;B树和二叉搜索树的区别&lt;/h4&gt;
&lt;p&gt;B树的每一个节点可以放更多的元素，可以有更多的儿子——为了优化磁盘的读写次数（磁盘存取次数与B树的高度成正比）。&lt;/p&gt;
&lt;h3&gt;红黑树&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/cy973071263/article/details/122543826&quot;&gt;【精选】【数据结构】史上最好理解的红黑树讲解，让你彻底搞懂红黑树_小七mod的博客-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;进制转换&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;例：13 --&amp;gt; 三进制 --&amp;gt; 111&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;1 * 3 * 3 + 1 * 3 + 1 = 13&lt;/p&gt;
&lt;p&gt;13 % 3 = 1         13 / 3 = 4&lt;/p&gt;
&lt;p&gt;4 % 3 = 1            4 / 3 = 1&lt;/p&gt;
&lt;p&gt;1 % 3 = 1            1 / 3 = 0&lt;/p&gt;
&lt;h2&gt;二进制运算&lt;/h2&gt;
&lt;h3&gt;位运算&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;与（&amp;amp;）（两位同时为 1，结果才为 1，否则为 0）&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;  1 0 0 1 1
&amp;amp; 1 1 0 0 1
------------------------------
  1 0 0 0 1
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;或（|）（参加运算的两个位只要有一个为 1，其值为 1 ）&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;  1 0 0 1 1
| 1 1 0 0 1
------------------------------
  1 1 0 1 1
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;异或（^）（参加运算的两个位只要不相同则为 1）&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;  1 0 0 1 1
^ 1 1 0 0 1
-----------------------------
  0 1 0 1 0
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;取反（~）（0 则变为 1，1 则变为 0）&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;~ 1 0 0 1 1
-----------------------------
  0 1 1 0 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;实例&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int a = 5; //二进制表示为 101
int b = 3; //二进制表示为 011
int c = a &amp;amp; b; //与运算，结果为 001，即 1
int d = a | b; //或运算，结果为 111，即 7
int e = a ^ b; //异或运算，结果为 110，即 6
int f = ~a; //取反运算，结果为 11111111111111111111111111111010，即-6
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;移位运算&lt;/h3&gt;
&lt;p&gt;位运算包括左移（&amp;lt;&amp;lt;）、右移（&amp;gt;&amp;gt;）以及无符号右移（&amp;gt;&amp;gt;&amp;gt; , 无符号右移就是右移之后，无 论该数为正还是为负，右移之后左边都是补上 0），它们分别将一个二进制数左移或右移一定 的位数。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int a = 5; //二进制表示为 101
int b = a &amp;lt;&amp;lt; 1; //左移一位，结果为 1010，即 10
int c = a &amp;gt;&amp;gt; 1; //右移一位，结果为 10，即 2
int d = a &amp;gt;&amp;gt;&amp;gt; 1; //无符号右移一位，结果为 10，即 2
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;位运算赋值运算符&lt;/h3&gt;
&lt;p&gt;位运算赋值运算符（&amp;amp;=、|=、^=、&amp;lt;&amp;lt;=、&amp;gt;&amp;gt;=、&amp;gt;&amp;gt;&amp;gt;=）是将位运算结果赋值给左操作数的运算。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int a = 5; //二进制表示为 101
int b = 3; //二进制表示为 011
a &amp;amp;= b; //相当于 a = a &amp;amp; b 
a |= b; //相当于 a = a | b
a ^= b; //相当于 a = a ^ b
a &amp;lt;&amp;lt;= 1; //相当于 a = a &amp;lt;&amp;lt; 1
a &amp;gt;&amp;gt;= 1; //相当于 a = a &amp;gt;&amp;gt; 1
a &amp;gt;&amp;gt;&amp;gt;= 1; //相当于 a = a &amp;gt;&amp;gt;&amp;gt; 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;操作系统&lt;/h1&gt;
&lt;h2&gt;进程和线程&lt;/h2&gt;
&lt;p&gt;进程包含若干个线程、逻辑内存（不同进程间的内存相互独立——为了安全性）以及文件/网络句柄（不同进程所共有的，以打开同一个文件或抢同一个网络的端口）。&lt;/p&gt;
&lt;p&gt;线程包含栈、PC（放在内存中；下一条执行指令的地址）以及TLS。&lt;/p&gt;
&lt;p&gt;操作系统实际真正在运行的是一个一个的线程，进程只是一个容器。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/shaomingmin/article/details/106180380&quot;&gt;Java线程基本方法详解_java中线程相关的基本方法-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;线程让步可以通过 yield ()方法来实现,该方法和 sleep ()方法有点相似,都可以让当前正在运行的线程暂停,区别在于 yield() 方法不会阻塞该线程,它只是将线程转换成就绪状态,让系统的调度器重新调度一次。当某个线程调用 yield ()方法之后,只有与当前线程优先级相同或者更高的线程才能获得执行的机会。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;线程安全不安全的区别在于有没有加锁机制。&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;存储&lt;/h2&gt;
&lt;p&gt;快	寄存器	贵&lt;/p&gt;
&lt;p&gt;|            缓存           |&lt;/p&gt;
&lt;p&gt;|            内存           |&lt;/p&gt;
&lt;p&gt;慢	  硬盘	 便宜&lt;/p&gt;
&lt;h2&gt;寻址空间&lt;/h2&gt;
&lt;p&gt;进程里面指针能取到的地址的范围。&lt;/p&gt;
&lt;p&gt;32位--&amp;gt;4G&lt;/p&gt;
&lt;p&gt;64位--&amp;gt;~10^19Bytes&lt;/p&gt;
&lt;h2&gt;进程间通信&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;文件&lt;/li&gt;
&lt;li&gt;Signal               Linux上常见&lt;/li&gt;
&lt;li&gt;消息队列&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/scarificed/article/details/121475146&quot;&gt;消息队列（定义、结构、如何创建、消息队列的发送与接收、发送与接收实例）_消息队列的数据结构_咋么又饿了的博客-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/9a0e9ffa17dd&quot;&gt;MQ（消息队列）功能介绍 - 简书 (jianshu.com)&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;管道/命名管道&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;匿名管道&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;匿名管道主要用于本地父进程和子进程之间的通信，只支持半双工通信。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;第一：匿名管道只能实现本地进程之间的通信，不能实现跨网络之间的进程间的通信。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;第二：匿名管道只能实现父进程和子进程之间的通信，而不能实现任意两个本地进程之间的通信。&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;共享内存&lt;/li&gt;
&lt;li&gt;同步机制，如信号量&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;信号量是一个计数器，可以用来控制多个进程对共享资源的访问。它常会被作为一种锁机制，用于防止某进程正在访问共享资源时，其他进程也来访问该资源。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Socket           重要&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Socket 连接是计算机网络中的一种通信机制，它允许两个程序在不同计算机上通过网络进行通信。在使用套接字进行通信时，一个程序作为客户端，另一个程序作为服务器端，它们通过创建和使用套接字进行数据传输。我们可以将套接字理解为网络通信的接口，它提供了一种标准的通信方式，使得不同的程序能够在网络上进行数据交换。&lt;/p&gt;
&lt;p&gt;在Socket 连接中，客户端程序首先会向服务器端发送一个连接请求，服务器端会接受这个连接请求，然后通过套接字与客户端进行通信。在通信过程中，客户端和服务器端通过套接字发送和接收数据。一旦通信完成，连接就会被断开，套接字也会被关闭。&lt;/p&gt;
&lt;p&gt;（1）在计算机网络中，Socket 连接是一种重要的通信机制。它允许两个程序在不同计算机上进行实时通信，通过套接字的创建和使用来实现数据的传输。&lt;/p&gt;
&lt;p&gt;（2）在 Socket 连接中，我们需要指定套接字的一些参数，例如 IP 地址、端口号、协议等等，以确保通信能够顺利进行。&lt;/p&gt;
&lt;p&gt;（3）常见的协议有 TCP 和 UDP 两种，它们在数据传输的方式和效率上有所不同。&lt;/p&gt;
&lt;p&gt;​        TCP 协议是一种可靠的协议，它保证数据在传输过程中不会丢失或损坏。TCP 协议通过连接的建立、数据的传输和连接的释放等步骤来保证数据的完整性和可靠性。TCP 协议适合于需要数据传输可靠性的场合，例如文件传输、网页浏览等。&lt;/p&gt;
&lt;p&gt;​        UDP 协议是一种不可靠的协议，它不对数据传输的可靠性做出保证。UDP 协议的传输速度比 TCP 更快，但在传输过程中数据可能会丢失或损坏。UDP 协议适合于实时通信，例如视频和音频流的传输。&lt;/p&gt;
&lt;p&gt;（4）Socket 连接被广泛应用于网络游戏、视频和音频流、文件传输、网络聊天、远程控制等方面。&lt;/p&gt;
&lt;h2&gt;中断&lt;/h2&gt;
&lt;p&gt;中断（interrupt）是指CPU对I/O设备发来的中断信号的一种响应。CPU暂停正在执行的程序，保存CPU现场环境后，自动转去执行该I/O设备的中断处理程序。执行完后再回到断点，继续执行原来的程序。陷入和陷阱（trap）时由CPU内部事件所引起的中断。中断和陷入的主要区别是信号的来源不同，即来自CPU外部（外中断或硬中断）还是CPU内部（内中断或软中断）。&lt;/p&gt;
&lt;h2&gt;同步&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;原子操作 (Atomic)。是指比如在一个原子操作哪检查和增加一个变量的值，中间不被打断。这保证了数据的完整性。但对于运行时长，其实没啥关系。&lt;/li&gt;
&lt;li&gt;互斥锁 (Mutex)。互斥，就是我只让一个人干活，其他人都等着。然后这个人运行时间还长，占着这个锁不放，系统的性能就非常低了。因此互斥锁更好的用于运行时间较短的任务。&lt;/li&gt;
&lt;li&gt;自旋锁 (SpinLock)。这个锁采用了不是被挂起，而是通过不断循环检查锁是否释放的机制。这个检查的过程是消耗CPU的。肯定只能适用于更短的任务。比如毫秒级。&lt;/li&gt;
&lt;li&gt;信号量 (Semaphore)。信号量是所有这些同步元语中稍微复杂的一种。信号量确保了同时最多只能有n个人占着“坑”干活。相对来说，这里面的活可以干的久一点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;同步和异步的区别&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;同步就相当于是当客户端发送请求给服务端，在等待服务端响应的请求时，客户端不做其他的事情。当服务端做完了才返回到客户端。这样的话客户端需要一直等待。用户使用起来会有不友好。&lt;/p&gt;
&lt;p&gt;异步就相当于当客户端发送给服务端请求时，在等待服务端响应的时候，客户端可以做其他的事情，这样节约了时间，提高了效率。&lt;/p&gt;
&lt;h2&gt;Linux系统&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.jianshu.com/p/2a14fe583cdf&quot;&gt;Linux命名空间概述&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;计算机网络&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;五层协议的体系结构&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;应用层&lt;/p&gt;
&lt;p&gt;运输层&lt;/p&gt;
&lt;p&gt;网络层&lt;/p&gt;
&lt;p&gt;数据链路层&lt;/p&gt;
&lt;p&gt;物理层&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OSI的体系结构&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;应用层&lt;/p&gt;
&lt;p&gt;表示层&lt;/p&gt;
&lt;p&gt;会话层&lt;/p&gt;
&lt;p&gt;运输层&lt;/p&gt;
&lt;p&gt;网络层&lt;/p&gt;
&lt;p&gt;数据链路层&lt;/p&gt;
&lt;p&gt;物理层&lt;/p&gt;
&lt;h2&gt;网络传输&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;不可靠&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;丢包，重复包&lt;/li&gt;
&lt;li&gt;出错&lt;/li&gt;
&lt;li&gt;乱序&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;不安全&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;中间人攻击&lt;/li&gt;
&lt;li&gt;窃取&lt;/li&gt;
&lt;li&gt;篡改&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;滑动窗口&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;TCP协议&lt;/li&gt;
&lt;li&gt;维持发送方/接收方缓冲区&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/xiaojie_570/article/details/87904328&quot;&gt;计算机网络（7）——滑动窗口_接收窗口跟滑动窗口的区别-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;能更好地利用带宽和流量控制。&lt;/p&gt;
&lt;h2&gt;TCP协议&lt;/h2&gt;
&lt;p&gt;建立连接-&amp;gt;三次握手:发[SYN];接[SYN, ACK];发[ACK]&lt;/p&gt;
&lt;p&gt;断开连接-&amp;gt;四次挥手:发[FIN];接[ACK];接[FIN];发[ACK]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/a19881029/article/details/38091243&quot;&gt;理解TCP序列号（Sequence Number）和确认号（Acknowledgment Number）_relative sequence number-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Acknowledgment number：期待收到的包。&lt;/p&gt;
&lt;p&gt;三次握手之后建立可靠的联系，可以发送HTTP协议。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;网络是不可靠的，任何包都有可能丢&lt;/li&gt;
&lt;li&gt;遇见问题，解决问题，不断迭代&lt;/li&gt;
&lt;li&gt;能用就好&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TCP协议要达成什么目的？&lt;/h4&gt;
&lt;p&gt;TCP协议是一种基于连接的协议，在连接的基础上达到一种可靠的传输。可靠的传输指发包的顺序和收包的顺序是一样的、能够保证包不出错、流量控制（不会发得太快来不及收）、拥塞控制（网络出现拥塞的时候不会使情况进一步恶化）。&lt;/p&gt;
&lt;h4&gt;TCP协议如何做到流量控制、拥塞控制？&lt;/h4&gt;
&lt;p&gt;流量控制：滑动窗口&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/tuyang1129/p/12439862.html&quot;&gt;计算机网络——TCP的拥塞控制（超详细） - 特务依昂 - 博客园 (cnblogs.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;因为网络层不会提供拥塞的反馈信息，所以&lt;strong&gt;TCP协议采用的是第一种方式——自己判断网络的拥塞情况&lt;/strong&gt;。当&lt;code&gt;TCP&lt;/code&gt;检测到网络拥塞，则降低数据的发送速率，否则增加数据的发送速率。&lt;/p&gt;
&lt;h4&gt;TCP与UDP的区别&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;基于连接与无连接；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对系统资源的要求（TCP较多，UDP少）；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UDP程序结构较简单；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;流模式与数据报模式 ；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TCP保证数据正确性，UDP可能丢包；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TCP保证数据顺序，UDP不保证。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;部分例题&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;TCP采用的滑动窗口大小为0是合法的。&lt;/li&gt;
&lt;li&gt;传输问题，已知距离、数据大小、要求时间、传输速率，问发送缓冲区最小设置大小
&lt;ul&gt;
&lt;li&gt;一个来回的时间：       距离 / 传输速度 * 2&lt;/li&gt;
&lt;li&gt;来回的最多次数：       要求传输时间 / 一个来回的时间&lt;/li&gt;
&lt;li&gt;每次来回最少传输大小：         文件大小 / 来回的最多次数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;帧同步&lt;/h2&gt;
&lt;p&gt;帧同步是通过在&lt;a href=&quot;https://www.zhihu.com/search?q=%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93&amp;amp;search_source=Entity&amp;amp;hybrid_search_source=Entity&amp;amp;hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3134623660%7D&quot;&gt;数据传输&lt;/a&gt;过程中插入&lt;a href=&quot;https://www.zhihu.com/search?q=%E5%90%8C%E6%AD%A5%E5%AD%97%E8%8A%82&amp;amp;search_source=Entity&amp;amp;hybrid_search_source=Entity&amp;amp;hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3134623660%7D&quot;&gt;同步字节&lt;/a&gt;或同步信号来保证数据的同步。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/357973435&quot;&gt;【网络同步】浅析帧同步和状态同步 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;DHCP与NAT的含义与作用&lt;/h2&gt;
&lt;p&gt;两个协议都是IP协议。&lt;/p&gt;
&lt;p&gt;DHCP（&lt;a href=&quot;https://gw-c.nowcoder.com/api/sparta/jump/link?link=https%3A%2F%2Fbaike.baidu.com%2Fitem%2F%E5%8A%A8%E6%80%81%E4%B8%BB%E6%9C%BA%E9%85%8D%E7%BD%AE%E5%8D%8F%E8%AE%AE%2F10778663&quot;&gt;动态主机配置协议&lt;/a&gt;）是一个局域网的网络协议。指的是由服务器控制一段IP地址范围，客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。&lt;/p&gt;
&lt;p&gt;NAT英文全称是“Network Address Translation”，中文意思是“网络地址转换”，它允许一个整体机构以一个公用IP地址出现在Internet上。&lt;/p&gt;
&lt;p&gt;顾名思义，它是一种把内部私有网络地址（IP地址）翻译成合法网络IP地址的技术。简单的说，NAT就是在局域网内部网络中使用内部地址，而当内部节点要与外部网络进行通讯时，就在网关（可以理解为出口，打个比方就像院子的门一样）处，将内部地址替换成公用地址，从而在外部公网（internet）上正常使用，NAT可以使多台计算机共享Internet连接，这一功能很好地解决了公共IP地址紧缺的问题。&lt;/p&gt;
&lt;h2&gt;子网掩码&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;例：A和B的IP地址分别为10.105.1.113和10.105.1.91，它们需要在一个子网中，求他们的子网掩码，选出不能使用的那个&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;10.105.1.113&lt;/th&gt;
&lt;th&gt;10.105.1.91&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;00001010.01101001.00000001.01110001&lt;/td&gt;
&lt;td&gt;00001010.01101001.00000001.01011011&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;255.255.255.0&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.00000000&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.00000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;255.255.255.128&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.10000000&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.10000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;255.255.255.192&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.11000000&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.11000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;255.255.255.224&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.11100000&lt;/td&gt;
&lt;td&gt;11111111.11111111.11111111.11100000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可知到255.255.255.224时不能使用，其实……根本不用算，这道题可以直接盲选嘛。&lt;/p&gt;
&lt;h2&gt;SSH&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/li528405176/article/details/82810342&quot;&gt;SSH简介及两种远程登录的方法_ssh @-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Secure Shell(SSH) 是由 IETF(The Internet Engineering Task Force) 制定的建立在&lt;strong&gt;应用层&lt;/strong&gt;基础上的安全网络协议。它是专为远程登录会话(甚至可以用Windows远程登录Linux服务器进行文件互传)和其他网络服务提供安全性的协议，可有效弥补网络中的漏洞。通过SSH，可以把所有传输的数据进行加密，也能够防止DNS欺骗和IP欺骗。还有一个额外的好处就是传输的数据是经过压缩的，所以可以加快传输的速度。目前已经成为Linux系统的标准配置。&lt;/p&gt;
&lt;p&gt;SSH之所以能够保证安全，原因在于它采用了非对称加密技术(RSA)加密了所有传输的数据。&lt;/p&gt;
&lt;h1&gt;数据库&lt;/h1&gt;
&lt;h2&gt;关系型数据库&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;基于关系代数理论&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缺点：表结构不直观，实现复杂，速度慢&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;优点：健壮性高，社区庞大&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;事务&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;事务管理（ACID）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;原子性（Atomicity）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;原子性是指事务是一个不可分割的工作单位，事务中的操作要么都发生，要么都不发生。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一致性（Consistency）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;事务前后数据的完整性必须保持一致。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;隔离性（Isolation）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;事务的隔离性是多个用户并发访问数据库时，数据库为每一个用户开启的事务，不能被其他事务的操作数据所干扰，多个并发事务之间要相互隔离。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;持久性（Durability）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;持久性是指一个事务一旦被提交，它对数据库中数据的改变就是永久性的，接下来即使数据库发生故障也不应该对其有任何影响。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;事务的隔离级别&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read uncommitted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;读未提交，即一个事务可以读取另一个未提交事务的数据；并发操作会导致脏读。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read Committed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;读操作，即一个事务要等到另一个事务提交后才能读取数据；解决脏读问题；并发操作会导致不可重复读。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Repeatable Reads&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重复读，即开始读取数据（事务开启）时，不再允许修改操作；解决不可重复读问题；并发操作会导致幻读（对应insert操作）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serializable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;序列化，最高的事务隔离级别，该级别下，事务串行化顺序执行；避免脏读、不可重复读与幻读；但是该级别效率低下，比较消耗数据库性能，一般不用。&lt;/p&gt;
&lt;h2&gt;乐观锁&lt;/h2&gt;
&lt;p&gt;乐观锁假设认为数据一般情况下不会造成冲突，所以在数据进行提交更新的时候，才会正式对数据的冲突与否进行检测，如果发现冲突了，则让返回用户错误的信息，让用户决定如何去做。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;读取数据，记录Timestamp&lt;/li&gt;
&lt;li&gt;修改数据&lt;/li&gt;
&lt;li&gt;检查和提交数据&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/Dhaihaihai/article/details/110454553&quot;&gt;MySQL数据库的锁 --- 六种分类 - 14种锁详细介绍_mysql 数据库锁-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;重点看粒度&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;范式&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/xidianliuy/article/details/51566576&quot;&gt;什么是第一，第二，第三范式_第一范式第二范式第三范式的定义-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;第一范式：简单说 列不能再分&lt;/p&gt;
&lt;p&gt;第二范式：简单说 建立在第一范式基础上，消除部分依赖&lt;/p&gt;
&lt;p&gt;第三范式：简单说 建立在第二范式基础上，消除传递依赖。&lt;/p&gt;
&lt;h2&gt;索引&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/weixin_51486343/article/details/113351092&quot;&gt;【精选】MySQL 数据库--索引（理论详解及实例演示）_https://blog.csdn.net/weixin_51486343/article/deta-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最好把要查的字段都加上索引，不然会很慢，怎么知道有没有索引呢？用EXPLAIN去看，看type，ref就是对的。&lt;/p&gt;
&lt;p&gt;主键和外键会自动建索引，自己把要查的数据量大的字段加上索引。&lt;/p&gt;
&lt;h3&gt;索引的实现&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;B树&lt;/li&gt;
&lt;li&gt;B+树&lt;/li&gt;
&lt;li&gt;二叉树优先&lt;strong&gt;比较&lt;/strong&gt;次数，B/B+树优化&lt;strong&gt;磁盘&lt;/strong&gt;读写次数&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;数据库索引的作用&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;加快查找速度&lt;/li&gt;
&lt;li&gt;约束数据的值&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;数据库索引的分类&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/338629505&quot;&gt;浅谈 MySQL 索引的分类 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;数据库的连接池&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;建立连接要花很多时间&lt;/li&gt;
&lt;li&gt;每个用户建立连接造成浪费&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;内连接和外连接&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/dove_knowledge/article/details/71420206&quot;&gt;数据库-内连接与外连接的区别(举例说明)_数据库内连接和外连接的区别举例-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内连接：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;取出两张表中匹配到的数据，匹配不到的不保留。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;外连接：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;取出连接表中匹配到的数据，匹配不到的也会保留，其值为NULL。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;外连接的分类：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;左外连接，右外连接，全外连接&lt;/p&gt;
&lt;h2&gt;当前读和快照读&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当前读：每次读取的都是当前最新的数据，但是读的时候不允许写，写的时候也不允许读。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;快照读：读写不冲突，每次读取的是快照数据，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;隔离级别Repeatable Read下（默认隔离级别）：有可能读取的不是最新的数据&lt;/li&gt;
&lt;li&gt;Read Committed隔离级别下：快照读和当前读读取的数据是一样的，都是最新的。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;当前读&lt;/h3&gt;
&lt;p&gt;Mysql实现当前读是通过共享锁+排他锁+Next-Key Lock实现的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每次对行数据进行读取的时候，加共享锁。此时就不允许修改，但是允许其他事务读取，所以每次都可以读到最新的数据。&lt;/li&gt;
&lt;li&gt;每次对行数据进行修改的时候，加排他锁，不允许其他事务读取和修改。这种情况下其他事务读取的数据也一定是最新的数据。&lt;/li&gt;
&lt;li&gt;每次对范围行数据进行读取的时候，对这个范围加一个范围共享锁。&lt;/li&gt;
&lt;li&gt;每次对范围行数据进行修改的时候，读这个范围加一个范围排它锁。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;基于上述锁机制，实现当前读，确保每次读取的都是最新的数据。&lt;/p&gt;
&lt;h3&gt;快照读&lt;/h3&gt;
&lt;p&gt;mysql中的快照读是通过MVCC+undolog实现的。
快照读，顾名思义，就是读取快照数据，也就是说当某个数据正在被修改的时候，也可以进行读取该数据，保证读写不冲突。
刚刚提到undolog，当我们对记录做了变更操作时，就会产生undo记录，undo记录中存储的是老版数据，当一个旧的事务需要读取数据时，为了能够读取到老版本的数据，需要顺着undo列找到满足其可见性的记录，这个找满足可见行的记录依赖。就是说每次都是读取undolog中的数据。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;MVCC&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;MVCC也称多版本并发控制，说的通俗易懂一点就是记录数据的不同版本。
实际上，不同事务或者相同事务的对同一记录的修改，会导致该记录的undo log成为一条记录版本线性表，既链表，undo log的链首就是最新的旧记录，链尾就是最早的旧记录。
所以快照读都是去读取undolog中链首的最新的旧记录。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;undolog&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在操作数据之前,把需要操作的数据和事务记录备份到undo log中,目的就是为了保证原子性，如果一个事务执行中发生了故障，就可以通过undolog进行回滚。&lt;/p&gt;
&lt;h2&gt;常见问题&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;介绍一下关系型数据库的理论基础&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;基于关系代数理论，一到五范式。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;给定一个场景，请设计表结构&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;至少到三范式&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;如何生成安全且不易重复的数据库ID？&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;[如何生成安全且不易重复的数据库ID？_生成不重复id_谢少迪的博客-CSDN博客](https://blog.csdn.net/youngerxsd/article/details/131001528#:~:text=使用自增主键可能会暴露数据库信息，采用随机数生成id%2C而使用随机数作为ID有重复的风险，下面我提供一些建议。 1、UUID（通用唯一识别码）%3A,可以考虑使用UUID作为主键。 UUID是一个128位的数字，其生成算法旨在确保在不同计算机和时间上生成的ID具有极低的重复概率。)&lt;/p&gt;
&lt;h1&gt;程序设计与算法&lt;/h1&gt;
&lt;h2&gt;归类&lt;/h2&gt;
&lt;h3&gt;类型检查&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;编译时：C，C++，Java，GO&lt;/li&gt;
&lt;li&gt;运行时：Python，Perl，JavaScript，Ruby&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;运行/编译&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;编译为机器代码运行：C，C++&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;速度快&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编译为中间代码，在虚拟机运行：Java，C#&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;提供程序跨平台的能力&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;解释执行：Python，Perl，JavaScript&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不需要编译，看到一行代码就运行一行代码&lt;/p&gt;
&lt;h3&gt;编程范式（Programming Paradigm）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;面向过程：C，Visual Basic&lt;/li&gt;
&lt;li&gt;面向对象：Java，C#，C++，Scala&lt;/li&gt;
&lt;li&gt;函数式：Haskell，Erlang&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;常见问题&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;比较一下Java和C++语言&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;介绍一下面向对象思想&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;介绍一下函数式编程，函数式编程和函数指针的区别&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Java创建对象的几种方式&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/Yearingforthefuture/article/details/115843044&quot;&gt;【面试题】Java中创建对象的方式有几种？_创建对象的方式有哪些 面试题-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Java IO&lt;/h2&gt;
&lt;p&gt;Java 把 Input输入流 和 Output 输出流，统称为IO流，它的核心就是对文件的操作，对于 字节 、字符类型的输入和输出。&lt;/p&gt;
&lt;p&gt;IO流主要分为两大类，字节流和字符流。字节流可以处理任何类型的数据，如图片，视频等，字符流只能处理字符类型的数据。&lt;/p&gt;
&lt;p&gt;IO流的本质是数据传输，并且流是单向的。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/wugongzi/p/12092326.html&quot;&gt;Java——IO流超详细总结 - 说故事的五公子 - 博客园 (cnblogs.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/25418336&quot;&gt;Java IO学习整理 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;数据类型&lt;/h2&gt;
&lt;h3&gt;整数类型&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;32位int的范围&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;-2^31 ~ 2^31-1&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;补码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;取反加1&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;符号位可以和数值位一起参加运算&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可以直接利用加法的形式计算整数间的减法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;唯一表示0，没有+0，-0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;总共表示2^32个数&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;浮点数与定点数&lt;/h3&gt;
&lt;p&gt;64位double范围：+/-10^308&lt;/p&gt;
&lt;p&gt;64位double精度：10^15&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;浮点数比较&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为精度问题，直接比较经常出错，常用&lt;code&gt;Math.abs(a - b) &amp;lt; eps ?&lt;/code&gt;来判断&lt;/p&gt;
&lt;p&gt;使用BigDecimal算钱&lt;/p&gt;
&lt;h3&gt;Java数据类型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;primitive type: int, long, float ...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;值类型&lt;/li&gt;
&lt;li&gt;用&lt;code&gt;a == b&lt;/code&gt;来判断值相等&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Object: Integer, Long, Float, String ...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引用类型&lt;/li&gt;
&lt;li&gt;用&lt;code&gt;a == b&lt;/code&gt;判断是否为同一个Object&lt;/li&gt;
&lt;li&gt;用&lt;code&gt;a.equals(b)&lt;/code&gt;或&lt;code&gt;Object.equals(a, b)&lt;/code&gt;判断是否相等&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;什么是值传递，什么是引用传递&lt;/h4&gt;
&lt;p&gt;在Java里面primitive type之间就是值传递，Object之间就是引用传递。&lt;/p&gt;
&lt;p&gt;在C++里面值传递和引用传递由程序员说了算。&lt;/p&gt;
&lt;h4&gt;String s = new String(&quot;test&quot;);创建了多少对象&lt;/h4&gt;
&lt;p&gt;两个对象。&lt;/p&gt;
&lt;h4&gt;equals和hashCode的关系&lt;/h4&gt;
&lt;p&gt;hashCode相等不一定equal，但equal一定hashCode相等。&lt;/p&gt;
&lt;h4&gt;什么是序列化和反序列化&lt;/h4&gt;
&lt;p&gt;当我们把内存中的对象转成字节流就是序列化，反序列化就是把字节流还原成原来的对象放进内存。&lt;/p&gt;
&lt;h3&gt;装箱和拆箱&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Integer a = 2; // Boxing
Integer b = new Integer(2); // Boxing
int v = a.intValue(); // Unboxing
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;new Integer(2) == 2; // true--&amp;gt;编译的时候会自动帮我们拆箱
new Integer(2) == new Integer(2); // false
Integer.valueOf(2) == Integer.valueOf(2); // true 数值比较小的时候会分配到同一个箱子，但是当数值比较大的时候可能不会分配到同一个箱子，即可能true可能false
Integer.valueOf(2).intValue() == 2; // true
new Integer(2).equals(new Integer(2)); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;面向对象&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/jianyuerensheng/article/details/51602015&quot;&gt;面向对象编程三大特性------封装、继承、多态_面向对象，封装继承多态-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;就是分析出解决问题所需要的步骤，然后用函数把这些步骤一步一步实现，使用的时候一个一个依次调用就可以了。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;从用户（终端用户，使用代码的用户）的角度思考问题，摈弃完全基于逻辑的思维。（易读性）&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;封装&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互。也就是说用户是无需知道对象内部的细节，但可以通过该对象对外的提供的接口来访问该对象。&lt;/p&gt;
&lt;p&gt;对于封装而言，一个对象它所封装的是自己的属性和方法，所以它是不需要依赖其他对象就可以完成自己的操作。&lt;/p&gt;
&lt;p&gt;1、良好的封装能够减少耦合。&lt;/p&gt;
&lt;p&gt;2、类内部的结构可以自由修改。&lt;/p&gt;
&lt;p&gt;3、可以对成员进行更精确的控制。&lt;/p&gt;
&lt;p&gt;4、隐藏信息，实现细节。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;尽量只使用&lt;code&gt;private&lt;/code&gt;和&lt;code&gt;public&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;继承&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;继承是使用已存在的类的定义作为基础建立新类的技术，新类的定义可以增加新的数据或新的功能，也可以用父类的功能，但不能选择性地继承父类。&lt;/p&gt;
&lt;p&gt;1、子类拥有父类非private的属性和方法。&lt;/p&gt;
&lt;p&gt;2、子类可以拥有自己属性和方法，即子类可以对父类进行扩展。&lt;/p&gt;
&lt;p&gt;3、子类可以用自己的方式实现父类的方法。。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;多态&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个引用变量倒底会指向哪个类的实例对象，该引用变量发出的方法调用到底是哪个类中实现的方法，必须在由程序运行期间才能决定。&lt;/p&gt;
&lt;p&gt;Java实现多态有三个必要条件：继承、重写、向上转型。&lt;/p&gt;
&lt;h3&gt;不可变性&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;code&gt;final&lt;/code&gt;关键字&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;类声明--&amp;gt;类不可以被继承&lt;/li&gt;
&lt;li&gt;函数声明--&amp;gt;函数不可以在派生类中重写&lt;/li&gt;
&lt;li&gt;变量声明--&amp;gt;变量不可以指向其他对象&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;不可变性的实现&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;final&lt;/code&gt;关键字无法保证不可变性&lt;/li&gt;
&lt;li&gt;从接口定义，类的实现上保证不可变性&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;类与对象&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;类的成员变量--&amp;gt;对象状态&lt;/li&gt;
&lt;li&gt;类的成员函数--&amp;gt;对象行为&lt;/li&gt;
&lt;li&gt;类的静态变量&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;没有this引用，全局变量。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;类的静态函数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;普通函数可以引用静态变量、静态函数。&lt;/p&gt;
&lt;p&gt;静态函数引用普通成员变量、函数是编译错误的。&lt;/p&gt;
&lt;p&gt;对象上引用静态变量、函数会被编译器警告。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;类的特殊函数&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;构造函数&lt;/li&gt;
&lt;li&gt;equals&lt;/li&gt;
&lt;li&gt;hashCode&lt;/li&gt;
&lt;li&gt;toString&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;接口与抽象类&lt;/h3&gt;
&lt;p&gt;接口里面定义了很多函数，但是他们没有实现，这个就叫接口，它做到了一个合约的作用，明确对象需要满足什么样的要求。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;为什么要有接口的概念&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;从用户（使用实现的代码）角度看问题，用户不需要关心它是怎么实现的。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;接口与类相比&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;由编译器强制的一个模块间协作的合约（Contract）；&lt;/li&gt;
&lt;li&gt;无成员变量；&lt;/li&gt;
&lt;li&gt;成员函数只能申明不能有实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;接口的申明&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Java：interface BankEndPoint {...}&lt;/li&gt;
&lt;li&gt;C++：一个全部是纯虚函数的类&lt;/li&gt;
&lt;li&gt;Python/大部分动态语言：依靠注释申明&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;接口和抽象类的区别&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;从实现角度看&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;抽象类可以有成员变量&lt;/p&gt;
&lt;p&gt;抽象类可以有部分实现&lt;/p&gt;
&lt;p&gt;抽象类不可以多重继承，接口可以&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;父类/子类的实例化/析构顺序&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;实例化顺序为先父类再子类，析构反之。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;final(Java)和const(C++)的作用&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;final可以用在变量上也可以用在方法、类上。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/xingjiarong/article/details/47282255&quot;&gt;C语言中const关键字的用法-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;虚函数与纯虚函数&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.runoob.com/w3cnote/cpp-virtual-functions.html&quot;&gt;C++ 虚函数和纯虚函数的区别 | 菜鸟教程 (runoob.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;虚函数：它虚就虚在所谓&quot;推迟联编&quot;或者&quot;动态联编&quot;上，一个类函数的调用并不是在编译时刻被确定的，而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数，所以被称为&quot;虚&quot;函数。虚函数只能借助于指针或者引用来达到多态的效果。&lt;/p&gt;
&lt;p&gt;纯虚函数是在基类中声明的虚函数，它在基类中没有定义，但要求任何派生类都要定义自己的实现方法。纯虚函数的声明就是在告诉子类的设计者，&quot;你必须提供一个纯虚函数的实现，但我不知道你会怎样实现它&quot;。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;多重继承&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;C++允许多重继承，Java不允许，但实现接口可以。&lt;/p&gt;
&lt;h4&gt;Iterable接口&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/weixin_43848614/article/details/114601737&quot;&gt;【Java】Iterable接口的使用_iterable的用法_何为xl的博客-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;泛型&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/qq_33537014/article/details/80575033&quot;&gt;JAVA中泛型和Object的区别_使用范型和object的区别-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ArrayList&amp;lt;Integer&amp;gt;&lt;/code&gt;是&lt;code&gt;List&amp;lt;Integer&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt;&lt;/code&gt;不是&lt;code&gt;List&amp;lt;Object&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 把List&amp;lt;Integer&amp;gt;转换成List&amp;lt;Object&amp;gt;
// 1.
new ArrayList&amp;lt;Object&amp;gt;(intList);
// 2.能运行，但危险！
(List&amp;lt;Object&amp;gt;)(List)intList;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;C++中的虚函数表&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://leehao.me/C-%E8%99%9A%E5%87%BD%E6%95%B0%E8%A1%A8%E5%89%96%E6%9E%90/&quot;&gt;C++虚函数表剖析 | Leo的技术分享 (leehao.me)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Java里所有的函数都相当于C++里的虚函数。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;理解指针的指向，引用的对象，vtable-&amp;gt;虚函数表，在其中找到虚函数。&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;程序编码&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;数学归纳法（俗称……找规律，显然法，高数里高阶函数问题常用的方法，这里用来推程序正确性）&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;用于证明断言对所有自然数成立&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;证明对于N=1成立&lt;/li&gt;
&lt;li&gt;证明N&amp;gt;1时：如果对于N-1成立，那么对于N成立&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;递归控制&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;要点&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;严格定义递归函数的作用，包括参数、返回值、Side-effect&lt;/li&gt;
&lt;li&gt;先写&lt;strong&gt;一般&lt;/strong&gt;情况，后写&lt;strong&gt;特殊&lt;/strong&gt;情况&lt;/li&gt;
&lt;li&gt;每次调用&lt;strong&gt;必须&lt;/strong&gt;缩小问题规模&lt;/li&gt;
&lt;li&gt;每次问题规模缩小程度必须为&lt;strong&gt;1&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;不要尝试递归改非递归&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一般化的方法仍需要使用栈&lt;/li&gt;
&lt;li&gt;代码复杂&lt;/li&gt;
&lt;li&gt;不能根本解决问题&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;循环控制&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;循环不变式&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;是一句断言定义各变量所满足的条件，说人话就是变量进入循环必须满足的条件。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;循环书写方法&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;定义循环不变式，并在循环体每次结束后保持循环不变式&lt;/li&gt;
&lt;li&gt;先一般，后特殊&lt;/li&gt;
&lt;li&gt;每次必须向前推进循环不变式中涉及的变量值&lt;/li&gt;
&lt;li&gt;每次推进的规模必须为1&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;边界控制&lt;/h3&gt;
&lt;p&gt;凭经验。&lt;/p&gt;
&lt;h2&gt;静态绑定与动态绑定&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/Untara/article/details/100115150&quot;&gt;java的动态绑定与静态绑定(彻底理解多态与重载)-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;静态绑定是发生在编译阶段；而动态绑定是在运行阶段；&lt;/p&gt;
&lt;p&gt;重载方法(overloaded methods)使用的是静态绑定，而重写方法(overridden methods)使用的是动态绑定&lt;/p&gt;
&lt;h2&gt;常见问题&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;如何判断对象已死亡&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/qq_33591903/article/details/82107686&quot;&gt;【JAVA】如何判断对象已经死亡？_java 如何判断对象已经“死去”-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;引用计数法&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;程序给对象添加一个引用计数器，每有一个变量引用它时，计数器加1。当引用断开时，计数器减1。当计数器为0时，代表着没有任何变量引用它，该对象就是死亡状态，JVM需要对此类对象进行回收。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;可达性分析法&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;程序创建一系列的GC Roots作为起始点，从这些节点开始向下搜索，搜索所走过的路径称为引用链，当一个对象与GC Roots没有任何引用链相连的话，即此对象到GC Roots不可达，则证明此对象是不可用的，JVM稍后将会对此类对象进行回收。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;web开发安全问题&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;[web开发常见的几大安全问题 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/113179679#:~:text=web开发常见的几大安全问题 1 1、涉及到私密信息 使用post请求，因为信息放在请求体中而不像get请求暴露在url上 2 2、HTTPS。 ... 3,XSS。 ... 7 7、点击劫持，点击劫持是一种视觉欺骗的攻击手段。 ... 8 8、URL跳转漏洞，借助未验证的URL跳转，将应用程序引导到不安全的第三方区域，从而导致的安全问题。 更多项目)&lt;/p&gt;
&lt;h1&gt;设计模式&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;单例模式&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确保全局至多只有一个对象&lt;/li&gt;
&lt;li&gt;用于：构造缓慢的对象，需要统一管理的资源&lt;/li&gt;
&lt;li&gt;缺点：很多全局状态，线程安全性&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实现的方法为先判断实例存在与否，如果存在则直接返回，如果不存在就创建了再返回，这就确保了一个类只有一个实例对象&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;工厂模式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;工厂模式通常会分成3个角色：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;工厂角色-负责实现创建所有实例的内部逻辑&lt;/li&gt;
&lt;li&gt;抽象产品角色-是所创建的所有对象的父类，负责描述所有实例所共有的公共接口&lt;/li&gt;
&lt;li&gt;具体产品角色-是创建目标，所有创建的对象都充当这个角色的某个具体类的实例&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;观察者模式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;观察者模式是一种行为型设计模式，它定义了一种一对多的依赖关系，当一个对象的状态发生改变时，其所有依赖者都会收到通知并自动更新。&lt;/p&gt;
&lt;p&gt;当对象间存在一对多关系时，则使用观察者模式（Observer Pattern）。比如，当一个对象被修改时，则会自动通知依赖它的对象。观察者模式属于行为型模式。&lt;/p&gt;
&lt;h1&gt;暂未分类&lt;/h1&gt;
&lt;h2&gt;分布式&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/382966178&quot;&gt;大白话告你什么是分布式，史上最全详解！ - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;分布式ID&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;全局唯一性&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;不能出现有重复的ID标识，这是基本要求。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;递增性&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;确保生成ID对于用户或业务是递增的。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;高可用性&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;确保任何时候都能生成正确的ID。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;高性能性&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在高并发的环境下依然表现良好。&lt;/p&gt;
&lt;h3&gt;UUID&lt;/h3&gt;
&lt;p&gt;Java自带的生成一串唯一随机36位字符串（32个字符串+4个“-”）的算法。它可以保证唯一性，且据说够用N亿年，但是其业务可读性差，无法有序递增。&lt;/p&gt;
&lt;h3&gt;雪花算法&lt;/h3&gt;
&lt;p&gt;Twitter开源的由64位整数组成分布式ID，性能较高，并且在单机上递增。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/433690272&quot;&gt;面试官：讲讲雪花算法，越详细越好 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;MVC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/101038664&quot;&gt;基础 | 三层架构与MVC模式 - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MVC模式&lt;/strong&gt;是软件工程中常见的一种软件架构模式，该模式把软件系统（项目）分为三个基本部分：&lt;strong&gt;模型（Model）、视图（View）和控制器（Controller）。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;使用MVC模式有很多优势，例如:简化后期对项目的修改、扩展等维护操作；使项目的某一部分变得可以重复利用；使项目的结构更加直观。&lt;/p&gt;
&lt;p&gt;具体来讲，MVC模式可以将项目划分为模型（M）、视图（V）和控制器（C）三个部分，并赋予各个部分不同的功能，方便开发人员进行分组。&lt;/p&gt;
&lt;h2&gt;设计原则&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/110130347&quot;&gt;六大设计原则超详细介绍（再不理解你打我） - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;单一职责原则：一个类或接口只承担一个职责。&lt;/li&gt;
&lt;li&gt;里氏替换原则：在继承类时，务必重写（override）父类中所有的方法，尤其需要注意父类的protected方法（它们往往是让你重写的），子类尽量不要暴露自己的public方法供外界调用。&lt;/li&gt;
&lt;li&gt;依赖倒置原则：高层模块不应该依赖于低层模块，而应该依赖于抽象。抽象不应依赖于细节，细节应依赖于抽象。&lt;/li&gt;
&lt;li&gt;接口隔离原则：不要对外暴露没有实际意义的接口。&lt;/li&gt;
&lt;li&gt;迪米特法则：尽量减少对象之间的交互，从而减小类之间的耦合。&lt;/li&gt;
&lt;li&gt;开闭原则：对软件实体的改动，最好用扩展而非修改的方式。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;深拷贝与浅拷贝&lt;/h2&gt;
&lt;p&gt;浅拷贝只复制指向某个对象的指针，而不复制对象本身，相当于是新建了一个对象，该对象复制了原对象的指针，新旧对象还是共用一个内存块。&lt;/p&gt;
&lt;p&gt;深拷贝是新建一个一模一样的对象，该对象与原对象不共享内存，修改新对象也不会影响原对象。&lt;/p&gt;
&lt;h2&gt;GC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/laomo_bible/article/details/83112622&quot;&gt;【JAVA核心】Java GC机制详解-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;程序运行时，内存空间是有限的，那么如何及时的把不再使用的对象清除将内存释放出来，这就是GC要做的事。&lt;/p&gt;
&lt;p&gt;需要进行回收的对象就是已经没有存活的对象，&lt;strong&gt;判断一个对象是否存活&lt;/strong&gt;常用的有两种办法：引用计数和可达分析。&lt;/p&gt;
&lt;p&gt;(1)程序调用System.gc时可以触发&lt;/p&gt;
&lt;p&gt;(2)系统自身来决定GC触发的时机（根据Eden区和From Space区的内存大小来决定。当内存大小不足时，则会启动GC线程并停止应用线程）&lt;/p&gt;
&lt;p&gt;主要做了清理对象，整理内存的工作。&lt;/p&gt;
&lt;p&gt;标记-清除算法，标记-压缩算法，复制算法，分代收集算法。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.html&quot;&gt;新一代垃圾回收器ZGC的探索与实践 - 美团技术团队 (meituan.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;与CMS中的ParNew和G1类似，ZGC也采用标记-复制算法，不过ZGC对该算法做了重大改进：ZGC在标记、转移和重定位阶段几乎都是并发的，这是ZGC实现停顿时间小于10ms目标的最关键原因。&lt;/p&gt;
&lt;h2&gt;Redis&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://zhuanlan.zhihu.com/p/37982685&quot;&gt;Redis【入门】就这一篇！ - 知乎 (zhihu.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NoSQL是一种&lt;strong&gt;基于内存的数据库&lt;/strong&gt;，并且提供一定的持久化功能。Redis的性能十分优越，可以&lt;strong&gt;支持每秒十几万此的读/写操作&lt;/strong&gt;，其性能远超数据库，并且还&lt;strong&gt;支持集群、分布式、主从同步等&lt;/strong&gt;配置，原则上可以无限扩展，让更多的数据存储在内存中，更让人欣慰的是它还&lt;strong&gt;支持一定的事务能力&lt;/strong&gt;，这保证了高并发的场景下数据的安全和一致性。&lt;/p&gt;
&lt;p&gt;Redis 在 Java Web 主要有两个应用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;存储 &lt;strong&gt;缓存&lt;/strong&gt; 用的数据；&lt;/li&gt;
&lt;li&gt;需要高速读/写的场合&lt;strong&gt;使用它快速读/写&lt;/strong&gt;；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.cnblogs.com/powertoolsteam/p/redis.html&quot;&gt;Redis是什么？看这一篇就够了 - 葡萄城技术团队 - 博客园 (cnblogs.com)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;相比于其他数据库类型，Redis具备的特点是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;C/S通讯模型&lt;/li&gt;
&lt;li&gt;单进程单线程模型&lt;/li&gt;
&lt;li&gt;丰富的数据类型&lt;/li&gt;
&lt;li&gt;操作具有原子性&lt;/li&gt;
&lt;li&gt;持久化&lt;/li&gt;
&lt;li&gt;高并发读写&lt;/li&gt;
&lt;li&gt;支持lua脚本&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Redis 的应用场景包括：缓存系统（“热点”数据：高频读、低频写）、计数器、消息队列系统、排行榜、社交网络和实时系统。&lt;/p&gt;
&lt;p&gt;Redis提供的数据类型主要分为5种自有类型和一种自定义类型，这5种自有类型包括：String类型、哈希类型、列表类型、集合类型和顺序集合类型。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/qq_44469202/article/details/115496920&quot;&gt;什么是Redis？简述它的优缺点？_redis介绍和优缺点_SONNIE在路上的博客-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Redis的特点&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/qq_29974229/article/details/121673809&quot;&gt;【精选】简述redis特点及其应用场景-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Redis的一些问题&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/fcvtb/article/details/89478554&quot;&gt;【面试】redis缓存穿透、缓存击穿、缓存雪崩区别和解决方案-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;缓存穿透是指&lt;strong&gt;缓存和数据库中都没有的数据&lt;/strong&gt;，而用户不断发起请求。由于缓存是不命中时被动写的，并且出于容错考虑，如果从存储层查不到数据则不写入缓存，这将导致这个不存在的数据每次请求都要到存储层去查询，失去了缓存的意义。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​	&lt;strong&gt;接口层增加校验&lt;/strong&gt;，如用户鉴权校验，id做基础校验&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;缓存击穿是指缓存中没有但数据库中有的数据（一般是缓存时间到期）&lt;/strong&gt;，这时由于并发用户特别多，同时读缓存没读到数据，又同时去数据库去取数据，引起数据库压力瞬间增大，造成过大压力。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​	&lt;strong&gt;接口限流与熔断，降级&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;​	&lt;strong&gt;设置热点数据永远不过期&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;​	&lt;strong&gt;加互斥锁&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;缓存雪崩是指缓存中数据大批量到过期时间&lt;/strong&gt;，而查询数据量巨大，引起数据库压力过大甚至down机。和缓存击穿不同的是，        缓存击穿指并发查同一条数据，缓存雪崩是不同数据都过期了，很多数据都查不到从而查数据库。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​	缓存数据的过期时间设置随机，防止同一时间大量数据过期现象发生。&lt;/p&gt;
&lt;p&gt;​	如果缓存数据库是分布式部署，将热点数据均匀分布在不同搞得缓存数据库中。&lt;/p&gt;
&lt;p&gt;​	设置热点数据永远不过期。&lt;/p&gt;
&lt;h2&gt;JVM中导致OOM的原因与解决&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.aliyun.com/article/726472&quot;&gt;1篇文章搞清楚8种JVM内存溢出（OOM）的原因和解决方法-阿里云开发者社区 (aliyun.com)&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;堆溢出&lt;/li&gt;
&lt;li&gt;永久代/元空间溢出&lt;/li&gt;
&lt;li&gt;方法栈溢出&lt;/li&gt;
&lt;li&gt;非常规溢出&lt;/li&gt;
&lt;li&gt;swap溢出&lt;/li&gt;
&lt;li&gt;本地方法溢出&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;字节对齐&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;例：&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class` `A {
  ``int` `a;
  ``short` `b;
  ``int` `c;
  ``char` `d;
};
class` `B {
  ``double` `a;
  ``short` `b;
  ``int` `c;
  ``char` `d;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;在32位机器上用gcc编译以上代码，求sizeof(A)，sizeof(B)分别是（）&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;A -----&amp;gt;   △△△△||△△==||△△△△||△=== 

B -----&amp;gt;  △△△△△△△△||△△==(short)△△△△(int)||△======= 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中△为数据存储，=为填充&lt;/p&gt;
&lt;p&gt;A: int a    （4个字节）                         4&lt;/p&gt;
&lt;p&gt;short b   (2个字节，起始地址4是2的倍数，不补)    4+2&lt;/p&gt;
&lt;p&gt;int c     (4个字节，4+2不是4的倍数，补2个 )    4+2+2（补）+4&lt;/p&gt;
&lt;p&gt;char d    (1个字节，4+2+2+4是1的倍数，不补)  4+2+2（补）+4 +1&lt;/p&gt;
&lt;p&gt;最后补3个字节，让整体大小为4的倍数   4+2+2(补)+4+1+3（补） =16&lt;/p&gt;
&lt;p&gt;B: double a    （8个字节）                         8&lt;/p&gt;
&lt;p&gt;short b   (2个字节，起始地址8是2的倍数，不补)    8+2&lt;/p&gt;
&lt;p&gt;int c     (4个字节，8+2不是4的倍数，补2个 )    8+2+2（补）+4&lt;/p&gt;
&lt;p&gt;char d    (1个字节，8+2+2+4是1的倍数，不补)  8+2+2（补）+4 +1
最后补7个字节，让整体大小为8的倍数   8+2+2(补)+4+1+7（补） =24&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;结构体变量的首地址 必须 是内部最宽数据类型的倍数&lt;/li&gt;
&lt;li&gt;按顺序一个变量一个变量看，要求current变量的首地址 必须是自己大小的倍数。&lt;/li&gt;
&lt;li&gt;到了最后一个变量，要求整个结构体的大小的最宽数据类型的倍数。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;推荐算法&lt;/h2&gt;
&lt;p&gt;[[毕业设计]电商大数据的商品推荐系统_电商商品推荐怎么实现的_HaiLang_IT的博客-CSDN博客](https://blog.csdn.net/qq_37340229/article/details/128040139#:~:text=常见的推荐算法思路 1 基于商品相似度：比如食物A和食物B，对于它们价格、味道、保质期、品牌等维度，可以计算它们的相似程度，可以想象，我买了包子，很有可能顺路带一盒水饺回家。 ... 2,基于关联规则：最常见的就是通过用户购买的习惯，经典的就是“啤酒尿布”的案例，但是实际运营中这种方法运用的也是最少的，首先要做关联规则，数据量一定要充足，否则置信度太低，当数据量上升了，我们有更多优秀的方法，可以说没有什么亮点，业内的算法有apriori、ftgrow之类的 ... 3 基于物品的协同推荐：假设物品A被小张、小明、小董买过，物品B被小红、小丽、小晨买过，物品C被小张、小明、小李买过；直观的看来，物品A和物品C的购买人群相似度更高（相对于物品B），现在我们可以对小董推荐物品C，小李推荐物品A，这个推荐算法比较成熟，运用的公司也比较多 ... 更多项目)&lt;/p&gt;
&lt;h2&gt;排序算法&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;算法复杂度与初始状态无关的有：选择排序、堆排序、归并排序、基数排序；&lt;/li&gt;
&lt;li&gt;元素总比较次数与初始状态无关的有：选择排序、基数排序；&lt;/li&gt;
&lt;li&gt;元素总移动次数与初始状态无关的有：归并排序、基数排序。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;简单排序算法&lt;/h3&gt;
&lt;h4&gt;插入排序&lt;/h4&gt;
&lt;p&gt;就像扑克牌一张张排序一样，我们每次从牌堆摸一张牌到手上，就把牌插入相应的位置。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; a.length; i++) {
  for (int j = i; j &amp;gt; 0 &amp;amp;&amp;amp; a[j] &amp;lt; a[j - 1]; j--) {
    swap(a, j, j - 1);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;选择排序&lt;/h4&gt;
&lt;p&gt;我们考虑桌上有一堆面相上的明牌，我们要排序的话，通常会先选择A，然后选择2,3…K，完成排序。选择排序就是这样，每次从数组中剩下的元素中选择最小的那个即可。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; a.length; i++) {
  // a[0...i)为原数组中最小的i个元素排序完成的结果
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;冒泡排序&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; a.length; i++) {
  for (int j = a.length - 1; j &amp;gt; i; j--) {
    if (a[j] &amp;lt; a[j - 1]) {
      swap(a, j, j - 1);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在里层的for里面，我们j是&lt;strong&gt;反向&lt;/strong&gt;移动的，这个非常重要。每次这样反向比较+交换一轮之后，我们总能保证剩下的数据中最小的数被换到a[i]的位置，这个交换的过程就像在模拟气泡在水中慢慢升起的过程。&lt;/p&gt;
&lt;h3&gt;高效排序算法&lt;/h3&gt;
&lt;p&gt;平均复杂度为O(nlogn)的算法。&lt;/p&gt;
&lt;h4&gt;快速排序&lt;/h4&gt;
&lt;p&gt;快速排序和归并排序更是“分治”思想方法的典型体现。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void sort(int[] a) {
  // 分组：扫描a，把比a[0]小的数移到左边，把比a[0]大的数移到a[0]右边。
  // 递归：对于左右两半边分别递归调用sort
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;归并排序&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;void sort(int[] a) {
  // 分组：把a分成左右两边，这次我们不管数据大小，直接中间切一刀，分组就完成了
  // 递归：把左右两边分别递归调用归并排序，获得两个排好序的子数组
  // 归并：把两个排好序的子数组进行归并
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;把问题分成（若干个）互相独立的子问题，分别解决它们，并把子问题的解合成最终解&lt;/strong&gt;。&lt;/p&gt;
&lt;h4&gt;堆排序&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;所有数据建堆&lt;/li&gt;
&lt;li&gt;不断从堆中取出一个元素，重复n次。由于堆中取出的总是最小元素，因此排序完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;非基于比较的排序算法&lt;/h3&gt;
&lt;h4&gt;计数排序&lt;/h4&gt;
&lt;p&gt;我们考虑一个问题，如果我告诉你我们所有的数据都是0-100的范围内的整数，但是数据的个数非常大，我们如何来排序呢？我们这样来做&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;分别数一下有几个0，有几个1，几个2。。。&lt;/li&gt;
&lt;li&gt;计算累进的计数c，c[i]为&amp;lt;=i的个数。比如有2个0，3个1，那么c[0]=2, c[1]=5&lt;/li&gt;
&lt;li&gt;这个累进的计数c有一个重要的特点，数值为i的数在排好序的数组中位于[ c[i-1]…c[i] )&lt;/li&gt;
&lt;li&gt;利用这个累进计数的特点，可以重建出排序结果&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;桶排序&lt;/h4&gt;
&lt;p&gt;扫描数据，放在自己建立的对应的“桶”里。&lt;/p&gt;
&lt;h4&gt;基数排序&lt;/h4&gt;
&lt;p&gt;根据位数来排序，不需要像桶排一样人为指定桶。&lt;/p&gt;
&lt;p&gt;比如&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;原始数据：       10,21,17,34,44,11,654,123
根据个位数排序：  10,21,11,123,34,44,654,17
根据十位数排序：  10,11,17,21,123,34,44,654
根据百位数排序：  10,11,17,21,34,44,123,644
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;总结&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;算法&lt;/th&gt;
&lt;th&gt;平均时间复杂度&lt;/th&gt;
&lt;th&gt;最好时间复杂度&lt;/th&gt;
&lt;th&gt;最坏时间复杂度&lt;/th&gt;
&lt;th&gt;空间复杂度&lt;/th&gt;
&lt;th&gt;稳定性&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;插入排序&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;选择排序&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;不稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;冒泡排序&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;快速排序&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;n2&lt;/td&gt;
&lt;td&gt;logn&lt;/td&gt;
&lt;td&gt;不稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;归并排序&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;堆排序&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;nlogn&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;不稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;计数排序&lt;/td&gt;
&lt;td&gt;n+s&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;n+s&lt;/td&gt;
&lt;td&gt;稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;桶排序&lt;/td&gt;
&lt;td&gt;n+s&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;n+s&lt;/td&gt;
&lt;td&gt;稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基数排序&lt;/td&gt;
&lt;td&gt;dn&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content:encoded></item><item><title>RocketMQ因内存不足无法启动的一个坑（Linux）</title><link>https://blog-yunsheng.cn/posts/archives/old-post/rocketmq-memory/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/rocketmq-memory/</guid><description>查logs经验+1，双眼视力-1</description><pubDate>Thu, 15 Jun 2023 14:34:29 GMT</pubDate><content:encoded>&lt;p&gt;RocketMQ启动了将近一个小时，均无法启动，以失败告终，查了一堆文档，都没有找到解决方法，最后找到logs文件，里面记录了error原因，系JVM内存不足，于是才终于找到解决方法。&lt;/p&gt;
&lt;p&gt;到bin文件夹下，修改runserver.sh、runbroker.sh、tools.sh三个文件中以下值：&lt;s&gt;&lt;em&gt;默认设定为8g和4g，怪不得我的小破云服务器启动不起来，不是，就一个消息队列都这么吃内存吗？&lt;/em&gt;&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231115143736083.png&quot; alt=&quot;image-20231115143736083&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;JAVA_OPT=&quot;${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;相关参数&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Xms 是指设定程序启动时占用内存大小。一般来讲，大点，程序会启动的快一点，但是也可能会导致机器暂时
间变慢。
Xmx 是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存，超出了这个设置值，
就会抛出OutOfMemory异常。
xmn 年轻代的heap大小，一般设置为Xmx的3、4分之一。&lt;/p&gt;
&lt;h4&gt;成果&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;image-20231115144518338.png&quot; alt=&quot;image-20231115144518338&quot; /&gt;&lt;/p&gt;
&lt;p&gt;终于启动成功，但是似乎还有一些其他建议，与GC有关，暂时先忽略，等之后优化，仅此记录一下。&lt;/p&gt;
</content:encoded></item><item><title>本地远程连接云服务器上Docker下的MySQL</title><link>https://blog-yunsheng.cn/posts/archives/old-post/remote-connection-server/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/remote-connection-server/</guid><description>虚拟机烧不动了，还是买了云服务器，先把环境再慢慢重新部署完吧。</description><pubDate>Mon, 12 Jun 2023 14:51:26 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker ps
docker exec -it [container name] /bin/bash
mysql -u -p
# 对远程连接进行授权
GRANT ALL ON *.* TO &apos;root&apos;@&apos;%&apos;;
# 刷新权限
flush privileges;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;云服务器实例&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在网卡中新建安全组，新增MySQL规则。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231112145553920.png&quot; alt=&quot;image-20231112145553920&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Navicat&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231112145738864.png&quot; alt=&quot;image-20231112145738864&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231112145752364.png&quot; alt=&quot;image-20231112145752364&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>通过SSH连接虚拟机及其中Docker下的MySQL数据库</title><link>https://blog-yunsheng.cn/posts/archives/old-post/ssh/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/ssh/</guid><description>记录一下虚拟机网络之间连接的实现。</description><pubDate>Sat, 10 Jun 2023 21:10:11 GMT</pubDate><content:encoded>&lt;h1&gt;通过SSH连接虚拟机&lt;/h1&gt;
&lt;h2&gt;Oracle VM VirtualBox&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;image-20231110211142826-1699621908213-1.png&quot; alt=&quot;image-20231110211142826&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231110211206278-1699621927347-3.png&quot; alt=&quot;image-20231110211206278&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;MobaXterm&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;image-20231110211237429.png&quot; alt=&quot;image-20231110211237429&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;连接其中Docker下的MySQL数据库&lt;/h1&gt;
&lt;p&gt;在Docker中成功启动MySQL，确认Docker中MySQL无问题。&lt;/p&gt;
&lt;p&gt;在Oracle VM VirtualBox中给端口转发列表添加Docker中映射的端口。&lt;/p&gt;
&lt;p&gt;在宿主机中打开cmd，用&lt;code&gt;ipconfig&lt;/code&gt;查到虚拟机ip地址。&lt;/p&gt;
&lt;p&gt;打开Navicat，输入对应信息即测试连接。&lt;/p&gt;
</content:encoded></item><item><title>基于Astro的全新静态网站搭建部署回顾</title><link>https://blog-yunsheng.cn/posts/archives/old-post/astro-deployment-record/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/astro-deployment-record/</guid><description>一个专门用来记录生活的网站。</description><pubDate>Sun, 04 Jun 2023 12:02:01 GMT</pubDate><content:encoded>&lt;h1&gt;问题分析&lt;/h1&gt;
&lt;p&gt;网站地址：&lt;a href=&quot;https://yunsheng-car.cn/&quot;&gt;Home • 云升的手推车 (yunsheng-car.cn)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;之前有过计划做一个用来个人记录生活（游记、影评等等）的网站，于是在上周周末的时候开始完成了这个网站，这次不想再用&lt;code&gt;Hexo&lt;/code&gt;框架，想尝试一下新鲜的东西，于是选中了去年正式发布并迅速迭代的&lt;a href=&quot;https://docs.astro.build/zh-cn/getting-started/&quot;&gt;Astro框架&lt;/a&gt;（&lt;a href=&quot;https://zhuanlan.zhihu.com/p/614425033&quot;&gt;2023Web框架性能报告&lt;/a&gt;），并且这次直接采用Vercel部署，尝试引入CMS，原本以为有相关的技术经验，但是这次还是遇到了不少麻烦。&lt;/p&gt;
&lt;p&gt;首先是&lt;code&gt;Astro&lt;/code&gt;作为一款极新的前端框架，目前国内相关教程极少，较老框架来说门槛较高，好在有比较详尽的官方文档，基本还是可以自主解决问题。&lt;/p&gt;
&lt;p&gt;其次是困扰最久的CMS（内容管理系统，方便编辑管理Web内容），由于&lt;code&gt;Astro&lt;/code&gt;是新框架，与之相关的CMS文档就更少了，而且是全英文档，后续在打包的&lt;code&gt;package.json&lt;/code&gt;配置文件和CMS相关配置以及&lt;code&gt;schema&lt;/code&gt;等模块方面都花了较长的时间处理解决，最后才终于解决，并通过&lt;code&gt;TinaCMS Cloud&lt;/code&gt;连接&lt;code&gt;GitHub&lt;/code&gt;仓库实现生产模式部署。&lt;/p&gt;
&lt;h1&gt;前置工作&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;TinaCMS&lt;/li&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;过程重点&lt;/h1&gt;
&lt;h2&gt;Astro&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Astro&lt;/code&gt;的基本构建是最简单的，参考&lt;code&gt;Astro&lt;/code&gt;官方文档就可以简单地通过脚手架搭建，&lt;a href=&quot;https://docs.astro.build/zh-cn/getting-started/&quot;&gt;入门指南 🚀 Astro 文档&lt;/a&gt;，大多数资料都可以参考官方文档解决，完成简单的构建后的各种调试以及组件的引入、部署才是困难的地方。&lt;/p&gt;
&lt;h2&gt;CDN&lt;/h2&gt;
&lt;p&gt;CDN和&lt;a href=&quot;https://blog-yunsheng.cn/2023/11/23/Vercel-CloudFlare%E5%AE%9E%E7%8E%B0%E8%BF%91%E9%9B%B6%E6%88%90%E6%9C%ACTwikoo%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/&quot;&gt;这篇文章&lt;/a&gt;中的操作一直，已经踩过的坑后面就很难再踩了，照着完成即可。&lt;/p&gt;
&lt;h2&gt;VS Code&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Astro&lt;/code&gt;项目推荐用VS Code进行编写以及终端调试。&lt;/p&gt;
&lt;h2&gt;TinaCMS&lt;/h2&gt;
&lt;p&gt;最折磨的地方，第一次尝试使用CMS，而且还是全英文的文档，需要慢慢啃，花了两天的时间才自己啃下来，目前已经实现了远程控制。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231204124004313.png&quot; alt=&quot;image-20231204124004313&quot; /&gt;&lt;/p&gt;
&lt;p&gt;但是我还不知道该怎么记录这块，虽然我是都啃下来了，但是要写这块的实现的话可能得单独写一整篇文章，而且有些功能还没有完全实现，可能等以后更加熟悉了会专门记录一下。&lt;/p&gt;
&lt;p&gt;基本原理是连接&lt;code&gt;GitHub&lt;/code&gt;仓库，然后远程对&lt;code&gt;GitHub&lt;/code&gt;存储库的内容进行管理。&lt;/p&gt;
&lt;h1&gt;后记&lt;/h1&gt;
&lt;p&gt;目前感受来看&lt;code&gt;Astro&lt;/code&gt;框架确实比&lt;code&gt;Hexo&lt;/code&gt;好很多，&lt;code&gt;Hexo&lt;/code&gt;的优势似乎只剩下使用门槛低了，但后续的管理远不如&lt;code&gt;Astro&lt;/code&gt;，大概到明年&lt;code&gt;Astro&lt;/code&gt;更加成熟，并且我也对其更加熟练以后应该会把博客迁移过去。&lt;/p&gt;
&lt;p&gt;后续想利用其做个个人简历使用，这个大概月底前完成吧，目前又要把精力回到毕设和竞赛上了。&lt;/p&gt;
&lt;p&gt;这次的折腾其实收获很大，主要在于自主解决问题的能力得到了验证和提升，我觉得这是很重要的，以后总会遇到不会的事情，自己能不能够解决至关重要。&lt;/p&gt;
</content:encoded></item><item><title>部分使用远程客户端连接MySql时报错问题的解决</title><link>https://blog-yunsheng.cn/posts/archives/old-post/remote-connection-mysql-problem/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/remote-connection-mysql-problem/</guid><description>一部分连接数据库时出错的问题解决。</description><pubDate>Wed, 24 May 2023 14:21:47 GMT</pubDate><content:encoded>&lt;p&gt;使用网上一些老旧的项目来完成课设时出现连接不上Mysql报错：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20230524142424694-1684909472394-1.png&quot; alt=&quot;image-20230524142424694&quot; /&gt;&lt;/p&gt;
&lt;p&gt;报错原因：mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password&lt;/p&gt;
&lt;p&gt;查看Mysql版本：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20230524142540037-1684909540955-3.png&quot; alt=&quot;image-20230524142540037&quot; /&gt;&lt;/p&gt;
&lt;p&gt;查看SQL用户信息：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;select host,user,plugin,authentication_string from mysql.user;  &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20230524143301920-1684909982888-5.png&quot; alt=&quot;image-20230524143301920&quot; /&gt;&lt;/p&gt;
&lt;p&gt;修改密码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ALTER USER &apos;root&apos;@&apos;localhost&apos; IDENTIFIED WITH mysql_native_password BY &apos;123456&apos;;
更新user为root，host为localhost 的密码为123456
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;参考文章：&lt;a href=&quot;https://blog.csdn.net/lovedingd/article/details/106728292&quot;&gt;Mysql 解决1251- Client does not support authentication protocol requested by server...的问题_慕城南风的博客-CSDN博客&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;补充一个mysql8.0的连接问题&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;网上有些项目用的是老版mysql，我个人电脑用的是mysql8.0.27版本，与老版项目jar包版本不符，需要更换对应版本jar包。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://downloads.mysql.com/archives/c-j/&quot;&gt;MySQL :: Download MySQL Connector/J (Archived Versions)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;数据库配置文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dataSource.driverClass=com.mysql.cj.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/ssm?useUnicode=true&amp;amp;characterEncoding=utf-8&amp;amp;useSSL=false&amp;amp;serverTimezone=UTC
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>算法学习笔记</title><link>https://blog-yunsheng.cn/posts/archives/old-post/algorithm/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/algorithm/</guid><description>有半年时间没有练算法了，近期忙完以后会继续学习与记录。</description><pubDate>Sun, 16 Apr 2023 00:33:43 GMT</pubDate><content:encoded>&lt;p&gt;工作后就停更啦！&lt;/p&gt;
&lt;h1&gt;入门&lt;/h1&gt;
&lt;hr /&gt;
&lt;h2&gt;循环结构&lt;/h2&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.luogu.com.cn/problem/P1307&quot;&gt;P1307数组反转&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;如何将数字逐位剥离&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;while (n != 0)
{
    int t = n % 10;
    n /= 10;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;如何求解&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;int ans = 0;
ans = 10 * ans + t;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;随机数&lt;/h3&gt;
&lt;p&gt;计算机通过确定的算法生成“伪随机数”，因此每次执行随机数算法前都要“喂给它”不同的初始值(srand()函数)作为随机数种子，这样才能生成不同的随机数。喂给它当前的时间就是一个比较好的选择，当然也可以把部分输入数据作为随机数种子。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int ans;
srand(time(0)); // 以当前时间作为随机数种子
ans = rand() % 100 + 1; // 定义变量ans是一个1~100的随机数
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;code&gt;rand() % a&lt;/code&gt; 看起来能产生一个 0 到 a - 1 的随机数，但是每个数字并不是等可能的。假设 &lt;code&gt;RAND_MAX&lt;/code&gt; 是 32767 ，取 0 ~ 99 的随机数时，抽到 0 ~ 67 的可能要比剩下的数字大一点。如果 &lt;code&gt;RAND_MAX&lt;/code&gt; 远大于 a 时，影响并不大。&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;质数口袋&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.luogu.com.cn/problem/P5723&quot;&gt;P5723 【深基4.例13】质数口袋 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如何判断质数：如果一个大于1的整数仅能被1和自身整除，它就是一个质数，否则就是合数（1既不是质数也不是合数）。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int main()
{
    int L;
    cin &amp;gt;&amp;gt; L;
    int i = 2, weight = 0, count = 0;
    // 从2开始
    for (int i = 2;; i++)
    {
        bool flag = true; // 质数标识
        for (int j = 2; j * j &amp;lt;= i; j++)
            if (i % j == 0)
            {
                flag = false; // i可以被j整除，i不是质数，标识改变
                break;        // 退出j的for循环
            }
        if (flag == false)
            continue; // 如果不是质数，i++，进入while的下一循环
        if (i + weight &amp;gt; L)
            break; // 如果超重了，直接退出循环
        cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; endl;
        count++;
        weight += i;
    }
    cout &amp;lt;&amp;lt; count &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;质因数分解&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.luogu.com.cn/problem/P1075&quot;&gt;P1075 [NOIP2012 普及组] 质因数分解 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;想复杂了，只要找出 n 的最小约数，再用 n 除以这个数，就能得到结果。&lt;em&gt;&lt;s&gt;其实这是一道数学题&lt;/s&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;一个数能且只能分解为一组质数的乘积。&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int main()
{
    long long n;
    cin &amp;gt;&amp;gt; n;
    for (int i = 2; i &amp;lt;= n; i++)
        if (n % i == 0)
        {
            cout &amp;lt;&amp;lt; n / i;
            break;
        }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;其他&lt;/h2&gt;
&lt;hr /&gt;
&lt;h3&gt;常见的输入输出占位符&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;占位符&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;%d&lt;/td&gt;
&lt;td&gt;一个十进制整数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%nd&lt;/td&gt;
&lt;td&gt;输出一个整数，如果不足 n 位，前面用空格补齐直到够 n 位&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%.nf&lt;/td&gt;
&lt;td&gt;输出一个固定n位小数的浮点数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%0nd&lt;/td&gt;
&lt;td&gt;输出一个整数，如果不足 n 位，前面用 0 补齐知道够 n 位&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%c&lt;/td&gt;
&lt;td&gt;一个 char 类型的字符&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%s&lt;/td&gt;
&lt;td&gt;一个字符串&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h3&gt;关于浮点数精度误差&lt;/h3&gt;
&lt;p&gt;一种解决方式是先乘以 10^n 让其不触及浮点数，最后将其结果除回来。&lt;/p&gt;
&lt;h3&gt;数学函数&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;函数原型&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;double sin(double x)     double cos(double x)&lt;/td&gt;
&lt;td&gt;三角函数正弦和余弦，x是弧度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double exp(double x)&lt;/td&gt;
&lt;td&gt;返回$$e^x$$，其中e是自然常熟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double pow(double x, double y)&lt;/td&gt;
&lt;td&gt;返回$$x^y$$，也可以用来运算多次根式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double sqrt(double x)&lt;/td&gt;
&lt;td&gt;返回$$\sqrt{x}$$&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;double ceil(double x)&lt;/td&gt;
&lt;td&gt;返回大于或等于x的最小的整数值(上取整)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content:encoded></item><item><title>命令行过长导致SpringBoot项目无法启动问题解决方法</title><link>https://blog-yunsheng.cn/posts/archives/old-post/command-line-too-long/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/command-line-too-long/</guid><description>奇奇怪怪的问题+1</description><pubDate>Sun, 13 Nov 2022 13:55:36 GMT</pubDate><content:encoded>&lt;p&gt;application.yml文件过长后项目无法启动了，最后找到了解决方法：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231113135659900.png&quot; alt=&quot;image-20231113135659900&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;image-20231113135720989.png&quot; alt=&quot;image-20231113135720989&quot; /&gt;&lt;/p&gt;
&lt;p&gt;如图设置即可！&lt;/p&gt;
</content:encoded></item><item><title>hexo博客美化</title><link>https://blog-yunsheng.cn/posts/archives/old-post/hexo-beautify/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/hexo-beautify/</guid><description>一些自定义美化组件引用方法，虽然这些内容花了我不少时间才弄好，但还是属于文字垃圾，对不起我太菜了::&gt;_&lt;::。</description><pubDate>Tue, 12 Apr 2022 14:00:29 GMT</pubDate><content:encoded>&lt;h2&gt;鼠标点击爆炸特效&lt;/h2&gt;
&lt;p&gt;在制作完评论系统后逛博客时看到的不错的烟花爆炸特效&lt;a href=&quot;https://blog.yuzi.dev/posts/49f7102e.html&quot;&gt;博文地址&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\source\js&lt;/code&gt; 目录下创建文件 &lt;a href=&quot;http://blog-yunsheng.cn/js/fireworks.min.js&quot;&gt;fireworks.min.js&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\layout&lt;/code&gt; 目录下打开 &lt;code&gt;layout.ejs&lt;/code&gt; 文件，添加：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;canvas
	id=&quot;fireworks&quot;
	style=&quot;position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 32767&quot;
&amp;gt;&amp;lt;/canvas&amp;gt;
&amp;lt;script src=&quot;https://cdn.staticfile.org/animejs/3.2.1/anime.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;/js/fireworks.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;流星雨特效&lt;/h2&gt;
&lt;p&gt;根据主题作者的&lt;a href=&quot;https://argvchs.netlify.app/2022/04/17/hexo-blog-3/&quot;&gt;原教程&lt;/a&gt;使用。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\source\js&lt;/code&gt; 目录下创建文件 &lt;a href=&quot;http://blog-yunsheng.cn/js/background.min.js&quot;&gt;background.min.js&lt;/a&gt; 。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\layout&lt;/code&gt; 目录下打开 &lt;code&gt;layout.ejs&lt;/code&gt; 文件，添加：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;canvas
    id=&quot;background&quot;
    style=&quot;position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: -1&quot;
&amp;gt;&amp;lt;/canvas&amp;gt;
&amp;lt;script src=&quot;/js/background.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;补充&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;要将背景图片层级上移，在 &lt;code&gt;Blog\themes\particlex\source\css&lt;/code&gt; 目录下对 &lt;code&gt;main.css&lt;/code&gt; 文件进行修改：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#home-head #home-background {
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    height: 100vh;
    left: 0;
    position: absolute;
    top: 0;
    width: 100vw;
    z-index: 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;代码雨特效&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\source\js&lt;/code&gt; 目录下创建文件  &lt;a href=&quot;http://blog-yunsheng.cn/js/digitalrain.min.js&quot;&gt;digitalrain.min.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\source\css&lt;/code&gt; 目录下创建文件  &lt;a href=&quot;http://blog-yunsheng.cn/js/digitalrain.min.css&quot;&gt;digitalrain.min.css&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Blog\themes\particlex\layout&lt;/code&gt; 目录下打开 &lt;code&gt;layout.ejs&lt;/code&gt; 文件，添加：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- 数字雨 --&amp;gt;
&amp;lt;canvas id=&quot;canvas&quot; width=&quot;1440&quot; height=&quot;900&quot; &amp;gt;&amp;lt;/canvas&amp;gt;
&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;/css/digitalrain.min.css&quot; /&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;/js/digitalrain.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;补充&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为在 &lt;code&gt;layout.ejs&lt;/code&gt; 文件下设置会在全局生效，而代码雨在文章页会显得非常乱，所以我把其挪到了 &lt;code&gt;index.ejs&lt;/code&gt; 文件下，然后将流星雨特效放回 &lt;code&gt;layout.ejs&lt;/code&gt; 文件，即可实现代码雨特效仅在主页生效。&lt;/p&gt;
</content:encoded></item><item><title>用Git上传项目到GitHub或Gitee</title><link>https://blog-yunsheng.cn/posts/archives/old-post/git/</link><guid isPermaLink="true">https://blog-yunsheng.cn/posts/archives/old-post/git/</guid><description>需要提前配置好Git，以下是上传本地项目到GitHub或Gitee的方法的简单记录，GitHub仓库与Gitee仓库上传方法通用。</description><pubDate>Tue, 12 Apr 2022 00:19:50 GMT</pubDate><content:encoded>&lt;h1&gt;上传本地项目到GitHub&lt;/h1&gt;
&lt;p&gt;在GitHub上创建一个仓库，进入仓库，点击 &lt;code&gt;code&lt;/code&gt; ，在展开菜单内复制仓库路径。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Git全局设置&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;全局环境已设置可略过&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ git config --global user.name &quot;云升&quot;
$ git config --global user.email &quot;bycj1106@163.com&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;用Git上传到仓库&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;$ mkdir 项目名 #一般略过这一段！
$ git init
$ touch README.md
$ git add README.md
$ git commit -m &quot;first commit&quot;
$ git remote add origin git@gitee.com:Gitee仓库路径.git
$ git push -u origin &quot;main&quot; #Gitee上似乎是master
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Git的部分指令注释&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;$ git init #把这个目录变成Git可以管理的仓库
$ git add README.md #文件添加到仓库
$ git add . #不但可以跟单一文件，还可以跟通配符，更可以跟目录。一个点就把当前目录下所有未追踪的文件全部add了 
$ git commit -m &quot;first commit&quot; #把文件提交到仓库
$ git remote add origin git@github.com:wangjiax9/practice.git #关联远程仓库
$ git push -u origin master #把本地库的所有内容推送到远程库上
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;.gitignore文件的使用方法&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# dir 不需要提交的目录
/node_modules
​
# file 不需要提交的文件
config.ini
​
# log 不需要提交的任意包含后缀名为log的文件
*.log
​
# Package Files 不需要提交的任意包含后缀名为jar的文件
*.jar
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;简明指南&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://www.runoob.com/manual/git-guide/&quot;&gt;git 简明指南 (runoob.com)&lt;/a&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>