Skip to content

Commit

Permalink
add mds
Browse files Browse the repository at this point in the history
  • Loading branch information
looly committed Aug 29, 2020
1 parent 59f6829 commit e269e42
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 47 deletions.
5 changes: 4 additions & 1 deletion docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@
* [数学相关-MathUtil](core/数学/数学相关-MathUtil.md)
* 线程和并发
* [线程工具-ThreadUtil](core/线程和并发/线程工具-ThreadUtil.md)
* [自定义线程池-ExecutorBuilder](core/线程和并发/自定义线程池-ExecutorBuilder.md)
* [高并发测试-ConcurrencyTester](core/线程和并发/高并发测试-ConcurrencyTester.md)
* 图片
* [图片工具-ImgUtil](core/图片/图片工具-ImgUtil.md)
* [图片编辑器-Img](core/图片/图片编辑器-Img.md)
Expand Down Expand Up @@ -136,7 +138,8 @@
* [加密解密工具-SecureUtil](crypto/加密解密工具-SecureUtil.md)
* [对称加密-SymmetricCrypto](crypto/对称加密-SymmetricCrypto.md)
* [非对称加密-AsymmetricCrypto](crypto/非对称加密-AsymmetricCrypto.md)
* [摘要加密-Digester和HMac](crypto/摘要加密-Digester和HMac.md)
* [摘要加密-Digester](crypto/摘要加密-Digester.md)
* [消息认证码算法-HMac.md](crypto/消息认证码算法-HMac.md)
* [签名和验证-Sign](crypto/签名和验证-Sign.md)
* [国密算法工具-SmUtil](crypto/国密算法工具-SmUtil.md)
* DFA查找(Hutool-dfa)
Expand Down
31 changes: 29 additions & 2 deletions docs/core/日期时间/农历日期-ChineseDate.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,22 @@

## 使用

1. 构建`ChineseDate`对象

`ChineseDate`表示了农历的对象,构建此对象既可以使用公历的日期,也可以使用农历的日期。

```java
//通过农历构建
ChineseDate chineseDate = new ChineseDate(1992,12,14);

//通过公历构建
ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate("1993-01-06"));
```

2. 基本使用

```java
//通过公历构建
ChineseDate date = new ChineseDate(DateUtil.parseDate("2020-01-25"));
// 一月
date.getChineseMonth();
Expand All @@ -14,10 +29,22 @@ date.getChineseMonthName();
date.getChineseDay();
// 庚子
date.getCyclical();
//
// 生肖:
date.getChineseZodiac();
// 春节
// 传统节日(部分支持,逗号分隔):春节
date.getFestivals();
// 庚子鼠年 正月初一
date.toString();
```

3. 获取天干地支

`5.4.1`开始,Hutool支持天干地支的获取:

```java
//通过公历构建
ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate("2020-08-28"));

// 庚子年甲申月癸卯日
String cyclicalYMD = chineseDate.getCyclicalYMD();
```
2 changes: 1 addition & 1 deletion docs/core/线程和并发/线程工具-ThreadUtil.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

并发在Java中算是一个比较难理解和容易出问题的部分,而并发的核心在线程。好在从JDK1.5开始Java提供了`concurrent`包可以很好的帮我们处理大部分并发、异步等问题。

不过,ExecutorService和Executors等众多概念依旧让我们使用这个包变得比较麻烦,如何才能隐藏这些概念?又如何用一个方法解决问题?`ThreadUtil`便为此而生。
不过,`ExecutorService``Executors`等众多概念依旧让我们使用这个包变得比较麻烦,如何才能隐藏这些概念?又如何用一个方法解决问题?`ThreadUtil`便为此而生。

## 原理
Hutool使用`GlobalThreadPool`持有一个全局的线程池,默认所有异步方法在这个线程池中执行。
Expand Down
81 changes: 81 additions & 0 deletions docs/core/线程和并发/自定义线程池-ExecutorBuilder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
## 由来

在JDK中,提供了`Executors`用于创建自定义的线程池对象`ExecutorService`,但是考虑到线程池中存在众多概念,这些概念通过不同的搭配实现灵活的线程管理策略,单独使用`Executors`无法满足需求,构建了`ExecutorBuilder`

### 概念

- `corePoolSize` 初始池大小
- `maxPoolSize` 最大池大小(允许同时执行的最大线程数)
- `workQueue` 队列,用于存在未执行的线程
- `handler` 当线程阻塞(block)时的异常处理器,所谓线程阻塞即线程池和等待队列已满,无法处理线程时采取的策略

### 线程池对待线程的策略

1. 如果池中任务数 < corePoolSize -> 放入立即执行
2. 如果池中任务数 > corePoolSize -> 放入队列等待
3. 队列满 -> 新建线程立即执行
4. 执行中的线程 > maxPoolSize -> 触发handler(RejectedExecutionHandler)异常

### workQueue线程池策略

