Procházet zdrojové kódy

#985 修复多WxApp场景下initHttp方法执行时的空指针异常错误

master
liaochuntao před 5 roky
committed by Binary Wang
rodič
revize
0937ac85b1
6 změnil soubory, kde provedl 122 přidání a 23 odebrání
  1. +21
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
  2. +38
    -17
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java
  3. +2
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java
  4. +6
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/WxMpConfigStorageHolder.java
  5. +47
    -0
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java
  6. +8
    -3
      weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java

+ 21
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java Zobrazit soubor

@@ -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.enums.TicketType;

import java.util.HashMap;
import java.util.Map;

/**
@@ -309,12 +308,32 @@ public interface WxMpService {
*/
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} 值
* @return
* 随机采用一个{@link String lable}进行Http初始化操作
* @param 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 切换
* @param label


+ 38
- 17
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/BaseWxMpServiceImpl.java Zobrazit soubor

@@ -1,5 +1,15 @@
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.JsonElement;
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.crypto.SHA1;
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.result.WxMpCurrentAutoReplyInfo;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
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.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 WxSessionManager sessionManager = new StandardSessionManager();
protected WxMpConfigStorage wxMpConfigStorage;
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this);
private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(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 Map<String, WxMpConfigStorage> wxMpConfigStoragePool;
private boolean isMultiWxApp = false;

private int retrySleepMillis = 1000;
private int maxRetryTimes = 5;
@@ -334,26 +335,46 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH

@Override
public WxMpConfigStorage getWxMpConfigStorage() {
if (isMultiWxApp) {
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get());
}

return this.wxMpConfigStorage;
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get());
}

@Override
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) {
this.wxMpConfigStorage = wxConfigProvider;
this.initHttp();
Map<String, WxMpConfigStorage> map = new HashMap<>(1);
map.put(WxMpConfigStorageHolder.get(), wxConfigProvider);
setMultiWxMpConfigStorage(map, WxMpConfigStorageHolder.get());
}

@Override
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;
isMultiWxApp = true;
WxMpConfigStorageHolder.set(defaultInitLabel);
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
public boolean switchover(String label) {
if (wxMpConfigStoragePool.containsKey(label)) {


+ 2
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java Zobrazit soubor

@@ -6,6 +6,7 @@ import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.HttpType;
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import okhttp3.*;

@@ -66,6 +67,7 @@ public class WxMpServiceOkHttpImpl extends BaseWxMpServiceImpl<OkHttpClient, OkH

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


+ 6
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/WxMpConfigStorageHolder.java Zobrazit soubor

@@ -7,7 +7,12 @@ package me.chanjar.weixin.mp.util;
*/
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() {
return WX_MP_CONFIG_STORAGE_CHOSE.get();


+ 47
- 0
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpMenuServiceImplTest.java Zobrazit soubor

@@ -85,6 +85,53 @@ public class WxMpMenuServiceImplTest {
"}";

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);
}



+ 8
- 3
weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/test/ApiTestModule.java Zobrazit soubor

@@ -2,6 +2,8 @@ package me.chanjar.weixin.mp.api.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl;
@@ -29,11 +31,14 @@ public class ApiTestModule implements Module {

TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream);
config.setAccessTokenLock(new ReentrantLock());
WxMpService wxService = new WxMpServiceHttpClientImpl();
wxService.setWxMpConfigStorage(config);
WxMpService wxMpServiceMulti = new WxMpServiceHttpClientImpl();

// TODO 多WxAppId
wxMpServiceMulti.setWxMpConfigStorage(config);
wxMpServiceMulti.addWxMpConfigStorage("test-1", config);

binder.bind(WxMpService.class).toInstance(wxService);
binder.bind(WxMpConfigStorage.class).toInstance(config);
binder.bind(WxMpService.class).toInstance(wxMpServiceMulti);
} catch (IOException e) {
this.log.error(e.getMessage(), e);
}


Načítá se…
Zrušit
Uložit