### 5.8.27

JDK版本： jdk8u332-b09
hutool版本： 5.8.27

### `HttpUtil.urlWithFormUrlEncoded` 方法重复 URL 编码

其中调用 `urlWithForm` 方法入参写死了两个 `true`：
```java
public static String urlWithFormUrlEncoded(String url, Map<String, Object> form, Charset charset) {
    return urlWithForm(url, toParams(form, charset, true), charset, true);
}
```
`toParams` 方法会对参数键值对都进行编码。

<br>


进入 `urlWithForm` 方法中，此时入参 `queryString` 已经是编码后的参数字符串：
```java
public static String urlWithForm(String url, String queryString, Charset charset, boolean isEncode) {
	// ...
	urlBuilder.append(isEncode ? encodeParams(queryString, charset) : queryString);
	return urlBuilder.toString();
}
```
但最后 `encodeParams` 方法中会调用 `normalizeParams` 方法，对 `queryString` 又进行了一次URL 编码，最终的 URL 进行了两次编码。

<br>

同时我也发现，直接调用 `urlWithForm(,,,true)` 方法也并不会进行 URL 编码，反而是 `queryString` 如果已经编码过，最终在 `normalizeParams ` 方法中又会额外再编码一次：
```java
HttpUtil.urlWithForm("https://xxx.com/test", HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8), StandardCharsets.UTF_8, true);
```

<br>

最后这样写才得到我期望的结果：
```java
HttpUtil.urlWithForm("https://xxx.com/test", HttpUtil.toParams(paramMap, StandardCharsets.UTF_8, true), StandardCharsets.UTF_8, false);
```


<br>

<br>

_eg：_

```java
String url = "https://xxx.com/test";

Map<String, Object> paramMap = new HashMap<>(16);
paramMap.put("redirect_uri", "https://api.xxx.com/v1/test");
paramMap.put("scope", "a,b,c");

System.out.println(HttpUtil.urlWithFormUrlEncoded(url, paramMap, StandardCharsets.UTF_8));
System.out.println(HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8), StandardCharsets.UTF_8, false));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8), StandardCharsets.UTF_8, true));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.toParams(paramMap, StandardCharsets.UTF_8, true), StandardCharsets.UTF_8, false));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.toParams(paramMap, StandardCharsets.UTF_8, true), StandardCharsets.UTF_8, true));
```
```
https://xxx.com/test?scope=a%252Cb%252Cc&redirect_uri=https%253A%252F%252Fapi.xxx.com%252Fv1%252Ftest
scope=a,b,c&redirect_uri=https://api.xxx.com/v1/test
https://xxx.com/test?scope=a,b,c&redirect_uri=https://api.xxx.com/v1/test
https://xxx.com/test?scope=a,b,c&redirect_uri=https://api.xxx.com/v1/test
https://xxx.com/test?scope=a%2Cb%2Cc&redirect_uri=https%3A%2F%2Fapi.xxx.com%2Fv1%2Ftest
https://xxx.com/test?scope=a%252Cb%252Cc&redirect_uri=https%253A%252F%252Fapi.xxx.com%252Fv1%252Ftest
```

<br>

不知道是我对这几个方法的定义理解有误还是使用不当，让我感到很困惑。
HttpUtil.urlWithFormUrlEncoded 方法重复 URL 编码
This is a GitHub Issue
repo:hutool
owner:dromara
Title : HttpUtil.urlWithFormUrlEncoded 方法重复 URL 编码
Issue date:

--- start body ---
### 5.8.27

JDK版本： jdk8u332-b09
hutool版本： 5.8.27

### `HttpUtil.urlWithFormUrlEncoded` 方法重复 URL 编码

其中调用 `urlWithForm` 方法入参写死了两个 `true`：
```java
public static String urlWithFormUrlEncoded(String url, Map<String, Object> form, Charset charset) {
    return urlWithForm(url, toParams(form, charset, true), charset, true);
}
```
`toParams` 方法会对参数键值对都进行编码。

<br>


进入 `urlWithForm` 方法中，此时入参 `queryString` 已经是编码后的参数字符串：
```java
public static String urlWithForm(String url, String queryString, Charset charset, boolean isEncode) {
	// ...
	urlBuilder.append(isEncode ? encodeParams(queryString, charset) : queryString);
	return urlBuilder.toString();
}
```
但最后 `encodeParams` 方法中会调用 `normalizeParams` 方法，对 `queryString` 又进行了一次URL 编码，最终的 URL 进行了两次编码。

<br>

同时我也发现，直接调用 `urlWithForm(,,,true)` 方法也并不会进行 URL 编码，反而是 `queryString` 如果已经编码过，最终在 `normalizeParams ` 方法中又会额外再编码一次：
```java
HttpUtil.urlWithForm("https://xxx.com/test", HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8), StandardCharsets.UTF_8, true);
```

<br>

最后这样写才得到我期望的结果：
```java
HttpUtil.urlWithForm("https://xxx.com/test", HttpUtil.toParams(paramMap, StandardCharsets.UTF_8, true), StandardCharsets.UTF_8, false);
```


<br>

<br>

_eg：_

```java
String url = "https://xxx.com/test";

Map<String, Object> paramMap = new HashMap<>(16);
paramMap.put("redirect_uri", "https://api.xxx.com/v1/test");
paramMap.put("scope", "a,b,c");

System.out.println(HttpUtil.urlWithFormUrlEncoded(url, paramMap, StandardCharsets.UTF_8));
System.out.println(HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8), StandardCharsets.UTF_8, false));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.encodeParams(HttpUtil.toParams(paramMap), StandardCharsets.UTF_8), StandardCharsets.UTF_8, true));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.toParams(paramMap, StandardCharsets.UTF_8, true), StandardCharsets.UTF_8, false));
System.out.println(HttpUtil.urlWithForm(url, HttpUtil.toParams(paramMap, StandardCharsets.UTF_8, true), StandardCharsets.UTF_8, true));
```
```
https://xxx.com/test?scope=a%252Cb%252Cc&redirect_uri=https%253A%252F%252Fapi.xxx.com%252Fv1%252Ftest
scope=a,b,c&redirect_uri=https://api.xxx.com/v1/test
https://xxx.com/test?scope=a,b,c&redirect_uri=https://api.xxx.com/v1/test
https://xxx.com/test?scope=a,b,c&redirect_uri=https://api.xxx.com/v1/test
https://xxx.com/test?scope=a%2Cb%2Cc&redirect_uri=https%3A%2F%2Fapi.xxx.com%2Fv1%2Ftest
https://xxx.com/test?scope=a%252Cb%252Cc&redirect_uri=https%253A%252F%252Fapi.xxx.com%252Fv1%252Ftest
```

<br>

不知道是我对这几个方法的定义理解有误还是使用不当，让我感到很困惑。
--- end body ---
