mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-10-30 01:58:23 +08:00
#985 修复多WxApp场景下initHttp方法执行时的空指针异常错误
This commit is contained in:
@ -12,7 +12,6 @@ import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
|||||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||||
import me.chanjar.weixin.mp.enums.TicketType;
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -309,12 +308,32 @@ public interface WxMpService {
|
|||||||
*/
|
*/
|
||||||
void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider);
|
void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Map<String, WxMpConfigStorage>} 加入新的 {@link WxMpConfigStorage},适用于动态添加新的微信应用
|
||||||
|
* @param configStorages
|
||||||
|
*/
|
||||||
|
void addWxMpConfigStorage(String label, WxMpConfigStorage configStorages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从{@link Map<String, WxMpConfigStorage>} 移除 {@link String label} 所对应的 {@link WxMpConfigStorage},适用于动态移除的微信应用
|
||||||
|
* @param label
|
||||||
|
*/
|
||||||
|
void removeWxMpConfigStorage(String label);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值
|
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值
|
||||||
* @return
|
* 随机采用一个{@link String lable}进行Http初始化操作
|
||||||
|
* @param configStorages
|
||||||
*/
|
*/
|
||||||
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages);
|
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值
|
||||||
|
* @param configStorages
|
||||||
|
* @param defaultInitLabel 设置一个{@link WxMpConfigStorage} 所对应的{@link String label}进行Http初始化
|
||||||
|
*/
|
||||||
|
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages, String defaultInitLabel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 进行相应的 WxApp 切换
|
* 进行相应的 WxApp 切换
|
||||||
* @param label
|
* @param label
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
package me.chanjar.weixin.mp.api.impl;
|
package me.chanjar.weixin.mp.api.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.mp.api.*;
|
||||||
|
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
@ -13,21 +23,14 @@ import me.chanjar.weixin.common.util.DataUtils;
|
|||||||
import me.chanjar.weixin.common.util.RandomUtils;
|
import me.chanjar.weixin.common.util.RandomUtils;
|
||||||
import me.chanjar.weixin.common.util.crypto.SHA1;
|
import me.chanjar.weixin.common.util.crypto.SHA1;
|
||||||
import me.chanjar.weixin.common.util.http.*;
|
import me.chanjar.weixin.common.util.http.*;
|
||||||
import me.chanjar.weixin.mp.api.*;
|
|
||||||
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
|
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||||
import me.chanjar.weixin.mp.enums.TicketType;
|
import me.chanjar.weixin.mp.enums.TicketType;
|
||||||
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础实现类.
|
* 基础实现类.
|
||||||
@ -40,7 +43,6 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
|
|||||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
protected WxSessionManager sessionManager = new StandardSessionManager();
|
protected WxSessionManager sessionManager = new StandardSessionManager();
|
||||||
protected WxMpConfigStorage wxMpConfigStorage;
|
|
||||||
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
|
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
|
||||||
private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this);
|
private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this);
|
||||||
private WxMpMenuService menuService = new WxMpMenuServiceImpl(this);
|
private WxMpMenuService menuService = new WxMpMenuServiceImpl(this);
|
||||||
@ -62,7 +64,6 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
|
|||||||
private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this);
|
private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this);
|
||||||
|
|
||||||
private Map<String, WxMpConfigStorage> wxMpConfigStoragePool;
|
private Map<String, WxMpConfigStorage> wxMpConfigStoragePool;
|
||||||
private boolean isMultiWxApp = false;
|
|
||||||
|
|
||||||
private int retrySleepMillis = 1000;
|
private int retrySleepMillis = 1000;
|
||||||
private int maxRetryTimes = 5;
|
private int maxRetryTimes = 5;
|
||||||
@ -334,26 +335,46 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WxMpConfigStorage getWxMpConfigStorage() {
|
public WxMpConfigStorage getWxMpConfigStorage() {
|
||||||
if (isMultiWxApp) {
|
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get());
|
||||||
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.wxMpConfigStorage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
|
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
|
||||||
this.wxMpConfigStorage = wxConfigProvider;
|
Map<String, WxMpConfigStorage> map = new HashMap<>(1);
|
||||||
this.initHttp();
|
map.put(WxMpConfigStorageHolder.get(), wxConfigProvider);
|
||||||
|
setMultiWxMpConfigStorage(map, WxMpConfigStorageHolder.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages) {
|
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages) {
|
||||||
|
String randomKey = configStorages.keySet().iterator().next();
|
||||||
|
setMultiWxMpConfigStorage(configStorages, randomKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages, String defaultInitLabel) {
|
||||||
wxMpConfigStoragePool = configStorages;
|
wxMpConfigStoragePool = configStorages;
|
||||||
isMultiWxApp = true;
|
WxMpConfigStorageHolder.set(defaultInitLabel);
|
||||||
this.initHttp();
|
this.initHttp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addWxMpConfigStorage(String label, WxMpConfigStorage configStorages) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (wxMpConfigStoragePool.containsKey(label)) {
|
||||||
|
throw new RuntimeException("该label已存在,请重新设置一个label");
|
||||||
|
}
|
||||||
|
wxMpConfigStoragePool.put(label, configStorages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeWxMpConfigStorage(String label) {
|
||||||
|
synchronized (this) {
|
||||||
|
wxMpConfigStoragePool.remove(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean switchover(String label) {
|
public boolean switchover(String label) {
|
||||||
if (wxMpConfigStoragePool.containsKey(label)) {
|
if (wxMpConfigStoragePool.containsKey(label)) {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import me.chanjar.weixin.common.error.WxError;
|
|||||||
import me.chanjar.weixin.common.error.WxErrorException;
|
import me.chanjar.weixin.common.error.WxErrorException;
|
||||||
import me.chanjar.weixin.common.util.http.HttpType;
|
import me.chanjar.weixin.common.util.http.HttpType;
|
||||||
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
|
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
|
||||||
|
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
|
||||||
import me.chanjar.weixin.mp.api.WxMpService;
|
import me.chanjar.weixin.mp.api.WxMpService;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ public class WxMpServiceOkHttpImpl extends BaseWxMpServiceImpl<OkHttpClient, OkH
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initHttp() {
|
public void initHttp() {
|
||||||
|
WxMpConfigStorage wxMpConfigStorage = getWxMpConfigStorage();
|
||||||
//设置代理
|
//设置代理
|
||||||
if (wxMpConfigStorage.getHttpProxyHost() != null && wxMpConfigStorage.getHttpProxyPort() > 0) {
|
if (wxMpConfigStorage.getHttpProxyHost() != null && wxMpConfigStorage.getHttpProxyPort() > 0) {
|
||||||
httpProxy = OkHttpProxyInfo.httpProxy(wxMpConfigStorage.getHttpProxyHost(),
|
httpProxy = OkHttpProxyInfo.httpProxy(wxMpConfigStorage.getHttpProxyHost(),
|
||||||
|
|||||||
@ -7,7 +7,12 @@ package me.chanjar.weixin.mp.util;
|
|||||||
*/
|
*/
|
||||||
public class WxMpConfigStorageHolder {
|
public class WxMpConfigStorageHolder {
|
||||||
|
|
||||||
private final static ThreadLocal<String> WX_MP_CONFIG_STORAGE_CHOSE = new ThreadLocal<>();
|
private final static ThreadLocal<String> WX_MP_CONFIG_STORAGE_CHOSE = new ThreadLocal<String>() {
|
||||||
|
@Override
|
||||||
|
protected String initialValue() {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public static String get() {
|
public static String get() {
|
||||||
return WX_MP_CONFIG_STORAGE_CHOSE.get();
|
return WX_MP_CONFIG_STORAGE_CHOSE.get();
|
||||||
|
|||||||
@ -85,6 +85,53 @@ public class WxMpMenuServiceImplTest {
|
|||||||
"}";
|
"}";
|
||||||
|
|
||||||
this.menuId = this.wxService.getMenuService().menuCreate(json);
|
this.menuId = this.wxService.getMenuService().menuCreate(json);
|
||||||
|
if (this.wxService.switchover("test-1")) {
|
||||||
|
this.menuId = this.wxService.getMenuService().menuCreate(json);
|
||||||
|
}
|
||||||
|
System.out.println(this.menuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiCreateConditionalMenu() throws WxErrorException {
|
||||||
|
String json = "{\n" +
|
||||||
|
" \"button\":[\n" +
|
||||||
|
" { \n" +
|
||||||
|
" \"type\":\"click\",\n" +
|
||||||
|
" \"name\":\"今日歌曲\",\n" +
|
||||||
|
" \"key\":\"V1001_TODAY_MUSIC\" \n" +
|
||||||
|
" },\n" +
|
||||||
|
" { \n" +
|
||||||
|
" \"name\":\"菜单\",\n" +
|
||||||
|
" \"sub_button\":[\n" +
|
||||||
|
" { \n" +
|
||||||
|
" \"type\":\"view\",\n" +
|
||||||
|
" \"name\":\"搜索\",\n" +
|
||||||
|
" \"url\":\"http://www.soso.com/\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"type\":\"view\",\n" +
|
||||||
|
" \"name\":\"视频\",\n" +
|
||||||
|
" \"url\":\"http://v.qq.com/\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"type\":\"click\",\n" +
|
||||||
|
" \"name\":\"赞一下我们\",\n" +
|
||||||
|
" \"key\":\"V1001_GOOD\"\n" +
|
||||||
|
" }]\n" +
|
||||||
|
" }],\n" +
|
||||||
|
"\"matchrule\":{\n" +
|
||||||
|
" \"tag_id\":\"2\",\n" +
|
||||||
|
" \"sex\":\"1\",\n" +
|
||||||
|
" \"country\":\"中国\",\n" +
|
||||||
|
" \"province\":\"广东\",\n" +
|
||||||
|
" \"city\":\"广州\",\n" +
|
||||||
|
" \"client_platform_type\":\"2\",\n" +
|
||||||
|
" \"language\":\"zh_CN\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}";
|
||||||
|
if (this.wxService.switchover("test-1")) {
|
||||||
|
this.menuId = this.wxService.getMenuService().menuCreate(json);
|
||||||
|
}
|
||||||
System.out.println(this.menuId);
|
System.out.println(this.menuId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package me.chanjar.weixin.mp.api.test;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
|
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
|
||||||
@ -29,11 +31,14 @@ public class ApiTestModule implements Module {
|
|||||||
|
|
||||||
TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream);
|
TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream);
|
||||||
config.setAccessTokenLock(new ReentrantLock());
|
config.setAccessTokenLock(new ReentrantLock());
|
||||||
WxMpService wxService = new WxMpServiceHttpClientImpl();
|
WxMpService wxMpServiceMulti = new WxMpServiceHttpClientImpl();
|
||||||
wxService.setWxMpConfigStorage(config);
|
|
||||||
|
// TODO 多WxAppId
|
||||||
|
wxMpServiceMulti.setWxMpConfigStorage(config);
|
||||||
|
wxMpServiceMulti.addWxMpConfigStorage("test-1", config);
|
||||||
|
|
||||||
binder.bind(WxMpService.class).toInstance(wxService);
|
|
||||||
binder.bind(WxMpConfigStorage.class).toInstance(config);
|
binder.bind(WxMpConfigStorage.class).toInstance(config);
|
||||||
|
binder.bind(WxMpService.class).toInstance(wxMpServiceMulti);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
this.log.error(e.getMessage(), e);
|
this.log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user