🎨 #3834 【基础架构】小程序和开放平台两个模块补充了 Apache HttpClient 5.x 实现,同时并将多个模块的默认服务实现迁移至 Apache HttpClient 5.x 客户端

This commit is contained in:
buaazyl
2026-01-08 15:08:58 +08:00
committed by GitHub
parent e572ddfba6
commit 2c5a33917e
21 changed files with 233 additions and 22 deletions

View File

@@ -28,12 +28,11 @@
| weixin-java-cp企业微信 | ⚠️ 视集成方式而定 | 参考对应 starter 配置 |
| weixin-java-channel视频号 | ✅ 是 | HttpComponents (5.x) |
| weixin-java-qidian企点 | ✅ 是 | HttpComponents (5.x) |
| weixin-java-miniapp小程序 | ✅ 是 | HttpClient (4.x) |
| weixin-java-miniapp小程序 | ✅ 是 | HttpComponents (5.x) |
| weixin-java-pay支付 | ✅ 是 | HttpComponents (5.x) |
| weixin-java-open开放平台 | ✅ 是 | HttpComponents (5.x) |
**注意**
- **weixin-java-miniapp 模块**已在核心 SDK 中提供 HttpClient 5.x`HttpComponents`)支持,但默认仍使用 HttpClient 4.x`HttpClient`)。如需启用 HttpClient 5.x可通过配置 `http-client-type=HttpComponents` 显式指定。
- **weixin-java-cp 模块**的支持情况取决于具体使用的 Starter 版本,请参考对应模块文档。
## 对现有项目的影响
@@ -97,9 +96,6 @@ A: 不会。项目保持完全向后兼容HttpClient 4.x 的所有实现都
### Q: 我需要修改代码吗?
A: 大多数情况下不需要。如果希望继续使用 HttpClient 4.x只需在配置中指定 `http-client-type=HttpClient` 即可。
### Q: MiniApp 模块支持 HttpClient 5.x 吗?
A: 支持。MiniApp 模块在核心 SDK 中已经提供了基于 HttpClient 5.x`HttpComponents`)的支持,但默认仍会使用 HttpClient 4.x`HttpClient`)以保持向后兼容。如果你使用的是框架集成(例如 Spring Boot Starter 或 Solon Plugin可以通过显式配置 `http-client-type=HttpComponents` 来启用 HttpClient 5.x。
### Q: 我可以在同一个项目中同时使用两个版本吗?
A: 可以。不同的模块可以配置使用不同的 HTTP 客户端。例如MP 模块使用 HttpClient 5.xMiniApp 模块默认使用 HttpClient 4.x但也可以按需配置为 HttpClient 5.x。

View File

@@ -55,7 +55,7 @@ public class WxChannelMultiProperties implements Serializable {
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.HTTP_CLIENT;
private HttpClientType httpClientType = HttpClientType.HTTP_COMPONENTS;
/**
* http代理主机.

View File

@@ -52,7 +52,7 @@ public class WxCpMultiProperties implements Serializable {
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.HTTP_CLIENT;
private HttpClientType httpClientType = HttpClientType.HTTP_COMPONENTS;
/**
* http代理主机

View File

@@ -2,6 +2,7 @@ package com.binarywang.solon.wxjava.miniapp.configuration.services;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpClientImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpComponentsImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceJoddHttpImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceOkHttpImpl;
@@ -89,6 +90,9 @@ public abstract class AbstractWxMaConfiguration {
case HTTP_CLIENT:
wxMaService = new WxMaServiceHttpClientImpl();
break;
case HTTP_COMPONENTS:
wxMaService = new WxMaServiceHttpComponentsImpl();
break;
default:
wxMaService = new WxMaServiceImpl();
break;

View File

@@ -77,7 +77,7 @@ public class WxMaMultiProperties implements Serializable {
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.HTTP_CLIENT;
private HttpClientType httpClientType = HttpClientType.HTTP_COMPONENTS;
/**
* http代理主机.
@@ -149,6 +149,10 @@ public class WxMaMultiProperties implements Serializable {
/**
* JoddHttp
*/
JODD_HTTP
JODD_HTTP,
/**
* HttpComponents
*/
HTTP_COMPONENTS
}
}

