优化:侧边栏支持显示置顶文章分组
@@ -37,7 +37,7 @@ yarn build
|
||||
|
||||
- [x] 拆分配置文件:解决“大”配置文件问题,提取公有配置选项进行复用,方便维护
|
||||
- [x] GitHub Action:push 到 GitHub,自动进行项目打包及 GitHub Pages 部署,并同步到 Gitee Pages(可根据需要自行删除同步 Gitee Pages 部分工作流配置)
|
||||
- [x] 自动生成导航:将文章按规律性目录存放后,导航和侧边栏将自动生成
|
||||
- [x] 自动生成侧边栏:将文章按规律性目录存放后,侧边栏将自动生成,支持文章置顶🔝(在文章 frontmatter 中配置 `isTop: true`,即可在侧边栏自动出现置顶分组)
|
||||
- [x] 主页美化:参照 vite 文档主页进行美化
|
||||
- [x] 自定义页脚:支持ICP备案号、公安备案号、版权信息配置(符合大陆网站审核要求)
|
||||
- [x] 文章元数据信息显示:文章标题下显示作者、发布时间、所属分类、标签列表等信息,可全局配置作者及作者主页信息
|
||||
@@ -53,6 +53,10 @@ yarn build
|
||||
|
||||

|
||||
|
||||
### 侧边栏置顶分组(自动生成侧边栏及置顶分组)
|
||||
|
||||

|
||||
|
||||
### 文章元数据信息
|
||||
|
||||

