281 lines
220 KiB
JSON
281 lines
220 KiB
JSON
{
|
||
"version": "https://jsonfeed.org/version/1",
|
||
"title": "涛声依旧",
|
||
"subtitle": "天下事有难易乎?为之,则难者亦易矣",
|
||
"icon": "https://hitoli.com/images/favicon.ico",
|
||
"description": "天生我材必有用",
|
||
"home_page_url": "https://hitoli.com",
|
||
"items": [
|
||
{
|
||
"id": "https://hitoli.com/2025/02/16/%E6%9E%81%E7%A9%BA%E9%97%B4%E9%83%A8%E7%BD%B2Deepseek%EF%BC%88API%E8%B0%83%E7%94%A8%EF%BC%89/",
|
||
"url": "https://hitoli.com/2025/02/16/%E6%9E%81%E7%A9%BA%E9%97%B4%E9%83%A8%E7%BD%B2Deepseek%EF%BC%88API%E8%B0%83%E7%94%A8%EF%BC%89/",
|
||
"title": "极空间部署DeepSeek(API调用)",
|
||
"date_published": "2025-02-16T14:32:00.000Z",
|
||
"content_html": "<h4 id=\"前言\"><a class=\"anchor\" href=\"#前言\">#</a> 前言</h4>\n<p>最近 DeepSeek 比较火爆,到处都在夸。大部分人都想搭建自己的私有服务器,但我查了查资料还是放弃了想法,毕竟 32B 以下的没啥鸟用,以上的我又搞不起。🙂,最后又经不住诱惑就搞一个调用 api 的吧。经过研究,最终决定使用 justsong/one-api 加 vinlic/deepseek-free-api 加 yidadaa/chatgpt-next-web 的方案。justsong/one-api 用于统一管理、调用 AI 服务(当然也可以调用自己搭建的 DeepSeek🙂),vinlic/deepseek-free-api 用于调用 DeepSeek 官方接口,yidadaa/chatgpt-next-web 提供 web 界面用户和 ai 进行对话。大致了解清楚后就开始吧!</p>\n<h4 id=\"前期准备\"><a class=\"anchor\" href=\"#前期准备\">#</a> 前期准备</h4>\n<p>需要自己先申请一个<span class=\"exturl\" data-url=\"aHR0cHM6Ly9jaGF0LmRlZXBzZWVrLmNvbS8=\"> DeepSeek</span> 账号,并获取 token。获取方法是登陆后随便说一句话,然后按 F12 到应用程序 - 存储 - 本地存储中找到 userToken 的 value 值。<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/16/2025-02-16-23-54-54.png\" alt=\"2025-02-16-23-54-54.png\" /></p>\n<h5 id=\"安装deepseek-free-api\"><a class=\"anchor\" href=\"#安装deepseek-free-api\">#</a> 安装 deepseek-free-api</h5>\n<ul>\n<li>1、端口</li>\n</ul>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2025/02/16/2025-02-16-23-52-13.png\" alt=\"2025-02-16-23-52-13.png\" /></p>\n<ul>\n<li>2、环境<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/16/2025-02-16-23-53-30.png\" alt=\"2025-02-16-23-53-30.png\" /></li>\n</ul>\n<div class=\"note info\">\n<p>增加参数 DEEP_SEEK_CHAT_AUTHORIZATION 值:userToken 的 value 值</p>\n</div>\n<h5 id=\"安装one-api\"><a class=\"anchor\" href=\"#安装one-api\">#</a> 安装 one-api</h5>\n<ul>\n<li>\n<p>1、文件夹与路径<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/16/2025-02-16-23-56-44.png\" alt=\"2025-02-16-23-56-44.png\" /></p>\n</li>\n<li>\n<p>2、端口<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/16/2025-02-16-23-57-30.png\" alt=\"2025-02-16-23-57-30.png\" /></p>\n</li>\n<li>\n<p>3、配置</p>\n</li>\n</ul>\n<div class=\"note info\">\n<p>登陆 web 页面(极空间 ip+one-api 的本地端口,默认用户名密码 root/123456),先添加渠道,再添加令牌。渠道用于调用指定的 api,我这里调用的是 deepseek-free-api(密钥为 userToken 的 value 值)。令牌用于给 chatgpt-next-web 使用,记录、控制权限等。</p>\n</div>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2025/03/09/c200886ba8c9.jpg\" alt=\"c200886ba8c9.jpg\" /></p>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2025/02/17/2025-02-17-00-01-17.png\" alt=\"2025-02-17-00-01-17.png\" /></p>\n<h5 id=\"安装chatgpt-next-web\"><a class=\"anchor\" href=\"#安装chatgpt-next-web\">#</a> 安装 chatgpt-next-web</h5>\n<ul>\n<li>\n<p>1、端口<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/17/2025-02-17-00-02-14.png\" alt=\"2025-02-17-00-02-14.png\" /></p>\n</li>\n<li>\n<p>2、环境</p>\n</li>\n</ul>\n<div class=\"note info\">\n<p>参数 OPENAI_API_KEY 的值填 one-api 令牌页面复制的值。再增加一个 BASE_URL 参数,值为 one-api 的地址(极空间 ip+one-api 的本地端口)</p>\n</div>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2025/02/17/2025-02-17-00-04-28.png\" alt=\"2025-02-17-00-04-28.png\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/17/2025-02-17-00-03-04.png\" alt=\"2025-02-17-00-03-04.png\" /></p>\n<ul>\n<li>3、对话</li>\n</ul>\n<div class=\"note info\">\n<p>恭喜你,至此已经搭建完成。通过极空间 ip+chatgpt-next-web 的本地端口就可以开始和 DeepSeek 对话了。</p>\n</div>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2025/02/17/2025-02-17-00-06-07.png\" alt=\"2025-02-17-00-06-07.png\" /></p>\n<h5 id=\"nginx-proxy-manager配置\"><a class=\"anchor\" href=\"#nginx-proxy-manager配置\">#</a> nginx proxy manager 配置</h5>\n<div class=\"note info\">\n<p>chatgpt-next-web 反代时需要在高级里加入以下代码,否则会报错。</p>\n</div>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">location</span> <span class=\"string\">/</span> {</span><br><span class=\"line\"> <span class=\"string\">proxy_pass</span> <span class=\"string\">http://极空间ip:chatgpt-next-web的本地端口;</span></span><br><span class=\"line\"> <span class=\"string\">proxy_set_header</span> <span class=\"string\">Host</span> <span class=\"string\">$host;</span></span><br><span class=\"line\"> <span class=\"string\">proxy_set_header</span> <span class=\"string\">X-Forwarded-Host</span> <span class=\"string\">$http_host;</span></span><br><span class=\"line\"> <span class=\"string\">proxy_set_header</span> <span class=\"string\">X-Forwarded-Proto</span> <span class=\"string\">$scheme;</span></span><br><span class=\"line\"> }</span><br></pre></td></tr></table></figure><br />\n 最终成果<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2025/02/16/0d5ddc77d244fcc4e1a60a1828eed054.png\" alt=\"0d5ddc77d244fcc4e1a60a1828eed054.png\" /></p>\n",
|
||
"tags": [
|
||
"极空间",
|
||
"Docker",
|
||
"DeepSeek",
|
||
"AI"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/09/29/dante-stunnel-clash-%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91/",
|
||
"url": "https://hitoli.com/2024/09/29/dante-stunnel-clash-%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91/",
|
||
"title": "dante+stunnel+clash 科学上网",
|
||
"date_published": "2024-09-29T08:25:00.000Z",
|
||
"content_html": "<h4 id=\"前言\"><a class=\"anchor\" href=\"#前言\">#</a> 前言</h4>\n<p>上次介绍了使用 squid+stunnel 的方案进行科学上网。但是那个方案只适合在浏览器上使用,并不能让其它 app 也可以科学上网。此次介绍使用 dante+stunnel+clash 的方式来代理其它 app 科学上网。</p>\n<h4 id=\"准备\"><a class=\"anchor\" href=\"#准备\">#</a> 准备</h4>\n<p>一台可以访问外网的服务器,如香港的云主机并安装 Ubuntu 系统。</p>\n<h5 id=\"dante部分\"><a class=\"anchor\" href=\"#dante部分\">#</a> dante 部分</h5>\n<ul>\n<li>1、安装</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">apt-get install -y dante-server</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>2、配置</li>\n</ul>\n<div class=\"note info\">\n<p>修改 dante 配置<br />\n 1、修改 /etc/danted.conf 文件,在末尾加入下面的配置<br />\n 2、如果不需要用户密码认证,则把 socksmethod 改为 none<br />\n3、可以为认证单独添加一个用户<br />\n sudo useradd -r -s /bin/false proxy<br />\nsudo passwd proxy<br />\n4、重启服务<br />\n systemctl restart danted<br />\n5、查看状态<br />\n systemctl status danted</p>\n</div>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">logoutput:</span> <span class=\"string\">syslog</span></span><br><span class=\"line\"><span class=\"attr\">internal:</span> <span class=\"number\">0.0</span><span class=\"number\">.0</span><span class=\"number\">.0</span> <span class=\"string\">port</span> <span class=\"string\">=</span> <span class=\"number\">1080</span></span><br><span class=\"line\"><span class=\"attr\">external:</span> <span class=\"string\">eth0</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"attr\">socksmethod:</span> <span class=\"string\">username</span></span><br><span class=\"line\"><span class=\"attr\">clientmethod:</span> <span class=\"string\">none</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"attr\">user.privileged:</span> <span class=\"string\">root</span></span><br><span class=\"line\"><span class=\"attr\">user.notprivileged:</span> <span class=\"string\">nobody</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">client</span> <span class=\"string\">pass</span> {</span><br><span class=\"line\"> <span class=\"attr\">from: 0.0.0.0/0 to:</span> <span class=\"number\">0.0</span><span class=\"number\">.0</span><span class=\"number\">.0</span><span class=\"string\">/0</span></span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">socks</span> <span class=\"string\">pass</span> {</span><br><span class=\"line\"> <span class=\"attr\">from: 0.0.0.0/0 to:</span> <span class=\"number\">0.0</span><span class=\"number\">.0</span><span class=\"number\">.0</span><span class=\"string\">/0</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h5 id=\"stunnel服务端部分\"><a class=\"anchor\" href=\"#stunnel服务端部分\">#</a> stunnel 服务端部分</h5>\n<ul>\n<li>1、安装(和 danted 装在一起)</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">apt-get install -y stunnel</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>2、生成 TLS/SSL 证书</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">openssl req -new -x509 -days 3650 -nodes -out stunnel.pem -keyout stunnel.pem</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>\n<p>3、将证书 stunnel.pem 放到 /etc/stunnel/ 目录下</p>\n</li>\n<li>\n<p>4、修改 stunnel 配置 (/etc/stunnle/stunnle.conf)</p>\n</li>\n</ul>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">设置stunnel的pid文件路径</span></span><br><span class=\"line\"><span class=\"string\">pid</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.pid</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">设置stunnel工作的用户(组)</span></span><br><span class=\"line\"><span class=\"string\">setuid</span> <span class=\"string\">=</span> <span class=\"string\">root</span></span><br><span class=\"line\"><span class=\"string\">setgid</span> <span class=\"string\">=</span> <span class=\"string\">root</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">开启日志等级:emerg</span> <span class=\"string\">(0),</span> <span class=\"string\">alert</span> <span class=\"string\">(1),</span> <span class=\"string\">crit</span> <span class=\"string\">(2),</span> <span class=\"string\">err</span> <span class=\"string\">(3),</span> <span class=\"string\">warning</span> <span class=\"string\">(4),</span> <span class=\"string\">notice</span> <span class=\"string\">(5),</span> <span class=\"string\">info</span> <span class=\"string\">(6),</span> <span class=\"string\">or</span> <span class=\"string\">debug</span> <span class=\"string\">(7)</span></span><br><span class=\"line\"><span class=\"string\">debug</span> <span class=\"string\">=</span> <span class=\"number\">7</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">日志文件路径</span></span><br><span class=\"line\"><span class=\"string\">output</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.log</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">证书文件</span></span><br><span class=\"line\"><span class=\"string\">cert</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.pem</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">私钥文件</span></span><br><span class=\"line\"><span class=\"string\">key</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.pem</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">自定义服务名danted</span></span><br><span class=\"line\">[<span class=\"string\">danted</span>]</span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">服务监听的端口,client要连接这个端口与server通信</span></span><br><span class=\"line\"><span class=\"string\">accept</span> <span class=\"string\">=</span> <span class=\"number\">1081</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">服务要连接的端口,连接到danted的1080端口,将数据发给danted</span></span><br><span class=\"line\"><span class=\"string\">connect</span> <span class=\"string\">=</span> <span class=\"number\">1080</span></span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>5、重启服务<br />\n systemctl restart stunnel4</li>\n<li>6、查看状态<br />\n systemctl status stunnel4</li>\n</ul>\n<h5 id=\"stunnel客户端部分\"><a class=\"anchor\" href=\"#stunnel客户端部分\">#</a> stunnel 客户端部分</h5>\n<div class=\"note info\">\n<p>可以安装在要代理的机器上,在需要代理的情况下再开启(代理地址填 127.0.0.1 加客户端监听端口)。也可以安装在国内的服务器上一直保持连接(代理信息填国内服务器 ip 加客户端监听端口)。本示例客户端为 ubuntu 系统</p>\n</div>\n<ul>\n<li>1、安装(和 danted 装在一起)</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">apt-get install -y stunnel</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>2、修改配置(/etc/stunnel/stunnel.conf)</li>\n</ul>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[<span class=\"string\">danted</span>]</span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">监听端口,用户的代理设置就是</span> <span class=\"string\">stunnel-client-ip:1080</span></span><br><span class=\"line\"><span class=\"string\">accept</span> <span class=\"string\">=</span> <span class=\"number\">1080</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">要连接到的stunnel</span> <span class=\"string\">server的ip与端口</span></span><br><span class=\"line\"><span class=\"string\">connect</span> <span class=\"string\">=</span> <span class=\"string\">stunnel服务端ip:1081</span></span><br><span class=\"line\"><span class=\"string\">client</span> <span class=\"string\">=</span> <span class=\"literal\">yes</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">需要验证对方发过来的证书</span></span><br><span class=\"line\"><span class=\"string\">;verify</span> <span class=\"string\">=</span> <span class=\"number\">2</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">用来进行证书验证的文件</span></span><br><span class=\"line\"><span class=\"string\">;CAfile</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel-server.pem</span></span><br></pre></td></tr></table></figure></p>\n<h5 id=\"clash部分\"><a class=\"anchor\" href=\"#clash部分\">#</a> Clash 部分</h5>\n<ul>\n<li>\n<p>1、下载<br />\n<span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2NsYXNoLXZlcmdlLXJldi9jbGFzaC12ZXJnZS1yZXY/dGFiPXJlYWRtZS1vdi1maWxl\"> Clash 客户端</span></p>\n</li>\n<li>\n<p>2、配置</p>\n</li>\n</ul>\n<p>新建订阅<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/09/29/1e11845b78cb.png\" alt=\"\" /></p>\n<p>编辑文件并写入以下配置<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/09/29/d4f21f01c4bc.jpg\" alt=\"\" /></p>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\"># Profile Template for clash verge</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"attr\">proxies:</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"attr\">name:</span> <span class=\"string\">"PROXY"</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">socks5</span> <span class=\"comment\"># 节点类型</span></span><br><span class=\"line\"> <span class=\"attr\">server:</span> <span class=\"string\">""</span> <span class=\"comment\"># SOCKS5 服务器地址</span></span><br><span class=\"line\"> <span class=\"attr\">port:</span> <span class=\"number\">1080</span> <span class=\"comment\"># 服务器端口</span></span><br><span class=\"line\"> <span class=\"attr\">username:</span> <span class=\"string\">"proxy"</span> <span class=\"comment\"># 可选,用户名</span></span><br><span class=\"line\"> <span class=\"attr\">password:</span> <span class=\"string\">""</span> <span class=\"comment\"># 可选,密码</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"attr\">rule-providers:</span></span><br><span class=\"line\"> <span class=\"attr\">reject:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/reject.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">icloud:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/icloud.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/icloud.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">apple:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/apple.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/apple.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">google:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/google.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">proxy:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/proxy.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">direct:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/direct.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/direct.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">private:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/private.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/private.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">gfw:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/gfw.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">tld-not-cn:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">domain</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/tld-not-cn.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/tld-not-cn.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">telegramcidr:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">ipcidr</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/telegramcidr.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/telegramcidr.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">cncidr:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">ipcidr</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/cncidr.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">lancidr:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">ipcidr</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/lancidr.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/lancidr.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"attr\">applications:</span></span><br><span class=\"line\"> <span class=\"attr\">type:</span> <span class=\"string\">http</span></span><br><span class=\"line\"> <span class=\"attr\">behavior:</span> <span class=\"string\">classical</span></span><br><span class=\"line\"> <span class=\"attr\">url:</span> <span class=\"string\">"https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/applications.txt"</span></span><br><span class=\"line\"> <span class=\"attr\">path:</span> <span class=\"string\">./ruleset/applications.yaml</span></span><br><span class=\"line\"> <span class=\"attr\">interval:</span> <span class=\"number\">86400</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"attr\">rules:</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,applications,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">DOMAIN,clash.razord.top,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">DOMAIN,yacd.haishan.me,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,private,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,reject,REJECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,icloud,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,apple,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,google,PROXY</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,proxy,PROXY</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,direct,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,lancidr,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,cncidr,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">RULE-SET,telegramcidr,PROXY</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">GEOIP,LAN,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">GEOIP,CN,DIRECT</span></span><br><span class=\"line\"> <span class=\"bullet\">-</span> <span class=\"string\">MATCH,PROXY</span></span><br></pre></td></tr></table></figure><br />\n 开启代理和自启动<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/09/29/d6c8dfeb5997.png\" alt=\"\" /></p>\n<div class=\"note primary\">\n<p>至次运行 clash 的电脑就可以愉快的科学上网了,并且还可以代理同局域网的其它电脑科学上网。</p>\n</div>\n",
|
||
"tags": [
|
||
"生活",
|
||
"技术分享",
|
||
"stunnel",
|
||
"科学上网",
|
||
"dante",
|
||
"clash",
|
||
"socket"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/08/21/%E5%88%A9%E7%94%A8jackson%E5%AF%B9%E8%BF%94%E5%9B%9E%E6%95%B0%E6%8D%AE%E5%81%9A%E5%AD%97%E5%85%B8%E8%BD%AC%E6%8D%A2/",
|
||
"url": "https://hitoli.com/2024/08/21/%E5%88%A9%E7%94%A8jackson%E5%AF%B9%E8%BF%94%E5%9B%9E%E6%95%B0%E6%8D%AE%E5%81%9A%E5%AD%97%E5%85%B8%E8%BD%AC%E6%8D%A2/",
|
||
"title": "利用jackson对返回数据做字典转换",
|
||
"date_published": "2024-08-21T02:00:00.000Z",
|
||
"content_html": "<h4 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h4>\n<blockquote>\n<p>在项目中经常有一些类型字段用数字或者字母保存,但是前端展示时,则需要转换为用户能够理解的文字。于是公司内有人写了一个公用的注解,利用 java 的反射机制,修改字段的值或者添加属性来实现字典转换。由于 java 是静态类型语言,类在编译时固定,所以无法动态添加属性。于是他的解决方法是先把对象转为 map 再添加属性,或者在定义对象时先预定义字典的属于名称。我在使用中发现如果转换为 map(也可能是拦截处理的时机不对)则会丢失字段上的其它注解,如 swagger 文档定义、时间格式化等等。预设字典属性名称毕竟又增加了一道工序,操作起来也比较繁琐。于是我就想到了在返回阶段利用 jackson 的序列化步骤来对属性进行字典转换。json 对象类似 map 都是键值对,不用担心增减属性的问题。序列化时其它注解也已经处理完成,不会造成影响。</p>\n</blockquote>\n<h4 id=\"实现细节\"><a class=\"anchor\" href=\"#实现细节\">#</a> 实现细节</h4>\n<h6 id=\"需要的jar\"><a class=\"anchor\" href=\"#需要的jar\">#</a> 需要的 jar</h6>\n<p><figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><!-- 版本根据需求调整 --></span><br><span class=\"line\"><dependency></span><br><span class=\"line\"> <groupId>com.fasterxml.jackson.core</groupId></span><br><span class=\"line\"> <artifactId>jackson-core</artifactId></span><br><span class=\"line\"> <version><span class=\"number\">2.15</span><span class=\"number\">.2</span></version></span><br><span class=\"line\"></dependency></span><br><span class=\"line\"><dependency></span><br><span class=\"line\"> <groupId>com.fasterxml.jackson.core</groupId></span><br><span class=\"line\"> <artifactId>jackson-databind</artifactId></span><br><span class=\"line\"> <version><span class=\"number\">2.15</span><span class=\"number\">.2</span></version> </span><br><span class=\"line\"></dependency></span><br><span class=\"line\"><dependency></span><br><span class=\"line\"> <groupId>com.fasterxml.jackson.core</groupId></span><br><span class=\"line\"> <artifactId>jackson-annotations</artifactId></span><br><span class=\"line\"> <version><span class=\"number\">2.15</span><span class=\"number\">.2</span></version></span><br><span class=\"line\"></dependency></span><br></pre></td></tr></table></figure></p>\n<h6 id=\"定义注解\"><a class=\"anchor\" href=\"#定义注解\">#</a> 定义注解</h6>\n<p><figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">enum</span> <span class=\"title class_\">DicHandleStrategy</span> {</span><br><span class=\"line\"> replace,</span><br><span class=\"line\"> add;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"title function_\">DicHandleStrategy</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.annotation.JacksonAnnotationsInside;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.databind.annotation.JsonSerialize;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> java.lang.annotation.ElementType;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.lang.annotation.Retention;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.lang.annotation.RetentionPolicy;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.lang.annotation.Target;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">@Target({ElementType.FIELD, ElementType.METHOD})</span></span><br><span class=\"line\"><span class=\"meta\">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class=\"line\"><span class=\"meta\">@JacksonAnnotationsInside</span></span><br><span class=\"line\"><span class=\"meta\">@JsonSerialize(using = JsonDicHandle.class)</span></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"meta\">@interface</span> JsonDicField {</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 业务表名</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> String <span class=\"title function_\">tableName</span><span class=\"params\">()</span> <span class=\"keyword\">default</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 业务字段名</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> String <span class=\"title function_\">fieldName</span><span class=\"params\">()</span> <span class=\"keyword\">default</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 默认增加一个对应属性名加_dic的新属性(如type_dic)* newFieldName为空的情况下</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> DicHandleStrategy <span class=\"title function_\">strategy</span><span class=\"params\">()</span> <span class=\"keyword\">default</span> DicHandleStrategy.add;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 字典属性名称(如不指定,并且strategy为add的情况下则字典名称默认为原属性加_dic)</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> String <span class=\"title function_\">newFieldName</span><span class=\"params\">()</span> <span class=\"keyword\">default</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"注解处理\"><a class=\"anchor\" href=\"#注解处理\">#</a> 注解处理</h6>\n<p><figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br><span class=\"line\">120</span><br><span class=\"line\">121</span><br><span class=\"line\">122</span><br><span class=\"line\">123</span><br><span class=\"line\">124</span><br><span class=\"line\">125</span><br><span class=\"line\">126</span><br><span class=\"line\">127</span><br><span class=\"line\">128</span><br><span class=\"line\">129</span><br><span class=\"line\">130</span><br><span class=\"line\">131</span><br><span class=\"line\">132</span><br><span class=\"line\">133</span><br><span class=\"line\">134</span><br><span class=\"line\">135</span><br><span class=\"line\">136</span><br><span class=\"line\">137</span><br><span class=\"line\">138</span><br><span class=\"line\">139</span><br><span class=\"line\">140</span><br><span class=\"line\">141</span><br><span class=\"line\">142</span><br><span class=\"line\">143</span><br><span class=\"line\">144</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.beans.BeansException;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.beans.factory.NoSuchBeanDefinitionException;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.context.ApplicationContext;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.context.ApplicationContextAware;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Timer;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.TimerTask;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> <span class=\"title class_\">SpringContextUtil</span> <span class=\"keyword\">implements</span> <span class=\"title class_\">ApplicationContextAware</span> {</span><br><span class=\"line\">\t<span class=\"keyword\">private</span> <span class=\"keyword\">static</span> ApplicationContext applicationContext;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">void</span> <span class=\"title function_\">setApplicationContext</span><span class=\"params\">(ApplicationContext applicationContext)</span> <span class=\"keyword\">throws</span> BeansException {</span><br><span class=\"line\">\t\tSpringContextUtil.applicationContext = applicationContext;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> ApplicationContext <span class=\"title function_\">getApplicationContext</span><span class=\"params\">()</span> {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext;</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> Object <span class=\"title function_\">getBean</span><span class=\"params\">(String name)</span> <span class=\"keyword\">throws</span> BeansException {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.getBean(name);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> Object <span class=\"title function_\">getBean</span><span class=\"params\">(String name, Class<?> requiredType)</span> <span class=\"keyword\">throws</span> BeansException {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.getBean(name, requiredType);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> Object <span class=\"title function_\">getBean</span><span class=\"params\">(Class<?> requiredType)</span> <span class=\"keyword\">throws</span> BeansException {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.getBean(requiredType);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"type\">boolean</span> <span class=\"title function_\">containsBean</span><span class=\"params\">(String name)</span> {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.containsBean(name);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"type\">boolean</span> <span class=\"title function_\">isSingleton</span><span class=\"params\">(String name)</span> <span class=\"keyword\">throws</span> NoSuchBeanDefinitionException {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.isSingleton(name);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> Class<?> getType(String name) <span class=\"keyword\">throws</span> NoSuchBeanDefinitionException {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.getType(name);</span><br><span class=\"line\">\t}</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">public</span> <span class=\"keyword\">static</span> String[] getAliases(String name) <span class=\"keyword\">throws</span> NoSuchBeanDefinitionException {</span><br><span class=\"line\">\t\t<span class=\"keyword\">return</span> applicationContext.getAliases(name);</span><br><span class=\"line\">\t}</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.core.JsonGenerator;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.databind.BeanProperty;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.databind.JsonMappingException;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.databind.JsonSerializer;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.databind.SerializerProvider;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.fasterxml.jackson.databind.ser.ContextualSerializer;</span><br><span class=\"line\"><span class=\"keyword\">import</span> com.ys.szygl.util.SpringContextUtil;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.apache.commons.collections.CollectionUtils;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.apache.commons.collections.MapUtils;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.apache.commons.lang3.StringUtils;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> java.io.IOException;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.*;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.stream.Collectors;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> <span class=\"title class_\">JsonDicHandle</span> <span class=\"keyword\">extends</span> <span class=\"title class_\">JsonSerializer</span><Object> <span class=\"keyword\">implements</span> <span class=\"title class_\">ContextualSerializer</span> {</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">final</span> <span class=\"type\">String</span> <span class=\"variable\">DIC_FIELD_SUFFIX</span> <span class=\"operator\">=</span> <span class=\"string\">"_dic"</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">tableName</span> <span class=\"operator\">=</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">fieldName</span> <span class=\"operator\">=</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">DicHandleStrategy</span> <span class=\"variable\">strategy</span> <span class=\"operator\">=</span> DicHandleStrategy.add;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">newFieldName</span> <span class=\"operator\">=</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">propertyName</span> <span class=\"operator\">=</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">static</span> <span class=\"keyword\">final</span> <span class=\"type\">IDicService</span> <span class=\"variable\">iDicService</span> <span class=\"operator\">=</span> (IDicService)SpringContextUtil.getBean(IDicService.class);</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"title function_\">JsonDicHandle</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"title function_\">JsonDicHandle</span><span class=\"params\">(String tableName, String fieldName, DicHandleStrategy strategy, String newFieldName, String propertyName)</span> {</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.tableName = tableName;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.fieldName = fieldName;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.strategy = strategy;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.newFieldName = newFieldName;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.propertyName = propertyName;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> <span class=\"title function_\">serialize</span><span class=\"params\">(Object value, JsonGenerator gen, SerializerProvider serializers)</span> <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (StringUtils.isBlank(<span class=\"built_in\">this</span>.newFieldName) && StringUtils.isNotBlank(<span class=\"built_in\">this</span>.propertyName)) {</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.newFieldName = <span class=\"built_in\">this</span>.propertyName + DIC_FIELD_SUFFIX;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">dicValue</span> <span class=\"operator\">=</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (Objects.nonNull(value)) {</span><br><span class=\"line\"> dicValue = <span class=\"built_in\">this</span>.getDicValue(<span class=\"built_in\">this</span>.tableName, <span class=\"built_in\">this</span>.fieldName, String.valueOf(value));</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (DicHandleStrategy.replace.name().equals(<span class=\"built_in\">this</span>.strategy.name())) {</span><br><span class=\"line\"> gen.writeObject(dicValue);</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> gen.writeObject(value);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> gen.writeObject(value);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (DicHandleStrategy.add.name().equals(<span class=\"built_in\">this</span>.strategy.name()) && StringUtils.isNotBlank(<span class=\"built_in\">this</span>.newFieldName)) {</span><br><span class=\"line\"> gen.writeStringField(<span class=\"built_in\">this</span>.newFieldName, dicValue);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) <span class=\"keyword\">throws</span> JsonMappingException {</span><br><span class=\"line\"> <span class=\"type\">JsonDicField</span> <span class=\"variable\">annotation</span> <span class=\"operator\">=</span> property.getAnnotation(JsonDicField.class);</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (Objects.nonNull(annotation)) {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"title class_\">JsonDicHandle</span>(annotation.tableName(), annotation.fieldName(), annotation.strategy(),</span><br><span class=\"line\"> annotation.newFieldName(), property.getName());</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"title class_\">JsonDicHandle</span>();</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 把值转为字典值</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param</span> value</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> String <span class=\"title function_\">getDicValue</span><span class=\"params\">(String tableName, String fieldName, String value)</span> {</span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">dicValue</span> <span class=\"operator\">=</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (Objects.nonNull(iDicService)) {</span><br><span class=\"line\"> Map<String, String> dicMap = <span class=\"built_in\">this</span>.iDicService.getDicMapFromCatch(tableName, fieldName);</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (MapUtils.isNotEmpty(dicMap)) {</span><br><span class=\"line\"> List<String> dicValues = Arrays.stream(value.split(<span class=\"string\">","</span>)).map(s -> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> Optional.ofNullable(dicMap.get(s)).map(String::valueOf).orElse(<span class=\"string\">""</span>);</span><br><span class=\"line\"> }).collect(Collectors.toList());</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (CollectionUtils.isNotEmpty(dicValues)) {</span><br><span class=\"line\"> dicValue = String.join(<span class=\"string\">","</span>, dicValues);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> dicValue;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"其它\"><a class=\"anchor\" href=\"#其它\">#</a> 其它</h6>\n<blockquote>\n<p>IDicService 是自己的字典缓存服务,利用 tableName 和 fieldName 来定位属性的对应字典名称。请根据自己的业务逻辑进行修改。</p>\n</blockquote>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"jackson",
|
||
"字典转换"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/06/25/idea-%E4%B8%BB%E9%A2%98-%E4%BB%A3%E7%A0%81%E9%A2%9C%E8%89%B2-%E4%BB%A3%E7%A0%81%E5%8C%BA%E8%83%8C%E6%99%AF-%E8%A1%8C%E5%8F%B7%E8%83%8C%E6%99%AF-%E6%B3%A8%E9%87%8A%E9%A2%9C%E8%89%B2%E4%BF%AE%E6%94%B9/",
|
||
"url": "https://hitoli.com/2024/06/25/idea-%E4%B8%BB%E9%A2%98-%E4%BB%A3%E7%A0%81%E9%A2%9C%E8%89%B2-%E4%BB%A3%E7%A0%81%E5%8C%BA%E8%83%8C%E6%99%AF-%E8%A1%8C%E5%8F%B7%E8%83%8C%E6%99%AF-%E6%B3%A8%E9%87%8A%E9%A2%9C%E8%89%B2%E4%BF%AE%E6%94%B9/",
|
||
"title": "idea 主题 代码颜色 代码区背景 行号背景 注释颜色修改",
|
||
"date_published": "2024-06-25T08:03:00.000Z",
|
||
"content_html": "<h4 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h4>\n<blockquote>\n<p>最近写代码眼睛总是看的不舒服,想着换一个主题,但是换了主题,代码的颜色显示和之前又不一样了,接下来就是修改主题,但是代码颜色仍然保持 Darcula 主题的颜色。</p>\n</blockquote>\n<h4 id=\"修改主题\"><a class=\"anchor\" href=\"#修改主题\">#</a> 修改主题</h4>\n<p>我这里用的是 <span class=\"red\">One Dark theme</span> 可以直接去下载这个插件<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/c4ad60fe33ac.png\" alt=\"\" /></p>\n<h4 id=\"修改代码颜色与背景\"><a class=\"anchor\" href=\"#修改代码颜色与背景\">#</a> 修改代码颜色与背景</h4>\n<ol>\n<li>代码颜色<br />\n这里只修改代码颜色的话,idea 整体背景将不统一,看着非常难受,因此不仅要修改代码颜色,还要修改与当前主题相同的背景颜色。<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/18141ff20abc.png\" alt=\"\" /><br />\n这里直接修改为 Darcula ,那么整体的代码颜色风格都会变成 Darcula,但是代码区域的背景颜色也会变成 Darcula ,使得 idea 背景一体性破坏。</li>\n<li>代码区背景<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/b70f144b887f.png\" alt=\"\" /><br />\n这里如果你用的跟我一样的 One Dark theme ,那么你就可以修改颜色为 21252B 这样代码区颜色就会和主题相一致,但是到这里你会发现,行号区域的颜色又不一样了。</li>\n</ol>\n<h4 id=\"修改行号背景\"><a class=\"anchor\" href=\"#修改行号背景\">#</a> 修改行号背景</h4>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/89836b9fdd65.png\" alt=\"\" /><br />\n这里按照相同的方法修改,即可达到整体的一致性。</p>\n<h4 id=\"修改注释颜色\"><a class=\"anchor\" href=\"#修改注释颜色\">#</a> 修改注释颜色</h4>\n<p>这里就是个人习惯了,我习惯注释都是绿色的,清晰明了。<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/974673f11984.png\" alt=\"\" /><br />\n这里提供一个参考 629755 ,我个人比较喜欢这个颜色。</p>\n<h4 id=\"鼠标悬停代码提示框背景修改\"><a class=\"anchor\" href=\"#鼠标悬停代码提示框背景修改\">#</a> 鼠标悬停代码提示框背景修改</h4>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/f9dc4b6e63ce.png\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/5b1ec78282db.png\" alt=\"\" /></p>\n<h4 id=\"代码快捷提示框背景颜色修改\"><a class=\"anchor\" href=\"#代码快捷提示框背景颜色修改\">#</a> 代码快捷提示框背景颜色修改</h4>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/af59bb847efd.png\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/06/25/31b7512149f7.png\" alt=\"\" /></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"IDE",
|
||
"IDE",
|
||
"intellIJ"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/05/22/%E5%AF%B9XML%E6%A0%BC%E5%BC%8F%E7%9A%84Word%E6%A8%A1%E6%9D%BF%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%A4%84%E7%90%86/",
|
||
"url": "https://hitoli.com/2024/05/22/%E5%AF%B9XML%E6%A0%BC%E5%BC%8F%E7%9A%84Word%E6%A8%A1%E6%9D%BF%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%A4%84%E7%90%86/",
|
||
"title": "对XML格式的Word模板格式化处理",
|
||
"date_published": "2024-05-22T07:43:00.000Z",
|
||
"content_html": "<h4 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h4>\n<blockquote>\n<p>生成复杂的 word 文档需要使用 xml 格式的 word 模板,但是另存为 xml 文件的 word 文件格式比较杂乱。现提供一个格式化 xml 的工具类,代码如下:</p>\n</blockquote>\n<p><figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">package</span> xxx.util;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> cn.hutool.core.io.FileUtil;</span><br><span class=\"line\"><span class=\"keyword\">import</span> cn.hutool.core.io.file.FileAppender;</span><br><span class=\"line\"><span class=\"keyword\">import</span> cn.hutool.core.io.file.FileReader;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.List;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> <span class=\"title class_\">WordConvertXmlHandle</span> {</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"keyword\">static</span> <span class=\"keyword\">void</span> <span class=\"title function_\">main</span><span class=\"params\">(String[] args)</span> {</span><br><span class=\"line\"> <span class=\"comment\">//文件读取-FileReader</span></span><br><span class=\"line\"> <span class=\"comment\">//默认UTF-8编码,可以在构造中传入第二个参数作为编码</span></span><br><span class=\"line\"> <span class=\"type\">FileReader</span> <span class=\"variable\">fileReader</span> <span class=\"operator\">=</span> <span class=\"keyword\">new</span> <span class=\"title class_\">FileReader</span>(<span class=\"string\">"D:\\\\mb.xml"</span>);</span><br><span class=\"line\"> <span class=\"comment\">//从文件中读取每一行数据</span></span><br><span class=\"line\"> List<String> strings = fileReader.readLines();</span><br><span class=\"line\"> <span class=\"comment\">//文件追加-FileAppender</span></span><br><span class=\"line\"> <span class=\"comment\">//destFile – 目标文件</span></span><br><span class=\"line\"> <span class=\"comment\">//capacity – 当行数积累多少条时刷入到文件</span></span><br><span class=\"line\"> <span class=\"comment\">//isNewLineMode – 追加内容是否为新行</span></span><br><span class=\"line\"> <span class=\"type\">FileAppender</span> <span class=\"variable\">appender</span> <span class=\"operator\">=</span> <span class=\"keyword\">new</span> <span class=\"title class_\">FileAppender</span>(FileUtil.newFile(<span class=\"string\">"D:\\\\mb.ftl"</span>), <span class=\"number\">16</span>, <span class=\"literal\">true</span>);</span><br><span class=\"line\"> <span class=\"comment\">//遍历得到每一行数据</span></span><br><span class=\"line\"> <span class=\"keyword\">for</span> (String string : strings) {</span><br><span class=\"line\"> <span class=\"comment\">//判断每一行数据中不包含'$'的数据先添加进新文件</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!string.contains(<span class=\"string\">"$"</span>)) {</span><br><span class=\"line\"> appender.append(string);</span><br><span class=\"line\"> <span class=\"keyword\">continue</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">//如果一行数据中包含'$'变量符将替换为'#$'</span></span><br><span class=\"line\"> string = string.replaceAll(<span class=\"string\">"\\\\$"</span>, <span class=\"string\">"#\\\\$"</span>);</span><br><span class=\"line\"> <span class=\"comment\">//然后以'#'切割成每一行(数组),这样一来'$'都将在每一行的开头</span></span><br><span class=\"line\"> String[] ss = string.split(<span class=\"string\">"#"</span>);</span><br><span class=\"line\"> <span class=\"comment\">// 同一行的数据写到同一行,文件追加自动换行了(最后的完整数据)</span></span><br><span class=\"line\"> <span class=\"type\">StringBuilder</span> <span class=\"variable\">sb</span> <span class=\"operator\">=</span> <span class=\"keyword\">new</span> <span class=\"title class_\">StringBuilder</span>();</span><br><span class=\"line\"> <span class=\"comment\">//遍历每一行(数组ss)</span></span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> <span class=\"variable\">i</span> <span class=\"operator\">=</span> <span class=\"number\">0</span>; i < ss.length; i++) {</span><br><span class=\"line\"> <span class=\"comment\">//暂存数据</span></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">s1</span> <span class=\"operator\">=</span> ss[i];</span><br><span class=\"line\"> <span class=\"comment\">//将不是以'$'开头的行数据放进StringBuilder</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!s1.startsWith(<span class=\"string\">"$"</span>)) {</span><br><span class=\"line\"> sb.append(s1);</span><br><span class=\"line\"> <span class=\"keyword\">continue</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">//被分离的数据一般都是'${'这样被分开</span></span><br><span class=\"line\"> <span class=\"comment\">//匹配以'$'开头的变量找到'}' 得到索引位置</span></span><br><span class=\"line\"> <span class=\"type\">int</span> <span class=\"variable\">i1</span> <span class=\"operator\">=</span> s1.lastIndexOf(<span class=\"string\">"}"</span>);</span><br><span class=\"line\"> <span class=\"comment\">//先切割得到这个完整体</span></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">substr</span> <span class=\"operator\">=</span> s1.substring(<span class=\"number\">0</span>, i1 + <span class=\"number\">1</span>);</span><br><span class=\"line\"> <span class=\"comment\">//把变量追加到StringBuilder</span></span><br><span class=\"line\"> sb.append(substr.replaceAll(<span class=\"string\">"<[^>]+>"</span>, <span class=\"string\">""</span>));</span><br><span class=\"line\"> <span class=\"comment\">//再将标签数据追加到StringBuilder包裹变量</span></span><br><span class=\"line\"> sb.append(s1.substring(i1 + <span class=\"number\">1</span>));</span><br><span class=\"line\"> }</span><br><span class=\"line\"> appender.append(sb.toString());</span><br><span class=\"line\"> }</span><br><span class=\"line\"> appender.flush();</span><br><span class=\"line\"> appender.toString();</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"xml",
|
||
"word"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/05/10/MySQL%E8%A1%A8%E5%88%86%E5%8C%BA/",
|
||
"url": "https://hitoli.com/2024/05/10/MySQL%E8%A1%A8%E5%88%86%E5%8C%BA/",
|
||
"title": "MySQL表分区",
|
||
"date_published": "2024-05-10T09:09:00.000Z",
|
||
"content_html": "<h4 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h4>\n<blockquote>\n<p>当单表数据量过大时,就需要考虑对表进行分表或者分区了。分表和分区都是用来解决数据库中大量数据存储和查询效率的问题,但它们的实现方式和解决的问题有所不同。</p>\n</blockquote>\n<blockquote>\n<p>分表(Sharding):</p>\n</blockquote>\n<ul>\n<li>分表是将一个大表按照某种规则拆分成多个较小的表,每个小表称为一个分表,这些分表可以分布在不同的数据库实例中。</li>\n<li>分表通常基于某种规则进行拆分,例如按照用户 ID、地理位置等进行拆分。</li>\n<li>分表的主要目的是解决单个表过大的问题,提高查询效率和并发能力。</li>\n</ul>\n<blockquote>\n<p>分区(Partitioning):</p>\n</blockquote>\n<ul>\n<li>分区是将一个表按照某种规则拆分成多个逻辑上的部分,每个部分称为一个分区,但这些分区仍然属于同一个表。</li>\n<li>分区通常基于某种规则进行拆分,例如按照时间、范围、哈希值等进行拆分。</li>\n<li>分区的主要目的是提高数据的管理和查询效率,通过将数据分散到不同的分区中,可以提高查询性能和管理灵活性。</li>\n</ul>\n<blockquote>\n<p>区别:</p>\n</blockquote>\n<ul>\n<li>实现方式:分表是将一个表拆分成多个子表,每个子表都是一个独立的表;而分区是将一个表按照某种规则拆分成多个逻辑上的部分,这些部分仍然属于同一个表。</li>\n<li>解决的问题:分表主要解决单个表过大的问题,提高查询效率和并发能力;而分区主要提高数据的管理和查询效率,通过将数据分散到不同的分区中,可以提高查询性能和管理灵活性。</li>\n<li>适用场景:分表适用于单表数据量巨大的情况,例如大型电商平台的订单表;而分区适用于需要根据某种规则对数据进行划分管理的情况,例如按照时间对日志表进行分区。</li>\n</ul>\n<h4 id=\"实现细节\"><a class=\"anchor\" href=\"#实现细节\">#</a> 实现细节</h4>\n<blockquote>\n<p>本文章介绍的是如何对单表进行分区。</p>\n</blockquote>\n<h6 id=\"给表添加分区\"><a class=\"anchor\" href=\"#给表添加分区\">#</a> 给表添加分区</h6>\n<p><figure class=\"highlight sql\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">ALTER</span> <span class=\"keyword\">TABLE</span> 表名(字段)</span><br><span class=\"line\"><span class=\"keyword\">PARTITION</span> <span class=\"keyword\">BY</span> <span class=\"keyword\">RANGE</span> COLUMNS (时间字段名) (</span><br><span class=\"line\">\t<span class=\"comment\">-- 分区条件(时间小于2022-02-01的数据放入p202201分区中)</span></span><br><span class=\"line\"> <span class=\"keyword\">PARTITION</span> p202201 <span class=\"keyword\">VALUES</span> LESS THAN (<span class=\"string\">'2022-02-01'</span>),</span><br><span class=\"line\"> <span class=\"keyword\">PARTITION</span> p202202 <span class=\"keyword\">VALUES</span> LESS THAN (<span class=\"string\">'2022-03-01'</span>),</span><br><span class=\"line\"> <span class=\"keyword\">PARTITION</span> p202203 <span class=\"keyword\">VALUES</span> LESS THAN (<span class=\"string\">'2022-04-01'</span>),</span><br><span class=\"line\"> <span class=\"comment\">-- 继续定义更多的分区...</span></span><br><span class=\"line\">);</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"按指定表名创建当前年月的分区\"><a class=\"anchor\" href=\"#按指定表名创建当前年月的分区\">#</a> 按指定表名创建当前年月的分区</h6>\n<p><figure class=\"highlight sql\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">CREATE</span> <span class=\"keyword\">PROCEDURE</span> create_monthly_partition(<span class=\"keyword\">IN</span> tableName <span class=\"type\">VARCHAR</span>(<span class=\"number\">255</span>))</span><br><span class=\"line\"><span class=\"keyword\">BEGIN</span></span><br><span class=\"line\"> <span class=\"keyword\">DECLARE</span> currentYear <span class=\"type\">INT</span>;</span><br><span class=\"line\"> <span class=\"keyword\">DECLARE</span> currentMonth <span class=\"type\">INT</span>;</span><br><span class=\"line\"> \t<span class=\"keyword\">DECLARE</span> nextYear <span class=\"type\">INT</span>;</span><br><span class=\"line\"> <span class=\"keyword\">DECLARE</span> nextMonth <span class=\"type\">INT</span>;</span><br><span class=\"line\"> <span class=\"keyword\">DECLARE</span> partitionName <span class=\"type\">VARCHAR</span>(<span class=\"number\">255</span>);</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> currentYear <span class=\"operator\">=</span> <span class=\"keyword\">YEAR</span>(<span class=\"built_in\">CURRENT_DATE</span>);</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> currentMonth <span class=\"operator\">=</span> <span class=\"keyword\">MONTH</span>(<span class=\"built_in\">CURRENT_DATE</span>);</span><br><span class=\"line\"> \t<span class=\"comment\">-- 计算下一个月的年份和月份</span></span><br><span class=\"line\"> IF currentMonth <span class=\"operator\">=</span> <span class=\"number\">12</span> <span class=\"keyword\">THEN</span></span><br><span class=\"line\"> <span class=\"keyword\">SET</span> nextYear <span class=\"operator\">=</span> currentYear <span class=\"operator\">+</span> <span class=\"number\">1</span>;</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> nextMonth <span class=\"operator\">=</span> <span class=\"number\">1</span>;</span><br><span class=\"line\"> <span class=\"keyword\">ELSE</span></span><br><span class=\"line\"> <span class=\"keyword\">SET</span> nextYear <span class=\"operator\">=</span> currentYear;</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> nextMonth <span class=\"operator\">=</span> currentMonth <span class=\"operator\">+</span> <span class=\"number\">1</span>;</span><br><span class=\"line\"> <span class=\"keyword\">END</span> IF;</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> partitionName <span class=\"operator\">=</span> CONCAT(<span class=\"string\">'p'</span>, currentYear, LPAD(currentMonth, <span class=\"number\">2</span>, <span class=\"number\">0</span>));</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> <span class=\"variable\">@sql</span> <span class=\"operator\">=</span> CONCAT(<span class=\"string\">'ALTER TABLE '</span>, tableName, </span><br><span class=\"line\"> <span class=\"string\">' ADD PARTITION (PARTITION '</span>, partitionName,</span><br><span class=\"line\"> <span class=\"string\">' VALUES LESS THAN (\\'', nextYear, '</span><span class=\"operator\">-</span><span class=\"string\">', LPAD(nextMonth, 2, 0), '</span><span class=\"number\">-01</span>\\<span class=\"string\">''</span>, <span class=\"string\">'))'</span>);</span><br><span class=\"line\"> <span class=\"keyword\">PREPARE</span> stmt <span class=\"keyword\">FROM</span> <span class=\"variable\">@sql</span>;</span><br><span class=\"line\"> <span class=\"keyword\">EXECUTE</span> stmt;</span><br><span class=\"line\"> <span class=\"keyword\">DEALLOCATE</span> <span class=\"keyword\">PREPARE</span> stmt;</span><br><span class=\"line\"><span class=\"keyword\">END</span></span><br></pre></td></tr></table></figure></p>\n<h6 id=\"调用创建新分区\"><a class=\"anchor\" href=\"#调用创建新分区\">#</a> 调用创建新分区</h6>\n<p><figure class=\"highlight sql\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">CALL</span> create_monthly_partition(<span class=\"string\">'表名'</span>);</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"删除指定分区\"><a class=\"anchor\" href=\"#删除指定分区\">#</a> 删除指定分区</h6>\n<p><figure class=\"highlight sql\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">ALTER</span> <span class=\"keyword\">TABLE</span> 表名 <span class=\"keyword\">drop</span> <span class=\"keyword\">PARTITION</span> 分区名;</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"每月执行一次调用指定表添加新分区\"><a class=\"anchor\" href=\"#每月执行一次调用指定表添加新分区\">#</a> 每月执行一次调用指定表添加新分区</h6>\n<p><figure class=\"highlight sql\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">CREATE</span> EVENT create_monthly_partition_event</span><br><span class=\"line\"><span class=\"keyword\">ON</span> SCHEDULE <span class=\"keyword\">EVERY</span> <span class=\"number\">1</span> <span class=\"keyword\">MONTH</span></span><br><span class=\"line\">STARTS <span class=\"string\">'2024-01-01 00:00:00.000'</span></span><br><span class=\"line\"><span class=\"keyword\">ON</span> COMPLETION <span class=\"keyword\">NOT</span> PRESERVE</span><br><span class=\"line\">ENABLE</span><br><span class=\"line\">DO <span class=\"keyword\">begin</span></span><br><span class=\"line\">\t<span class=\"keyword\">DECLARE</span> CONTINUE HANDLER <span class=\"keyword\">FOR</span> <span class=\"keyword\">SQLEXCEPTION</span></span><br><span class=\"line\"> <span class=\"keyword\">BEGIN</span></span><br><span class=\"line\"> <span class=\"comment\">-- 捕获异常,记录错误信息,然后继续执行</span></span><br><span class=\"line\"> <span class=\"keyword\">SET</span> <span class=\"variable\">@error</span>_message <span class=\"operator\">=</span> CONCAT(<span class=\"string\">'Error occurred while processing table: '</span>, <span class=\"variable\">@tableName</span>);</span><br><span class=\"line\"> <span class=\"comment\">-- 可以将错误信息插入到日志表,或者使用 SELECT 输出错误信息</span></span><br><span class=\"line\"> <span class=\"keyword\">SELECT</span> <span class=\"variable\">@error</span>_message;</span><br><span class=\"line\"> <span class=\"keyword\">END</span>;</span><br><span class=\"line\"> <span class=\"comment\">-- 定义需要分区的表名列表</span></span><br><span class=\"line\"> <span class=\"keyword\">SET</span> <span class=\"variable\">@tables</span> <span class=\"operator\">=</span> <span class=\"string\">'表名1,表名2'</span>;</span><br><span class=\"line\"> <span class=\"comment\">-- 遍历表名列表并为每个表创建分区</span></span><br><span class=\"line\"> WHILE <span class=\"keyword\">CHAR_LENGTH</span>(<span class=\"variable\">@tables</span>) <span class=\"operator\">></span> <span class=\"number\">0</span> DO</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> <span class=\"variable\">@tableName</span> <span class=\"operator\">=</span> SUBSTRING_INDEX(<span class=\"variable\">@tables</span>, <span class=\"string\">','</span>, <span class=\"number\">1</span>);</span><br><span class=\"line\"> <span class=\"keyword\">SET</span> <span class=\"variable\">@tables</span> <span class=\"operator\">=</span> <span class=\"built_in\">SUBSTRING</span>(<span class=\"variable\">@tables</span>, <span class=\"keyword\">CHAR_LENGTH</span>(<span class=\"variable\">@tableName</span>) <span class=\"operator\">+</span> <span class=\"number\">2</span>);</span><br><span class=\"line\"> <span class=\"keyword\">CALL</span> create_monthly_partition(<span class=\"variable\">@tableName</span>);</span><br><span class=\"line\"> <span class=\"keyword\">END</span> WHILE;</span><br><span class=\"line\"><span class=\"keyword\">end</span></span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"mysql",
|
||
"表分区"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/04/30/Java%E5%90%8E%E7%AB%AF%E7%A6%81%E6%AD%A2%E6%8E%A5%E5%8F%A3%E7%9E%AC%E6%97%B6%E9%87%8D%E5%A4%8D%E8%B0%83%E7%94%A8/",
|
||
"url": "https://hitoli.com/2024/04/30/Java%E5%90%8E%E7%AB%AF%E7%A6%81%E6%AD%A2%E6%8E%A5%E5%8F%A3%E7%9E%AC%E6%97%B6%E9%87%8D%E5%A4%8D%E8%B0%83%E7%94%A8/",
|
||
"title": "Java后端禁止接口瞬时重复调用",
|
||
"date_published": "2024-04-30T03:44:00.000Z",
|
||
"content_html": "<h4 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h4>\n<p>由于前端会莫名其妙的对同一接口请求多次,从而占用后端资源造成浪费。所以采用了后端拦截相关重复请求的方案。此方案会将请求用户 id 加接口 url 加参数作为 key,请求时间作为 value,使用 ConcurrentHashMap 进行缓存。如果下次相同的请求和上次请求的时间在指定的范围内则认为此请求属于重复请求。</p>\n<h4 id=\"实现细节\"><a class=\"anchor\" href=\"#实现细节\">#</a> 实现细节</h4>\n<h6 id=\"自定义可重复读request\"><a class=\"anchor\" href=\"#自定义可重复读request\">#</a> 自定义可重复读 Request</h6>\n<p>request 的 body 只能读取一次,所以对其进行封装。<br />\n<figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br><span class=\"line\">107</span><br><span class=\"line\">108</span><br><span class=\"line\">109</span><br><span class=\"line\">110</span><br><span class=\"line\">111</span><br><span class=\"line\">112</span><br><span class=\"line\">113</span><br><span class=\"line\">114</span><br><span class=\"line\">115</span><br><span class=\"line\">116</span><br><span class=\"line\">117</span><br><span class=\"line\">118</span><br><span class=\"line\">119</span><br><span class=\"line\">120</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">package</span> xxx.support;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> com.alibaba.fastjson.JSON;</span><br><span class=\"line\"><span class=\"keyword\">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.ReadListener;</span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.ServletInputStream;</span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequestWrapper;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.io.*;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.nio.charset.StandardCharsets;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Enumeration;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Map;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Objects;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.TreeMap;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">@Slf4j</span></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> <span class=\"title class_\">RepeatableReadHttpServletRequestWrapper</span> <span class=\"keyword\">extends</span> <span class=\"title class_\">HttpServletRequestWrapper</span> {</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"keyword\">final</span> <span class=\"type\">byte</span>[] requestBody;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"title function_\">RepeatableReadHttpServletRequestWrapper</span><span class=\"params\">(HttpServletRequest request)</span> <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"built_in\">super</span>(request);</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.requestBody = readRequestBody(request);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"type\">byte</span>[] readRequestBody(HttpServletRequest request) <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"keyword\">try</span> (<span class=\"type\">InputStream</span> <span class=\"variable\">inputStream</span> <span class=\"operator\">=</span> request.getInputStream();</span><br><span class=\"line\"> <span class=\"type\">ByteArrayOutputStream</span> <span class=\"variable\">result</span> <span class=\"operator\">=</span> <span class=\"keyword\">new</span> <span class=\"title class_\">ByteArrayOutputStream</span>()) {</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">byte</span>[] buffer = <span class=\"keyword\">new</span> <span class=\"title class_\">byte</span>[<span class=\"number\">1024</span>];</span><br><span class=\"line\"> <span class=\"type\">int</span> length;</span><br><span class=\"line\"> <span class=\"keyword\">while</span> ((length = inputStream.read(buffer)) != -<span class=\"number\">1</span>) {</span><br><span class=\"line\"> result.write(buffer, <span class=\"number\">0</span>, length);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">return</span> result.toByteArray();</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> ServletInputStream <span class=\"title function_\">getInputStream</span><span class=\"params\">()</span> <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"comment\">// 直接使用 ByteArrayInputStream,它提供可重复读取的输入流</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"title class_\">ServletInputStream</span>() {</span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"keyword\">final</span> <span class=\"type\">ByteArrayInputStream</span> <span class=\"variable\">byteArrayInputStream</span> <span class=\"operator\">=</span> <span class=\"keyword\">new</span> <span class=\"title class_\">ByteArrayInputStream</span>(requestBody);</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"type\">int</span> <span class=\"title function_\">read</span><span class=\"params\">()</span> <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> byteArrayInputStream.read();</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"type\">boolean</span> <span class=\"title function_\">isFinished</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> byteArrayInputStream.available() == <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"type\">boolean</span> <span class=\"title function_\">isReady</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"literal\">true</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> <span class=\"title function_\">setReadListener</span><span class=\"params\">(ReadListener readListener)</span> {</span><br><span class=\"line\"> <span class=\"comment\">// 不需要实现,可以留空</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> BufferedReader <span class=\"title function_\">getReader</span><span class=\"params\">()</span> <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"comment\">// 使用 InputStreamReader 包装 ByteArrayInputStream,提供可重复读取的字符流</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"title class_\">BufferedReader</span>(<span class=\"keyword\">new</span> <span class=\"title class_\">InputStreamReader</span>(<span class=\"keyword\">new</span> <span class=\"title class_\">ByteArrayInputStream</span>(requestBody)));</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 获取json格式的参数</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> String <span class=\"title function_\">getParamsToJSONString</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">jsonStr</span> <span class=\"operator\">=</span> <span class=\"string\">""</span>;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (<span class=\"string\">"POST"</span>.equals(<span class=\"built_in\">this</span>.getMethod().toUpperCase()) && <span class=\"built_in\">this</span>.isJsonRequest()) {</span><br><span class=\"line\"> <span class=\"keyword\">try</span> {</span><br><span class=\"line\"> jsonStr = <span class=\"built_in\">this</span>.readJsonData();</span><br><span class=\"line\"> } <span class=\"keyword\">catch</span> (Exception e) {</span><br><span class=\"line\"> log.error(e.getMessage());</span><br><span class=\"line\"> }</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> Enumeration<String> parameterNames = <span class=\"built_in\">this</span>.getParameterNames();</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (Objects.nonNull(parameterNames) && parameterNames.hasMoreElements()) {</span><br><span class=\"line\"> <span class=\"comment\">// 将参数排序后转为json</span></span><br><span class=\"line\"> Map<String, String> paramsMap = <span class=\"keyword\">new</span> <span class=\"title class_\">TreeMap</span><>();</span><br><span class=\"line\"> <span class=\"keyword\">while</span> (parameterNames.hasMoreElements()) {</span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">paramName</span> <span class=\"operator\">=</span> parameterNames.nextElement();</span><br><span class=\"line\"> paramsMap.put(paramName, <span class=\"built_in\">this</span>.getParameter(paramName));</span><br><span class=\"line\"> }</span><br><span class=\"line\"> jsonStr = JSON.toJSONString(paramsMap);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> jsonStr;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 判断是否json请求</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"type\">boolean</span> <span class=\"title function_\">isJsonRequest</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">contentType</span> <span class=\"operator\">=</span> <span class=\"built_in\">this</span>.getContentType();</span><br><span class=\"line\"> <span class=\"keyword\">return</span> contentType != <span class=\"literal\">null</span> && contentType.toLowerCase().contains(<span class=\"string\">"application/json"</span>);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 获取json格式的参数</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@throws</span> IOException</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> String <span class=\"title function_\">readJsonData</span><span class=\"params\">()</span> <span class=\"keyword\">throws</span> IOException {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"title class_\">String</span>(<span class=\"built_in\">this</span>.readRequestBody(<span class=\"built_in\">this</span>), StandardCharsets.UTF_8);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"重复请求过滤器\"><a class=\"anchor\" href=\"#重复请求过滤器\">#</a> 重复请求过滤器</h6>\n<p><figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br><span class=\"line\">104</span><br><span class=\"line\">105</span><br><span class=\"line\">106</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">package</span> xxx.filter;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> cn.hutool.core.collection.CollectionUtil;</span><br><span class=\"line\"><span class=\"keyword\">import</span> xxx.RepeatableReadHttpServletRequestWrapper;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.boot.actuate.endpoint.web.WebEndpointResponse;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.web.util.matcher.RequestMatcher;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.web.filter.OncePerRequestFilter;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.FilterChain;</span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.ServletException;</span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.io.IOException;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.List;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Map;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Objects;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.concurrent.ConcurrentHashMap;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> <span class=\"title class_\">DuplicateRequestFilter</span> <span class=\"keyword\">extends</span> <span class=\"title class_\">OncePerRequestFilter</span> {</span><br><span class=\"line\"> <span class=\"comment\">// 是否启用</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Boolean duplicateRequestFilter;</span><br><span class=\"line\"> <span class=\"comment\">// 间隔时间(毫秒)</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Long intervalTime;</span><br><span class=\"line\"> <span class=\"comment\">// 清除缓存时间(毫秒)</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Long clearCachetime;</span><br><span class=\"line\"> <span class=\"comment\">// 放行url</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> List<RequestMatcher> permitAll;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"title function_\">DuplicateRequestFilter</span><span class=\"params\">(Boolean duplicateRequestFilter, List<RequestMatcher> permitAll, Long intervalTime,</span></span><br><span class=\"line\"><span class=\"params\"> Long clearCachetime)</span> {</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.duplicateRequestFilter = duplicateRequestFilter;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.permitAll = permitAll;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.intervalTime = intervalTime;</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.clearCachetime = clearCachetime;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">// 存储参数和请求时间</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Map<String, Long> requestCache = <span class=\"keyword\">new</span> <span class=\"title class_\">ConcurrentHashMap</span><>();</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">protected</span> <span class=\"keyword\">void</span> <span class=\"title function_\">doFilterInternal</span><span class=\"params\">(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)</span></span><br><span class=\"line\"> <span class=\"keyword\">throws</span> ServletException, IOException {</span><br><span class=\"line\"> <span class=\"type\">boolean</span> <span class=\"variable\">doFilter</span> <span class=\"operator\">=</span> <span class=\"literal\">true</span>;</span><br><span class=\"line\"> <span class=\"comment\">// 使用 ContentCachingRequestWrapper 包装原始请求</span></span><br><span class=\"line\"> <span class=\"type\">RepeatableReadHttpServletRequestWrapper</span> <span class=\"variable\">wrappedRequest</span> <span class=\"operator\">=</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (<span class=\"built_in\">this</span>.duplicateRequestFilter) {</span><br><span class=\"line\"> <span class=\"comment\">// 判断请求路径是否需要放行</span></span><br><span class=\"line\"> <span class=\"type\">boolean</span> <span class=\"variable\">permit</span> <span class=\"operator\">=</span> <span class=\"literal\">false</span>;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (CollectionUtil.isNotEmpty(<span class=\"built_in\">this</span>.permitAll)) {</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (RequestMatcher matcher: <span class=\"built_in\">this</span>.permitAll) {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (matcher.matches(request)) {</span><br><span class=\"line\"> permit = <span class=\"literal\">true</span>;</span><br><span class=\"line\"> <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (!permit) {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (request <span class=\"keyword\">instanceof</span> RepeatableReadHttpServletRequestWrapper) {</span><br><span class=\"line\"> wrappedRequest = (RepeatableReadHttpServletRequestWrapper) request;</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> wrappedRequest = <span class=\"keyword\">new</span> <span class=\"title class_\">RepeatableReadHttpServletRequestWrapper</span>(request);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> doFilter = <span class=\"built_in\">this</span>.isValid(wrappedRequest);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (doFilter) {</span><br><span class=\"line\"> <span class=\"comment\">// 继续处理请求</span></span><br><span class=\"line\"> filterChain.doFilter(Objects.nonNull(wrappedRequest) ? wrappedRequest : request, response);</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> response.setContentType(<span class=\"string\">"application/json"</span>);</span><br><span class=\"line\"> response.setStatus(WebEndpointResponse.STATUS_TOO_MANY_REQUESTS);</span><br><span class=\"line\"><span class=\"comment\">// response.setStatus(HttpServletResponse.SC_OK);</span></span><br><span class=\"line\"><span class=\"comment\">// ObjectMapper mapper = new ObjectMapper();</span></span><br><span class=\"line\"><span class=\"comment\">// mapper.writeValue(response.getOutputStream(), R.error(WebEndpointResponse.STATUS_TOO_MANY_REQUESTS, "重复的请求"));</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 验证请求的有效性(判断是否重复请求)</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param</span> request</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@return</span></span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"type\">boolean</span> <span class=\"title function_\">isValid</span><span class=\"params\">(RepeatableReadHttpServletRequestWrapper request)</span> {</span><br><span class=\"line\"> <span class=\"type\">boolean</span> <span class=\"variable\">valid</span> <span class=\"operator\">=</span> <span class=\"literal\">true</span>;</span><br><span class=\"line\"> <span class=\"comment\">// 缓存的key</span></span><br><span class=\"line\"> <span class=\"type\">String</span> <span class=\"variable\">key</span> <span class=\"operator\">=</span> TokenUtil.getUidByToken() + <span class=\"string\">"_"</span> + request.getServletPath() + <span class=\"string\">"_"</span> + request.getParamsToJSONString();</span><br><span class=\"line\"> <span class=\"comment\">// 获取之前的请求时间</span></span><br><span class=\"line\"> <span class=\"type\">Long</span> <span class=\"variable\">previousRequestTime</span> <span class=\"operator\">=</span> requestCache.get(key);</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (previousRequestTime != <span class=\"literal\">null</span>) {</span><br><span class=\"line\"> <span class=\"comment\">// 如果距离上次请求时间很短(例如1秒),则拒绝当前请求</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span> (System.currentTimeMillis() - previousRequestTime < <span class=\"built_in\">this</span>.intervalTime) {</span><br><span class=\"line\"> valid = <span class=\"literal\">false</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.clearOldRequests();</span><br><span class=\"line\"> <span class=\"comment\">// 缓存当前请求时间</span></span><br><span class=\"line\"> requestCache.put(key, System.currentTimeMillis());</span><br><span class=\"line\"> <span class=\"keyword\">return</span> valid;</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">// 用于清除缓存中的旧请求数据,防止缓存无限增长</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> <span class=\"keyword\">void</span> <span class=\"title function_\">clearOldRequests</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> requestCache.entrySet().removeIf(entry -> System.currentTimeMillis() - entry.getValue() > <span class=\"built_in\">this</span>.clearCachetime);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h6 id=\"配置oauth2资源\"><a class=\"anchor\" href=\"#配置oauth2资源\">#</a> 配置 OAuth2 资源</h6>\n<p><figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br><span class=\"line\">64</span><br><span class=\"line\">65</span><br><span class=\"line\">66</span><br><span class=\"line\">67</span><br><span class=\"line\">68</span><br><span class=\"line\">69</span><br><span class=\"line\">70</span><br><span class=\"line\">71</span><br><span class=\"line\">72</span><br><span class=\"line\">73</span><br><span class=\"line\">74</span><br><span class=\"line\">75</span><br><span class=\"line\">76</span><br><span class=\"line\">77</span><br><span class=\"line\">78</span><br><span class=\"line\">79</span><br><span class=\"line\">80</span><br><span class=\"line\">81</span><br><span class=\"line\">82</span><br><span class=\"line\">83</span><br><span class=\"line\">84</span><br><span class=\"line\">85</span><br><span class=\"line\">86</span><br><span class=\"line\">87</span><br><span class=\"line\">88</span><br><span class=\"line\">89</span><br><span class=\"line\">90</span><br><span class=\"line\">91</span><br><span class=\"line\">92</span><br><span class=\"line\">93</span><br><span class=\"line\">94</span><br><span class=\"line\">95</span><br><span class=\"line\">96</span><br><span class=\"line\">97</span><br><span class=\"line\">98</span><br><span class=\"line\">99</span><br><span class=\"line\">100</span><br><span class=\"line\">101</span><br><span class=\"line\">102</span><br><span class=\"line\">103</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">package</span> xxx.config;</span><br><span class=\"line\"></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> xxx.AuthExceptionEntryPoint;</span><br><span class=\"line\"><span class=\"keyword\">import</span> xxx.CustomAccessDeniedHandler;</span><br><span class=\"line\"><span class=\"keyword\">import</span> xxx.DuplicateRequestFilter;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.slf4j.Logger;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.slf4j.LoggerFactory;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.beans.factory.annotation.Qualifier;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.beans.factory.annotation.Value;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.context.annotation.Bean;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.context.annotation.Configuration;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.config.annotation.web.builders.HttpSecurity;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.oauth2.provider.token.TokenStore;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;</span><br><span class=\"line\"><span class=\"keyword\">import</span> org.springframework.security.web.util.matcher.AntPathRequestMatcher;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">import</span> javax.servlet.Filter;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.Arrays;</span><br><span class=\"line\"><span class=\"keyword\">import</span> java.util.stream.Collectors;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"meta\">@Configuration</span></span><br><span class=\"line\"><span class=\"meta\">@EnableResourceServer</span></span><br><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">class</span> <span class=\"title class_\">ResourceServerConfig</span> <span class=\"keyword\">extends</span> <span class=\"title class_\">ResourceServerConfigurerAdapter</span> {</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"type\">Logger</span> <span class=\"variable\">log</span> <span class=\"operator\">=</span> LoggerFactory.getLogger(ResourceServerConfig.class);</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Autowired</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> TokenStore tokenStore;</span><br><span class=\"line\"> </span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 是否开放所有接口</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"meta\">@Value("${http.security.permitAll:false}")</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Boolean isPermitAll;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 是否启用重复请求过滤</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"meta\">@Value("${request.duplicateFilter.enabled:true}")</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Boolean duplicateRequestFilter;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 间隔时间(毫秒)</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"meta\">@Value("${request.duplicateFilter.interval_time:1000}")</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Long intervalTime;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 清除缓存时间(毫秒)</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"meta\">@Value("${request.duplicateFilter.clear_cache_time:30000}")</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> Long clearCachetime;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 不需要验证权限的接口</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"keyword\">private</span> String[] permitAll = <span class=\"keyword\">new</span> <span class=\"title class_\">String</span>[] {</span><br><span class=\"line\"> <span class=\"string\">"/auth/getVCode"</span>, <span class=\"string\">"/auth/login"</span></span><br><span class=\"line\"> };</span><br><span class=\"line\"></span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">/**</span></span><br><span class=\"line\"><span class=\"comment\"> * 通行规则</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@param</span> http</span></span><br><span class=\"line\"><span class=\"comment\"> * <span class=\"doctag\">@throws</span> Exception</span></span><br><span class=\"line\"><span class=\"comment\"> */</span></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> <span class=\"title function_\">configure</span><span class=\"params\">(HttpSecurity http)</span> <span class=\"keyword\">throws</span> Exception {</span><br><span class=\"line\"> <span class=\"type\">HttpSecurity</span> <span class=\"variable\">httpSecurity</span> <span class=\"operator\">=</span> http.csrf().disable();</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (isPermitAll) {</span><br><span class=\"line\"> httpSecurity.authorizeRequests().antMatchers(<span class=\"string\">"/**"</span>).permitAll();</span><br><span class=\"line\"> } <span class=\"keyword\">else</span> {</span><br><span class=\"line\"> httpSecurity.authorizeRequests()</span><br><span class=\"line\"> .antMatchers(permitAll).permitAll()</span><br><span class=\"line\"> .antMatchers(<span class=\"string\">"/**"</span>).authenticated();</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (<span class=\"built_in\">this</span>.duplicateRequestFilter) {</span><br><span class=\"line\"> httpSecurity.addFilterAfter(duplicateRequestFilter(), AbstractPreAuthenticatedProcessingFilter.class);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">//让X-frame-options失效,去除iframe限制</span></span><br><span class=\"line\"> http.headers().frameOptions().disable();</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> <span class=\"keyword\">void</span> <span class=\"title function_\">configure</span><span class=\"params\">(ResourceServerSecurityConfigurer resources)</span> <span class=\"keyword\">throws</span> Exception {</span><br><span class=\"line\"> resources.tokenStore(tokenStore).authenticationEntryPoint(<span class=\"keyword\">new</span> <span class=\"title class_\">AuthExceptionEntryPoint</span>())</span><br><span class=\"line\"> .accessDeniedHandler(<span class=\"keyword\">new</span> <span class=\"title class_\">CustomAccessDeniedHandler</span>());</span><br><span class=\"line\"></span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"meta\">@Bean</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> Filter <span class=\"title function_\">duplicateRequestFilter</span><span class=\"params\">()</span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"title class_\">DuplicateRequestFilter</span>(<span class=\"built_in\">this</span>.duplicateRequestFilter, Arrays.asList(<span class=\"built_in\">this</span>.permitAll)</span><br><span class=\"line\"> .stream().map(AntPathRequestMatcher::<span class=\"keyword\">new</span>).collect(Collectors.toList()), <span class=\"built_in\">this</span>.intervalTime,</span><br><span class=\"line\"> <span class=\"built_in\">this</span>.clearCachetime);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"java",
|
||
"429"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/03/03/Docker%E5%AE%B9%E5%99%A8%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0-Portainer%E5%AE%89%E8%A3%85/",
|
||
"url": "https://hitoli.com/2024/03/03/Docker%E5%AE%B9%E5%99%A8%E7%AE%A1%E7%90%86%E5%B9%B3%E5%8F%B0-Portainer%E5%AE%89%E8%A3%85/",
|
||
"title": "Docker容器管理平台-Portainer安装",
|
||
"date_published": "2024-03-03T07:52:00.000Z",
|
||
"content_html": "<h4 id=\"简介\"><a class=\"anchor\" href=\"#简介\">#</a> 简介</h4>\n<p>Portainer 是一款开源的容器管理平台,它提供了易于使用的 Web UI 界面,用于管理和监控容器及容器集群。该软件支持多种容器技术和配置,包括但不限于 Docker、Kubernetes 和 Swarm。</p>\n<h4 id=\"部署\"><a class=\"anchor\" href=\"#部署\">#</a> 部署</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#原版</span></span><br><span class=\"line\">docker run -d --restart=always --name=<span class=\"string\">"portainer"</span> -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v D:\\docker\\portainer\\data:/data portainer/portainer-ce</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">#汉化版</span></span><br><span class=\"line\">docker run -d --restart=always --name=<span class=\"string\">"portainer"</span> -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v D:\\docker\\portainer\\data:/data 6053537/portainer-ce</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"登录\"><a class=\"anchor\" href=\"#登录\">#</a> 登录</h4>\n<p><span class=\"exturl\" data-url=\"aHR0cDovL2xvY2FsaG9zdDo5MDAwLyMhL2hvbWU=\">http://localhost:9000/#!/home</span><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2024/03/03/923bc8f6ac2a.png\" alt=\"\" /></p>\n",
|
||
"tags": [
|
||
"Windows",
|
||
"工具",
|
||
"Docker",
|
||
"Portainer"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/01/19/IntellIJ%E5%8F%AA%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97/",
|
||
"url": "https://hitoli.com/2024/01/19/IntellIJ%E5%8F%AA%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97/",
|
||
"title": "IntellIJ只编译打包指定的模块",
|
||
"date_published": "2024-01-19T08:06:00.000Z",
|
||
"content_html": "<h4 id=\"新增maven配置\"><a class=\"anchor\" href=\"#新增maven配置\">#</a> 新增 Maven 配置</h4>\n<p>IntellIJ -》 右侧小锤子旁下拉按钮选择 Edit Configurations -》+ 号按钮 -》Maven</p>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2024/01/19/58082ccf2487.png\" alt=\"\" /></p>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2024/01/19/3097ede8d80c.png\" alt=\"\" /></p>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2024/01/19/31412cdf03de.png\" alt=\"\" /></p>\n<h4 id=\"填写maven命令\"><a class=\"anchor\" href=\"#填写maven命令\">#</a> 填写 Maven 命令</h4>\n<p>Working directory 选择根目录,命令是基于选中的目录为执行目录,Run 填写以下命令</p>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">clean package -pl emergency-dzdz/dzdz-yzt -am -Dmaven.test.skip=<span class=\"literal\">true</span> -f pom.xml</span><br><span class=\"line\">或者</span><br><span class=\"line\">clean install -pl emergency-dzdz/dzdz-yzt -am -Dmaven.test.skip=<span class=\"literal\">true</span> -f pom.xml</span><br><span class=\"line\"></span><br><span class=\"line\">clean: 这个命令会删除目标目录(target),确保每次构建是干净的。</span><br><span class=\"line\">install: 这个命令会将项目打包,并安装到本地的 Maven 仓库中。</span><br><span class=\"line\">-pl emergency-dzdz/dzdz-yzt: -pl 参数指定要构建的项目模块。dzdz-yzt 是模块的名称。这个参数告诉 Maven 只构建 dzdz-yzt 及其依赖的模块。注意模块路径,此处是构建emergency-dzdz下的dzdz-yzt模块。</span><br><span class=\"line\">-am: -am 参数与 -pl 一起使用,表示还要构建 dzdz-yzt 模块所依赖的所有模块。</span><br><span class=\"line\">package: 这个命令会将项目打包为 JAR 文件或 WAR 文件,取决于项目类型。</span><br><span class=\"line\">-f pom.xml: 这个参数指定要使用的 pom.xml 文件。默认情况下,Maven 会在当前目录下查找 pom.xml 文件,但可以通过此参数指定一个不同的位置。</span><br><span class=\"line\">-DskipTests=<span class=\"literal\">true</span>:跳过测试的执行,但会编译测试代码。</span><br><span class=\"line\">-Dmaven.test.skip=<span class=\"literal\">true</span>:跳过测试的编译和执行。</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"IntellIJ",
|
||
"Maven"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/01/03/%E8%A7%A3%E5%86%B3Nginx%E8%AE%BF%E9%97%AE%E8%87%AA%E7%AD%BEssl%E8%AF%81%E4%B9%A6%E6%8A%A5%E4%B8%8D%E5%AE%89%E5%85%A8%E5%91%8A%E8%AD%A6/",
|
||
"url": "https://hitoli.com/2024/01/03/%E8%A7%A3%E5%86%B3Nginx%E8%AE%BF%E9%97%AE%E8%87%AA%E7%AD%BEssl%E8%AF%81%E4%B9%A6%E6%8A%A5%E4%B8%8D%E5%AE%89%E5%85%A8%E5%91%8A%E8%AD%A6/",
|
||
"title": "解决Nginx访问自签ssl证书报不安全告警",
|
||
"date_published": "2024-01-03T10:01:00.000Z",
|
||
"content_html": "<h4 id=\"生成根证书私钥和根证书\"><a class=\"anchor\" href=\"#生成根证书私钥和根证书\">#</a> 生成根证书私钥和根证书</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -subj <span class=\"string\">"/C=国家/ST=省/L=市/O=机构"</span> -keyout CA-private.key -out CA-certificate.crt -reqexts v3_req -extensions v3_ca</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">#示例</span></span><br><span class=\"line\">openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -subj <span class=\"string\">"/C=CN/ST=EZ/L=EZ/O=EZ"</span> -keyout CA-private.key -out CA-certificate.crt -reqexts v3_req -extensions v3_ca</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"生成自签名证书私钥\"><a class=\"anchor\" href=\"#生成自签名证书私钥\">#</a> 生成自签名证书私钥</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">openssl genrsa -out private.key 2048</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"根据自签名证书私钥生成自签名证书申请文件\"><a class=\"anchor\" href=\"#根据自签名证书私钥生成自签名证书申请文件\">#</a> 根据自签名证书私钥生成自签名证书申请文件</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">openssl req -new -key private.key -subj <span class=\"string\">"/C=CN/ST=EZ/L=EZ/O=EZ/CN=192.168.2.117"</span> -sha256 -out private.csr</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"定义自签名证书扩展文件解决chrome安全告警新建privateext文件并写入以下内容ip为nginx服务器ip同nginxconf中的server_name\"><a class=\"anchor\" href=\"#定义自签名证书扩展文件解决chrome安全告警新建privateext文件并写入以下内容ip为nginx服务器ip同nginxconf中的server_name\">#</a> 定义自签名证书扩展文件 (解决 chrome 安全告警),新建 private.ext 文件并写入以下内容(IP 为 nginx 服务器 ip,同 nginx.conf 中的 server_name)</h4>\n<p><figure class=\"highlight text\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[ req ]</span><br><span class=\"line\">default_bits = 1024</span><br><span class=\"line\">distinguished_name = req_distinguished_name</span><br><span class=\"line\">req_extensions = san</span><br><span class=\"line\">extensions = san</span><br><span class=\"line\">[ req_distinguished_name ]</span><br><span class=\"line\">countryName = CN</span><br><span class=\"line\">stateOrProvinceName = Definesys</span><br><span class=\"line\">localityName = Definesys</span><br><span class=\"line\">organizationName = Definesys</span><br><span class=\"line\">[SAN]</span><br><span class=\"line\">authorityKeyIdentifier=keyid,issuer</span><br><span class=\"line\">basicConstraints=CA:FALSE</span><br><span class=\"line\">keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment</span><br><span class=\"line\">subjectAltName = IP:192.168.2.117</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"生成自签名证书有效期100年\"><a class=\"anchor\" href=\"#生成自签名证书有效期100年\">#</a> 生成自签名证书(有效期 100 年)</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">openssl x509 -req -days 36500 -<span class=\"keyword\">in</span> private.csr -CA CA-certificate.crt -CAkey CA-private.key -CAcreateserial -sha256 -out private.crt -extfile private.ext -extensions SAN</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"nginx的ssl证书配置\"><a class=\"anchor\" href=\"#nginx的ssl证书配置\">#</a> nginx 的 ssl 证书配置</h4>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">ssl_certificate_key</span> <span class=\"string\">/usr/local/nginx/ssl/private.key;</span></span><br><span class=\"line\"><span class=\"string\">ssl_certificate</span> <span class=\"string\">/usr/local/nginx/ssl/private.crt;</span></span><br></pre></td></tr></table></figure></p>\n<h4 id=\"证书安装\"><a class=\"anchor\" href=\"#证书安装\">#</a> 证书安装</h4>\n<p>需要安装 CA-certificate.crt 到受信任的根证书颁发机构下,即可从浏览器正常访问且不会报不安全警告。</p>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#ssl测试</span></span><br><span class=\"line\">openssl s_client -connect localhost:8080</span><br><span class=\"line\"><span class=\"comment\">#检查证书格式</span></span><br><span class=\"line\">openssl x509 -<span class=\"keyword\">in</span> private.crt -text -noout</span><br><span class=\"line\">openssl rsa -<span class=\"keyword\">in</span> private.key -check</span><br><span class=\"line\"><span class=\"comment\">#检查证书是否过期(确保 "notBefore" 小于当前日期,"notAfter" 大于当前日期)</span></span><br><span class=\"line\">openssl x509 -<span class=\"keyword\">in</span> private.crt -noout -dates</span><br><span class=\"line\"><span class=\"comment\">#查看证书链</span></span><br><span class=\"line\">openssl x509 -<span class=\"keyword\">in</span> private.crt -noout -issuer -subject</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"Nginx",
|
||
"https",
|
||
"SSL",
|
||
"证书"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2024/01/03/Centos7%E7%BC%96%E8%AF%91%E5%8D%87%E7%BA%A7nginx/",
|
||
"url": "https://hitoli.com/2024/01/03/Centos7%E7%BC%96%E8%AF%91%E5%8D%87%E7%BA%A7nginx/",
|
||
"title": "Centos7编译升级nginx",
|
||
"date_published": "2024-01-03T09:40:00.000Z",
|
||
"content_html": "<h4 id=\"配置\"><a class=\"anchor\" href=\"#配置\">#</a> 配置</h4>\n<p>./configure<br />\n# 安装目录<br />\n --prefix=/usr/local/nginx<br />\n#nginx 运行时的非特权用户<br />\n --user=nginx<br />\n#nginx 运行时的非特权用户组<br />\n --group=nginx<br />\n#nginx 运行时 pid 的目录<br />\n --pid-path=/var/run/nginx/nginx.pid<br />\n# 锁定文件目录,防止误操作,或其他使用<br />\n --lock-path=/var/lock/nginx.lock<br />\n#nginx 错误日志目录<br />\n --error-log-path=/var/log/nginx/error.log<br />\n#nginx 运行日志目录<br />\n --http-log-path=/var/log/nginx/access.log<br />\n# 开启 gz 模块,压缩静态页面<br />\n --with-http_gzip_static_module<br />\n--with-http_gunzip_module<br />\n# 开启 ssl 模块<br />\n --with-http_ssl_module<br />\n# 开启 http2 模块<br />\n --with-http_v2_module<br />\n#openssl 目录<br />\n --with-openssl=/home/openssl-3.2.0<br />\n#nginx 的客户端状态<br />\n --with-http_stub_status_module<br />\n--with-http_realip_module<br />\n# 设定客户端请求的临时目录<br />\n --http-client-body-temp-path=/usr/local/nginx/client<br />\n# 设定 http 代理临时目录<br />\n --http-proxy-temp-path=/usr/local/nginx/proxy<br />\n# 设定 fastcgi 临时目录<br />\n --http-fastcgi-temp-path=/usr/local/nginx/fastcgi<br />\n# 设定 uwsgi 临时目录<br />\n --http-uwsgi-temp-path=/usr/local/nginx/uwsgi<br />\n# 设定 scgi 临时目录<br />\n --http-scgi-temp-path=/usr/local/nginx/scgi<br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-openssl=/home/openssl-3.2.0</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"编译\"><a class=\"anchor\" href=\"#编译\">#</a> 编译</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">make(不要make install)</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"备份\"><a class=\"anchor\" href=\"#备份\">#</a> 备份</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">cp</span> /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"更新\"><a class=\"anchor\" href=\"#更新\">#</a> 更新</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#关闭nginx</span></span><br><span class=\"line\">nginx -s stop</span><br><span class=\"line\"><span class=\"comment\">#更新nginx</span></span><br><span class=\"line\"><span class=\"built_in\">cp</span> /root/nginx-1.24.0/objs/nginx /usr/local/nginx/sbin/</span><br><span class=\"line\"><span class=\"comment\">#启动nginx</span></span><br><span class=\"line\">nginx</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"Nginx",
|
||
"CentOS"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/12/24/Docker-desktop%E9%83%A8%E7%BD%B2nacos/",
|
||
"url": "https://hitoli.com/2023/12/24/Docker-desktop%E9%83%A8%E7%BD%B2nacos/",
|
||
"title": "Docker desktop部署nacos",
|
||
"date_published": "2023-12-24T13:37:00.000Z",
|
||
"content_html": "<h4 id=\"创建数据库\"><a class=\"anchor\" href=\"#创建数据库\">#</a> 创建数据库</h4>\n<p><figure class=\"highlight sql\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">create</span> database nacos</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"下载初始化脚本\"><a class=\"anchor\" href=\"#下载初始化脚本\">#</a> 下载初始化脚本</h4>\n<p><span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2FsaWJhYmEvbmFjb3MvYmxvYi9tYXN0ZXIvZGlzdHJpYnV0aW9uL2NvbmYvbXlzcWwtc2NoZW1hLnNxbA==\">脚本文件</span></p>\n<h4 id=\"以普通模式启动获取数据\"><a class=\"anchor\" href=\"#以普通模式启动获取数据\">#</a> 以普通模式启动获取数据</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">docker run -d --restart=always --name=<span class=\"string\">"nacos"</span> -e MODE=standalone -p 8848:8848 -p 9848:9848 nacos/nacos-server:latest</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"进入容器内修改文件权限\"><a class=\"anchor\" href=\"#进入容器内修改文件权限\">#</a> 进入容器内修改文件权限</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">chmod</span> 777 /home/nacos/conf</span><br><span class=\"line\"><span class=\"built_in\">chmod</span> 777 /home/nacos/data</span><br><span class=\"line\"><span class=\"built_in\">chmod</span> 777 /home/nacos/logs</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"拷贝文件到本地\"><a class=\"anchor\" href=\"#拷贝文件到本地\">#</a> 拷贝文件到本地</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">docker <span class=\"built_in\">cp</span> nacos:/home/nacos/conf D:\\docker\\nacos\\data\\</span><br><span class=\"line\">docker <span class=\"built_in\">cp</span> nacos:/home/nacos/data D:\\docker\\nacos\\data\\</span><br><span class=\"line\">docker <span class=\"built_in\">cp</span> nacos:/home/nacos/logs D:\\docker\\nacos\\data\\</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"创建正式容器\"><a class=\"anchor\" href=\"#创建正式容器\">#</a> 创建正式容器</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">docker run -d --name nacos --restart=always --network my-net -p 8848:8848 -p 9848:9848 -p 9849:9849 -e MODE=standalone --privileged=<span class=\"literal\">true</span> -e SPRING_DATASOURCE_PLATFORM=mysql -e MYSQL_SERVICE_HOST=mysql地址 -e MYSQL_SERVICE_PORT=mysql端口 -e MYSQL_SERVICE_USER=mysql用户名 -e MYSQL_SERVICE_PASSWORD=mysql密码 -e MYSQL_SERVICE_DB_NAME=nacos -e TIME_ZONE=<span class=\"string\">'Asia/Shanghai'</span> -v D:\\docker\\nacos\\data\\logs:/home/nacos/logs -v D:\\docker\\nacos\\data\\data:/home/nacos/data -v D:\\docker\\nacos\\data\\conf:/home/nacos/conf nacos/nacos-server:latest</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"Windows",
|
||
"工具",
|
||
"docker",
|
||
"nacos"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/12/02/fastjson%E5%BA%8F%E5%88%97%E5%8C%96%E5%8E%BB%E9%99%A4%E7%A9%BA%E5%AD%97%E7%AC%A6%E4%B8%B2/",
|
||
"url": "https://hitoli.com/2023/12/02/fastjson%E5%BA%8F%E5%88%97%E5%8C%96%E5%8E%BB%E9%99%A4%E7%A9%BA%E5%AD%97%E7%AC%A6%E4%B8%B2/",
|
||
"title": "fastjson序列化去除空字符串属性",
|
||
"date_published": "2023-12-02T13:47:00.000Z",
|
||
"content_html": "<p>今天在把对象转为 json 时需要去除 key 或者 value 为 null 或空字符串的属性,特此记录一下后续好复用。<br />\n<figure class=\"highlight java\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">public</span> <span class=\"keyword\">static</span> String <span class=\"title function_\">toJSONString</span><span class=\"params\">(Object object)</span> {</span><br><span class=\"line\"> SerializerFeature[] serializerFeatures = <span class=\"keyword\">new</span> <span class=\"title class_\">SerializerFeature</span>[] {</span><br><span class=\"line\"> <span class=\"comment\">//格式化时间</span></span><br><span class=\"line\"> SerializerFeature.WriteDateUseDateFormat</span><br><span class=\"line\"> };</span><br><span class=\"line\"> <span class=\"keyword\">return</span> JSON.toJSONString(object, <span class=\"keyword\">new</span> <span class=\"title class_\">ValueFilter</span>() {</span><br><span class=\"line\"> <span class=\"meta\">@Override</span></span><br><span class=\"line\"> <span class=\"keyword\">public</span> Object <span class=\"title function_\">process</span><span class=\"params\">(Object object, String name, Object value)</span> {</span><br><span class=\"line\"> <span class=\"comment\">// 如果名称或者值为null或空字符串,则不序列化该属性</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span> (name == <span class=\"literal\">null</span> || (name <span class=\"keyword\">instanceof</span> String && ((String) name).isEmpty()) ||</span><br><span class=\"line\"> value == <span class=\"literal\">null</span> || (value <span class=\"keyword\">instanceof</span> String && ((String) value).isEmpty())) {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> value;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }, serializerFeatures);</span><br><span class=\"line\"> }</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"fastjson"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/11/03/Linux%E4%B8%8B%E5%BF%AB%E9%80%9F%E9%83%A8%E7%BD%B2SpringBoot%E9%A1%B9%E7%9B%AE%E7%9A%84%E8%84%9A%E6%9C%AC/",
|
||
"url": "https://hitoli.com/2023/11/03/Linux%E4%B8%8B%E5%BF%AB%E9%80%9F%E9%83%A8%E7%BD%B2SpringBoot%E9%A1%B9%E7%9B%AE%E7%9A%84%E8%84%9A%E6%9C%AC/",
|
||
"title": "Linux下快速部署SpringBoot项目的脚本",
|
||
"date_published": "2023-11-03T13:35:00.000Z",
|
||
"content_html": "<h4 id=\"windows部署脚本\"><a class=\"anchor\" href=\"#windows部署脚本\">#</a> Windows 部署脚本</h4>\n<p>只需要把 jar 和 yml 跟脚本放在同一目录下即可快速启动。</p>\n<div class=\"note info\">\n<p>拷贝以下代码放入 txt 文本,<span class=\"exturl\" data-url=\"aHR0cDovL3huLS1zdGFydC1kcTFoNzE2YXVzOGFldHcuc2g=\">然后改为 start.sh</span></p>\n</div>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#!/bin/bash</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">export</span> CLOUD_HOME=`<span class=\"built_in\">pwd</span>`</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\"># 获取当前目录中的第一个JAR文件的名称</span></span><br><span class=\"line\">jar_file=$(find . -maxdepth 1 -<span class=\"built_in\">type</span> f -name <span class=\"string\">"*.jar"</span> | <span class=\"built_in\">head</span> -n 1)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> [ -n <span class=\"string\">"<span class=\"variable\">$jar_file</span>"</span> ]; <span class=\"keyword\">then</span></span><br><span class=\"line\"> jar_file=<span class=\"variable\">${jar_file#./}</span></span><br><span class=\"line\"> <span class=\"comment\">#echo "JAR文件的名称是: $jar_file"</span></span><br><span class=\"line\"> jar_file_name=$(<span class=\"built_in\">basename</span> <span class=\"string\">"<span class=\"variable\">$jar_file</span>"</span> .jar)</span><br><span class=\"line\"><span class=\"keyword\">else</span></span><br><span class=\"line\"> <span class=\"built_in\">echo</span> <span class=\"string\">"当前目录没有JAR文件."</span></span><br><span class=\"line\"> <span class=\"built_in\">exit</span></span><br><span class=\"line\"><span class=\"keyword\">fi</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\"># 获取当前目录中的第一个yml文件的名称</span></span><br><span class=\"line\">yml_file=$(find . -maxdepth 1 -<span class=\"built_in\">type</span> f -name <span class=\"string\">"*.yml"</span> | <span class=\"built_in\">head</span> -n 1)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> [ -n <span class=\"string\">"<span class=\"variable\">$yml_file</span>"</span> ]; <span class=\"keyword\">then</span></span><br><span class=\"line\"> yml_file=<span class=\"variable\">${yml_file#./}</span></span><br><span class=\"line\"> <span class=\"comment\">#echo "YML文件的名称是: $yml_file"</span></span><br><span class=\"line\"><span class=\"keyword\">else</span></span><br><span class=\"line\"> <span class=\"built_in\">echo</span> <span class=\"string\">"当前目录中没有YML文件."</span></span><br><span class=\"line\"><span class=\"keyword\">fi</span></span><br><span class=\"line\"></span><br><span class=\"line\">pids=$(ps -ef | grep java | grep <span class=\"variable\">$jar_file_name</span> | grep -v grep | awk <span class=\"string\">'{print $2}'</span>)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span> pid <span class=\"keyword\">in</span> <span class=\"variable\">$pids</span>; <span class=\"keyword\">do</span></span><br><span class=\"line\"> <span class=\"built_in\">echo</span> <span class=\"string\">"<span class=\"variable\">$jar_file_name</span> is running, pid="</span><span class=\"variable\">$pid</span></span><br><span class=\"line\"> <span class=\"built_in\">exit</span> 0</span><br><span class=\"line\"><span class=\"keyword\">done</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">"<span class=\"variable\">$jar_file_name</span> is pedding..."</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">sleep</span> 3</span><br><span class=\"line\"></span><br><span class=\"line\">JAVA_OPTS=<span class=\"string\">"-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8"</span></span><br><span class=\"line\">JAVA_OPTS=<span class=\"string\">"<span class=\"variable\">$JAVA_OPTS</span> -Dsun.jnu.encoding=UTF8 -Xms512m -Xmx1024m"</span></span><br><span class=\"line\">JAVA_OPTS=<span class=\"string\">"<span class=\"variable\">$JAVA_OPTS</span> -Dpid.path=<span class=\"variable\">$CLOUD_HOME</span>/temp -Dspring.config.additional-location=<span class=\"variable\">$CLOUD_HOME</span>/<span class=\"variable\">$yml_file</span>"</span></span><br><span class=\"line\">JAVA_OPTS=<span class=\"string\">"<span class=\"variable\">$JAVA_OPTS</span> -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5007"</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">nohup</span> java <span class=\"variable\">$JAVA_OPTS</span> -jar <span class=\"variable\">$CLOUD_HOME</span>/<span class=\"variable\">$jar_file</span> >/dev/null 2> <span class=\"variable\">$CLOUD_HOME</span>/<span class=\"variable\">$jar_file_name</span>.run &</span><br><span class=\"line\"><span class=\"comment\">#nohup java $JAVA_OPTS -jar $CLOUD_HOME/$jar_file > $CLOUD_HOME/$jar_file_name.run 2>&1 &</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">"<span class=\"variable\">$jar_file_name</span> started."</span></span><br></pre></td></tr></table></figure></p>\n<div class=\"note info\">\n<p>拷贝以下代码放入 txt 文本,<span class=\"exturl\" data-url=\"aHR0cDovL3huLS1zdG9wLXVoNWZ0MjJhOWs1YXBidS5zaA==\">然后改为 stop.sh</span></p>\n</div>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#!/bin/bash</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">export</span> CLOUD_HOME=`<span class=\"built_in\">pwd</span>`</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\"># 获取当前目录中的第一个JAR文件的名称</span></span><br><span class=\"line\">jar_file=$(find . -maxdepth 1 -<span class=\"built_in\">type</span> f -name <span class=\"string\">"*.jar"</span> | <span class=\"built_in\">head</span> -n 1)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> [ -n <span class=\"string\">"<span class=\"variable\">$jar_file</span>"</span> ]; <span class=\"keyword\">then</span></span><br><span class=\"line\"> jar_file=<span class=\"variable\">${jar_file#./}</span></span><br><span class=\"line\"> <span class=\"comment\">#echo "JAR文件的名称是: $jar_file"</span></span><br><span class=\"line\"> jar_file_name=$(<span class=\"built_in\">basename</span> <span class=\"string\">"<span class=\"variable\">$jar_file</span>"</span> .jar)</span><br><span class=\"line\"><span class=\"keyword\">else</span></span><br><span class=\"line\"> <span class=\"built_in\">echo</span> <span class=\"string\">"当前目录没有JAR文件."</span></span><br><span class=\"line\"> <span class=\"built_in\">exit</span></span><br><span class=\"line\"><span class=\"keyword\">fi</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\"># 获取当前目录中的第一个yml文件的名称</span></span><br><span class=\"line\">yml_file=$(find . -maxdepth 1 -<span class=\"built_in\">type</span> f -name <span class=\"string\">"*.yml"</span> | <span class=\"built_in\">head</span> -n 1)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> [ -n <span class=\"string\">"<span class=\"variable\">$yml_file</span>"</span> ]; <span class=\"keyword\">then</span></span><br><span class=\"line\"> yml_file=<span class=\"variable\">${yml_file#./}</span></span><br><span class=\"line\"> <span class=\"comment\">#echo "YML文件的名称是: $yml_file"</span></span><br><span class=\"line\"><span class=\"keyword\">else</span></span><br><span class=\"line\"> <span class=\"built_in\">echo</span> <span class=\"string\">"当前目录中没有YML文件."</span></span><br><span class=\"line\"><span class=\"keyword\">fi</span></span><br><span class=\"line\"></span><br><span class=\"line\">pids=$(ps -ef | grep java | grep <span class=\"variable\">$jar_file_name</span> | grep -v grep | awk <span class=\"string\">'{print $2}'</span>)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span> pid <span class=\"keyword\">in</span> <span class=\"variable\">$pids</span>; <span class=\"keyword\">do</span></span><br><span class=\"line\"> <span class=\"built_in\">kill</span> -9 <span class=\"variable\">$pid</span></span><br><span class=\"line\"><span class=\"keyword\">done</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">"<span class=\"variable\">$jar_file_name</span> is stopping..."</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">sleep</span> 5</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">"<span class=\"variable\">$jar_file_name</span> stopped."</span></span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"Linux",
|
||
"Shell",
|
||
"Linux",
|
||
"SpringBoot",
|
||
"快速部署",
|
||
"bash"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/10/29/%E7%BB%99%E6%88%91%E7%9A%84%E8%80%81%E7%AC%94%E8%AE%B0%E6%9C%AC%E6%B8%85%E7%90%86%E7%81%B0%E5%B0%98/",
|
||
"url": "https://hitoli.com/2023/10/29/%E7%BB%99%E6%88%91%E7%9A%84%E8%80%81%E7%AC%94%E8%AE%B0%E6%9C%AC%E6%B8%85%E7%90%86%E7%81%B0%E5%B0%98/",
|
||
"title": "给我的老笔记本清理灰尘",
|
||
"date_published": "2023-10-29T12:41:00.000Z",
|
||
"content_html": "<p>今天闲着无事就把我的老笔记本拆了,清理了一下灰尘。笔记本已经 10 多年了,中间加过内存,换过固态硬盘。清理一下还能发挥它的余热!<br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/c7b84a3d703a.jpg\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/fd2e099d875d.jpg\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/0fea7641ccde.jpg\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/73c63c1438a8.jpg\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/4c5d526af3e7.jpg\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/4b9bcbecbca3.jpg\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/29/38ffc2e9639f.jpg\" alt=\"\" /></p>\n",
|
||
"tags": [
|
||
"生活",
|
||
"日常记录",
|
||
"笔记本",
|
||
"DELL"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/10/28/Windows%E4%B8%8B%E5%BF%AB%E9%80%9F%E9%83%A8%E7%BD%B2SpringBoot%E9%A1%B9%E7%9B%AE%E7%9A%84%E6%89%B9%E5%A4%84%E7%90%86/",
|
||
"url": "https://hitoli.com/2023/10/28/Windows%E4%B8%8B%E5%BF%AB%E9%80%9F%E9%83%A8%E7%BD%B2SpringBoot%E9%A1%B9%E7%9B%AE%E7%9A%84%E6%89%B9%E5%A4%84%E7%90%86/",
|
||
"title": "Windows下快速部署SpringBoot项目的批处理",
|
||
"date_published": "2023-10-28T11:56:00.000Z",
|
||
"content_html": "<h4 id=\"windows部署脚本\"><a class=\"anchor\" href=\"#windows部署脚本\">#</a> Windows 部署脚本</h4>\n<p>只需要把 jar 和 yml 跟批处理放在同一目录下即可点击快速启动。启动后再次点击会关闭上次启动的窗口并重新启动。</p>\n<div class=\"note info\">\n<p>拷贝以下代码放入 txt 文本,然后改为 start.bat</p>\n</div>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br><span class=\"line\">56</span><br><span class=\"line\">57</span><br><span class=\"line\">58</span><br><span class=\"line\">59</span><br><span class=\"line\">60</span><br><span class=\"line\">61</span><br><span class=\"line\">62</span><br><span class=\"line\">63</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">@ECHO OFF</span><br><span class=\"line\">setlocal enabledelayedexpansion</span><br><span class=\"line\"></span><br><span class=\"line\">REM 关闭上次进程</span><br><span class=\"line\">SET <span class=\"string\">"pidFile=pid.txt"</span></span><br><span class=\"line\"><span class=\"keyword\">if</span> exist <span class=\"string\">"%pidFile%"</span> (</span><br><span class=\"line\">\t<span class=\"keyword\">for</span> /f <span class=\"string\">"usebackq"</span> %%a <span class=\"keyword\">in</span> (<span class=\"string\">"pid.txt"</span>) <span class=\"keyword\">do</span> (</span><br><span class=\"line\">\t\t<span class=\"built_in\">set</span> PID=%%a</span><br><span class=\"line\">\t)</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> not <span class=\"string\">"!PID!"</span>==<span class=\"string\">""</span> (</span><br><span class=\"line\">\t\ttaskkill /F /T /PID !pid!</span><br><span class=\"line\">\t\tdel pid.txt</span><br><span class=\"line\">\t)</span><br><span class=\"line\">)</span><br><span class=\"line\"></span><br><span class=\"line\">REM 存储当前进程</span><br><span class=\"line\"><span class=\"keyword\">for</span> /f %%i <span class=\"keyword\">in</span> (<span class=\"string\">'wmic process where "name='</span>cmd.exe<span class=\"string\">' and CommandLine like '</span>%%<scriptname>.bat%%<span class=\"string\">'" get ParentProcessId ^| findstr /r "[0-9]"'</span>) <span class=\"keyword\">do</span> <span class=\"built_in\">set</span> pid=%%i</span><br><span class=\"line\"><span class=\"built_in\">echo</span> %PID% > pid.txt</span><br><span class=\"line\"></span><br><span class=\"line\">REM 设置title</span><br><span class=\"line\"><span class=\"keyword\">for</span> /f <span class=\"string\">"tokens=2"</span> %%i <span class=\"keyword\">in</span> (<span class=\"string\">'chcp'</span>) <span class=\"keyword\">do</span> <span class=\"built_in\">set</span> codepage=%%i</span><br><span class=\"line\">chcp 65001 > nul</span><br><span class=\"line\">title 我的SpringBoot项目</span><br><span class=\"line\">chcp %codepage% > nul</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">cd</span> %~dp0</span><br><span class=\"line\"></span><br><span class=\"line\">REM 获取jar</span><br><span class=\"line\"><span class=\"built_in\">set</span> <span class=\"string\">"jarFile="</span></span><br><span class=\"line\"><span class=\"keyword\">for</span> %%i <span class=\"keyword\">in</span> (*.jar) <span class=\"keyword\">do</span> (</span><br><span class=\"line\"> <span class=\"keyword\">if</span> not defined jarFile (</span><br><span class=\"line\"> <span class=\"built_in\">set</span> <span class=\"string\">"jarFile=%%i"</span></span><br><span class=\"line\"> )</span><br><span class=\"line\">)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> not defined jarFile (</span><br><span class=\"line\"> <span class=\"built_in\">echo</span> not find jar</span><br><span class=\"line\"> pause</span><br><span class=\"line\"> <span class=\"built_in\">exit</span></span><br><span class=\"line\">)</span><br><span class=\"line\"></span><br><span class=\"line\">SET JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8</span><br><span class=\"line\"><span class=\"built_in\">set</span> JAVA_OPTS=%JAVA_OPTS% -Dsun.jnu.encoding=UTF8 -Xms512m -Xmx1024m</span><br><span class=\"line\"><span class=\"built_in\">set</span> JAVA_OPTS=%JAVA_OPTS% -agentlib:jdwp=transport=dt_socket,server=y,<span class=\"built_in\">suspend</span>=n,address=5007</span><br><span class=\"line\"><span class=\"built_in\">set</span> JAVA_OPTS=%JAVA_OPTS% -Dpid.path=./temp</span><br><span class=\"line\"></span><br><span class=\"line\">REM 获取yml</span><br><span class=\"line\"><span class=\"built_in\">set</span> <span class=\"string\">"ymlFile="</span></span><br><span class=\"line\"><span class=\"keyword\">for</span> %%i <span class=\"keyword\">in</span> (*.yml) <span class=\"keyword\">do</span> (</span><br><span class=\"line\"> <span class=\"keyword\">if</span> not defined ymlFile (</span><br><span class=\"line\"> <span class=\"built_in\">set</span> <span class=\"string\">"ymlFile=%%i"</span></span><br><span class=\"line\"> )</span><br><span class=\"line\">)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> defined ymlFile (</span><br><span class=\"line\">\t<span class=\"built_in\">set</span> JAVA_OPTS=%JAVA_OPTS% -Dspring.config.additional-location=!ymlFile!</span><br><span class=\"line\">) <span class=\"keyword\">else</span> (</span><br><span class=\"line\">\t<span class=\"built_in\">echo</span> not find yml</span><br><span class=\"line\">)</span><br><span class=\"line\"></span><br><span class=\"line\">REM 启动服务</span><br><span class=\"line\">java %JAVA_OPTS% -jar !jarFile!</span><br><span class=\"line\">pause</span><br></pre></td></tr></table></figure></p>\n<div class=\"note info\">\n<p>拷贝以下代码放入 txt 文本,然后改为 stop.bat</p>\n</div>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">@ECHO OFF</span><br><span class=\"line\">setlocal enabledelayedexpansion</span><br><span class=\"line\"></span><br><span class=\"line\">REM 关闭上次进程</span><br><span class=\"line\">SET <span class=\"string\">"pidFile=pid.txt"</span></span><br><span class=\"line\"><span class=\"keyword\">if</span> exist <span class=\"string\">"%pidFile%"</span> (</span><br><span class=\"line\">\t<span class=\"keyword\">for</span> /f <span class=\"string\">"usebackq"</span> %%a <span class=\"keyword\">in</span> (<span class=\"string\">"pid.txt"</span>) <span class=\"keyword\">do</span> (</span><br><span class=\"line\">\t\t<span class=\"built_in\">set</span> PID=%%a</span><br><span class=\"line\">\t)</span><br><span class=\"line\">\t<span class=\"keyword\">if</span> not <span class=\"string\">"!PID!"</span>==<span class=\"string\">""</span> (</span><br><span class=\"line\">\t\ttaskkill /F /T /PID !pid!</span><br><span class=\"line\">\t\tdel pid.txt</span><br><span class=\"line\">\t)</span><br><span class=\"line\">)</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">exit</span></span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"Windows",
|
||
"工具",
|
||
"SpringBoot",
|
||
"快速部署",
|
||
"Bat",
|
||
"批处理"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/10/28/Centos%E6%8C%82%E8%BD%BD%E6%96%B0%E7%A1%AC%E7%9B%98/",
|
||
"url": "https://hitoli.com/2023/10/28/Centos%E6%8C%82%E8%BD%BD%E6%96%B0%E7%A1%AC%E7%9B%98/",
|
||
"title": "Centos挂载新硬盘",
|
||
"date_published": "2023-10-28T11:26:00.000Z",
|
||
"content_html": "<h4 id=\"查看磁盘信息\"><a class=\"anchor\" href=\"#查看磁盘信息\">#</a> 查看磁盘信息</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">fdisk -l 查看当前磁盘的分区情况</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/4dc953fc5a5e.png\" alt=\"\" /><br />\n 可从图中获取以下信息:<br />\n/dev/vdb 数据盘容量为 60GB,包含 MBR 分区 /dev/vdb1,容量为 50GB。<br />\n/dev/vdc 数据盘容量为 60GB,包含 GPT 分区 /dev/vdc1,容量为 50GB。</p>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">df</span> -TH 分区的文件系统类型</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/8996c9620632.png\" alt=\"\" /><br />\n 可从图中获取以下信息:<br />\n/dev/vdb1 文件系统类型为 ext4,已挂载至 /mnt/disk1。<br />\n/dev/vdc1 文件系统类型为 xfs,已挂载至 /mnt/disk2。<br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">fdisk /dev/vdb 查看新磁盘情况</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/0f1237aef57b.png\" alt=\"\" /><br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">lsbl 查看分区情况</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/8071a3832e29.png\" alt=\"\" /></p>\n<h4 id=\"挂载新硬盘\"><a class=\"anchor\" href=\"#挂载新硬盘\">#</a> 挂载新硬盘</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">mkfs.ext4 /dev/vdb 格式化磁盘</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/9353dd85579f.png\" alt=\"\" /><br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">cd</span> /mnt</span><br><span class=\"line\"><span class=\"built_in\">mkdir</span> data 新建挂载点</span><br><span class=\"line\">mount /dev/vdb /mnt/data 挂载</span><br></pre></td></tr></table></figure><br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">df</span> -h 查看挂载情况</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/ead4f7b1323f.png\" alt=\"\" /><br />\n 查看 UUID 有三种方式:<br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">blkid</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/236412bc1e3f.png\" alt=\"\" /><br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">lsblk -f</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/35d7182c5647.png\" alt=\"\" /><br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">ll /dev/disk/by-uuid/</span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/10/28/3f9d4f69d8ea.png\" alt=\"\" /><br />\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">设置自动挂载:</span><br><span class=\"line\"><span class=\"built_in\">echo</span> <span class=\"string\">"UUID=c8ac09ca-fd4d-4511-bd2c-4fdf96f08168 /data ext4 defaults 0 0"</span> >> /etc/fstab</span><br><span class=\"line\">自动挂载/etc/fstab里面的东西</span><br><span class=\"line\">mount -a</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"临时卸载\"><a class=\"anchor\" href=\"#临时卸载\">#</a> 临时卸载</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">umount /dev/vdb 重启机器之后又恢复到挂载状态</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"永久卸载\"><a class=\"anchor\" href=\"#永久卸载\">#</a> 永久卸载</h4>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">vim /etc/fstab 把添加的磁盘信息删除即可。</span><br></pre></td></tr></table></figure></p>\n",
|
||
"tags": [
|
||
"Linux",
|
||
"Centos",
|
||
"Centos",
|
||
"Linux",
|
||
"Mount"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/09/09/squid-stunnel-%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91/",
|
||
"url": "https://hitoli.com/2023/09/09/squid-stunnel-%E7%A7%91%E5%AD%A6%E4%B8%8A%E7%BD%91/",
|
||
"title": "squid+stunnel 科学上网",
|
||
"date_published": "2023-09-09T08:48:00.000Z",
|
||
"content_html": "<h4 id=\"前言\"><a class=\"anchor\" href=\"#前言\">#</a> 前言</h4>\n<p>科学上网的方法有多种,有很多第三方提供的免费方案,这些方案优缺点暂时不予讨论。实际工作生活中还是会有需要自己搭建的情况,这次介绍的是使用 squid+stunnel 方案进行搭建。</p>\n<h4 id=\"准备\"><a class=\"anchor\" href=\"#准备\">#</a> 准备</h4>\n<p>一台可以访问外网的服务器,如香港的云主机并安装 Ubuntu 系统。</p>\n<h5 id=\"squid部分\"><a class=\"anchor\" href=\"#squid部分\">#</a> squid 部分</h5>\n<ul>\n<li>1、安装</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">apt-get install -y squid</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>2、配置</li>\n</ul>\n<div class=\"note info\">\n<p>生成用户文件</p>\n</div>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">apt-get install apache2-utils</span><br><span class=\"line\">htpasswd -c /etc/squid/squid_user.txt 用户名</span><br></pre></td></tr></table></figure></p>\n<div class=\"note info\">\n<p>修改 squid 配置<br />\n 1、直接修改 /etc/squid/squid.conf 文件<br />\n 2、修改 /etc/squid/conf.d/debian.conf 文件<br />\n两种方式都一样,在底部加入以下代码</p>\n</div>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br><span class=\"line\">38</span><br><span class=\"line\">39</span><br><span class=\"line\">40</span><br><span class=\"line\">41</span><br><span class=\"line\">42</span><br><span class=\"line\">43</span><br><span class=\"line\">44</span><br><span class=\"line\">45</span><br><span class=\"line\">46</span><br><span class=\"line\">47</span><br><span class=\"line\">48</span><br><span class=\"line\">49</span><br><span class=\"line\">50</span><br><span class=\"line\">51</span><br><span class=\"line\">52</span><br><span class=\"line\">53</span><br><span class=\"line\">54</span><br><span class=\"line\">55</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#dns服务器地址</span></span><br><span class=\"line\"><span class=\"string\">dns_nameservers</span> <span class=\"number\">8.8</span><span class=\"number\">.8</span><span class=\"number\">.8</span> <span class=\"number\">8.8</span><span class=\"number\">.4</span><span class=\"number\">.4</span></span><br><span class=\"line\"><span class=\"string\">dns_v4_first</span> <span class=\"string\">on</span></span><br><span class=\"line\"><span class=\"comment\"># 监听端口</span></span><br><span class=\"line\"><span class=\"string\">http_port</span> <span class=\"number\">3128</span></span><br><span class=\"line\"><span class=\"comment\"># 定义squid密码文件与ncsa_auth文件位置</span></span><br><span class=\"line\"><span class=\"string\">auth_param</span> <span class=\"string\">basic</span> <span class=\"string\">program</span> <span class=\"string\">/usr/lib/squid/basic_ncsa_auth</span> <span class=\"string\">/etc/squid/squid_user.txt</span></span><br><span class=\"line\"><span class=\"comment\"># 认证进程的数量</span></span><br><span class=\"line\"><span class=\"string\">auth_param</span> <span class=\"string\">basic</span> <span class=\"string\">children</span> <span class=\"number\">15</span></span><br><span class=\"line\"><span class=\"comment\"># 认证对话框显示提示信息</span></span><br><span class=\"line\"><span class=\"string\">auth_param</span> <span class=\"string\">basic</span> <span class=\"string\">realm</span> <span class=\"string\">Squid</span> <span class=\"string\">proxy-caching</span> <span class=\"string\">web</span> <span class=\"string\">server</span></span><br><span class=\"line\"><span class=\"comment\"># 认证有效期</span></span><br><span class=\"line\"><span class=\"string\">auth_param</span> <span class=\"string\">basic</span> <span class=\"string\">credentialsttl</span> <span class=\"number\">24</span> <span class=\"string\">hours</span></span><br><span class=\"line\"><span class=\"comment\"># 是否区分用户名大小,off为不区分</span></span><br><span class=\"line\"><span class=\"string\">auth_param</span> <span class=\"string\">basic</span> <span class=\"string\">casesensitive</span> <span class=\"string\">off</span></span><br><span class=\"line\"><span class=\"comment\"># 对定义的squid_user文件内的用户开启认证访问</span></span><br><span class=\"line\"><span class=\"string\">acl</span> <span class=\"string\">用户名</span> <span class=\"string\">proxy_auth</span> <span class=\"string\">REQUIRED</span></span><br><span class=\"line\"><span class=\"comment\"># 允许squid_user文件内用户进行代理</span></span><br><span class=\"line\"><span class=\"string\">http_access</span> <span class=\"string\">allow</span> <span class=\"string\">用户名</span></span><br><span class=\"line\"><span class=\"comment\"># 顺序匹配,最后添加拒绝所有未允许的规则。不添加会发现,未匹配到的规则会被放行</span></span><br><span class=\"line\"><span class=\"string\">http_access</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"comment\"># 缓存设置</span></span><br><span class=\"line\"><span class=\"string\">cache_dir</span> <span class=\"string\">ufs</span> <span class=\"string\">/var/spool/squid</span> <span class=\"number\">100</span> <span class=\"number\">16</span> <span class=\"number\">256</span> <span class=\"string\">read-only</span></span><br><span class=\"line\"><span class=\"string\">cache_mem</span> <span class=\"number\">0</span> <span class=\"string\">MB</span></span><br><span class=\"line\"><span class=\"string\">coredump_dir</span> <span class=\"string\">/var/spool/squid</span></span><br><span class=\"line\"><span class=\"comment\"># 配置高匿,不允许设置任何多余头信息,保持原请求header。</span></span><br><span class=\"line\"><span class=\"string\">header_access</span> <span class=\"string\">Via</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"string\">header_access</span> <span class=\"string\">X-Forwarded-For</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"string\">header_access</span> <span class=\"string\">Server</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"string\">header_access</span> <span class=\"string\">X-Cache</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"string\">header_access</span> <span class=\"string\">X-Cache-Lookup</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"string\">forwarded_for</span> <span class=\"string\">off</span></span><br><span class=\"line\"><span class=\"string\">via</span> <span class=\"string\">off</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\"># logs相关配置</span></span><br><span class=\"line\"><span class=\"string\">emulate_httpd_log</span> <span class=\"string\">on</span></span><br><span class=\"line\"><span class=\"string\">logformat</span> <span class=\"string\">squid</span> <span class=\"string\">%{X-Forwarded-For}>h</span> <span class=\"string\">%ui</span> <span class=\"string\">%un</span> [<span class=\"string\">%tl</span>] <span class=\"string\">"%rm %ru HTTP/%rv"</span> <span class=\"string\">%Hs</span> <span class=\"string\">%<st</span> <span class=\"string\">"<span class=\"template-variable\">%{Referer}</span>>h"</span> <span class=\"string\">"<span class=\"template-variable\">%{User-Agent}</span>>h"</span> <span class=\"string\">%Ss:%Sh</span></span><br><span class=\"line\"><span class=\"string\">access_log</span> <span class=\"string\">/var/log/squid/access.log</span> <span class=\"string\">squid</span></span><br><span class=\"line\"><span class=\"string\">cache_log</span> <span class=\"string\">/var/log/squid/cache.log</span></span><br><span class=\"line\"><span class=\"string\">cache_store_log</span> <span class=\"string\">/var/log/squid/store.log</span></span><br><span class=\"line\"><span class=\"string\">logfile_rotate</span> <span class=\"number\">20</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">########新版########</span></span><br><span class=\"line\"><span class=\"comment\">#Hide client ip</span></span><br><span class=\"line\"><span class=\"string\">forwarded_for</span> <span class=\"string\">delete</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">#Turn off via header</span></span><br><span class=\"line\"><span class=\"string\">via</span> <span class=\"string\">off</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">#Deny request for original source of a request</span></span><br><span class=\"line\"><span class=\"string\">follow_x_forwarded_for</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">#See below</span></span><br><span class=\"line\"><span class=\"string\">request_header_access</span> <span class=\"string\">X-Forwarded-For</span> <span class=\"string\">deny</span> <span class=\"string\">all</span></span><br><span class=\"line\"><span class=\"comment\">########新版########</span></span><br></pre></td></tr></table></figure></p>\n<div class=\"note primary\">\n<p>至次已经可以通过填写安装 squid 的服务器 ip 加端口 3128 加用户名密码进行代理访问了(通过访问<span class=\"blue\"><span class=\"exturl\" data-url=\"aHR0cHM6Ly93d3cuaXAuY24v\"> https://www.ip.cn/</span></span> 查看 ip 就会发现自己的出口 ip 已经变成了 squid 服务器的 ip 了)。但是要想科学上网还必须对代理的数据进行加密,否则访问外网还是会被我国的长城防火墙阻挡,所以还需要安装 stunnel 来实现此目的。</p>\n</div>\n<h5 id=\"stunnel服务端部分\"><a class=\"anchor\" href=\"#stunnel服务端部分\">#</a> stunnel 服务端部分</h5>\n<ul>\n<li>1、安装(和 squid 装在一起)</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">apt-get install -y stunnel</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>2、生成 TLS/SSL 证书</li>\n</ul>\n<p><figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">openssl req -new -x509 -days 3650 -nodes -out stunnel.pem -keyout stunnel.pem</span><br></pre></td></tr></table></figure></p>\n<ul>\n<li>\n<p>3、将证书 stunnel.pem 放到 /etc/stunnel/ 目录下</p>\n</li>\n<li>\n<p>4、修改 stunnel 配置 (/etc/stunnle/stunnle.conf)</p>\n</li>\n</ul>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">设置stunnel的pid文件路径</span></span><br><span class=\"line\"><span class=\"string\">pid</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.pid</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">设置stunnel工作的用户(组)</span></span><br><span class=\"line\"><span class=\"string\">setuid</span> <span class=\"string\">=</span> <span class=\"string\">root</span></span><br><span class=\"line\"><span class=\"string\">setgid</span> <span class=\"string\">=</span> <span class=\"string\">root</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">开启日志等级:emerg</span> <span class=\"string\">(0),</span> <span class=\"string\">alert</span> <span class=\"string\">(1),</span> <span class=\"string\">crit</span> <span class=\"string\">(2),</span> <span class=\"string\">err</span> <span class=\"string\">(3),</span> <span class=\"string\">warning</span> <span class=\"string\">(4),</span> <span class=\"string\">notice</span> <span class=\"string\">(5),</span> <span class=\"string\">info</span> <span class=\"string\">(6),</span> <span class=\"string\">or</span> <span class=\"string\">debug</span> <span class=\"string\">(7)</span></span><br><span class=\"line\"><span class=\"string\">debug</span> <span class=\"string\">=</span> <span class=\"number\">7</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">日志文件路径</span></span><br><span class=\"line\"><span class=\"string\">output</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.log</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">证书文件</span></span><br><span class=\"line\"><span class=\"string\">cert</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.pem</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">私钥文件</span></span><br><span class=\"line\"><span class=\"string\">key</span> <span class=\"string\">=</span> <span class=\"string\">/etc/stunnel/stunnel.pem</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">自定义服务名squid-proxy</span></span><br><span class=\"line\">[<span class=\"string\">squid-proxy</span>]</span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">服务监听的端口,client要连接这个端口与server通信</span></span><br><span class=\"line\"><span class=\"string\">accept</span> <span class=\"string\">=</span> <span class=\"number\">1234</span><span class=\"string\">(自定义)</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">服务要连接的端口,连接到squid的3128端口,将数据发给squid</span></span><br><span class=\"line\"><span class=\"string\">connect</span> <span class=\"string\">=</span> <span class=\"number\">3128</span></span><br></pre></td></tr></table></figure></p>\n<h5 id=\"stunnel客户端部分\"><a class=\"anchor\" href=\"#stunnel客户端部分\">#</a> stunnel 客户端部分</h5>\n<div class=\"note info\">\n<p>可以安装在要代理的机器上,在需要代理的情况下再开启(代理地址填 127.0.0.1 加客户端监听端口)。也可以安装在国内的服务器上一直保持连接(代理信息填国内服务器 ip 加客户端监听端口)。本示例客户端为 windows 系统</p>\n</div>\n<ul>\n<li>1、下载地址</li>\n</ul>\n<p><span class=\"blue\"><span class=\"exturl\" data-url=\"aHR0cHM6Ly93d3cuc3R1bm5lbC5vcmcvZG93bmxvYWRzLmh0bWw=\">https://www.stunnel.org/downloads.html</span></span></p>\n<ul>\n<li>2、修改配置(C:\\Program Files (x86)\\stunnel\\config\\stunnel.conf)</li>\n</ul>\n<p><figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[<span class=\"string\">squid-proxy</span>]</span><br><span class=\"line\"><span class=\"string\">client</span> <span class=\"string\">=</span> <span class=\"literal\">yes</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">监听3128端口,那么用户浏览器的代理设置就是</span> <span class=\"string\">stunnel-client-ip:3128</span></span><br><span class=\"line\"><span class=\"string\">accept</span> <span class=\"string\">=</span> <span class=\"number\">3128</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">要连接到的stunnel</span> <span class=\"string\">server的ip与端口</span></span><br><span class=\"line\"><span class=\"string\">connect</span> <span class=\"string\">=</span> <span class=\"string\">stunnel服务端ip:1234(服务端自定义端口)</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">需要验证对方发过来的证书</span></span><br><span class=\"line\"><span class=\"string\">verify</span> <span class=\"string\">=</span> <span class=\"number\">2</span></span><br><span class=\"line\"><span class=\"string\">;</span> <span class=\"string\">用来进行证书验证的文件(stunnel服务端生成的证书复制到以下目录并改名为stunnel-server.pem)</span></span><br><span class=\"line\"><span class=\"string\">CAfile</span> <span class=\"string\">=</span> <span class=\"string\">C:\\Program</span> <span class=\"string\">Files</span> <span class=\"string\">(x86)\\stunnel\\config\\stunnel-server.pem</span></span><br></pre></td></tr></table></figure></p>\n<div class=\"note primary\">\n<p>至次配置好代理 ip 为 stunnel 客户端 ip 加端口 3128 就可以正式科学上网了。如果只想对需要科学的 url 进行代理,可以通过安装 Proxy SwitchyOmega 插件实现(规则地址可通过<span class=\"blue\"><span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2dmd2xpc3QvZ2Z3bGlzdA==\"> https://github.com/gfwlist/gfwlist</span></span> 获取)。</p>\n</div>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2023/09/09/6a38fcb32752.png\" alt=\"\" /><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/09/09/72892168bfeb.png\" alt=\"\" /></p>\n",
|
||
"tags": [
|
||
"生活",
|
||
"技术分享",
|
||
"stunnel",
|
||
"科学上网",
|
||
"squid",
|
||
"代理"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/09/09/Windows-11%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95%E6%81%A2%E5%A4%8D%E8%80%81%E7%89%88%E6%9C%AC/",
|
||
"url": "https://hitoli.com/2023/09/09/Windows-11%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95%E6%81%A2%E5%A4%8D%E8%80%81%E7%89%88%E6%9C%AC/",
|
||
"title": "Windows 11右键菜单恢复老版本",
|
||
"date_published": "2023-09-09T08:38:00.000Z",
|
||
"content_html": "<h4 id=\"恢复方法\"><a class=\"anchor\" href=\"#恢复方法\">#</a> 恢复方法</h4>\n<p>1、按【Win+X】</p>\n<p>2、选择【终端管理员】</p>\n<p>3、输入以下命令并回车:<br />\n <code>reg add "HKCU\\Software\\Classes\\CLSID\\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\\InprocServer32" /f /ve</code></p>\n<p>4、重启电脑</p>\n",
|
||
"tags": [
|
||
"Windows",
|
||
"系统优化",
|
||
"Windows 11"
|
||
]
|
||
},
|
||
{
|
||
"id": "https://hitoli.com/2023/07/08/%E8%A7%A3%E5%86%B3Lombok%E6%8A%A5%E9%94%99/",
|
||
"url": "https://hitoli.com/2023/07/08/%E8%A7%A3%E5%86%B3Lombok%E6%8A%A5%E9%94%99/",
|
||
"title": "解决Lombok报错",
|
||
"date_published": "2023-07-08T02:51:00.000Z",
|
||
"content_html": "<h4 id=\"问题描述\"><a class=\"anchor\" href=\"#问题描述\">#</a> 问题描述</h4>\n<ol>\n<li>报错详情</li>\n</ol>\n<div class=\"note info\">\n<p>java: You aren’t using a compiler supported by lombok, so lombok will not work and has been disabled.<br />\nYour processor is: com.sun.proxy.$Proxy26<br />\nLombok supports: OpenJDK javac, ECJ</p>\n</div>\n<p><img data-src=\"https://npic.hitoli.com:8443/images/2023/07/08/393a238856e4.png\" alt=\"\" /></p>\n<ol start=\"2\">\n<li>\n<p>问题分析<br />\n属于 lombok 编译不通过,原因可能是因为依赖没有更到最新版本</p>\n</li>\n<li>\n<p>解决办法<br />\n在 IntelliJ IDEA 的全局配置 Compiler 中添加如下配置:<br />\n<figure class=\"highlight yaml\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"string\">-Djps.track.ap.dependencies=false</span></span><br></pre></td></tr></table></figure><br />\n<img data-src=\"https://npic.hitoli.com:8443/images/2023/07/08/34bac08a5d10.png\" alt=\"\" /></p>\n</li>\n</ol>\n",
|
||
"tags": [
|
||
"工作",
|
||
"解决问题",
|
||
"Lombok",
|
||
"IntelliJ",
|
||
"IDEA"
|
||
]
|
||
}
|
||
]
|
||
} |