View File

@@ -2,6 +2,7 @@ package com.binarywang.solon.wxjava.miniapp.config;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpClientImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpComponentsImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceJoddHttpImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceOkHttpImpl;
@@ -44,6 +45,9 @@ public class WxMaServiceAutoConfiguration {
case HttpClient:
wxMaService = new WxMaServiceHttpClientImpl();
break;
case HttpComponents:
wxMaService = new WxMaServiceHttpComponentsImpl();
break;
default:
wxMaService = new WxMaServiceImpl();
break;

View File

@@ -76,7 +76,7 @@ public class WxMaProperties {
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.HttpClient;
private HttpClientType httpClientType = HttpClientType.HttpComponents;
/**
* http代理主机.

View File

@@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpComponentsImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceJoddHttpImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceOkHttpImpl;
@@ -91,6 +92,9 @@ public abstract class AbstractWxMpConfiguration {
case HTTP_CLIENT:
wxMpService = new WxMpServiceHttpClientImpl();
break;
case HTTP_COMPONENTS:
wxMpService = new WxMpServiceHttpComponentsImpl();
break;
default:
wxMpService = new WxMpServiceImpl();
break;

View File

@@ -77,7 +77,7 @@ public class WxMpMultiProperties implements Serializable {
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.HTTP_CLIENT;
private HttpClientType httpClientType = HttpClientType.HTTP_COMPONENTS;
/**
* http代理主机.
@@ -149,6 +149,10 @@ public class WxMpMultiProperties implements Serializable {
/**
* JoddHttp
*/
JODD_HTTP
JODD_HTTP,
/**
* HttpComponents
*/
HTTP_COMPONENTS
}
}

View File

@@ -4,6 +4,7 @@ import com.binarywang.solon.wxjava.mp.enums.HttpClientType;
import com.binarywang.solon.wxjava.mp.properties.WxMpProperties;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpComponentsImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceJoddHttpImpl;
import me.chanjar.weixin.mp.api.impl.WxMpServiceOkHttpImpl;
@@ -35,6 +36,9 @@ public class WxMpServiceAutoConfiguration {
case HttpClient:
wxMpService = newWxMpServiceHttpClientImpl();
break;
case HttpComponents:
wxMpService = newWxMpServiceHttpComponentsImpl();
break;
default:
wxMpService = newWxMpServiceImpl();
break;
@@ -60,4 +64,8 @@ public class WxMpServiceAutoConfiguration {
return new WxMpServiceJoddHttpImpl();
}
private WxMpService newWxMpServiceHttpComponentsImpl() {
return new WxMpServiceHttpComponentsImpl();
}
}

View File

@@ -4,6 +4,7 @@ import com.binarywang.solon.wxjava.qidian.enums.HttpClientType;
import com.binarywang.solon.wxjava.qidian.properties.WxQidianProperties;
import me.chanjar.weixin.qidian.api.WxQidianService;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceHttpClientImpl;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceHttpComponentsImpl;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceImpl;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceJoddHttpImpl;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceOkHttpImpl;
@@ -35,6 +36,9 @@ public class WxQidianServiceAutoConfiguration {
case HttpClient:
wxQidianService = newWxQidianServiceHttpClientImpl();
break;
case HttpComponents:
wxQidianService = newWxQidianServiceHttpComponentsImpl();
break;
default:
wxQidianService = newWxQidianServiceImpl();
break;
@@ -60,4 +64,8 @@ public class WxQidianServiceAutoConfiguration {
return new WxQidianServiceJoddHttpImpl();
}
private WxQidianService newWxQidianServiceHttpComponentsImpl() {
return new WxQidianServiceHttpComponentsImpl();
}
}

View File

