Skip to content

Commit 0937ac8

Browse files
chuntaojunbinarywang
authored andcommitted
#985 修复多WxApp场景下initHttp方法执行时的空指针异常错误
1 parent 28c03d7 commit 0937ac8

File tree

6 files changed

+122
-23
lines changed

6 files changed

+122
-23
lines changed

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import me.chanjar.weixin.mp.bean.result.WxMpUser;
1313
import me.chanjar.weixin.mp.enums.TicketType;
1414

15-
import java.util.HashMap;
1615
import java.util.Map;
1716

1817
/**
@@ -309,12 +308,32 @@ public interface WxMpService {
309308
*/
310309
void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider);
311310

311+
/**
312+
* {@link Map<String, WxMpConfigStorage>} 加入新的 {@link WxMpConfigStorage},适用于动态添加新的微信应用
313+
* @param configStorages
314+
*/
315+
void addWxMpConfigStorage(String label, WxMpConfigStorage configStorages);
316+
317+
/**
318+
* 从{@link Map<String, WxMpConfigStorage>} 移除 {@link String label} 所对应的 {@link WxMpConfigStorage},适用于动态移除的微信应用
319+
* @param label
320+
*/
321+
void removeWxMpConfigStorage(String label);
322+
312323
/**
313324
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值
314-
* @return
325+
* 随机采用一个{@link String lable}进行Http初始化操作
326+
* @param configStorages
315327
*/
316328
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages);
317329