- `SynchronousQueue` 它将任务直接提交给线程而不保持它们。当运行线程小于`maxPoolSize`时会创建新线程,否则触发异常策略
- `LinkedBlockingQueue` 默认无界队列,当运行线程大于`corePoolSize`时始终放入此队列,此时`maxPoolSize`无效。当构造LinkedBlockingQueue对象时传入参数,变为有界队列,队列满时,运行线程小于`maxPoolSize`时会创建新线程,否则触发异常策略
- `ArrayBlockingQueue` 有界队列,相对无界队列有利于控制队列大小,队列满时,运行线程小于`maxPoolSize`时会创建新线程,否则触发异常策略

## 使用

1. 默认线程池

策略如下:

- 初始线程数为corePoolSize指定的大小
- 没有最大线程数限制
- 默认使用LinkedBlockingQueue,默认队列大小为1024(最大等待数1024)
- 当运行线程大于corePoolSize放入队列,队列满后抛出异常

```java
ExecutorService executor = ExecutorBuilder builder = ExecutorBuilder.create()..build();
```

2. 单线程线程池

- 初始线程数为 1
- 最大线程数为 1
- 默认使用LinkedBlockingQueue,默认队列大小为1024
- 同时只允许一个线程工作,剩余放入队列等待,等待数超过1024报错

```java
ExecutorService executor = ExecutorBuilder.create()//
.setCorePoolSize(1)//
.setMaxPoolSize(1)//
.setKeepAliveTime(0)//
.build();
```

3. 更多选项的线程池

- 初始5个线程
- 最大10个线程
- 有界等待队列,最大等待数是100

```java
ExecutorService executor = ExecutorBuilder.create()
.setCorePoolSize(5)
.setMaxPoolSize(10)
.setWorkQueue(new LinkedBlockingQueue<>(100))
.build();
```

3. 特殊策略的线程池

- 初始5个线程
- 最大10个线程
- 它将任务直接提交给线程而不保持它们。当运行线程小于maxPoolSize时会创建新线程,否则触发异常策略

```java
ExecutorService executor = ExecutorBuilder.create()
.setCorePoolSize(5)
.setMaxPoolSize(10)
.useSynchronousQueue()
.build();
```
17 changes: 17 additions & 0 deletions docs/core/线程和并发/高并发测试-ConcurrencyTester.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## 由来

很多时候,我们需要简单模拟N个线程调用某个业务测试其并发状况,于是Hutool提供了一个简单的并发测试类——ConcurrencyTester。

## 使用

```java
ConcurrencyTester tester = ThreadUtil.concurrencyTest(100, () -> {
// 测试的逻辑内容
long delay = RandomUtil.randomLong(100, 1000);
ThreadUtil.sleep(delay);
Console.log("{} test finished, delay: {}", Thread.currentThread().getName(), delay);
});

// 获取总的执行时间,单位毫秒
Console.log(tester.getInterval());
```
51 changes: 47 additions & 4 deletions docs/crypto/国密算法工具-SmUtil.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ Hutool针对`Bouncy Castle`做了简化包装,用于实现国密算法中的SM

```xml
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.66</version>
</dependency>
```

> 说明
> `bcprov-jdk15on`的版本请前往Maven中央库搜索,查找对应JDK的版本
> `bcprov-jdk15to18`的版本请前往Maven中央库搜索,查找对应JDK的最新版本
### 非对称加密SM2

Expand Down Expand Up @@ -52,6 +52,49 @@ String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
```

3. SM2签名和验签

```java
String content = "我是Hanley.";
final SM2 sm2 = SmUtil.sm2();
String sign = sm2.signHex(HexUtil.encodeHexStr(content));

// true
boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(content), sign);
```

当然,也可以自定义密钥对:

```java
String content = "我是Hanley.";
KeyPair pair = SecureUtil.generateKeyPair("SM2");
final SM2 sm2 = new SM2(pair.getPrivate(), pair.getPublic());

byte[] sign = sm2.sign(content.getBytes());

// true
boolean verify = sm2.verify(content.getBytes(), sign);
```

4. 使用SM2曲线点构建SM2

使用曲线点构建中的点生成和验证见:[https://i.goto327.top/CryptTools/SM2.aspx?tdsourcetag=s_pctim_aiomsg](https://i.goto327.top/CryptTools/SM2.aspx?tdsourcetag=s_pctim_aiomsg)

```java
String privateKeyHex = "FAB8BBE670FAE338C9E9382B9FB6485225C11A3ECB84C938F10F20A93B6215F0";
String x = "9EF573019D9A03B16B0BE44FC8A5B4E8E098F56034C97B312282DD0B4810AFC3";
String y = "CC759673ED0FC9B9DC7E6FA38F0E2B121E02654BF37EA6B63FAF2A0D6013EADF";

// 数据和ID此处使用16进制表示
String dataHex = "434477813974bf58f94bcf760833c2b40f77a5fc360485b0b9ed1bd9682edb45";
String idHex = "31323334353637383132333435363738";

final SM2 sm2 = new SM2(privateKeyHex, x, y);
final String sign = sm2.signHex(data, id);
// true
boolean verify = sm2.verifyHex(data, sign)
```

### 摘要加密算法SM3

```java
Expand Down
49 changes: 15 additions & 34 deletions docs/crypto/摘要加密-Digester和HMac.md → docs/crypto/摘要加密-Digester.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