@@ -2,6 +2,7 @@ package com.binarywang.spring.starter.wxjava.miniapp.config;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpClientImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceHttpComponentsImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceJoddHttpImpl;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceOkHttpImpl;
@@ -46,6 +47,9 @@ public class WxMaServiceAutoConfiguration {
case HttpClient:
wxMaService = new WxMaServiceHttpClientImpl();
break;
case HttpComponents:
wxMaService = new WxMaServiceHttpComponentsImpl();
break;
default:
wxMaService = new WxMaServiceImpl();
break;

View File

@@ -88,7 +88,7 @@ public class WxMaProperties {
/**
* http客户端类型.
*/
private HttpClientType httpClientType = HttpClientType.HttpClient;
private HttpClientType httpClientType = HttpClientType.HttpComponents;
/**
* http代理主机.

View File

@@ -8,7 +8,7 @@ import lombok.extern.slf4j.Slf4j;
* @author <a href="https://github.com/lixize">Zeyes</a>
*/
@Slf4j
public class WxChannelServiceImpl extends WxChannelServiceHttpClientImpl {
public class WxChannelServiceImpl extends WxChannelServiceHttpComponentsImpl {
public WxChannelServiceImpl() {
}

View File

@@ -0,0 +1,101 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.bean.WxMaStableAccessTokenRequest;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.util.http.HttpClientType;
import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.io.entity.StringEntity;
import java.io.IOException;
/**
* Apache Http client5 方式实现
*
* @author <a href="https://github.com/buaazyl">zhangyl</a>
*/
@Slf4j
public class WxMaServiceHttpComponentsImpl extends BaseWxMaServiceImpl<CloseableHttpClient, HttpHost> {
private CloseableHttpClient httpClient;
private HttpHost httpProxy;
@Override
public void initHttp() {
WxMaConfig configStorage = this.getWxMaConfig();
HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost())
.httpProxyPort(configStorage.getHttpProxyPort())
.httpProxyUsername(configStorage.getHttpProxyUsername())
.httpProxyPassword(configStorage.getHttpProxyPassword() == null ? null :
configStorage.getHttpProxyPassword().toCharArray());
if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort());
}
this.httpClient = apacheHttpClientBuilder.build();
}
@Override
public CloseableHttpClient getRequestHttpClient() {
return httpClient;
}
@Override
public HttpHost getRequestHttpProxy() {
return httpProxy;
}
@Override
public HttpClientType getRequestType() {
return HttpClientType.HTTP_COMPONENTS;
}
@Override
protected String doGetAccessTokenRequest() throws IOException {
String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ?
this.getWxMaConfig().getAccessTokenUrl() :
GET_ACCESS_TOKEN_URL.replace(WxMaConfig.DEFAULT_API_HOST_URL, this.getWxMaConfig().getEffectiveApiHostUrl());
url = String.format(url, this.getWxMaConfig().getAppid(), this.getWxMaConfig().getSecret());
HttpGet httpGet = new HttpGet(url);
if (this.getRequestHttpProxy() != null) {
RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
httpGet.setConfig(config);
}
return getRequestHttpClient().execute(httpGet, BasicResponseHandler.INSTANCE);
}
@Override
protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
String url = StringUtils.isNotEmpty(this.getWxMaConfig().getAccessTokenUrl()) ?
this.getWxMaConfig().getAccessTokenUrl() :
GET_STABLE_ACCESS_TOKEN.replace(
WxMaConfig.DEFAULT_API_HOST_URL, this.getWxMaConfig().getEffectiveApiHostUrl());
HttpPost httpPost = new HttpPost(url);
if (this.getRequestHttpProxy() != null) {
RequestConfig config = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
httpPost.setConfig(config);
}
WxMaStableAccessTokenRequest wxMaAccessTokenRequest = new WxMaStableAccessTokenRequest();
wxMaAccessTokenRequest.setAppid(this.getWxMaConfig().getAppid());
wxMaAccessTokenRequest.setSecret(this.getWxMaConfig().getSecret());
wxMaAccessTokenRequest.setGrantType("client_credential");
wxMaAccessTokenRequest.setForceRefresh(forceRefresh);
httpPost.setEntity(new StringEntity(wxMaAccessTokenRequest.toJson(), ContentType.APPLICATION_JSON));
return getRequestHttpClient().execute(httpPost, BasicResponseHandler.INSTANCE);
}
}