330+
/**
331+
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值
332+
* @param configStorages
333+
* @param defaultInitLabel 设置一个{@link WxMpConfigStorage} 所对应的{@link String label}进行Http初始化
334+
*/
335+
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages, String defaultInitLabel);
336+
318337
/**
319338
* 进行相应的 WxApp 切换
320339
* @param label

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
package me.chanjar.weixin.mp.api.impl;
22

3+
import java.io.IOException;
4+
import java.util.HashMap;
5+
import java.util.concurrent.locks.Lock;
6+
7+
import me.chanjar.weixin.mp.api.*;
8+
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder;
9+
import org.apache.commons.lang3.StringUtils;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
313
import com.google.gson.JsonArray;
414
import com.google.gson.JsonElement;
515
import com.google.gson.JsonObject;
@@ -13,21 +23,14 @@
1323
import me.chanjar.weixin.common.util.RandomUtils;
1424
import me.chanjar.weixin.common.util.crypto.SHA1;
1525
import me.chanjar.weixin.common.util.http.*;
16-
import me.chanjar.weixin.mp.api.*;
1726
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
1827
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
1928
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
2029
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
2130
import me.chanjar.weixin.mp.bean.result.WxMpUser;
2231
import me.chanjar.weixin.mp.enums.TicketType;
23-
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder;
24-
import org.apache.commons.lang3.StringUtils;
25-
import org.slf4j.Logger;
26-
import org.slf4j.LoggerFactory;
2732

28-
import java.io.IOException;
2933
import java.util.Map;
30-
import java.util.concurrent.locks.Lock;
3134

3235
/**
3336
* 基础实现类.
@@ -40,7 +43,6 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
4043
protected final Logger log = LoggerFactory.getLogger(this.getClass());
4144

4245
protected WxSessionManager sessionManager = new StandardSessionManager();
43-
protected WxMpConfigStorage wxMpConfigStorage;
4446
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
4547
private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this);
4648
private WxMpMenuService menuService = new WxMpMenuServiceImpl(this);
@@ -62,7 +64,6 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
6264
private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this);
6365

6466
private Map<String, WxMpConfigStorage> wxMpConfigStoragePool;
65-
private boolean isMultiWxApp = false;
6667

6768
private int retrySleepMillis = 1000;
6869
private int maxRetryTimes = 5;
@@ -334,26 +335,46 @@ public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E da
334335

335336
@Override
336337
public WxMpConfigStorage getWxMpConfigStorage() {
337-
if (isMultiWxApp) {
338-
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get());
339-
}
340-
341-
return this.wxMpConfigStorage;
338+
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get());
342339
}
343340

344341
@Override
345342
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
346-
this.wxMpConfigStorage = wxConfigProvider;
347-
this.initHttp();
343+
Map<String, WxMpConfigStorage> map = new HashMap<>(1);
344+
map.put(WxMpConfigStorageHolder.get(), wxConfigProvider);
345+
setMultiWxMpConfigStorage(map, WxMpConfigStorageHolder.get());
348346
}
349347

350348
@Override
351349
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages) {
350+
String randomKey = configStorages.keySet().iterator().next();
351+
setMultiWxMpConfigStorage(configStorages, randomKey);
352+
}
353+
354+
@Override
355+
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages, String defaultInitLabel) {
352356
wxMpConfigStoragePool = configStorages;
353-
isMultiWxApp = true;
357+
WxMpConfigStorageHolder.set(defaultInitLabel);
354358
this.initHttp();
355359
}
356360

361+
@Override
362+
public void addWxMpConfigStorage(String label, WxMpConfigStorage configStorages) {
363+
synchronized (this) {
364+
if (wxMpConfigStoragePool.containsKey(label)) {
365+
throw new RuntimeException("该label已存在,请重新设置一个label");
366+
}
367+
wxMpConfigStoragePool.put(label, configStorages);
368+
}
369+
}
370+
371+
@Override
372+
public void removeWxMpConfigStorage(String label) {
373+
synchronized (this) {
374+
wxMpConfigStoragePool.remove(label);
375+
}
376+
}
377+
357378
@Override
358379
public boolean switchover(String label) {
359380
if (wxMpConfigStoragePool.containsKey(label)) {

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import me.chanjar.weixin.common.error.WxErrorException;
77
import me.chanjar.weixin.common.util.http.HttpType;
88
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
9+
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
910
import me.chanjar.weixin.mp.api.WxMpService;
1011
import okhttp3.*;
1112

@@ -66,6 +67,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException {
6667

6768
@Override
6869
public void initHttp() {
70+
WxMpConfigStorage wxMpConfigStorage = getWxMpConfigStorage();
6971
//设置代理
7072
if (wxMpConfigStorage.getHttpProxyHost() != null && wxMpConfigStorage.getHttpProxyPort() > 0) {
7173
httpProxy = OkHttpProxyInfo.httpProxy(wxMpConfigStorage.getHttpProxyHost(),

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/WxMpConfigStorageHolder.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
*/
88
public class WxMpConfigStorageHolder {
99

10-
private final static ThreadLocal<String> WX_MP_CONFIG_STORAGE_CHOSE = new ThreadLocal<>();
10+
private final static ThreadLocal<String> WX_MP_CONFIG_STORAGE_CHOSE = new ThreadLocal<String>() {
11+
@Override
12+
protected String initialValue() {
13+
return "default";
14+
}
15+
};
1116

1217
public static String get() {
1318
return WX_MP_CONFIG_STORAGE_CHOSE.get();

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,53 @@ public void testCreateConditionalMenu() throws WxErrorException {
8585
"}";
8686

8787
this.menuId = this.wxService.getMenuService().menuCreate(json);
88+
if (this.wxService.switchover("test-1")) {
89+
this.menuId = this.wxService.getMenuService().menuCreate(json);
90+
}
91+
System.out.println(this.menuId);
92+
}
93+
94+
@Test
95+
public void testMultiCreateConditionalMenu() throws WxErrorException {
96+
String json = "{\n" +
97+
" \"button\":[\n" +
98+
" { \n" +
99+
" \"type\":\"click\",\n" +
100+
" \"name\":\"今日歌曲\",\n" +
101+
" \"key\":\"V1001_TODAY_MUSIC\" \n" +
102+
" },\n" +
103+
" { \n" +
104+
" \"name\":\"菜单\",\n" +
105+
" \"sub_button\":[\n" +
106+
" { \n" +
107+
" \"type\":\"view\",\n" +
108+
" \"name\":\"搜索\",\n" +
109+
" \"url\":\"http://www.soso.com/\"\n" +
110+
" },\n" +
111+
" {\n" +
112+
" \"type\":\"view\",\n" +
113+
" \"name\":\"视频\",\n" +
114+
" \"url\":\"http://v.qq.com/\"\n" +
115+
" },\n" +
116+
" {\n" +
117+
" \"type\":\"click\",\n" +
118+
" \"name\":\"赞一下我们\",\n" +
119+
" \"key\":\"V1001_GOOD\"\n" +
120+
" }]\n" +
121+
" }],\n" +
122+
"\"matchrule\":{\n" +
123+
" \"tag_id\":\"2\",\n" +
124+
" \"sex\":\"1\",\n" +
125+
" \"country\":\"中国\",\n" +
126+
" \"province\":\"广东\",\n" +
127+
" \"city\":\"广州\",\n" +
128+
" \"client_platform_type\":\"2\",\n" +
129+
" \"language\":\"zh_CN\"\n" +
130+
" }\n" +
131+
"}";
132+
if (this.wxService.switchover("test-1")) {
133+
this.menuId = this.wxService.getMenuService().menuCreate(json);
134+
}
88135
System.out.println(this.menuId);
89136
}
90137

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.io.IOException;
44
import java.io.InputStream;
5+
import java.util.HashMap;
6+
import java.util.Map;
57
import java.util.concurrent.locks.ReentrantLock;
68

79
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
@@ -29,11 +31,14 @@ public void configure(Binder binder) {
2931

3032
TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream);
3133
config.setAccessTokenLock(new ReentrantLock());
32-
WxMpService wxService = new WxMpServiceHttpClientImpl();
33-
wxService.setWxMpConfigStorage(config);
34+
WxMpService wxMpServiceMulti = new WxMpServiceHttpClientImpl();
35+
36+
// TODO 多WxAppId
37+
wxMpServiceMulti.setWxMpConfigStorage(config);
38+
wxMpServiceMulti.addWxMpConfigStorage("test-1", config);
3439

35-
binder.bind(WxMpService.class).toInstance(wxService);
3640
binder.bind(WxMpConfigStorage.class).toInstance(config);
41+
binder.bind(WxMpService.class).toInstance(wxMpServiceMulti);
3742
} catch (IOException e) {
3843
this.log.error(e.getMessage(), e);
3944
}

0 commit comments

Comments
 (0)