但是,由于输出的密文是提取原数据经过处理的定长值,所以它已经不能还原为原数据,即消息摘要算法是不可逆的,理论上无法通过反向运算取得原数据内容,因此它通常只能被用来做数据完整性验证。

### HMAC介绍
HMAC,全称为“Hash Message Authentication Code”,中文名“散列消息鉴别码”,主要是利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。一般的,消息鉴别码用于验证传输于两个共 同享有一个密钥的单位之间的消息。HMAC 可以与任何迭代散列函数捆绑使用。MD5 和 SHA-1 就是这种散列函数。HMAC 还可以使用一个用于计算和确认消息鉴别值的密钥。

## Hutool支持的摘要算法类型

在不引入第三方库的情况下,JDK支持有限的摘要算法:

详细见:[https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest](https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest)

### 摘要算法
Expand All @@ -21,66 +20,48 @@ HMAC,全称为“Hash Message Authentication Code”,中文名“散列消
- SHA-384
- SHA-512

### Hmac算法
- HmacMD5
- HmacSHA1
- HmacSHA256
- HmacSHA384
- HmacSHA512

## 摘要算法抽象

摘要对象被抽象为两个对象:
- Digester
- HMac

## 使用

### Digester

以MD5为例:
```java
Digester md5 = new Digester(DigestAlgorithm.MD5);
String digestHex = md5.digestHex(testStr);//5393554e94bf0eb6436f240a4fd71282

// 5393554e94bf0eb6436f240a4fd71282
String digestHex = md5.digestHex(testStr);
```

当然,做为最为常用的方法,MD5等方法被封装为工具方法在`DigestUtil`中,以上代码可以进一步简化为:

```java
// 5393554e94bf0eb6436f240a4fd71282
String md5Hex1 = DigestUtil.md5Hex(testStr);
//Junit单元测试
//Assert.assertEquals("5393554e94bf0eb6436f240a4fd71282", md5Hex1);
```

### HMac

以HmacMD5为例:
```java
String testStr = "test中文";

byte[] key = "password".getBytes();
HMac mac = new HMac(HmacAlgorithm.HmacMD5, key);

String macHex1 = mac.digestHex(testStr);//b977f4b13f93f549e06140971bded384
```
## 更多摘要算法

### SM3

在4.2.1之后,Hutool借助Bouncy Castle库可以支持国密算法,以SM3为例:
`4.2.1`之后,Hutool借助`Bouncy Castle`库可以支持国密算法,以SM3为例:

我们首先需要引入Bouncy Castle库:

```xml
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.60</version>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.66</version>
</dependency>
```

然后可以调用SM3算法,调用方法与其它摘要算法一致:

```java
Digester digester = DigestUtil.digester("sm3");

//136ce3c86e4ed909b76082055a61586af20b4dab674732ebd4b599eef080c9be
String digestHex = digester.digestHex("aaaaa");
```
```

> Java标准库的`java.security`包提供了一种标准机制,允许第三方提供商无缝接入。当引入`Bouncy Castle`库的jar后,Hutool会自动检测并接入。具体方法可见`SecureUtil.createMessageDigest`
40 changes: 40 additions & 0 deletions docs/crypto/消息认证码算法-HMac.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## 介绍

### HMAC介绍
HMAC,全称为“Hash Message Authentication Code”,中文名“散列消息鉴别码”,主要是利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。一般的,消息鉴别码用于验证传输于两个共 同享有一个密钥的单位之间的消息。HMAC 可以与任何迭代散列函数捆绑使用。MD5 和 SHA-1 就是这种散列函数。HMAC 还可以使用一个用于计算和确认消息鉴别值的密钥。

## Hutool支持的算法类型

### Hmac算法

在不引入第三方库的情况下,JDK支持有限的摘要算法:

- HmacMD5
- HmacSHA1
- HmacSHA256
- HmacSHA384
- HmacSHA512

## 使用

### HMac

以HmacMD5为例:
```java
String testStr = "test中文";

// 此处密钥如果有非ASCII字符,考虑编码
byte[] key = "password".getBytes();
HMac mac = new HMac(HmacAlgorithm.HmacMD5, key);

// b977f4b13f93f549e06140971bded384
String macHex1 = mac.digestHex(testStr);
```

## 更多HMac算法

与摘要算法类似,通过加入`Bouncy Castle`库可以调用更多算法,使用也类似:

```java
HMac mac = new HMac("XXXX", key);
```
4 changes: 2 additions & 2 deletions docs/crypto/签名和验证-Sign.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
## 介绍
Hutool针对`java.security.Signature`做了简化包装,包装类为:`Sign`,用于生成签名和签名验证。

对于签名算法,Hutool封装了JDK的,具体介绍见:[https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature](https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature)
对于签名算法,Hutool封装了JDK的Signature,具体介绍见:[https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature](https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#Signature)

```
```java
// The RSA signature algorithm
NONEwithRSA

Expand Down
Loading

0 comments on commit e269e42

Please sign in to comment.