View File

@@ -6,6 +6,6 @@ import lombok.extern.slf4j.Slf4j;
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Slf4j
public class WxMaServiceImpl extends WxMaServiceHttpClientImpl {
public class WxMaServiceImpl extends WxMaServiceHttpComponentsImpl {
}

View File

@@ -2,11 +2,11 @@ package me.chanjar.weixin.mp.api.impl;
/**
* <pre>
* 默认接口实现类使用apache httpclient实现
* 默认接口实现类使用apache httpClient 5实现
* Created by Binary Wang on 2017-5-27.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxMpServiceImpl extends WxMpServiceHttpClientImpl {
public class WxMpServiceImpl extends WxMpServiceHttpComponentsImpl {
}

View File

@@ -0,0 +1,74 @@
package me.chanjar.weixin.open.api.impl;
import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpClientType;
import me.chanjar.weixin.common.util.http.MinishopUploadRequestExecutor;
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
import me.chanjar.weixin.open.api.WxOpenConfigStorage;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.core5.http.HttpHost;
import java.io.File;
/**
* httpclient 5 实现
*
* @author <a href="https://github.com/buaazyl">zhangyl</a>
*/
public class WxOpenServiceHttpComponentsImpl extends WxOpenServiceAbstractImpl<CloseableHttpClient, HttpHost> {
private CloseableHttpClient httpClient;
private HttpHost httpProxy;
@Override
public void initHttp() {
WxOpenConfigStorage configStorage = this.getWxOpenConfigStorage();
HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
apacheHttpClientBuilder.httpProxyHost(configStorage.getHttpProxyHost())
.httpProxyPort(configStorage.getHttpProxyPort())
.httpProxyUsername(configStorage.getHttpProxyUsername())
.httpProxyPassword(configStorage.getHttpProxyPassword() == null ? null :
configStorage.getHttpProxyPassword().toCharArray());
if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort());
}
this.httpClient = apacheHttpClientBuilder.build();
}
@Override
public CloseableHttpClient getRequestHttpClient() {
return httpClient;
}
@Override
public HttpHost getRequestHttpProxy() {
return httpProxy;
}
@Override
public HttpClientType getRequestType() {
return HttpClientType.HTTP_COMPONENTS;
}
@Override
public String get(String url, String queryParam) throws WxErrorException {
return execute(SimpleGetRequestExecutor.create(this), url, queryParam);
}
@Override
public String post(String url, String postData) throws WxErrorException {
return execute(SimplePostRequestExecutor.create(this), url, postData);
}
@Override
public WxMinishopImageUploadResult uploadMinishopMediaFile(String url, File file) throws WxErrorException {
return execute(MinishopUploadRequestExecutor.create(this), url, file);
}
}

View File

@@ -3,6 +3,6 @@ package me.chanjar.weixin.open.api.impl;
/**
* @author <a href="https://github.com/007gzs">007</a>
*/
public class WxOpenServiceImpl extends WxOpenServiceApacheHttpClientImpl {
public class WxOpenServiceImpl extends WxOpenServiceHttpComponentsImpl {
}

View File

@@ -2,11 +2,11 @@ package com.github.binarywang.wxpay.service.impl;
/**
* <pre>
* 微信支付接口请求实现类默认使用Apache HttpClient实现
* 微信支付接口请求实现类默认使用Apache HttpClient 5实现
* Created by Binary Wang on 2017-7-8.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxPayServiceImpl extends WxPayServiceApacheHttpImpl {
public class WxPayServiceImpl extends WxPayServiceHttpComponentsImpl {
}

View File

@@ -2,11 +2,11 @@ package me.chanjar.weixin.qidian.api.impl;
/**
* <pre>
* 默认接口实现类使用apache httpclient实现
* 默认接口实现类使用apache httpClient 5实现
* Created by Binary Wang on 2017-5-27.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxQidianServiceImpl extends WxQidianServiceHttpClientImpl {
public class WxQidianServiceImpl extends WxQidianServiceHttpComponentsImpl {
}