You need to sign in or sign up before continuing.
提交 0d2db0f2 编写于 作者: 小傅哥's avatar 小傅哥

feat: 部署

上级 e13821e7
name: Deploy Blog Pages
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18.16.0'
- name: Install dependencies
run: npm install
- name: Build
run: npm run docs:build
- name: Deploy to Nginx Server
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USERNAME: ${{ secrets.SSH_USERNAME }}
SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }}
REMOTE_PATH: ${{ secrets.REMOTE_PATH }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan $SSH_HOST >> ~/.ssh/known_hosts
#scp -r ./docs/.vuepress/dist/* $SSH_USERNAME@$SSH_HOST:$REMOTE_PATH
sshpass -p $SSH_PASSWORD scp -r ./dev-ops/nginx/html/* root@$SSH_HOST:$REMOTE_PATH
......@@ -4,7 +4,7 @@ version: '3.9'
services:
# yum install -y httpd-tools
nginx:
image: nginx:latest
image: nginx:1.25.1
container_name: nginx
restart: always
ports:
......
#!/bin/bash
# 设置默认的密钥文件路径
KEY_PATH="$HOME/.ssh/id_rsa"
# 检查是否已经存在密钥文件
if [ -f "$KEY_PATH" ]; then
echo "SSH 密钥文件 $KEY_PATH 已经存在。"
read -p "是否覆盖现有密钥?(y/n): " choice
if [ "$choice" != "y" ]; then
echo "操作已取消。"
exit 1
fi
fi
# 生成新的 SSH 密钥对
ssh-keygen -t rsa -b 4096 -f "$KEY_PATH" -N ""
# 确保 .ssh 目录和 authorized_keys 文件存在
mkdir -p "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
# 将公钥添加到 authorized_keys 文件中
cat "${KEY_PATH}.pub" >> "$HOME/.ssh/authorized_keys"
# 设置正确的权限
chmod 700 "$HOME/.ssh"
chmod 600 "$HOME/.ssh/authorized_keys"
echo "新的 SSH 密钥对已生成,并添加到 authorized_keys 文件中。"
此差异已折叠。
import{_ as e}from"./plugin-vue_export-helper-c27b6911.js";import{o as t,c}from"./app-730966a2.js";const o={};function r(_,n){return t(),c("div")}const f=e(o,[["render",r],["__file","404.html.vue"]]);export{f as default};
const t=JSON.parse('{"key":"v-3706649a","path":"/404.html","title":"","lang":"zh-CN","frontmatter":{"layout":"NotFound","description":"","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/404.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"article:author","content":"小傅哥"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"\\"}"]]},"headers":[],"git":{},"readingTime":{"minutes":0,"words":0},"filePathRelative":null,"autoDesc":true}');export{t as data};
因为 它太大了无法显示 source diff 。你可以改为 查看blob
const e=JSON.parse('{"key":"v-49312a44","path":"/md/dev-log/day01.html","title":"Day01","lang":"zh-CN","frontmatter":{"title":"Day01","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务\\r[x] 环境配置; \\r[x] 搭建项目结构; \\r[x] 跑通广播模式 RPC 过程调用; 学习过程 1. 项目整体了解 通过对第一节文档的阅读,了解整个项目的生命周期、所需要的技术以及代码提交规范 2. 搭建项目结构,理解每个模块应该干什么 模块 作用 | ---------------------- ----------------------...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day01.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day01"}],["meta",{"property":"og:description","content":"任务\\r[x] 环境配置; \\r[x] 搭建项目结构; \\r[x] 跑通广播模式 RPC 过程调用; 学习过程 1. 项目整体了解 通过对第一节文档的阅读,了解整个项目的生命周期、所需要的技术以及代码提交规范 2. 搭建项目结构,理解每个模块应该干什么 模块 作用 | ---------------------- ----------------------..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day01\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":2,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":2,"title":"学习过程","slug":"学习过程","link":"#学习过程","children":[]},{"level":2,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":4.48,"words":1343},"filePathRelative":"md/dev-log/day01.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as o}from"./plugin-vue_export-helper-c27b6911.js";import{r as p,o as e,c as l,a as t,d as n,e as r,f as s}from"./app-730966a2.js";const c={},i=t("h2",{id:"任务",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#任务","aria-hidden":"true"},"#"),n(" 任务")],-1),u=t("ul",null,[t("li",null,"[x] 环境配置"),t("li",null,"[x] 搭建项目结构"),t("li",null,"[x] 跑通广播模式 RPC 过程调用")],-1),d=t("h2",{id:"学习过程",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#学习过程","aria-hidden":"true"},"#"),n(" 学习过程")],-1),k=s("<li><p>项目整体了解</p><p>通过对第一节文档的阅读,了解整个项目的生命周期、所需要的技术以及代码提交规范</p></li><li><p>搭建项目结构,理解每个模块应该干什么</p><table><thead><tr><th>模块</th><th>作用</th></tr></thead><tbody><tr><td>Lottery</td><td>总项目,用来管理整个项目的依赖</td></tr><tr><td>lottery-application</td><td>应用层,为用户接口层提供各种应用数据展现支持服务</td></tr><tr><td>lottery-common</td><td>定义通用数据,比如统一响应数据、常量、异常、枚举等</td></tr><tr><td>lottery-domain</td><td>领域层,核心业务逻辑</td></tr><tr><td>lottery-infrastructure</td><td>基础层,为其他各层提供通用技术能力,包括数据库、Redis、ES 等</td></tr><tr><td>lottery-interfaces</td><td>用户接口层,存放与前端交互、展现数据相关的代码</td></tr><tr><td>lottery-rpc</td><td>RPC 接口文件</td></tr></tbody></table><blockquote><p>注:因为并不了解 DDD 架构,所以每个模块目前只有模糊的概念,具体的东西在后续代码编写中进行体会</p></blockquote></li>",2),q={href:"https://gitcode.net/KnowledgePlanet/Lottery/-/tree/210801_xfg_initProject",target:"_blank",rel:"noopener noreferrer"},y=t("p",null,[n("通过对 POM 文件的阅读,更加清楚的了解这个项目所使用的技术,并且通过阅读发现项目没有添加 Lombok 来简化开发,具体项目开发是否使用这个插件我不知道,但是我想用,因为我"),t("strong",null,""),n(",所以就给加上了😄")],-1),h=s("<li><p>跑通 RPC</p><ol><li>定义 response 状态码枚举供通用返回对象 Result 进行使用</li><li>定义通用返回对象 Result 类</li><li>定义 activity 表的持久化对象</li><li>定义 activity 表的 Mapper 接口</li><li>定义 mybatis 配置文件</li><li>定义 activity 表的 mapper.xml 文件</li><li>定义 rpc 的数据传输对象(DTO) ActivityDto</li><li>定义 rpc 的 请求对象 ActivityReq</li><li>定义 rpc 的响应对象 ActivityRes</li><li>定义 rpc 接口 IActivityBooth</li><li>实现 IActivityBooth 接口</li><li>编写启动类</li><li>编写配置文件 application.yml</li><li>编写测试模块 <strong>这个我是直接加在工程里面的,教程是单独开了一个项目</strong></li></ol></li>",1),m=s(`<h2 id="遇到的问题" tabindex="-1"><a class="header-anchor" href="#遇到的问题" aria-hidden="true">#</a> 遇到的问题</h2><ol><li><p>代码分层不清晰,不知道每个模块应该干什么事</p><p>这个问题该怎么解决呢?我觉得最好的解决办法就是不解决,哈哈哈,因为当初学 MVC 的时候最开始也不清楚为什么要这样分层,为什么就要分 Controller、Service 和 DAO,但是后来经过大量代码的编写,也逐渐熟悉了这样的分层架构,所以现在并不想解决这个问题,具体还是靠后面的代码进行了解和熟悉吧</p></li><li><p>JSON.toJSonString() 方法返回了空 <code>{}</code></p><p>问题出现原因,忘了加 <code>@Data</code> 注解,导致没有 <code>getter/setter</code> 就导致了这个问题,加上注解即可</p><p>解决!</p></li><li><p>数据库乱码问题</p><p>测试模块 RPC 远程调用返回的结果为:</p><div class="language-json line-numbers-mode" data-ext="json"><pre class="language-json"><code>测试结果:<span class="token punctuation">{</span><span class="token property">&quot;activity&quot;</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">&quot;activityDesc&quot;</span><span class="token operator">:</span><span class="token string">&quot;?????????&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;activityId&quot;</span><span class="token operator">:</span><span class="token number">100002</span><span class="token punctuation">,</span><span class="token property">&quot;activityName&quot;</span><span class="token operator">:</span><span class="token string">&quot;????&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;beginDateTime&quot;</span><span class="token operator">:</span><span class="token number">1705215282000</span><span class="token punctuation">,</span><span class="token property">&quot;endDateTime&quot;</span><span class="token operator">:</span><span class="token number">1705215282000</span><span class="token punctuation">,</span><span class="token property">&quot;stockCount&quot;</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">&quot;takeCount&quot;</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">&quot;result&quot;</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">&quot;code&quot;</span><span class="token operator">:</span><span class="token string">&quot;0000&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;info&quot;</span><span class="token operator">:</span><span class="token string">&quot;成功&quot;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>明显的乱码问题,查看数据库,发现插入的时候就以及乱码了,看了一下配置文件中的数据库连接 url,发现使用了 useUnicode=true,并没有指定字符集,所以添加一下 utf-8 字符集即可,完整 url: <code>jdbc:mysql://127.0.0.1:3306/lottery?useUnicode=true&amp;characterEncoding=UTF-8</code></p><p>再进行一轮测试,测试结果:</p><div class="language-json line-numbers-mode" data-ext="json"><pre class="language-json"><code>测试结果:<span class="token punctuation">{</span><span class="token property">&quot;activity&quot;</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">&quot;activityDesc&quot;</span><span class="token operator">:</span><span class="token string">&quot;仅用于插入数据测试&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;activityId&quot;</span><span class="token operator">:</span><span class="token number">100003</span><span class="token punctuation">,</span><span class="token property">&quot;activityName&quot;</span><span class="token operator">:</span><span class="token string">&quot;测试活动&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;beginDateTime&quot;</span><span class="token operator">:</span><span class="token number">1705218054000</span><span class="token punctuation">,</span><span class="token property">&quot;endDateTime&quot;</span><span class="token operator">:</span><span class="token number">1705218054000</span><span class="token punctuation">,</span><span class="token property">&quot;stockCount&quot;</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">&quot;takeCount&quot;</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">&quot;result&quot;</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">&quot;code&quot;</span><span class="token operator">:</span><span class="token string">&quot;0000&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;info&quot;</span><span class="token operator">:</span><span class="token string">&quot;成功&quot;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>解决!</p></li></ol><h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2><p>今天干了说明呢?</p><ol><li>配置环境</li><li>跑通 RPC</li></ol><p>具体怎么跑通 RPC 的呢?</p><ol><li>在 common 模块创建通用类</li><li>在 infrastructure 模块创建 dao 接口以及和数据库相对应的 po 类</li><li>在 rpc 模块下创建 RPC 通信接口以及对应的请求和响应的封装类</li><li>然后在 interfaces 模块下实现 rpc 模块的接口,在这里调用 Mapper 进行增删改查</li><li>然后就写配置呗,SpringBoot 配置、Dubbo 配置、MyBatis 配置</li></ol><p>学到了什么呢?</p><ol><li>由于之前学习一直使用的是 MVC 架构,并且命名不太规范,所以对于包的命名现在很不适应,比如什么dto、vo啥的各种 o 不太熟悉,这个就不准备纠结了,准备靠代码量进行熟悉</li><li>对每个模块有了大概的了解,至少知道了接口写在哪个模块,接口实现类在哪个模块以及 Mapper 写在哪</li><li>现在在我眼中,这个 interfaces 模块,就跟以前学的 Dubbo 的服务提供者一样吧?因为这个模块用来实现接口的,所以就会引用其他模块,要调用其他模块的东西就要添加依赖,所以这个模块起起来之后,就带动了所有模块,整个项目也就 run 起来了</li></ol><p>第一天,脑子还有点迷糊,因为基础不太牢固,所以有些小 bug 花费了挺长时间的,但是至少是跑起来了吧?也还行,路虽远,行则将至嘛,虽然年后要找实习,但是还是慌不得,慢慢来,一口吃不成个大胖子,准备晚上再补一补 Dubbo 基础</p>`,10);function b(_,v){const a=p("ExternalLinkIcon");return e(),l("div",null,[i,u,d,t("ol",null,[k,t("li",null,[t("p",null,[n("阅读 "),t("a",q,[n("210801_xfg_initProject"),r(a)]),n(" 分支上的 POM 文件")]),y]),h]),m])}const x=o(c,[["render",b],["__file","day01.html.vue"]]);export{x as default};
const e=JSON.parse('{"key":"v-45c77906","path":"/md/dev-log/day02.html","title":"Day02","lang":"zh-CN","frontmatter":{"title":"Day02","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务\\r[x] 表设计; \\r[x] 抽奖领域模块开发; 学习过程 1. 查询分库分表相关知识点,了解到垂直和水平分库分表,主要是为了解决数据量过大导致 MySQL 查询慢、单体容量过大问题 2. 开始写代码 1. 编写基础的持久化对象 (PO) 2. 编写 Mapper 接口 3. 编写对应的 Mapper.xml 4. 设计抽奖策略顶级接口,主要是入参...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day02.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day02"}],["meta",{"property":"og:description","content":"任务\\r[x] 表设计; \\r[x] 抽奖领域模块开发; 学习过程 1. 查询分库分表相关知识点,了解到垂直和水平分库分表,主要是为了解决数据量过大导致 MySQL 查询慢、单体容量过大问题 2. 开始写代码 1. 编写基础的持久化对象 (PO) 2. 编写 Mapper 接口 3. 编写对应的 Mapper.xml 4. 设计抽奖策略顶级接口,主要是入参..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day02\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":2,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":2,"title":"学习过程","slug":"学习过程","link":"#学习过程","children":[]},{"level":2,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":3.53,"words":1059},"filePathRelative":"md/dev-log/day02.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as l}from"./plugin-vue_export-helper-c27b6911.js";import{o as i,c as a,f as e}from"./app-730966a2.js";const r={},o=e('<h2 id="任务" tabindex="-1"><a class="header-anchor" href="#任务" aria-hidden="true">#</a> 任务</h2><ul><li>[x] 表设计</li><li>[x] 抽奖领域模块开发</li></ul><h2 id="学习过程" tabindex="-1"><a class="header-anchor" href="#学习过程" aria-hidden="true">#</a> 学习过程</h2><ol><li>查询分库分表相关知识点,了解到垂直和水平分库分表,主要是为了解决数据量过大导致 MySQL 查询慢、单体容量过大问题</li><li>开始写代码 <ol><li>编写基础的持久化对象 (PO)</li><li>编写 Mapper 接口</li><li>编写对应的 Mapper.xml</li><li>设计抽奖策略顶级接口,主要是入参出参,如何封装,要封装哪些数据</li><li>编写顶级接口的基础实现,实现里面公用的方法,比如把初始化方法、哈希计算的方法以及判断是否初始化完成</li><li>编写两种算法的实现</li><li>算法单元测试</li></ol></li></ol><h2 id="遇到的问题" tabindex="-1"><a class="header-anchor" href="#遇到的问题" aria-hidden="true">#</a> 遇到的问题</h2><ol><li><p>为什么在设计阶段就考虑分库分表等问题</p><p>在之前的学习过程中,并没有项目环境的支撑,导致了这个问题,一个大的项目,如果要兼顾性能以及代码的可扩展性,那么在数据库设计阶段就应该想到这些,那些是热点数据,那些数据会进行大量的插入,没有全局把控的观念,只有了解这些,才能设计出一个性能良好且代码可维护性高的项目,这个需要项目积累,这是一个很重要的东西,以后在学习的时候一定要多注意这方面,多看看别人的数据库是怎么设计的,以及为什么要这么设计,要有全局把控的观念</p></li><li><p>抽奖算法是怎么实现的呢</p><p>首先这个初始化的时候,传入奖品和对应的概率,然后概率乘以 100,就是对应的下标范围,一个奖品一个范围,是不会重复的,然后经过斐波那契哈希散列算法,将这个对应的下标进行加工,使其均匀的分布在数组中,在对下标进行加工的过程中,确保了无论传入什么数字,都会在 0 ~ 128 的范围内</p><ol><li><p>SingleRateRandomDrawAlgorithm</p><p>这种策略是生成一个 1 ~ 100 的随机数,然后经过 hashIdx 计算对应的下标,然后去上面初始化好的数组中去取奖品</p></li><li><p>DefaultRateRandomDrawAlgorithm</p><p>这是一种必中奖策略,先排除掉不在抽奖范围内的奖品ID,然后生成随机数,然后判断这个随机数是否在指定的范围内,如果不在,那么这个奖品就没中,然后看下一个奖品,重新生成随机数,然后看是否在指定的中奖概率内加上上次生成的随机数范围内</p></li></ol></li></ol><h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2><p>今天主要把抽奖算法给搞定了,虽然代码不多,但是很难理解,最开始都搞不清楚为什么这样子就实现了抽奖算法,不懂这个概率是如何保证的,然后 debug 了好久,发现其实就是一个 128 长度的数组,然后经过哈希散列排列,保证随机的均匀性,其实这 128 长度的数组就已经保证了抽奖的概率,假设不经过哈希算法,直接放进去,假设两个的抽奖概率是 0.1 和 0.2,那么放进去的时候就是下标 1~10 全是第一个奖品,下标 11 ~ 30 全是第二个奖品,随机数生成的是 1 ~ 100,那么第一个奖品也就是有 10 个数字能中奖,那不就是 10% 的中奖概率了么,加哈希散列只是为了均匀分布,增加随机性和公平性</p><p>收获:</p><ol><li>对 DDD 有更深的了解,知道什么类该写在什么包下,比昨天更清楚代码该如何组织了</li><li>了解了分库分表,虽然是第一次接触,但是至少知道了为什么要分库分表,随着项目的进行,就会学会如何分库分表了吧</li><li>了解了 Hash 散列算法,后续看看源码,要搞清楚底层是如何运作的</li></ol>',10),h=[o];function t(d,p){return i(),a("div",null,h)}const s=l(r,[["render",t],["__file","day02.html.vue"]]);export{s as default};
const e=JSON.parse('{"key":"v-425dc7c8","path":"/md/dev-log/day03.html","title":"Day03","lang":"zh-CN","frontmatter":{"title":"Day03","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"day03 任务\\r[x] 模板模式处理抽奖流程; 学习过程 1. 因为之前没学过设计模式,先学一学模板模式,用到一种学一种,哈哈哈 2. 先看一下整个抽奖流程 ![抽奖过程][step] 3. 了解了抽奖流程之后就开始写代码 1. 先写对应的 dao 层 1. 要查策略吧?写个策略的 Mapper 2. 要查策略详情吧?写个策略详情的 Mapper 3...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day03.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day03"}],["meta",{"property":"og:description","content":"day03 任务\\r[x] 模板模式处理抽奖流程; 学习过程 1. 因为之前没学过设计模式,先学一学模板模式,用到一种学一种,哈哈哈 2. 先看一下整个抽奖流程 ![抽奖过程][step] 3. 了解了抽奖流程之后就开始写代码 1. 先写对应的 dao 层 1. 要查策略吧?写个策略的 Mapper 2. 要查策略详情吧?写个策略详情的 Mapper 3..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day03\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":2,"title":"day03","slug":"day03","link":"#day03","children":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":3,"title":"学习过程","slug":"学习过程","link":"#学习过程","children":[]},{"level":3,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":39.64,"words":11893},"filePathRelative":"md/dev-log/day03.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
此差异已折叠。
const e=JSON.parse('{"key":"v-3ef4168a","path":"/md/dev-log/day04.html","title":"Day04","lang":"zh-CN","frontmatter":{"title":"Day04","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务 [x] 简单工厂搭建发奖领域; 学习过程 1. 表结构变了,先导入 SQL,然后该对应的 PO 类,然后改一下 Mapper 文件 2. 先把包结构建好 1. 新建一个领域包,负责发奖 2. 领域包内建三个子包,model 实体封装包、repository 提供仓储服务、service 提供具体的服务(重点内容) 3. 看一下代码的继承关系 4....","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day04.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day04"}],["meta",{"property":"og:description","content":"任务 [x] 简单工厂搭建发奖领域; 学习过程 1. 表结构变了,先导入 SQL,然后该对应的 PO 类,然后改一下 Mapper 文件 2. 先把包结构建好 1. 新建一个领域包,负责发奖 2. 领域包内建三个子包,model 实体封装包、repository 提供仓储服务、service 提供具体的服务(重点内容) 3. 看一下代码的继承关系 4...."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day04\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":3,"title":"学习过程","slug":"学习过程","link":"#学习过程","children":[]},{"level":2,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":1.54,"words":461},"filePathRelative":"md/dev-log/day04.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as i}from"./plugin-vue_export-helper-c27b6911.js";import{o as l,c as e,f as a}from"./app-730966a2.js";const r={},o=a('<h3 id="任务" tabindex="-1"><a class="header-anchor" href="#任务" aria-hidden="true">#</a> 任务</h3><ul><li>[x] 简单工厂搭建发奖领域</li></ul><h3 id="学习过程" tabindex="-1"><a class="header-anchor" href="#学习过程" aria-hidden="true">#</a> 学习过程</h3><ol><li><p>表结构变了,先导入 SQL,然后该对应的 PO 类,然后改一下 Mapper 文件</p></li><li><p>先把包结构建好</p><ol><li>新建一个领域包,负责发奖</li><li>领域包内建三个子包,model 实体封装包、repository 提供仓储服务、service 提供具体的服务(重点内容)</li></ol></li><li><p>看一下代码的继承关系</p></li><li><p>debug 看一下代码执行流程,了解其中的调用关系</p><ol><li>先执行抽奖,返回抽奖结果</li><li>对抽奖结果进行判断,如果是未中奖,直接返回</li><li>中奖了就保存用户信息以及订单信息</li><li>根据中奖结果中的奖品类型获取对应的服务</li><li>然后把第三步保存的用户信息以及订单信息传进去,做一个发奖的操作</li><li>然后返回发奖结果</li></ol></li></ol><h2 id="遇到的问题" tabindex="-1"><a class="header-anchor" href="#遇到的问题" aria-hidden="true">#</a> 遇到的问题</h2><p>今天还没遇到啥问题,代码比较简单,主要是数据库字段规范之后,好多 Mapper 要改 T.T,最开始我还在纠结要不要当初建表的时候就改了</p><p><strong>就很气,本来能学两小节的,md,电脑被亲戚孩子给整挂了,直接开不了机了,麻了,修电脑都修了两小时,系统还重装了,又重装环境</strong></p><h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2><ol><li>越来越喜欢 DDD 架构这种包的组织方式了,虽然包很多,看着有点复杂,但是真的理解了之后,就感觉很干净,扩展性也很好,虽然目前还没完全搞清楚 DDD</li><li>学会了工厂模式,根据奖品类型,从工厂里面拿对应的实现类进行发奖操作</li></ol>',9),d=[o];function t(h,n){return l(),e("div",null,d)}const p=i(r,[["render",t],["__file","day04.html.vue"]]);export{p as default};
import{_ as n}from"./plugin-vue_export-helper-c27b6911.js";import{o as a,c as s,f as t}from"./app-730966a2.js";const e={},o=t(`<h2 id="任务" tabindex="-1"><a class="header-anchor" href="#任务" aria-hidden="true">#</a> 任务</h2><ul><li>[x] 活动领域的配置与状态</li></ul><h2 id="学习过程" tabindex="-1"><a class="header-anchor" href="#学习过程" aria-hidden="true">#</a> 学习过程</h2><ol><li>包结构变化,调整对应的包</li><li>了解活动创建的整个流程,然后将流程进行编排(其实就是落库的步骤呗),写对应的 repository 层代码 <ol><li>首先明确要做哪些操作 <ol><li>添加活动</li><li>添加奖品</li><li>添加活动配置</li><li>添加策略</li><li>添加策略明细</li></ol></li><li>编写对应的 repository 接口和实现类</li><li></li></ol></li><li>debug 了解状态模式如何进行的状态判断(感觉不用刻意去学这个设计模式,通过对项目的学习,从而达到状态模式的学习,<strong>后期进行设计模式的统一学习</strong>) <ol><li>首先定义一个状态处理的接口,入参统一是活动ID和当前状态</li><li>定义一个活动状态抽象类,这个抽象类的子类用来判断某种状态是否可以流转</li><li>编写抽象类的实现,里面定义是否可以流转</li><li>编写状态配置类,把每一种活动状态抽象类的实现注入进去并放入 Map 中,供状态处理服务使用</li><li>编写状态处理接口的实现类 <ol><li>先从状态配置中获取当前状态所对应的活动状态流转实现类</li><li>然后实现类调用方法,通过方法的返回值来确定是否能进行操作 <ol><li>如果能进行变更的,先进行落库操作,然后根据 MyBatis 返回值返回对应信息</li><li>如果不能进行变更的,直接返回对应的错误信息</li></ol></li></ol></li></ol></li></ol><h2 id="遇到的问题" tabindex="-1"><a class="header-anchor" href="#遇到的问题" aria-hidden="true">#</a> 遇到的问题</h2><ol><li><p>为什么要使用 <code>BeanUtils.copyProperties()</code></p><p>因为原来很少使用这种方法,以前都是 new 对象,然后把传进来的对象手动一个一个赋值,对这个方法不太了解,简单来说就是实现对象的拷贝,属性名相同的就进行拷贝,属性名不相同的就不进行操作,底层使用反射,首先把读写权限都设置为 true,然后再进行获取和赋值操作,这种操作是 <strong>浅拷贝</strong></p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token class-name">Modifier</span><span class="token punctuation">.</span><span class="token function">isPublic</span><span class="token punctuation">(</span>readMethod<span class="token punctuation">.</span><span class="token function">getDeclaringClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getModifiers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
readMethod<span class="token punctuation">.</span><span class="token function">setAccessible</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">Object</span> value <span class="token operator">=</span> readMethod<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token class-name">Modifier</span><span class="token punctuation">.</span><span class="token function">isPublic</span><span class="token punctuation">(</span>writeMethod<span class="token punctuation">.</span><span class="token function">getDeclaringClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getModifiers</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
writeMethod<span class="token punctuation">.</span><span class="token function">setAccessible</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
writeMethod<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></li><li><p>数据库 bug <code>### Error updating database. Cause: java.sql.SQLException: Incorrect string value: &#39;\\xE4\\xB8\\x80\\xE7\\xAD\\x89...&#39; for column &#39;award_name&#39; at row 1</code></p><p>中文插入乱码问题,我建数据库的时候设置了 utf8,但是建表的时候默认没有设置成 <code>utf8</code>,使用的编码是 <code>latin1</code>,所以需要修改字段的编码为 <code>utf8</code></p></li></ol><h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2><ol><li><p>包结果的变化</p><ol><li>首先呢这个解决了我之前的一个疑问:为啥要把数据库的真实操作写到领域层呢?这不应该写到基础服务层更符合逻辑吗?</li><li>更改详情:基础服务模块引入领域模块,在领域层写 repository 接口,在基础服务层写实现</li></ol></li><li><p>状态流程处理</p><p>相对于普通的 if-else 处理流程,状态模式设计模式把状态的流转转化为方法,从而简化了 if-else 一坨接着一坨的形式,如果有新的状态,只需要添加对应的抽象实现以及在其他实现中添加对应的流转方法</p><p><em>后期对设计模式进行统一的学习,目前只了解了基础的程序运行流程,根据流程来了解对应的设计模式,目前对于状态模式的了解仅限于以下两点</em></p><ol><li>将一种状态的流转包装成一个类,然后在类里面定义是否可以流转</li><li>状态的流转通过调用方法的形式进行,而不是通过 if-else 去判断,比如要把状态修改为审核通过,那么直接调用 <code>checkPass()</code> 然后找到当前状态处理类,调用处理类的 <code>checkPass()</code> 方法,然后返回结果就可以了</li></ol></li><li><p>对于学习的思考</p><p>最近陷入了日夜颠倒的死循环,主要就是晚上窝在床上玩手机呢,然后看了会儿星球就想起床学习,一学又搞到两三点三四点,搞不好 bug 多还通了个宵,导致第二天甚至第三天状态低迷,后面要压制学习欲望了,每天该做的做完了就休息,以后每周日休息一天,晚上一点前就睡觉,避免陷入死循环,再多的任务,人的精力也是有限的,只要按部就班稳扎稳打,相信最后也会有收获,不必急于求成</p></li></ol>`,8),i=[o];function p(l,c){return a(),s("div",null,i)}const d=n(e,[["render",p],["__file","day05.html.vue"]]);export{d as default};
const e=JSON.parse('{"key":"v-3b8a654c","path":"/md/dev-log/day05.html","title":"Day05","lang":"zh-CN","frontmatter":{"title":"Day05","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务\\r[x] 活动领域的配置与状态; 学习过程 1. 包结构变化,调整对应的包 2. 了解活动创建的整个流程,然后将流程进行编排(其实就是落库的步骤呗),写对应的 repository 层代码 1. 首先明确要做哪些操作 1. 添加活动 2. 添加奖品 3. 添加活动配置 4. 添加策略 5. 添加策略明细 2. 编写对应的 repository 接口...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day05.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day05"}],["meta",{"property":"og:description","content":"任务\\r[x] 活动领域的配置与状态; 学习过程 1. 包结构变化,调整对应的包 2. 了解活动创建的整个流程,然后将流程进行编排(其实就是落库的步骤呗),写对应的 repository 层代码 1. 首先明确要做哪些操作 1. 添加活动 2. 添加奖品 3. 添加活动配置 4. 添加策略 5. 添加策略明细 2. 编写对应的 repository 接口..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day05\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":2,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":2,"title":"学习过程","slug":"学习过程","link":"#学习过程","children":[]},{"level":2,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":3.98,"words":1193},"filePathRelative":"md/dev-log/day05.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
const e=JSON.parse('{"key":"v-3820b40e","path":"/md/dev-log/day06.html","title":"Day06","lang":"zh-CN","frontmatter":{"title":"Day06","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务 [x] ID 生成策略开发; 学习过程 1. 先看视频了解用到了啥 2. 看小傅哥策略模式的文章 (https://mp.weixin.qq.com/s/zOFLtSFVrYEyTuihzwgKYw) 3. 看代码结构 1. 定义一个接口,用来生成 id 2. 实现接口,实现不同的 id 生成算法 3. 定义一个上下文对象,包装各种 id 生成算...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day06.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day06"}],["meta",{"property":"og:description","content":"任务 [x] ID 生成策略开发; 学习过程 1. 先看视频了解用到了啥 2. 看小傅哥策略模式的文章 (https://mp.weixin.qq.com/s/zOFLtSFVrYEyTuihzwgKYw) 3. 看代码结构 1. 定义一个接口,用来生成 id 2. 实现接口,实现不同的 id 生成算法 3. 定义一个上下文对象,包装各种 id 生成算..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day06\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":3,"title":"学习过程","slug":"学习过程","link":"#学习过程","children":[]},{"level":3,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":3.6,"words":1081},"filePathRelative":"md/dev-log/day06.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as n}from"./plugin-vue_export-helper-c27b6911.js";import{r as o,o as a,c as t,a as l,d as e,e as r,f as s}from"./app-730966a2.js";const d={},c=l("h3",{id:"任务",tabindex:"-1"},[l("a",{class:"header-anchor",href:"#任务","aria-hidden":"true"},"#"),e(" 任务")],-1),p=l("ul",null,[l("li",null,"[x] ID 生成策略开发")],-1),h=l("h3",{id:"学习过程",tabindex:"-1"},[l("a",{class:"header-anchor",href:"#学习过程","aria-hidden":"true"},"#"),e(" 学习过程")],-1),_=l("li",null,[l("p",null,"先看视频了解用到了啥")],-1),u={href:"https://mp.weixin.qq.com/s/zOFLtSFVrYEyTuihzwgKYw",target:"_blank",rel:"noopener noreferrer"},f=l("li",null,[l("p",null,"看代码结构"),l("ol",null,[l("li",null,"定义一个接口,用来生成 id"),l("li",null,"实现接口,实现不同的 id 生成算法"),l("li",null,"定义一个上下文对象,包装各种 id 生成算法,然后放到 Spring 容器中供其他类注入使用")]),l("p",null,"今天的代码比较简单,主要就是涉及策略模式的使用,这里的上下文对象和之前的 config 类似,都是把写好的实现类进行包装,统一放到一个容器内,然后其他类通过这个容器,配合枚举拿到对应的实现类进行调用")],-1),D=l("li",null,[l("p",null,"实操")],-1),I=s('<h3 id="遇到的问题" tabindex="-1"><a class="header-anchor" href="#遇到的问题" aria-hidden="true">#</a> 遇到的问题</h3><ol><li>什么是雪花算法</li><li>项目代码中的雪花算法为什么要这么写</li></ol><h3 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h3><ol><li><p>对策略模式的新看法</p><p>现在对策略模式的看法如下:</p><ol><li>将每一种策略想象成一个又一个的工具类</li><li>这些工具类都来自同一个接口,也就是实现的功能是类似的,比如都是生成 ID,都是用来发奖的</li><li>把这些工具类进行 “打包” 处理,封装在一个 Map 中,键使用枚举进行处理</li><li>后续使用通过注入封装好的 Map 和枚举直接进行 get 操作然后使用就可以了</li></ol><p>好处:</p><p>减少 if else 的次数,如果以后要进行扩展,只需要添加一个接口实现,然后在 &quot;打包&quot; 里添加一种策略就可以了,易于扩展,避免代码过度耦合,把一坨代码进行分片,功能职责划分更清楚,并且可以动态切换算法:将实现类进行更改就可以实现动态切换</p></li><li><p>什么是雪花算法</p><p>雪花算法用于生成分布式唯一 ID,核心思想如下:</p><ol><li>将一个64位的整数划分为不同的部分,每一部分代表不同的含义</li><li>符号位(1位):始终为 0,表示生成的 ID 为正整数</li><li>时间戳(41位):记录生成 ID 的时间戳,精确到毫秒级,41位可以表示约 69 年的时间</li><li>工作机器 ID(10位):标识机器的唯一ID,用于解决分布式系统中的多节点生成 ID 的冲突问题,最多有 2^10 台机器 ,即 1024 个</li><li>序列号(12位):表示同一毫秒内的序列号,用于解决同一节点在同一毫秒内生成 ID 的冲突问题,最多可以用 2 的 12 次方个 ID,也就是同一毫秒内同一机器最多生成 4096 个</li></ol><p>通俗化:确保在分布式系统中,通过对时间戳、机器和序列号进行加工,生成一个唯一 ID</p><p>了解了这个东西就能理解项目中为啥要这么写了,后面看看雪花算法的具体源码,看看每个部分如何进行加工的</p></li><li><p>短码生成的时候进行打乱和再加工</p><p>因为没有实际项目经验之前就是直接拿当前时间戳进行获取的,没有进行打乱操作,以后要记住这个操作,避免项目数据被别人抓个包一下子就猜出来了 -.- 好歹穿件衣服,不能裸奔</p></li><li><p>预习预习明天的内容,哈哈哈,好像要开始上强度了,昨天亲戚结婚忙了一天,半夜才回来,今天就到这把,查点资料预习预习明天的,感觉 DDD 这种包组织方式特别适合每种设计模式和算法的落地,MVC 如果想要算法和设计模式落地的话,感觉要考虑的东西很多很多,要么就是牵一发而动全身,要么就是落地之后包里面有很多的多余的东西,这种方式则不会出现这种情况,一个领域里面,使用一种设计模式,并不会影响其他的包,其他的包只管调用所提供的接口就好了</p></li></ol>',4);function m(x,V){const i=o("ExternalLinkIcon");return a(),t("div",null,[c,p,h,l("ol",null,[_,l("li",null,[l("p",null,[e("看小傅哥策略模式的"),l("a",u,[e("文章"),r(i)])])]),f,D]),I])}const k=n(d,[["render",m],["__file","day06.html.vue"]]);export{k as default};
const e=JSON.parse('{"key":"v-649fe232","path":"/md/dev-log/day07~day08.html","title":"Day07 ~ Day08","lang":"zh-CN","frontmatter":{"title":"Day07 ~ Day08","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务\\r[x] 分库分表组件; 遇到的问题 问题就不说了,这一章节全是问题 T.T,基础不牢,地动山摇啊!!! 总结 首先建立一个大局观,要实现一个分库分表组件,那么先要学会如何编写 SpringBoot Starter,然后这个 Starter 需要实现的功能是分库分表,那么一定是有多个数据源,这个数据源从项目的 yml 配置文件传进来,然后就要实现多...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day07~day08.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day07 ~ Day08"}],["meta",{"property":"og:description","content":"任务\\r[x] 分库分表组件; 遇到的问题 问题就不说了,这一章节全是问题 T.T,基础不牢,地动山摇啊!!! 总结 首先建立一个大局观,要实现一个分库分表组件,那么先要学会如何编写 SpringBoot Starter,然后这个 Starter 需要实现的功能是分库分表,那么一定是有多个数据源,这个数据源从项目的 yml 配置文件传进来,然后就要实现多..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day07 ~ Day08\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":3,"title":"遇到的问题","slug":"遇到的问题","link":"#遇到的问题","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":2.75,"words":824},"filePathRelative":"md/dev-log/day07~day08.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as i}from"./plugin-vue_export-helper-c27b6911.js";import{o as l,c as a,f as e}from"./app-730966a2.js";const o={},r=e('<h3 id="任务" tabindex="-1"><a class="header-anchor" href="#任务" aria-hidden="true">#</a> 任务</h3><ul><li>[x] 分库分表组件</li></ul><h3 id="遇到的问题" tabindex="-1"><a class="header-anchor" href="#遇到的问题" aria-hidden="true">#</a> 遇到的问题</h3><p>问题就不说了,这一章节全是问题 T.T,基础不牢,地动山摇啊!!!</p><h3 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h3><p>首先建立一个大局观,要实现一个分库分表组件,那么先要学会如何编写 SpringBoot Starter,然后这个 Starter 需要实现的功能是分库分表,那么一定是有多个数据源,这个数据源从项目的 yml 配置文件传进来,然后就要实现多数据源的切换,然后分表操作就是要修改 SQL 的表名,所以需要做的事情大概是如下:</p><ol><li>读取数据源信息</li><li>动态修改数据源</li><li>动态修改 SQL</li></ol><p>那么细节该如何实现呢?需要想几个问题,某条数据应该分到哪个库的哪个表呢?这个库表信息该存到哪里进行共享呢?如何动态修改数据源呢?如何动态修改 SQL 呢?那么就需要对应的技术进行支持:</p><ol><li>Spring &amp; SpringBoot 基础框架,提供依赖注入、配置管理功能</li><li><code>AbstractRoutingDataSource </code> 实现动态数据源的路由逻辑</li><li><code>AspectJ</code> 切面编程,运行时动态拦截方法调用</li><li>反射 API,从方法参数中提取路由键的值</li><li>正则表达式,解析和修改 SQL</li><li>ThreadLocal,存储路由信息,以支持动态数据源路由</li></ol><p>总体执行流程:</p><ol><li>调用被 <code>@DBRouter</code> 注解的方法</li><li>然后被切面进行拦截,拦截之后先进行路由计算,然后把计算结果保存到 ThreadLocal 中</li><li>然后 DynamicDataSource 通过保存到 ThreadLocal 中的数据确定使用哪一个数据源</li><li>然后 MyBatis 插件修改 SQL 中的表字段</li><li>然后数据库操作执行完成</li><li>切面清理 ThreadLocal 里面的数据</li><li>方法执行完成,返回结果</li></ol><p>虽然步骤不多,但是稍不注意就会出现小 bug,抑或扰动函数算法出错,抑或解析 yml 配置出错等等诸多问题,也是花了两三天才大致搞明白这个路由组件,因为这里面的东西大部分之前都没接触过,查阅了许多文档,毕竟之前连切面都不怎么用,最多也就是拿来做全局日志处理</p><p>总之,要先在大脑里面理清总体的一个执行流程,然后根据这个流程再去看代码要清晰很多,最开始的时候没理清步骤,直接看的代码,那种感觉就像第一天学 DDD 一样,直接一脸懵逼,怎么这么多包,卧槽,第一遍下来大概只学到了百分之五十吧,这一遍大概只学到了整体架构,具体的细节还没掌握,下一次努力啃啃细节,如果要我写整个这一套代码,我肯定写出来会报很多错,但是第一次就想学透整个路程怎么可能呢?好在这一次理清了整体架构,至少有了头绪,不至于开不了头,有了头绪,到处搜一搜,拼拼凑凑也能写,哈哈哈</p>',13),t=[r];function c(d,h){return l(),a("div",null,t)}const p=i(o,[["render",c],["__file","day07~day08.html.vue"]]);export{p as default};
const e=JSON.parse('{"key":"v-c97ab98e","path":"/md/dev-log/day09~day10.html","title":"Day09 ~ Day10","lang":"zh-CN","frontmatter":{"title":"Day09 ~ Day10","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务 [x] 在应用层编排抽奖过程; 总结 有了前面的模板模式的基础,这一章节相对来说比较容易,自己实现的时候也没有什么大问题,大体流程就是写接口,编排流程,然后写实现类,然后写 Mapper,至于为什么花了两三天,这就不得不说上一章的分库分表了,没写过 SpringBoot Starter,没写过 MyBatis 插件,对 AOP 没有深刻的理解,纯...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day09~day10.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day09 ~ Day10"}],["meta",{"property":"og:description","content":"任务 [x] 在应用层编排抽奖过程; 总结 有了前面的模板模式的基础,这一章节相对来说比较容易,自己实现的时候也没有什么大问题,大体流程就是写接口,编排流程,然后写实现类,然后写 Mapper,至于为什么花了两三天,这就不得不说上一章的分库分表了,没写过 SpringBoot Starter,没写过 MyBatis 插件,对 AOP 没有深刻的理解,纯..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day09 ~ Day10\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":2.48,"words":744},"filePathRelative":"md/dev-log/day09~day10.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as e}from"./plugin-vue_export-helper-c27b6911.js";import{o as i,c as o,f as t}from"./app-730966a2.js";const r={},a=t('<h3 id="任务" tabindex="-1"><a class="header-anchor" href="#任务" aria-hidden="true">#</a> 任务</h3><ul><li>[x] 在应用层编排抽奖过程</li></ul><h3 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h3><p>有了前面的模板模式的基础,这一章节相对来说比较容易,自己实现的时候也没有什么大问题,大体流程就是写接口,编排流程,然后写实现类,然后写 Mapper,至于为什么花了两三天,这就不得不说上一章的分库分表了,没写过 SpringBoot Starter,没写过 MyBatis 插件,对 AOP 没有深刻的理解,纯硬啃下来的,但是记不太劳,所以晚上睡不着觉,总感觉缺点什么东西,就花了两天干了如下几件事:</p><ol><li><p>新建一个空的 SpringBoot 项目,从 <code>SpringApplication.run()</code> 方法开始 debug,一步一步看,在这一个过程中主要学到了如下几点:</p><ul><li>一个 SpringBoot 项目是如何初始化的,在哪里创建的容器等等</li><li>如何加载第三方 Starter 的</li><li><s>在哪里打印的Banner 以及如何设置</s> 这个不是重点,哈哈哈,但是挺好玩的</li><li>还有 <code>ApplicationRunner</code> 和 <code>CommandLineRunner</code></li><li>还有异常报告器 <code>exceptionReporters</code></li><li>还有几个关于上下文环境的重要方法 <code>prepareContext()</code> 、<code>refreshContext()</code>、<code>afterRefresh()</code></li></ul><p>明白了 SpringBoot 应用初始化流程就知道所写的分录分表路由 starter 是在哪个阶段进行数据源设置以及为什么要在 <code>AutoConfig</code> 类下进行 Bean 的注入了</p></li><li><p>看了看 MyBatis 插件相关的文档,大致了解了一个 MyBatis 插件如何编写,看了这个以后看 MyBatis-Plus 源码的时候可能会轻松一点</p></li><li><p>复习了一下 AOP,注解的属性有哪些以及该怎么写都有点忘了</p></li><li><p>在这个 debug 的过程中其实画了一些图,但是因为没有 OSS,所以图片不太好展示,所以使用 vuepress + github pages + github actions 搭建了一个博客,后面有空了会把看源码的过程发上去</p></li></ol><p>虽然很想继续往下学,但是感觉这个项目里面,分库分表这一章节应该是灵魂所在了,虽然还没学后面,但是感觉其他章节更多的是关注业务层面,主要是来解决业务问题的,但是分库分表这一章节感觉能彻彻底底搞明白的话收获应该是很大的,虽然进度慢了,但是通过对源码的阅读也学到了很多东西,比如代码规范,在阅读 SpringBoot 源码的时候,给我最大的感觉就是,其实好的东西是不需要太多注释的,因为他每一步所调用的方法都给你写的很明白,比如 SpringBoot 程序初始化过程,只要英文够好,就跟看<s>小学阅读一样</s>,不知道花的这两天值不值,毕竟还有一个月就找工作了,是不是应该快点把项目做完</p>',6),n=[a];function l(c,d){return i(),o("div",null,n)}const h=e(r,[["render",l],["__file","day09~day10.html.vue"]]);export{h as default};
import{_ as t}from"./plugin-vue_export-helper-c27b6911.js";import{o,c as n,a as e,d as a}from"./app-730966a2.js";const c={},i=e("h3",{id:"任务",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#任务","aria-hidden":"true"},"#"),a(" 任务")],-1),s=e("ul",null,[e("li",null,"[x] 在应用层编排抽奖过程")],-1),r=e("h3",{id:"总结",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#总结","aria-hidden":"true"},"#"),a(" 总结")],-1),d=e("p",null,"今天的内容比较简单,最主要的问题就是表改了,然后花了很多时间去改对应的 PO 以及 SQL,然后今天第一次开发 application 层,感觉就是把 domain 层各个领域进行组装,然后形成一个又一个的流程,在这里面会使用 MQ 把流程进行切片,之后写门面接口应该就是调 application 层里面各个流程了,这样对于 Controller 层感觉挺好的,只需要简单的封装一下前端传进来的参数,然后调用 application 层执行各个流程就可以了",-1),l=e("p",null,"感觉今天最大的收获就在于学到了在开发的过程中要把整个流程切分一下,分成一块一块的,然后用 MQ 进行后续的操作,用户不需要感知到这一切,他只需要点进去,然后执行一个小的片段,然后剩下的操作可以使用 MQ 来慢慢操作,而不是之前那样直接单线程一个流程写完,又臭又长,返回得还慢,用户体验很不好,学到了流程切片,今天不亏,哈哈哈哈,这个东西还是很有用的",-1),_=[i,s,r,d,l];function h(p,u){return o(),n("div",null,_)}const x=t(c,[["render",h],["__file","day11.html.vue"]]);export{x as default};
const e=JSON.parse('{"key":"v-104da61f","path":"/md/dev-log/day11.html","title":"Day011","lang":"zh-CN","frontmatter":{"title":"Day011","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务 [x] 在应用层编排抽奖过程; 总结 今天的内容比较简单,最主要的问题就是表改了,然后花了很多时间去改对应的 PO 以及 SQL,然后今天第一次开发 application 层,感觉就是把 domain 层各个领域进行组装,然后形成一个又一个的流程,在这里面会使用 MQ 把流程进行切片,之后写门面接口应该就是调 application 层里面各个...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day11.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day011"}],["meta",{"property":"og:description","content":"任务 [x] 在应用层编排抽奖过程; 总结 今天的内容比较简单,最主要的问题就是表改了,然后花了很多时间去改对应的 PO 以及 SQL,然后今天第一次开发 application 层,感觉就是把 domain 层各个领域进行组装,然后形成一个又一个的流程,在这里面会使用 MQ 把流程进行切片,之后写门面接口应该就是调 application 层里面各个..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day011\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":3,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":1.14,"words":341},"filePathRelative":"md/dev-log/day11.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as n}from"./plugin-vue_export-helper-c27b6911.js";import{o as s,c as a,f as t}from"./app-730966a2.js";const e={},p=t(`<h3 id="任务" tabindex="-1"><a class="header-anchor" href="#任务" aria-hidden="true">#</a> 任务</h3><ul><li>[x] 规则引擎量化人群参与活动</li></ul><h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2><p>首先先去了解了一下组合模式和决策树,然后看了看数据库,其实就是把一个类似于二叉树的结构存到了数据库里,分别对应了三个东西,一个表用来保存决策树的树根信息,然后一个表用来保存树上的所有节点的信息,然后一个表用来存决策树的连接信息,我们可以通过树根的 ID 拿到所有相关的连线信息以及所有相关的节点信息,明白了数据库相关的东西之后屡屡代码结构</p><p>什么是组合模式呢?先看看维基百科对组合模式的定义,然后直接看代码,给我的第一感觉就是把每一个 if-else 的条件抽取出来,然后变成一个又一个的 filter,然后在规则引擎中进行使用,首先把一个个 filter 包装到 map 中,供子类使用</p><p>其中最重要的代码我觉得是这个:</p><div class="language-java line-numbers-mode" data-ext="java"><pre class="language-java"><code> <span class="token keyword">protected</span> <span class="token class-name">TreeNodeVO</span> <span class="token function">engineDecisionMaker</span><span class="token punctuation">(</span><span class="token class-name">TreeRuleRich</span> treeRuleRich<span class="token punctuation">,</span> <span class="token class-name">DecisionMatterReq</span> matterReq<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">TreeRootVO</span> treeRoot <span class="token operator">=</span> treeRuleRich<span class="token punctuation">.</span><span class="token function">getTreeRoot</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">,</span> <span class="token class-name">TreeNodeVO</span><span class="token punctuation">&gt;</span></span> treeNodeMap <span class="token operator">=</span> treeRuleRich<span class="token punctuation">.</span><span class="token function">getTreeNodeMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Long</span> rootNodeId <span class="token operator">=</span> treeRoot<span class="token punctuation">.</span><span class="token function">getTreeRootNodeId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">TreeNodeVO</span> treeNodeInfo <span class="token operator">=</span> treeNodeMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>rootNodeId<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token class-name">Constants<span class="token punctuation">.</span>NodeType</span><span class="token punctuation">.</span><span class="token constant">STEM</span><span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>treeNodeInfo<span class="token punctuation">.</span><span class="token function">getNodeType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">String</span> ruleKey <span class="token operator">=</span> treeNodeInfo<span class="token punctuation">.</span><span class="token function">getRuleKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">LogicFilter</span> logicFilter <span class="token operator">=</span> logicFilterMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>ruleKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> matterValue <span class="token operator">=</span> logicFilter<span class="token punctuation">.</span><span class="token function">matterValue</span><span class="token punctuation">(</span>matterReq<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Long</span> nextNode <span class="token operator">=</span> logicFilter<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>matterValue<span class="token punctuation">,</span> treeNodeInfo<span class="token punctuation">.</span><span class="token function">getTreeNodeLineInfoList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
treeNodeInfo <span class="token operator">=</span> treeNodeMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>nextNode<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> treeNodeInfo<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol><li>获取树根节点信息</li><li>获取树根所对应的所有节点信息</li><li>判断每个节点是不是叶子节点 <ol><li>如果不是,就执行决策,如果通过就返回下一个节点</li><li>如果是叶子节点,也就是找到了对应的活动号,表示可以参与</li></ol></li></ol><p>那么就可以将代码结构分为两个部分,一个是决策者,提供决策相关逻辑,一个是执行者,对决策链条进行链路执行,然后返回最终结果,那么到这里应该代码逻辑就清晰了,决策者根据一定的比较规则,返回 ture 或者 false,执行者根据这个结果来判断是否要继续进行下一个判断,直到判断到叶子节点</p><p>了解了这个之后代码就好写了</p><p>感觉这个章节最大的难点就在于如果之前没有设计模式基础的话,会很难受,代码跳过去跳过来有时候找不到方向,一般我遇到这种情况的时候我就会梳理一下业务逻辑,代码结构无论怎么变,也一定是根据业务逻辑来的,之前做的事情一样不少,所以就按照自己想的逻辑去代码中找对应,去看看哪里做的比较,哪里拿到的链路结构,这样就将大问题化成了小问题,然后去对应代码中的每一个部分,这里也就是将逻辑执行步骤进行“打散”的过程,找到了每段代码对应那一段逻辑之后,看一看代码的继承体系,大概也就了解个七七八八了</p>`,11),o=[p];function c(l,i){return s(),a("div",null,o)}const k=n(e,[["render",c],["__file","day12.html.vue"]]);export{k as default};
const e=JSON.parse('{"key":"v-12027ebe","path":"/md/dev-log/day12.html","title":"Day012","lang":"zh-CN","frontmatter":{"title":"Day012","index":false,"icon":"laptop-code","category":["开发笔记","学习记录"],"description":"任务 [x] 规则引擎量化人群参与活动; 总结 首先先去了解了一下组合模式和决策树,然后看了看数据库,其实就是把一个类似于二叉树的结构存到了数据库里,分别对应了三个东西,一个表用来保存决策树的树根信息,然后一个表用来保存树上的所有节点的信息,然后一个表用来存决策树的连接信息,我们可以通过树根的 ID 拿到所有相关的连线信息以及所有相关的节点信息,明白了...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/day12.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Day012"}],["meta",{"property":"og:description","content":"任务 [x] 规则引擎量化人群参与活动; 总结 首先先去了解了一下组合模式和决策树,然后看了看数据库,其实就是把一个类似于二叉树的结构存到了数据库里,分别对应了三个东西,一个表用来保存决策树的树根信息,然后一个表用来保存树上的所有节点的信息,然后一个表用来存决策树的连接信息,我们可以通过树根的 ID 拿到所有相关的连线信息以及所有相关的节点信息,明白了..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Day012\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":3,"title":"任务","slug":"任务","link":"#任务","children":[]},{"level":2,"title":"总结","slug":"总结","link":"#总结","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":2.62,"words":786},"filePathRelative":"md/dev-log/day12.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
const e=JSON.parse('{"key":"v-2d0aa3df","path":"/md/","title":"Md","lang":"zh-CN","frontmatter":{"title":"Md","article":false,"feed":false,"sitemap":false,"description":"","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"Md"}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"article:author","content":"小傅哥"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"Md\\"}"]]},"headers":[],"git":{},"readingTime":{"minutes":0,"words":1},"filePathRelative":null,"autoDesc":true}');export{e as data};
const t=JSON.parse('{"key":"v-8daa1a0e","path":"/","title":"主页","lang":"zh-CN","frontmatter":{"home":true,"icon":"home","title":"主页","heroImage":"/logo.svg","bgImage":"https://theme-hope-assets.vuejs.press/bg/6-light.svg","bgImageDark":"https://theme-hope-assets.vuejs.press/bg/6-dark.svg","bgImageStyle":{"background-attachment":"fixed"},"heroText":"我的博客简历","tagline":"您好,我叫小傅哥,毕业于🎓吉林大学。在校期间积累了不错的编程经验,可熟练运用主流分布式技术栈,独立开发项目。","actions":[{"text":"查看简历 👣","link":"./md/","type":"primary"},{"text":"我的项目 💐","link":"https://openai.gaga.plus/"}],"highlights":[{"header":null,"bgImage":"/assets/bg/6-light.svg","bgImageDark":"/assets/bg/6-dark.svg","features":[{"title":"公众号 - 抽奖系统","icon":"comment-dots","details":"23年1月,以DDD领域驱动设计架构,开发完成分布式抽奖系统。运用了全面的分布式技术栈。"},{"title":"手写 MyBatis","icon":"box-archive","details":"23年4月,深度学习《手写MyBatis:渐进式源码实践》一书,完整实现了一个 MyBatis ORM 框架。"},{"title":"OpenAI 应用服务","icon":"table-columns","details":"23年8月,学习 OpenAi 技术,学习 OpenAi SDK 开发,完成应用场景的对接使用「涵盖支付对接」。"},{"title":"SpringBoot Stater","icon":"table-columns","details":"23年10月,通过对业务项目开发中的学习,对同类共性功能的重复开发,凝练成通用的服务治理组件。"}]}],"copyright":false,"footer":"<div class=\\"content\\"><a href=\\"http://beian.miit.gov.cn\\" target=\\"_blank\\">京ICP备1903****号</a> | MIT 协议, 版权所有 © 2023 你的名字,All rights reserved.</div>","description":"个人在大学/实习期间,参与过多次的技术类赛事项目,熟练使用各类技术框架,积累了丰富的开发经验。同时兼具着对技术的喜爱,长期对技术源码进行钻研学习吸收其中的设计精髓。尤其对 MyBatis 源码学习后,开发了一款监控 SQL 慢查询以及优化建议插件。并将此插件发布到了 IDEA Plugin 插件市场,半年获得了3000次下载量,获得了非常好的认可,个人...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"主页"}],["meta",{"property":"og:description","content":"个人在大学/实习期间,参与过多次的技术类赛事项目,熟练使用各类技术框架,积累了丰富的开发经验。同时兼具着对技术的喜爱,长期对技术源码进行钻研学习吸收其中的设计精髓。尤其对 MyBatis 源码学习后,开发了一款监控 SQL 慢查询以及优化建议插件。并将此插件发布到了 IDEA Plugin 插件市场,半年获得了3000次下载量,获得了非常好的认可,个人..."}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"主页\\",\\"description\\":\\"个人在大学/实习期间,参与过多次的技术类赛事项目,熟练使用各类技术框架,积累了丰富的开发经验。同时兼具着对技术的喜爱,长期对技术源码进行钻研学习吸收其中的设计精髓。尤其对 MyBatis 源码学习后,开发了一款监控 SQL 慢查询以及优化建议插件。并将此插件发布到了 IDEA Plugin 插件市场,半年获得了3000次下载量,获得了非常好的认可,个人...\\"}"]]},"headers":[],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":2.06,"words":619},"filePathRelative":"README.md","localizedDate":"2024年1月30日","autoDesc":true}');export{t as data};
const e=JSON.parse('{"key":"v-7c27fd02","path":"/md/dev-log/","title":"开发日志","lang":"zh-CN","frontmatter":{"title":"开发日志","index":false,"icon":"laptop-code","category":["自我介绍","专业技能","项目经验"],"description":"day01.md (day01.md);","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/dev-log/"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"开发日志"}],["meta",{"property":"og:description","content":"day01.md (day01.md);"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"开发日志\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":0.08,"words":25},"filePathRelative":"md/dev-log/README.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
import{_ as e}from"./plugin-vue_export-helper-c27b6911.js";import{o as n,c as o,a as t}from"./app-730966a2.js";const c={},l=t("br",null,null,-1),s=t("div",{class:"hint-container tip"},[t("p",{class:"hint-container-title"},"提示"),t("p",null,"个人在大学/实习期间,参与过多次的技术类赛事项目,熟练使用各类技术框架,积累了丰富的开发经验。同时兼具着对技术的喜爱,长期对技术源码进行钻研学习吸收其中的设计精髓。尤其对 MyBatis 源码学习后,开发了一款监控 SQL 慢查询以及优化建议插件。并将此插件发布到了 IDEA Plugin 插件市场,半年获得了3000次下载量,获得了非常好的认可,个人也得到了非常多的成长。地址:http://github.com/xxxx/xxxx")],-1),i=t("blockquote",null,[t("p",null,"我是一名热爱技术的Java程序员,自从踏入这个充满挑战与机遇的专业以来,我始终保持着对技术的高度热情和追求。我深信技术的力量可以改变世界,也能够提升个人的专业素养。在日常工作中,我不仅注重个人技能的提升,更致力于跟踪和学习行业内的最新技术动态,如SpringBoot、微服务架构、容器化技术等,以确保自己的技术栈始终保持现代化和竞争力。")],-1),_=[l,s,i];function a(r,u){return n(),o("div",null,_)}const h=e(c,[["render",a],["__file","index.html.vue"]]);export{h as default};
import{_ as o}from"./plugin-vue_export-helper-c27b6911.js";import{r as n,o as a,c as r,a as e,e as l,w as c,d as s}from"./app-730966a2.js";const d={};function _(m,i){const t=n("RouterLink");return a(),r("div",null,[e("ul",null,[e("li",null,[l(t,{to:"/md/dev-log/day01.html"},{default:c(()=>[s("day01.md")]),_:1})])])])}const p=o(d,[["render",_],["__file","index.html.vue"]]);export{p as default};
import{_ as o}from"./plugin-vue_export-helper-c27b6911.js";import{r as t,o as n,c,e as r}from"./app-730966a2.js";const a={};function _(s,l){const e=t("AutoCatalog");return n(),c("div",null,[r(e)])}const i=o(a,[["render",_],["__file","index.html.vue"]]);export{i as default};
import{_ as a}from"./plugin-vue_export-helper-c27b6911.js";import{r as t,o,c as n,a as i,d as l,e as r,f as s}from"./app-730966a2.js";const d={},h=i("h2",{id:"个人信息",tabindex:"-1"},[i("a",{class:"header-anchor",href:"#个人信息","aria-hidden":"true"},"#"),l(" 个人信息")],-1),c=i("li",null,"姓名",-1),u=i("li",null,"电话",-1),p=i("li",null,"邮箱",-1),S=i("li",null,"毕业时间",-1),_=i("li",null,"工作时间",-1),B=i("li",null,"Github:https://github.com/fuzhengwei",-1),M={href:"https://bugstack.cn/md/product/idea-plugin/vo2dto.html",target:"_blank",rel:"noopener noreferrer"},g=s('<h2 id="毕业院校" tabindex="-1"><a class="header-anchor" href="#毕业院校" aria-hidden="true">#</a> 毕业院校</h2><ul><li>时间、院校、专业、学位</li><li>荣誉、成绩</li></ul><h2 id="专业技能" tabindex="-1"><a class="header-anchor" href="#专业技能" aria-hidden="true">#</a> 专业技能</h2><ul><li>熟练掌握 Java 核心知识、JUC、HashMap、斐波那契散列等,具备良好的面向对象编程思想。</li><li>熟练掌握 Java 设计模式,如工厂、代理、组合、策略等设计模式,并善用设计原则构建可复用代码。</li><li>熟练使用 IDEA、Eclipse、Visual Studio Code、Navicat、PostMan、Git、Maven、SVN 等开发工具。</li><li>深入理解 JVM 底层原理,熟悉 JVM 各类垃圾收集器的使用及核心参数的调优,具备一定的 JVM 调优能力。</li><li><code>深入学习 Spring 核心流程模块,如IOC、AOP、依赖倒置等,掌握Spring解决复杂场景所需的分治、抽象和知识(设计模式、设计原则),能从核心原理上解决Spring场景问题。同时,具备基于 Spring 开发 SpringBoot Starter 的技能,减少研发成本,为复杂项目提供通用技术组件。</code></li><li><code>深入学习 MyBatis 核心流程模块,包括会话、反射、代理、事务和插件,熟练掌握 ORM 框架的设计思想、实现方式和应用价值。并根据需求结合 MyBatis 插件机制,开发企业所需的功能,如数据分页、数据库表路由、监控日志和数据安全等。</code></li><li>深入理解 Spring Boot,Spring Cloud 等微服务框架的设计原理及底层架构,熟悉各种微服务架构设计比如服务注册与发现,服务降级,限流,熔断,服务网关路由设计,服务安全认证架构。</li><li>熟悉 Dubbo、Zookeeper 等分布式服务协调与治理等技术。</li><li>熟练掌握 MySql,掌握 MySQL 主从同步,读写分离技术以及集群的搭建,具备一定的 SQL 调优能力。</li><li>深入理解 Redis 线程模型,熟练掌握 Redis 的核心数据结构的使用场景,熟悉各种缓存高并发的使用场景,比如缓存雪崩,缓存穿透等。</li><li>熟练掌握分布式场景中的常见的技术问题及解决,比如分布式锁,分布式事务,分布式 session,分布式任务调度。</li><li>熟悉 RabbitMQ、Kafka 等常用的消息中间件进行消息的异步数据处理。</li><li>了解分布式搜索引擎 ElasticSearch,并能基于 ELK+Kafka 搭建分布式日志收集系统,以及 x-pack-jdbc 的扩展使用。</li><li>熟悉 docker 常用命令,能够实现基于 docker+Jenkins 实现自动化部署</li><li>掌握 Linux 常用命令,了解 Nginx 服务器的反向代理、负载均衡、动静分离等。</li><li>熟练运用 DDD 四层架构领域驱动设计,构建出易于迭代和维护的工程架构,遵守整洁代码、洋葱架构设计思想。</li></ul><h2 id="工作经历【在校生无】" tabindex="-1"><a class="header-anchor" href="#工作经历【在校生无】" aria-hidden="true">#</a> 工作经历【在校生无】</h2><ul><li>公司</li><li>岗位</li><li>时间</li><li>职责【可选】</li><li>成绩【可选】</li></ul><h2 id="项目经验" tabindex="-1"><a class="header-anchor" href="#项目经验" aria-hidden="true">#</a> 项目经验</h2><h3 id="_1-营销活动平台-lottery-微服务抽奖系统" tabindex="-1"><a class="header-anchor" href="#_1-营销活动平台-lottery-微服务抽奖系统" aria-hidden="true">#</a> 1. 营销活动平台 - Lottery 微服务抽奖系统</h3><ul><li>系统架构:以 DDD 领域驱动设计开发,微服务拆分的分布式系统架构</li><li>核心技术:SpringBoot、MyBatis、Dubbo、MQ、MySQL、XDB-Router、ES、ZK</li><li>项目描述:抽奖系统是营销平台的重要微服务之一,可以满足 C 端人群的需求,例如拉新、促活、留存等。该系统运用抽象、分治和 DDD 知识,拆解服务边界,凝练领域服务功能。围绕抽奖服务建设领域服务,包括规则引擎、抽奖策略、活动玩法、奖品发放等。这可以满足业务产品快速迭代上线的需求,同时减少研发成本,提高交付效率。</li><li>核心职责: <ul><li>【高级】构建以 DDD 分层结构的处理方式,搭建整个抽奖系统架构。运用设计原则和工厂、代理、模板、组合、策略等设计模式的综合使用,搭建易于维护和迭代的系统工程。</li><li>【高级】鉴于系统内有较多的规则策略过滤,包括准入、人群、风控、A/BTest等需求,为适应系统规模可快速开发和使用的方式,搭建了去中心化的量化人群规则引擎组件。通过业务需求对逻辑的扩展和内置引擎执行器的使用,完成自由组合的人群过滤服务。这降低了共性功能重复开发所带来的成本问题,并提高了研发效率。</li><li>【高级】根据实际秒杀峰值场景 <code>TPS 5000 ~ 8000</code> 的需求,开发了统一路由组件。该组件不仅可以满足差异化不同字段的分库分表组合,还支持 Redis 库存分片和秒杀滑动库存分块。而且,开发了统一路由 XDB-Router 的 SpringBoot Starter 技术组件。该套组件已经经历了多次大促活动场景的考验,支持横向扩展,可以满足业务规模的快速增长。</li><li>【简单】运用模板、策略、工厂三个设计模式,定义抽奖过程标准和实现对应的多类型抽奖的服务模块。</li><li>【简单】因活动秒杀的并发场景,将秒杀从最开始的数据库行级锁优化为Redis Key 加锁,又从 Redis Key 的独占锁,优化为滑块锁。优化后整体秒杀有了非常可观的性能提升。</li><li>【简单】解耦抽奖流程,把抽奖和发奖用MQ消息串联起来,避免一个流程太长,导致用户一直等待。</li></ul></li></ul><h3 id="_2-手写-mybatis" tabindex="-1"><a class="header-anchor" href="#_2-手写-mybatis" aria-hidden="true">#</a> 2. 手写 MyBatis</h3><ul><li>项目架构:Object Relational Mapping</li><li>项目描述:MyBatis 是 Java 应用编程开发中,非常常用的技术框架。需要较深入的学习和使用,具备 MyBatis 插件开发能力,解决日常场景问题。才能更好更高效的工作。为此,深度学习了《手写MyBatis:渐进式源码实践》一书,完整实现了一个 MyBatis ORM 框架。技术积累颇深,提高了设计思维和编码能力。</li><li>个人收获: <ul><li>首先学习到为什么日常使用 MyBatis 时,可以仅提供 IDao 接口,就可以关联对应配置的SQL语句,完成数据库操作。这是因为做了代理与映射,封装调用逻辑到 SqlSession 会话功能实现中。</li><li>掌握了数10种设计模式的运用,其中感触最大的是 MyBatis 如何管理多边服务的设计。如创建会话模型,统一调度执行器使用和数据的封装,并把这些复杂的操作,通过 SqlSessionFactory 工厂统一对外提供 SqlSession 服务。</li><li>彻底了解并掌握了 MyBatis Plugin 设计模型,这个技术可以让我基于 MyBatis 做出日志监控、库表路由、字段加解密等操作。为以后编程工作,提供更多的解决方案。</li><li>除此之外,还有一级缓存、二级缓存的装饰器模式使用,MyBatis 开发后与 Spring、SpringBoot 整合的实现,让我对 MyBatis 的全体系开发流程和对应的技术整合,已经非常清晰,便于以后应用和从根上快速排查解决问题,并给出合理的技术方案。</li></ul></li></ul><h3 id="_3-openai-应用服务-辅助工作提效工具开发" tabindex="-1"><a class="header-anchor" href="#_3-openai-应用服务-辅助工作提效工具开发" aria-hidden="true">#</a> 3. OpenAI 应用服务 - 辅助工作提效工具开发</h3><ul><li>项目架构:微服务架构设计,OpenAI-SDK 多模型组件【ChatGLM、ChatGPT】、DDD 应用服务API封装、WEB REACT 前端界面【按需编写】</li><li>核心技术:SpringBoot、MyBatis、Redis/Guava、OKHttp3、OpenAI 大模型【可对接ChatGLM、腾讯混元等】、React、TypeScript</li><li>项目描述:此项目以应用OpenAI技术,对接多种大模型提供生成式服务,为XXX场景提效。项目的架构设计实现以微服务进行拆分,涵盖;OpenAI-SDK、OpenAI-API、公众号鉴权、企业支付【暂时申请中,如果你对接了可以写】等。并以模块化设计,积木式构建应用,让不同的场景诉求都可以配置化对接。</li><li>核心职责: <ul><li>首先这是我们xxx公司/实践/实训的第一个OpenAI项目,后续势必会有更多的场景以不同的方式接入。包括 SDK 独立接入、API 接口接入、MQ 消息接入,以及使用提供好的服务类接入。所以在这部分设计的时候,我采用了微服务的架构设计,按照职责边界进行拆分设计。</li><li>采用 DDD 架构 API,以及便于不同领域模块的独立设计,一个领域就是一个功能域。在功能域中提供模型、仓储、事件、服务。这样可以更好扩展。</li><li>鉴于生成式服务的文本生成可能会有不可靠信息,所以对这部分内容添加了敏感词的过滤。并可根据不同场景选择不同范围的敏感词处理。</li><li>OpenAI 大模型有多种,这部分在架构上设计独立的 SDK,在实现上采用了 Session 会话模型进行处理,以及通过工厂处理服务。在细节对上,采用了 OKHttp3 框架完成模型对接,这样的方式更好扩展,代码也更易于维护。</li><li>在整套工程的设计实现中,采用了较多的分治、抽象的思想和设计模式和设计原则知识的运用,来解决各类场景问题。</li><li>对接微信扫码支付,完成从商品库、下单支付、异步发货、掉单补偿等核心流程实现。让用户可以在线购买对话额度。</li><li>注意:你还可以根据项目中提到的各类技术和章节,来编写你的职责。</li></ul></li></ul><h3 id="_4-服务治理-springboot-中间件" tabindex="-1"><a class="header-anchor" href="#_4-服务治理-springboot-中间件" aria-hidden="true">#</a> 4. 服务治理 SpringBoot 中间件</h3><ul><li>系统架构:SpringBoot Starter 组件开发</li><li>核心技术:熔断、降级、限流、切量、白名单、人群控制</li><li>项目描述:该SpringBoot Starter中间件实现了熔断、降级、限流、切量、白名单等服务治理功能,减少了开发工作量和出错风险。利用SpringBoot的自动化配置机制简化了集成和使用,并提供了可扩展接口,以满足不同场景的需求。</li><li>核心职责: <ul><li>鉴于组内同类需求的重复开发,设计并实现服务治理 SpringBoot Starter 中间件,提高开发效率和降低重复开发成本。 该中间件的核心功能包括服务治理中的熔断、降级、限流、切量和白名单等。</li><li>通过利用SpringBoot的自动化配置机制,该中间件可以简化集成和使用,同时提供足够的配置选项以满足不同场景的需求。</li><li>此外,该中间件还提供了可扩展的接口,方便用户根据自身需求扩展功能,从而更好地满足不同的业务需求。</li></ul></li></ul>',15);function D(y,b){const e=t("ExternalLinkIcon");return o(),n("div",null,[h,i("ul",null,[c,u,p,S,_,B,i("li",null,[l("开源项目:"),i("a",M,[l("vo2dto"),r(e)]),l(" - IDEA Plugin 自动转换对象插件,5.4k 下载使用")])]),g])}const I=a(d,[["render",D],["__file","resume.html.vue"]]);export{I as default};
const e=JSON.parse('{"key":"v-1d59d0e6","path":"/md/resume.html","title":"个人简历","lang":"zh-CN","frontmatter":{"title":"个人简历","index":false,"icon":"laptop-code","category":["自我介绍","专业技能","项目经验"],"description":"个人信息 姓名; 电话; 邮箱; 毕业时间; 工作时间; Github:https://github.com/fuzhengwei; 开源项目:vo2dto (https://bugstack.cn/md/product/idea-plugin/vo2dto.html) - IDEA Plugin 自动转换对象插件,5.4k 下载使用; 毕业院校 时间...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/md/resume.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"个人简历"}],["meta",{"property":"og:description","content":"个人信息 姓名; 电话; 邮箱; 毕业时间; 工作时间; Github:https://github.com/fuzhengwei; 开源项目:vo2dto (https://bugstack.cn/md/product/idea-plugin/vo2dto.html) - IDEA Plugin 自动转换对象插件,5.4k 下载使用; 毕业院校 时间..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"个人简历\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":2,"title":"个人信息","slug":"个人信息","link":"#个人信息","children":[]},{"level":2,"title":"毕业院校","slug":"毕业院校","link":"#毕业院校","children":[]},{"level":2,"title":"专业技能","slug":"专业技能","link":"#专业技能","children":[]},{"level":2,"title":"工作经历【在校生无】","slug":"工作经历【在校生无】","link":"#工作经历【在校生无】","children":[]},{"level":2,"title":"项目经验","slug":"项目经验","link":"#项目经验","children":[{"level":3,"title":"1. 营销活动平台 - Lottery 微服务抽奖系统","slug":"_1-营销活动平台-lottery-微服务抽奖系统","link":"#_1-营销活动平台-lottery-微服务抽奖系统","children":[]},{"level":3,"title":"2. 手写 MyBatis","slug":"_2-手写-mybatis","link":"#_2-手写-mybatis","children":[]},{"level":3,"title":"3. OpenAI 应用服务 - 辅助工作提效工具开发","slug":"_3-openai-应用服务-辅助工作提效工具开发","link":"#_3-openai-应用服务-辅助工作提效工具开发","children":[]},{"level":3,"title":"4. 服务治理 SpringBoot 中间件","slug":"_4-服务治理-springboot-中间件","link":"#_4-服务治理-springboot-中间件","children":[]}]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":9.19,"words":2757},"filePathRelative":"md/resume.md","localizedDate":"2024年1月30日","autoDesc":true}');export{e as data};
const l=JSON.parse('{"key":"v-2e3eac9e","path":"/slides.html","title":"幻灯片页","lang":"zh-CN","frontmatter":{"title":"幻灯片页","icon":"person-chalkboard","layout":"Slide","description":"slidestart 幻灯片演示 一个简单的幻灯片演示与各种小贴士。 作者 Mr.Hope. 请滚动鼠标滚轮进入下一页 标注幻灯片 👇 (#/1/1) -- 标注幻灯片 使用 --- 标注水平幻灯片 在水平幻灯片中使用 -- 分割垂直幻灯片 使用 在幻灯片上添加属性 使用 在前一个 HTML 元素上添加属性 Markdown 你可以在幻灯片中使用 M...","head":[["meta",{"property":"og:url","content":"https://vuepress-theme-hope-docs-demo.netlify.app/slides.html"}],["meta",{"property":"og:site_name","content":"我的简历"}],["meta",{"property":"og:title","content":"幻灯片页"}],["meta",{"property":"og:description","content":"slidestart 幻灯片演示 一个简单的幻灯片演示与各种小贴士。 作者 Mr.Hope. 请滚动鼠标滚轮进入下一页 标注幻灯片 👇 (#/1/1) -- 标注幻灯片 使用 --- 标注水平幻灯片 在水平幻灯片中使用 -- 分割垂直幻灯片 使用 在幻灯片上添加属性 使用 在前一个 HTML 元素上添加属性 Markdown 你可以在幻灯片中使用 M..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T13:39:55.000Z"}],["meta",{"property":"article:author","content":"小傅哥"}],["meta",{"property":"article:modified_time","content":"2024-01-30T13:39:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"幻灯片页\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T13:39:55.000Z\\",\\"author\\":[{\\"@type\\":\\"Person\\",\\"name\\":\\"小傅哥\\",\\"url\\":\\"https://mister-hope.com\\"}]}"]]},"headers":[{"level":2,"title":"幻灯片演示","slug":"幻灯片演示","link":"#幻灯片演示","children":[]},{"level":2,"title":"标注幻灯片","slug":"标注幻灯片","link":"#标注幻灯片","children":[]},{"level":2,"title":"标注幻灯片","slug":"标注幻灯片-1","link":"#标注幻灯片-1","children":[]},{"level":2,"title":"Markdown","slug":"markdown","link":"#markdown","children":[]},{"level":2,"title":"Markdown","slug":"markdown-1","link":"#markdown-1","children":[{"level":3,"title":"这是一个 H3","slug":"这是一个-h3","link":"#这是一个-h3","children":[]}]},{"level":2,"title":"Markdown","slug":"markdown-2","link":"#markdown-2","children":[]},{"level":2,"title":"Markdown","slug":"markdown-3","link":"#markdown-3","children":[]},{"level":2,"title":"Markdown","slug":"markdown-4","link":"#markdown-4","children":[]},{"level":2,"title":"Markdown","slug":"markdown-5","link":"#markdown-5","children":[]},{"level":2,"title":"布局","slug":"布局","link":"#布局","children":[]},{"level":2,"title":"布局","slug":"布局-1","link":"#布局-1","children":[]},{"level":2,"title":"布局","slug":"布局-2","link":"#布局-2","children":[]},{"level":2,"title":"布局","slug":"布局-3","link":"#布局-3","children":[{"level":3,"title":"背景","slug":"背景","link":"#背景","children":[]}]},{"level":2,"title":"动画片段","slug":"动画片段","link":"#动画片段","children":[]},{"level":2,"title":"动画片段","slug":"动画片段-1","link":"#动画片段-1","children":[]},{"level":2,"title":"动画片段","slug":"动画片段-2","link":"#动画片段-2","children":[{"level":3,"title":"动画 class","slug":"动画-class","link":"#动画-class","children":[]}]},{"level":2,"title":"动画片段","slug":"动画片段-3","link":"#动画片段-3","children":[{"level":3,"title":"动画 class","slug":"动画-class-1","link":"#动画-class-1","children":[]}]},{"level":2,"title":"动画片段","slug":"动画片段-4","link":"#动画片段-4","children":[{"level":3,"title":"多个动画片段","slug":"多个动画片段","link":"#多个动画片段","children":[]}]},{"level":2,"title":"动画片段","slug":"动画片段-5","link":"#动画片段-5","children":[{"level":3,"title":"顺序","slug":"顺序","link":"#顺序","children":[]}]},{"level":2,"title":"渐变","slug":"渐变","link":"#渐变","children":[]},{"level":2,"title":"渐变","slug":"渐变-1","link":"#渐变-1","children":[]},{"level":2,"title":"渐变","slug":"渐变-2","link":"#渐变-2","children":[{"level":3,"title":"过渡动画","slug":"过渡动画","link":"#过渡动画","children":[]}]},{"level":2,"title":"功能","slug":"功能","link":"#功能","children":[]},{"level":2,"title":"功能","slug":"功能-1","link":"#功能-1","children":[{"level":3,"title":"代码","slug":"代码","link":"#代码","children":[]}]},{"level":2,"title":"功能","slug":"功能-2","link":"#功能-2","children":[{"level":3,"title":"预览模式","slug":"预览模式","link":"#预览模式","children":[]}]},{"level":2,"title":"功能","slug":"功能-3","link":"#功能-3","children":[{"level":3,"title":"全屏模式","slug":"全屏模式","link":"#全屏模式","children":[]}]},{"level":2,"title":"功能","slug":"功能-4","link":"#功能-4","children":[{"level":3,"title":"缩放","slug":"缩放","link":"#缩放","children":[]}]},{"level":2,"title":"结束","slug":"结束","link":"#结束","children":[]}],"git":{"createdTime":1706621995000,"updatedTime":1706621995000,"contributors":[{"name":"小傅哥","email":"184172133@qq.com","commits":1}]},"readingTime":{"minutes":4.51,"words":1352},"filePathRelative":"slides.md","localizedDate":"2024年1月30日","autoDesc":true}');export{l as data};
import{_ as l}from"./plugin-vue_export-helper-c27b6911.js";import{r as i,o as d,c as o,b as a,a as e,d as n,e as r,f as t}from"./app-730966a2.js";const c="/logo.svg",h={},u=e("p",null,"@slidestart",-1),_=e("h2",{id:"幻灯片演示",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#幻灯片演示","aria-hidden":"true"},"#"),n(" 幻灯片演示")],-1),p=e("p",null,"一个简单的幻灯片演示与各种小贴士。",-1),m=e("blockquote",null,[e("p",null,"作者 Mr.Hope. 请滚动鼠标滚轮进入下一页")],-1),f=e("hr",null,null,-1),g=e("h2",{id:"标注幻灯片",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#标注幻灯片","aria-hidden":"true"},"#"),n(" 标注幻灯片")],-1),k=e("p",null,[e("a",{href:"#/1/1"},"👇")],-1),x=e("p",null,"--",-1),b=e("h2",{id:"标注幻灯片-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#标注幻灯片-1","aria-hidden":"true"},"#"),n(" 标注幻灯片")],-1),w=e("p",null,[n("使用 "),e("code",null,"---"),n(" 标注水平幻灯片")],-1),v=e("p",null,[n("在水平幻灯片中使用 "),e("code",null,"--"),n(" 分割垂直幻灯片")],-1),M=e("p",null,[n("使用 "),e("code",null,"<!-- .slide: ... -->"),n(" 在幻灯片上添加属性")],-1),L=e("p",null,[n("使用 "),e("code",null,"<!-- .element: ... -->"),n(" 在前一个 HTML 元素上添加属性")],-1),j=e("hr",null,null,-1),T=e("h2",{id:"markdown",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#markdown","aria-hidden":"true"},"#"),n(" Markdown")],-1),y=e("p",null,"你可以在幻灯片中使用 Markdown 语法的各种标记.",-1),E=e("p",null,"--",-1),H=e("h2",{id:"markdown-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#markdown-1","aria-hidden":"true"},"#"),n(" Markdown")],-1),N=e("p",null,"你可以在幻灯片中使用 Markdown 语法的各种标记.",-1),V=e("h3",{id:"这是一个-h3",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#这是一个-h3","aria-hidden":"true"},"#"),n(" 这是一个 H3")],-1),$=e("p",null,"标题默认会自动转换为大写。",-1),B=e("strong",null,"粗体",-1),D=e("em",null,"斜体",-1),z=e("s",null,"删除线",-1),C={href:"https://mister-hope.com",target:"_blank",rel:"noopener noreferrer"},F=e("p",null,"--",-1),I=t('<h2 id="markdown-2" tabindex="-1"><a class="header-anchor" href="#markdown-2" aria-hidden="true">#</a> Markdown</h2><p>你可以在幻灯片中使用 Markdown 语法的各种标记.</p><p>列表默认为 <code>inline-block</code></p><ul><li>项目</li><li>项目</li><li>项目</li></ul><ol><li>项目 1</li><li>项目 2</li><li>项目 3</li></ol><p>--</p>',6),q=t(`<h2 id="markdown-3" tabindex="-1"><a class="header-anchor" href="#markdown-3" aria-hidden="true">#</a> Markdown</h2><p>你可以在幻灯片中使用 Markdown 语法的各种标记.</p><p>在你启用 <code>highlight</code> 插件后,代码块会自动高亮。</p><div class="language-javascript line-numbers-mode" data-ext="js"><pre class="language-javascript"><code><span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>--</p>`,5),J=e("h2",{id:"markdown-4",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#markdown-4","aria-hidden":"true"},"#"),n(" Markdown")],-1),O=e("p",null,"你可以在幻灯片中使用 Markdown 语法的各种标记.",-1),S=e("p",null,[n("在你启用 "),e("code",null,"math"),n(" 插件后,你也可以使用 TEX 格式使用数学公式。")],-1),X=e("p",null,"$$ J(\\theta_0,\\theta_1) = \\sum_{i=0} $$",-1),A=e("p",null,"--",-1),G=e("h2",{id:"markdown-5",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#markdown-5","aria-hidden":"true"},"#"),n(" Markdown")],-1),K=e("p",null,"你可以在幻灯片中使用 Markdown 语法的各种标记.",-1),P=e("p",null,[n(""),e("strong",null,"请注意"),n(": 表格和分割线,以及所有不在 Markdown 标准语法中的内容均不受支持。")],-1),Q=e("hr",null,null,-1),R=e("h2",{id:"布局",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#布局","aria-hidden":"true"},"#"),n(" 布局")],-1),U=e("p",null,"--",-1),W=e("h2",{id:"布局-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#布局-1","aria-hidden":"true"},"#"),n(" 布局")],-1),Y=e("p",null,[n("👆 "),e("code",null,"r-fit-text"),n(" class 会让文字在不超出幻灯片范围的情况下尽可能大。")],-1),Z=e("p",null,"--",-1),ee=e("h2",{id:"布局-2",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#布局-2","aria-hidden":"true"},"#"),n(" 布局")],-1),ae=e("figure",null,[e("img",{src:c,alt:"Logo",tabindex:"0",loading:"lazy"}),e("figcaption",null,"Logo")],-1),ne=e("p",null,[n("👆 "),e("code",null,"r-stretch"),n(" class 帮助你控制注入图片或视频的大小,使它们填充满幻灯片垂直方向上的剩余空间。")],-1),te=e("p",null,"--",-1),se=e("h2",{id:"布局-3",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#布局-3","aria-hidden":"true"},"#"),n(" 布局")],-1),le=e("h3",{id:"背景",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#背景","aria-hidden":"true"},"#"),n(" 背景")],-1),ie=e("p",null,[n("你可以通过向特定幻灯片添加 "),e("code",null,"data-background"),n(" 属性自定义幻灯片背景.")],-1),de=e("hr",null,null,-1),oe=e("h2",{id:"动画片段",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画片段","aria-hidden":"true"},"#"),n(" 动画片段")],-1),re=e("p",null,"--",-1),ce=e("h2",{id:"动画片段-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画片段-1","aria-hidden":"true"},"#"),n(" 动画片段")],-1),he=e("p",null,"动画片段用于高亮或显隐幻灯片中的元素。",-1),ue=e("p",null,[n("你需要在元素上添加 "),e("code",null,"fragment"),n(" 和动画 class。")],-1),_e=e("p",null,"--",-1),pe=e("h2",{id:"动画片段-2",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画片段-2","aria-hidden":"true"},"#"),n(" 动画片段")],-1),me=e("h3",{id:"动画-class",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画-class","aria-hidden":"true"},"#"),n(" 动画 class")],-1),fe=e("ul",null,[e("li",null,[e("code",null,"fade-in")])],-1),ge=e("ul",null,[e("li",null,[e("code",null,"fade-out")])],-1),ke=e("ul",null,[e("li",null,[e("code",null,"fade-up")])],-1),xe=e("ul",null,[e("li",null,[e("code",null,"fade-down")])],-1),be=e("ul",null,[e("li",null,[e("code",null,"fade-left")])],-1),we=e("ul",null,[e("li",null,[e("code",null,"fade-right")])],-1),ve=e("ul",null,[e("li",null,[e("code",null,"fade-in-then-out")])],-1),Me=e("ul",null,[e("li",null,[e("code",null,"fade-in-then-semi-out")])],-1),Le=e("p",null,"--",-1),je=e("h2",{id:"动画片段-3",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画片段-3","aria-hidden":"true"},"#"),n(" 动画片段")],-1),Te=e("h3",{id:"动画-class-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画-class-1","aria-hidden":"true"},"#"),n(" 动画 class")],-1),ye=e("ul",null,[e("li",null,[e("code",null,"grow")])],-1),Ee=e("ul",null,[e("li",null,[e("code",null,"shrink")])],-1),He=e("ul",null,[e("li",null,[e("code",null,"strike")])],-1),Ne=e("ul",null,[e("li",null,[e("code",null,"highlight-red")])],-1),Ve=e("ul",null,[e("li",null,[e("code",null,"highlight-green")])],-1),$e=e("ul",null,[e("li",null,[e("code",null,"highlight-blue")])],-1),Be=e("ul",null,[e("li",null,[e("code",null,"highlight-current-red")])],-1),De=e("ul",null,[e("li",null,[e("code",null,"highlight-current-green")])],-1),ze=e("ul",null,[e("li",null,[e("code",null,"highlight-current-blue")])],-1),Ce=e("p",null,"--",-1),Fe=t('<h2 id="动画片段-4" tabindex="-1"><a class="header-anchor" href="#动画片段-4" aria-hidden="true">#</a> 动画片段</h2><h3 id="多个动画片段" tabindex="-1"><a class="header-anchor" href="#多个动画片段" aria-hidden="true">#</a> 多个动画片段</h3><p>你可以按照顺序包裹一个 HTML 元素使其拥有多个动画片段</p><span class="fragment fade-in"><span class="fragment highlight-red"><span class="fragment fade-out"> 渐入 &gt; 变红 &gt; 渐出 </span></span></span><p>--</p>',5),Ie=e("h2",{id:"动画片段-5",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#动画片段-5","aria-hidden":"true"},"#"),n(" 动画片段")],-1),qe=e("h3",{id:"顺序",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#顺序","aria-hidden":"true"},"#"),n(" 顺序")],-1),Je=e("p",null,[n("你可以使用 "),e("code",null,"data-fragment-index"),n(" 属性改变元素的动画顺序。")],-1),Oe=e("p",null,"不同元素可以有相同的动画顺序。",-1),Se=e("ul",null,[e("li",null,"最后显示")],-1),Xe=e("ul",null,[e("li",null,"第二个显示")],-1),Ae=e("ul",null,[e("li",null,"第一个显示")],-1),Ge=e("ul",null,[e("li",null,"第二个显示")],-1),Ke=e("hr",null,null,-1),Pe=e("h2",{id:"渐变",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#渐变","aria-hidden":"true"},"#"),n(" 渐变")],-1),Qe=e("p",null,"--",-1),Re=e("h2",{id:"渐变-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#渐变-1","aria-hidden":"true"},"#"),n(" 渐变")],-1),Ue=e("p",null,[n("Transition 可以通过配置中的 "),e("code",null,"transition"),n(" 选项全局设置,也可以通过在特定幻灯片添加 "),e("code",null,"data-transition"),n(" 属性局部设置.")],-1),We=e("p",null,"可能的值:",-1),Ye=e("ul",null,[e("li",null,"none"),e("li",null,"fade"),e("li",null,"slide")],-1),Ze=e("ul",null,[e("li",null,"convex"),e("li",null,"concave"),e("li",null,"zoom")],-1),ea=e("p",null,"--",-1),aa=e("h2",{id:"渐变-2",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#渐变-2","aria-hidden":"true"},"#"),n(" 渐变")],-1),na=e("h3",{id:"过渡动画",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#过渡动画","aria-hidden":"true"},"#"),n(" 过渡动画")],-1),ta=e("p",null,[n("你可以在相邻的幻灯片上添加 "),e("code",null,"data-auto-animate"),n(" 使相同的 HTML 元素产生过渡动画效果。")],-1),sa=e("hr",null,null,-1),la=e("h2",{id:"功能",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#功能","aria-hidden":"true"},"#"),n(" 功能")],-1),ia=e("p",null,"--",-1),da=e("h2",{id:"功能-1",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#功能-1","aria-hidden":"true"},"#"),n(" 功能")],-1),oa=t(`<h3 id="代码" tabindex="-1"><a class="header-anchor" href="#代码" aria-hidden="true">#</a> 代码</h3><p>通过启用 <code>highlight</code> 插件,你可以对代码块进行高亮。</p><p>你可以使用 <code>[a-b|c-d]</code> 语法来分布高亮特定行。</p><div class="language-javascript line-numbers-mode" data-ext="js"><pre class="language-javascript"><code><span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> b <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token function-variable function">c</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">x</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token number">1</span> <span class="token operator">+</span> <span class="token number">2</span> <span class="token operator">+</span> x<span class="token punctuation">;</span>
<span class="token function">c</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>--</p>`,5),ra=e("h2",{id:"功能-2",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#功能-2","aria-hidden":"true"},"#"),n(" 功能")],-1),ca=e("h3",{id:"预览模式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#预览模式","aria-hidden":"true"},"#"),n(" 预览模式")],-1),ha=e("p",null,[n("按下 "),e("code",null,"Esc"),n(""),e("code",null,"O"),n(" 即可在幻灯片获得焦点时进入预览模式。")],-1),ua=e("p",null,"--",-1),_a=e("h2",{id:"功能-3",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#功能-3","aria-hidden":"true"},"#"),n(" 功能")],-1),pa=e("h3",{id:"全屏模式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#全屏模式","aria-hidden":"true"},"#"),n(" 全屏模式")],-1),ma=e("p",null,[n("按下 "),e("code",null,"F"),n(""),e("code",null,"F11"),n(" 即可在幻灯片获得焦点时进入全屏模式。")],-1),fa=e("p",null,"--",-1),ga=e("h2",{id:"功能-4",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#功能-4","aria-hidden":"true"},"#"),n(" 功能")],-1),ka=e("h3",{id:"缩放",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#缩放","aria-hidden":"true"},"#"),n(" 缩放")],-1),xa=e("p",null,[n("按下 "),e("code",null,"alt"),n(" (Linux 上使用 "),e("code",null,"ctrl"),n(") 的同时点击幻灯片的任何元素,即可以向此元素进行放大。")],-1),ba=e("p",null,"再次点击即可缩小。",-1),wa=e("hr",null,null,-1),va=e("h2",{id:"结束",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#结束","aria-hidden":"true"},"#"),n(" 结束")],-1),Ma=e("p",null,"@slideend",-1);function La(ja,Ta){const s=i("ExternalLinkIcon");return d(),o("div",null,[a(" markdownlint-disable MD024 MD033 MD051 "),u,a(' .slide: data-transition="slide" '),_,a(' .element: class="r-fit-text" '),p,a(' .element: class="r-fit-text" '),m,f,g,a(' .element: class="r-fit-text" '),k,x,b,a(' .element: class="r-fit-text" '),w,a(' .element: class="fragment fade-in" '),v,a(' .element: class="fragment fade-in" '),M,a(' .element: class="fragment fade-in" '),L,a(' .element: class="fragment fade-in" '),j,a(' .slide: data-transition="slide" data-auto-animate '),T,a(' .element: class="r-fit-text" '),y,a(' .element: class="r-fit-text" '),E,a(" .slide: data-auto-animate "),H,N,V,$,e("p",null,[n("这是一个有着 "),B,n(", "),D,n(", "),z,n(" 文字并包含 "),e("a",C,[n("一个链接"),r(s)]),n(" 的段落,并且它会自动换行。所以你无需担心它的长度。")]),F,a(" .slide: data-auto-animate "),I,a(" .slide: data-auto-animate "),q,a(" .slide: data-auto-animate "),J,O,S,X,A,a(" .slide: data-auto-animate "),G,K,P,Q,a(' .slide: data-transition="slide" data-auto-animate '),R,a(' .element: class="r-fit-text" '),U,a(" .slide: data-auto-animate "),W,a(' .element: class="r-fit-text" '),Y,Z,a(" .slide: data-auto-animate "),ee,ae,a(' .element: class="r-stretch" '),ne,te,a(' .slide: data-auto-animate data-background-color="rgb(70, 70, 255)" '),se,le,ie,de,a(" .slide: data-auto-animate "),oe,a(' .element: class="r-fit-text" '),re,a(" .slide: data-auto-animate "),ce,a(' .element: class="r-fit-text" '),he,ue,_e,a(" .slide: data-auto-animate "),pe,me,fe,a(' .element: class="fragment fade-in" '),ge,a(' .element: class="fragment fade-out" '),ke,a(' .element: class="fragment fade-up" '),a(" list break "),xe,a(' .element: class="fragment fade-down" '),be,a(' .element: class="fragment fade-left" '),we,a(' .element: class="fragment fade-right" '),a(" list break "),ve,a(' .element: class="fragment fade-in-then-out" '),Me,a(' .element: class="fragment fade-in-then-semi-out" '),Le,a(" .slide: data-auto-animate "),je,Te,ye,a(' .element: class="fragment grow" '),Ee,a(' .element: class="fragment shrink" '),He,a(' .element: class="fragment strike" '),a(" list break "),Ne,a(' .element: class="fragment highlight-red" '),Ve,a(' .element: class="fragment highlight-green" '),$e,a(' .element: class="fragment highlight-blue" '),a(" list break "),Be,a(' .element: class="fragment highlight-current-red" '),De,a(' .element: class="fragment highlight-current-green" '),ze,a(' .element: class="fragment highlight-current-blue" '),Ce,a(" .slide: data-auto-animate "),Fe,a(" .slide: data-auto-animate "),Ie,qe,Je,Oe,Se,a(' .element: class="fragment" data-fragment-index="3"'),Xe,a(' .element: class="fragment" data-fragment-index="2"'),a(" list break "),Ae,a(' .element: class="fragment" data-fragment-index="1"'),Ge,a(' .element: class="fragment" data-fragment-index="2"'),Ke,a(' .slide: data-transition="slide" data-auto-animate '),Pe,a(' .element: class="r-fit-text" '),Qe,a(' .slide: data-transition="slide" data-auto-animate '),Re,a(' .element: class="r-fit-text" '),Ue,We,Ye,a(" list break "),Ze,ea,a(" .slide: data-auto-animate "),aa,a(' .element: class="r-fit-text" '),na,ta,sa,a(' .slide: data-transition="slide" data-auto-animate '),la,a(' .element: class="r-fit-text" '),ia,a(' .slide: data-transition="slide" data-auto-animate '),da,a(' .element: class="r-fit-text" '),oa,a(' .slide: data-transition="slide" data-auto-animate '),ra,a(' .element: class="r-fit-text" '),ca,ha,ua,a(' .slide: data-transition="slide" data-auto-animate '),_a,a(' .element: class="r-fit-text" '),pa,ma,fa,a(' .slide: data-transition="slide" data-auto-animate '),ga,a(' .element: class="r-fit-text" '),ka,xa,ba,wa,a(' .element: class="r-fit-text" '),va,Ma])}const Ha=l(h,[["render",La],["__file","slides.html.vue"]]);export{Ha as default};
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册