|
||||
|
@@ -1,5 +1,6 @@
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import { sync } from 'fast-glob'
|
||||
import matter from 'gray-matter'
|
||||
|
||||
export const sidebar: DefaultTheme.Config['sidebar'] = {
|
||||
'/categories/issues/': getItemsByDate("categories/issues"),
|
||||
@@ -22,13 +23,16 @@ function getItemsByDate (path: string) {
|
||||
// 侧边栏年份分组数组
|
||||
let yearGroups: DefaultTheme.SidebarGroup[] = []
|
||||
|
||||
// 置顶数组
|
||||
let topArticleItems: DefaultTheme.SidebarItem[] = []
|
||||
|
||||
// 1.获取所有年份目录
|
||||
sync(`docs/${path}/*`, {
|
||||
onlyDirectories: true,
|
||||
objectMode: true
|
||||
}).forEach(({ name }) => {
|
||||
let year = name
|
||||
// 侧边栏文章标题数组
|
||||
// 年份数组
|
||||
let articleItems: DefaultTheme.SidebarItem[] = []
|
||||
|
||||
// 2.获取所有月份目录
|
||||
@@ -48,16 +52,27 @@ function getItemsByDate (path: string) {
|
||||
sync(`docs/${path}/${year}/${month}/${day}/*`, {
|
||||
onlyFiles: true,
|
||||
objectMode: true
|
||||
}).forEach(({ name }) => {
|
||||
// 向前追加标题
|
||||
}).forEach((article) => {
|
||||
const articleFile = matter.read(`${article.path}`)
|
||||
const { data } = articleFile
|
||||
if (data.isTop) {
|
||||
// 向置顶分组前追加标题
|
||||
topArticleItems.unshift({
|
||||
text: data.title,
|
||||
link: `/${path}/${year}/${month}/${day}/${data.title}`
|
||||
})
|
||||
}
|
||||
|
||||
// 向年份分组前追加标题
|
||||
articleItems.unshift({
|
||||
text: name.replace('.md', ''),
|
||||
link: `/${path}/${year}/${month}/${day}/${name}`
|
||||
text: data.title,
|
||||
link: `/${path}/${year}/${month}/${day}/${data.title}`
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// 添加年份分组
|
||||
yearGroups.unshift({
|
||||
text: `${year}年 (共 ${articleItems.length} 篇)`,
|
||||
collapsible: true,
|
||||
@@ -66,8 +81,21 @@ function getItemsByDate (path: string) {
|
||||
})
|
||||
})
|
||||
|
||||
// 将第一个侧边栏分组展开
|
||||
yearGroups[0].collapsed = false
|
||||
if (topArticleItems.length > 0) {
|
||||
// 添加置顶分组
|
||||
yearGroups.unshift({
|
||||
text: `🔝我的置顶 (共 ${topArticleItems.length} 篇)`,
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
items: topArticleItems
|
||||
})
|
||||
|
||||
// 将最近年份分组展开
|
||||
yearGroups[1].collapsed = false
|
||||
} else {
|
||||
// 将最近年份分组展开
|
||||
yearGroups[0].collapsed = false
|
||||
}
|
||||
return yearGroups
|
||||
}
|
||||
|
||||
|
48
docs/categories/fragments/2019/12/28/个人SQL优化技巧.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: 个人SQL优化技巧
|
||||
author: 查尔斯
|
||||
date: 2019/12/28 10:00
|
||||
isTop: true
|
||||
categories:
|
||||
- 杂碎逆袭史
|
||||
tags:
|
||||
- SQL
|
||||
- SQL优化
|
||||
---
|
||||
|
||||
# 个人SQL优化技巧
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## 如果确定结果只有一条,使用 LIMIT 1
|
||||
|
||||
我们在根据一个或多个条件查询数据时,如果确定查询结果只有一条,可以在结尾处添加 LIMIT 1 进行限制。
|
||||
|
||||
这样既可以让 EXPLAIN 中的 type 达到 const 类型,又可以免去担忧在程序中出现接收是单个对象却返回了一个集合对象的异常问题。
|
||||
|
||||
例如:
|
||||
|
||||
```sql
|
||||
# id 是主键,主键是非空唯一的,那么不需要添加 LIMIT 进行限制
|
||||
SELECT * FROM `user` WHERE `id` = 1;
|
||||
```
|
||||
|
||||
```sql
|
||||
# email 不是主键,也没有设置唯一约束,根据熵增定律,查询结果是有可能会出现多条的
|
||||
SELECT * FROM `user` WHERE `email` = 'charles7c@126.com' LIMIT 1;
|
||||
```
|
||||
|
||||
## 避免隐式类型转换
|
||||
|
||||
我们在使用 MySQL 时,或多或少都感受过 MySQL 的隐式类型转换。
|
||||
|
||||
例如:
|
||||
|
||||
```sql
|
||||
# age 是整数类型,但是依然可以使用字符串类型数据来进行赋值
|
||||
UPDATE `user` SET `age` = '12' WHERE `id ` = 10;
|
||||
# id 是整数类型,但是依然可以使用字符串类型数据来进行判断
|
||||
SELECT * FROM WHERE `id` = '10';
|
||||
```
|
||||
|
||||
但是,MySQL 帮你做完这种隐式类型转换是有代价的,什么代价呢? **索引不再生效了而已** 。
|
46
docs/categories/fragments/2019/12/29/个人常用Stream使用技巧.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: 个人常用Stream使用技巧
|
||||
author: 查尔斯
|
||||
date: 2019/12/29 15:00
|
||||
isTop: true
|
||||
categories:
|
||||
- 杂碎逆袭史
|
||||
tags:
|
||||
- Java
|
||||
- Stream
|
||||
- Lambda
|
||||
---
|
||||
|
||||
# 个人常用Stream使用技巧
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## 映射并以指定分隔符进行拼接
|
||||
|
||||
::: warning 需求
|
||||
将角色中的角色名称取出来,并以 `,` 号分隔的形式将所有角色名称拼接成一个字符串。
|
||||
:::
|
||||
|
||||
::: tip 实现方案
|
||||
通过 `map()` 可以只保留角色名称信息, 通过 `Collectors.joining()` 可以将角色名称以指定分隔符拼接起来。
|
||||
:::
|
||||
|
||||
```java
|
||||
// 1、准备一些实验数据, 代码不会像注释一样骗人, 所以就不单独对角色类中的字段解释了
|
||||
List<Role> roleList = new ArrayList<>(3);
|
||||
roleList.add(new Role(1, "超级管理员"));
|
||||
roleList.add(new Role(2, "管理员"));
|
||||
roleList.add(new Role(3, "普通用户"));
|
||||
|
||||
// 2、通过 map() 可以只保留角色名称, 通过 Collectors.joining() 可以将角色名称以指定分隔符拼接起来
|
||||
String result = roleList.stream()
|
||||
.map(Role::getName)
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
// 3、输出结果
|
||||
// 超级管理员,管理员,普通用户
|
||||
System.out.println(result);
|
||||
```
|
||||
|
||||
|
||||
|
219
docs/categories/fragments/2019/12/30/个人常用Hutool工具类.md
Normal file
@@ -0,0 +1,219 @@
|
||||
---
|
||||
title: 个人常用Hutool工具类
|
||||
author: 查尔斯
|
||||
date: 2019/12/30 19:00
|
||||
isTop: true
|
||||
categories:
|
||||
- 杂碎逆袭史
|
||||
tags:
|
||||
- Java
|
||||
- Java工具类
|
||||
- Hutool
|
||||
---
|
||||
|
||||
# 个人常用Hutool工具类
|
||||
|
||||
## 前言
|
||||
|
||||
**C:** 技术圈常说一句:“你要会写轮子,也要会用轮子”。工作的时候,为了提升开发效率,节约开发时间,也常常提醒自己不要重复造 “轮子”。
|
||||
|
||||
每次开启一个新项目,除了搭建项目必备环境之外,必然要整理一下之前项目沉淀下来的工具类,然后 C V 大法。习惯了一些工具类后,新项目中用不了或是换一下总是感觉缺点什么,再加上每个人都有自己遇到或沉淀的工具类,项目中遇到工具类重复也是很常见的事儿。
|
||||
|
||||
话说回来,这些工具类就是开发中必不可少的一种 “轮子”。对于大多数同学,受限于技术,轮子可能勉强写的出来,但是写的是不是够好,够完善,这质量就没法保证了。
|
||||
|
||||
谁都是从一开始过来的,但好在有这么一些有志之士,将经年累月写过的轮子反复整理,反复打磨,推出了一个项目,它就是 Hutool。
|
||||
|
||||
接下来,笔者就带大家学习一些个人常用的 Hutool 工具类。
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## 判断相等
|
||||
|
||||
### Java官方
|
||||
|
||||
判断两个内容相等很常见了吧?
|
||||
|
||||
Java 7 的时候,官方还在 java.util 包下给提供了一个 Objects 工具类,源代码如下:
|
||||
|
||||
```java
|
||||
/**
|
||||
* Returns {@code true} if the arguments are equal to each other
|
||||
* and {@code false} otherwise.
|
||||
* Consequently, if both arguments are {@code null}, {@code true}
|
||||
* is returned and if exactly one argument is {@code null}, {@code
|
||||
* false} is returned. Otherwise, equality is determined by using
|
||||
* the {@link Object#equals equals} method of the first
|
||||
* argument.
|
||||
*
|
||||
* @param a an object
|
||||
* @param b an object to be compared with {@code a} for equality
|
||||
* @return {@code true} if the arguments are equal to each other
|
||||
* and {@code false} otherwise
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
public static boolean equals(Object a, Object b) {
|
||||
return (a == b) || (a != null && a.equals(b));
|
||||
}
|
||||
```
|
||||
|
||||
这的确可以解决 80% 的判断相等问题了,也可以有效避免 NPE 问题。但是笔者比较贪心,所以一直使用的 Hutool 提供的 ObjectUtil 工具类来判断相等。
|
||||
|
||||
### ObjectUtil
|
||||
|
||||
在 Java 中,判断不同内容是否相等有多种情况,这在《阿里巴巴Java开发手册》中也有强调,笔者用 ObjectUtil 分别示范下不同情况的使用方法。
|
||||
|
||||
> 【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较。 说明:对于 Integer var = ? 在-128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生, 会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都 会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
|
||||
|
||||
```java
|
||||
System.out.println(ObjectUtil.equal(null, null)); // true
|
||||
System.out.println(ObjectUtil.equal(null, 0)); // false
|
||||
System.out.println(ObjectUtil.equal(0, 0)); // true
|
||||
System.out.println(ObjectUtil.equal(0, 0L)); // false
|
||||
System.out.println(ObjectUtil.equal(0L, 0L)); // true
|
||||
System.out.println(ObjectUtil.equal(1L, 1L)); // true
|
||||
System.out.println(ObjectUtil.notEqual(1L, 1L)); // false
|
||||
```
|
||||
|
||||
**ObjectUtil 的 equal() 源代码,如下:**
|
||||
|
||||
```java
|
||||
/**
|
||||
* 比较两个对象是否相等。<br>
|
||||
* 相同的条件有两个,满足其一即可:<br>
|
||||
* <ol>
|
||||
* <li>obj1 == null && obj2 == null</li>
|
||||
* <li>obj1.equals(obj2)</li>
|
||||
* <li>如果是BigDecimal比较,0 == obj1.compareTo(obj2)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param obj1 对象1
|
||||
* @param obj2 对象2
|
||||
* @return 是否相等
|
||||
* @see Objects#equals(Object, Object)
|
||||
*/
|
||||
public static boolean equal(Object obj1, Object obj2) {
|
||||
// 判断是否为 BigDecimal 类型,如果是用 compareTo 比较
|
||||
if (obj1 instanceof BigDecimal && obj2 instanceof BigDecimal) {
|
||||
return NumberUtil.equals((BigDecimal) obj1, (BigDecimal) obj2);
|
||||
}
|
||||
// 否则使用 Java 官方提供的 Objects 工具类比较
|
||||
return Objects.equals(obj1, obj2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较两个对象是否不相等。<br>
|
||||
*
|
||||
* @param obj1 对象1
|
||||
* @param obj2 对象2
|
||||
* @return 是否不等
|
||||
* @since 3.0.7
|
||||
*/
|
||||
public static boolean notEqual(Object obj1, Object obj2) {
|
||||
return false == equal(obj1, obj2);
|
||||
}
|
||||
```
|
||||
|
||||
要是觉得 equal 这个单词不喜欢,你还可以用它的别名方法:(作者们考虑的是有点周到了)
|
||||
|
||||
```java
|
||||
/**
|
||||
* 比较两个对象是否相等,此方法是 {@link #equal(Object, Object)}的别名方法。<br>
|
||||
* 相同的条件有两个,满足其一即可:<br>
|
||||
* <ol>
|
||||
* <li>obj1 == null && obj2 == null</li>
|
||||
* <li>obj1.equals(obj2)</li>
|
||||
* <li>如果是BigDecimal比较,0 == obj1.compareTo(obj2)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param obj1 对象1
|
||||
* @param obj2 对象2
|
||||
* @return 是否相等
|
||||
* @see #equal(Object, Object)
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public static boolean equals(Object obj1, Object obj2) {
|
||||
return equal(obj1, obj2);
|
||||
}
|
||||
```
|
||||
> 【强制】BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。 说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo() 则会忽略精度。
|
||||
>
|
||||
> 说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度。
|
||||
|
||||
诚然,从上方源代码中我们可以清楚地看到 ObjectUtil 比较的时候还区分了 BigDecimal 类型,这也轻松的解决了此强制问题。
|
||||
|
||||
**在 ObjectUtil 比较 BigDecimal 类型相等时用到的 NumberUtil 中的 equals() 源代码,如下:**
|
||||
|
||||
```java
|
||||
/**
|
||||
* 比较大小,值相等 返回true<br>
|
||||
* 此方法通过调用{@link BigDecimal#compareTo(BigDecimal)}方法来判断是否相等<br>
|
||||
* 此方法判断值相等时忽略精度的,即0.00 == 0
|
||||
*
|
||||
* @param bigNum1 数字1
|
||||
* @param bigNum2 数字2
|
||||
* @return 是否相等
|
||||
*/
|
||||
public static boolean equals(BigDecimal bigNum1, BigDecimal bigNum2) {
|
||||
if (bigNum1 == bigNum2) {
|
||||
// 如果用户传入同一对象,省略compareTo以提高性能。
|
||||
return true;
|
||||
}
|
||||
if (bigNum1 == null || bigNum2 == null) {
|
||||
return false;
|
||||
}
|
||||
return 0 == bigNum1.compareTo(bigNum2);
|
||||
}
|
||||
```
|
||||
### NumberUtil
|
||||
|
||||
> 【强制】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。
|
||||
>
|
||||
> 说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进 制无法精确表示大部分的十进制小数。
|
||||
>
|
||||
> 解决方法:
|
||||
>
|
||||
> 1. 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。
|
||||
> 2. 使用 BigDecimal 来定义值,再进行浮点数的运算操作。
|
||||
|
||||
浮点数比较的时候依然可以使用 ObjectUtil,但是也可以直接采用 NumberUtil:
|
||||
|
||||
```java
|
||||
System.out.println(NumberUtil.equals(0.1, 0.1)); // true
|
||||
System.out.println(ObjectUtil.equal(BigDecimal.valueOf(0.1), BigDecimal.valueOf(0.1))); // true
|
||||
```
|
||||
|
||||
**上方用到的 NumberUtil 的 equals() 源代码,如下:**
|
||||
|
||||
```java
|
||||
/**
|
||||
* 比较大小,值相等 返回true<br>
|
||||
* 此方法通过调用{@link Double#doubleToLongBits(double)}方法来判断是否相等<br>
|
||||
* 此方法判断值相等时忽略精度的,即0.00 == 0
|
||||
*
|
||||
* @param num1 数字1
|
||||
* @param num2 数字2
|
||||
* @return 是否相等
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public static boolean equals(double num1, double num2) {
|
||||
return Double.doubleToLongBits(num1) == Double.doubleToLongBits(num2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较大小,值相等 返回true<br>
|
||||
* 此方法通过调用{@link Float#floatToIntBits(float)}方法来判断是否相等<br>
|
||||
* 此方法判断值相等时忽略精度的,即0.00 == 0
|
||||
*
|
||||
* @param num1 数字1
|
||||
* @param num2 数字2
|
||||
* @return 是否相等
|
||||
* @since 5.4.5
|
||||
*/
|
||||
public static boolean equals(float num1, float num2) {
|
||||
return Float.floatToIntBits(num1) == Float.floatToIntBits(num2);
|
||||
}
|
||||
```
|
||||
|
||||
## 后记
|
||||
|
||||
**C:** 我个人对 Hutool 还是非常认可的,经过这么久的打磨,基础工具类日趋完善,用起来也放心。各位同学,根据自己项目的实际情况来选择吧。
|
69
docs/categories/fragments/2019/12/31/个人常用Linux命令.md
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: 个人常用Linux命令
|
||||
author: 查尔斯
|
||||
date: 2019/12/31 21:00
|
||||
isTop: true
|
||||
categories:
|
||||
- 杂碎逆袭史
|
||||
tags:
|
||||
- Linux
|
||||
---
|
||||
|
||||
# 个人常用Linux命令
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## 系统相关
|
||||
|
||||
### 查询系统详情
|
||||
|
||||
```shell
|
||||
# 详细输出所有信息,依次为内核名称,主机名,内核版本号,内核版本,硬件名,处理器类型,硬件平台类型,操作系统名称
|
||||
uname -a
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 查询系统发行版本
|
||||
|
||||
```shell
|
||||
# 只适合Redhat系的Linux
|
||||
cat /etc/redhat-release
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 查看CPU信息
|
||||
|
||||
```shell
|
||||
# 逻辑CPU数量和CPU型号
|
||||
cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
|
||||
```
|
||||
|
||||

|
||||
|
||||
```shell
|
||||
# CPU真实数量(有时候虽然逻辑CPU是8核,但可能是由两颗4核CPU构成的)
|
||||
cat /proc/cpuinfo | grep physical | uniq -c
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 查询RAM信息(内存)
|
||||
|
||||
```shell
|
||||
# 用于查看有关系统 RAM 使用情况的信息(带大小单位)
|
||||
free -h
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 查询ROM信息(磁盘)
|
||||
|
||||
```shell
|
||||
# 以磁盘分区为单位查看文件系统,可以获取硬盘被占用了多少空间,目前还剩下多少空间等信息
|
||||
df -h
|
||||
```
|
||||
|
||||

|
||||
|
BIN
docs/public/img/2019/12/31/201912312031666.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
docs/public/img/2019/12/31/201912312031777.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
docs/public/img/2019/12/31/201912312031888.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/public/img/2019/12/31/201912312031999.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
docs/public/img/2019/12/31/201912312032666.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
docs/public/img/2019/12/31/201912312032777.png
Normal file
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 383 KiB |
BIN
docs/public/screenshot/侧边栏置顶分组.png
Normal file
After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 219 KiB |