code clean up for common module

This commit is contained in:
BinaryWang
2016-08-02 19:40:44 +08:00
parent baf99d6809
commit 6643498a66
47 changed files with 956 additions and 977 deletions

View File

@@ -62,20 +62,6 @@ public class WxConsts {
* 群发反馈消息代码所对应的文字描述 * 群发反馈消息代码所对应的文字描述
*/ */
public static final Map<String, String> MASS_ST_2_DESC = new HashMap<String, String>(); public static final Map<String, String> MASS_ST_2_DESC = new HashMap<String, String>();
static {
MASS_ST_2_DESC.put(MASS_ST_SUCCESS, "发送成功");
MASS_ST_2_DESC.put(MASS_ST_FAIL, "发送失败");
MASS_ST_2_DESC.put(MASS_ST_涉嫌广告, "涉嫌广告");
MASS_ST_2_DESC.put(MASS_ST_涉嫌政治, "涉嫌政治");
MASS_ST_2_DESC.put(MASS_ST_涉嫌社会, "涉嫌社会");
MASS_ST_2_DESC.put(MASS_ST_涉嫌色情, "涉嫌色情");
MASS_ST_2_DESC.put(MASS_ST_涉嫌违法犯罪, "涉嫌违法犯罪");
MASS_ST_2_DESC.put(MASS_ST_涉嫌欺诈, "涉嫌欺诈");
MASS_ST_2_DESC.put(MASS_ST_涉嫌版权, "涉嫌版权");
MASS_ST_2_DESC.put(MASS_ST_涉嫌互推_互相宣传, "涉嫌互推_互相宣传");
MASS_ST_2_DESC.put(MASS_ST_涉嫌其他, "涉嫌其他");
}
/////////////////////// ///////////////////////
// 微信端推送过来的事件类型 // 微信端推送过来的事件类型
/////////////////////// ///////////////////////
@@ -103,11 +89,9 @@ public class WxConsts {
public static final String EVT_USER_VIEW_CARD = "user_view_card"; public static final String EVT_USER_VIEW_CARD = "user_view_card";
public static final String EVT_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card"; public static final String EVT_USER_ENTER_SESSION_FROM_CARD = "user_enter_session_from_card";
public static final String EVT_CARD_SKU_REMIND = "card_sku_remind"; // 库存报警 public static final String EVT_CARD_SKU_REMIND = "card_sku_remind"; // 库存报警
public static final String EVT_KF_CREATE_SESSION = "kf_create_session"; // 客服接入会话 public static final String EVT_KF_CREATE_SESSION = "kf_create_session"; // 客服接入会话
public static final String EVT_KF_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话 public static final String EVT_KF_CLOSE_SESSION = "kf_close_session"; // 客服关闭会话
public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话 public static final String EVT_KF_SWITCH_SESSION = "kf_switch_session"; // 客服转接会话
/////////////////////// ///////////////////////
// 上传多媒体文件的类型 // 上传多媒体文件的类型
/////////////////////// ///////////////////////
@@ -116,7 +100,6 @@ public class WxConsts {
public static final String MEDIA_VIDEO = "video"; public static final String MEDIA_VIDEO = "video";
public static final String MEDIA_THUMB = "thumb"; public static final String MEDIA_THUMB = "thumb";
public static final String MEDIA_FILE = "file"; public static final String MEDIA_FILE = "file";
/////////////////////// ///////////////////////
// 文件类型 // 文件类型
/////////////////////// ///////////////////////
@@ -124,40 +107,63 @@ public class WxConsts {
public static final String FILE_MP3 = "mp3"; public static final String FILE_MP3 = "mp3";
public static final String FILE_AMR = "amr"; public static final String FILE_AMR = "amr";
public static final String FILE_MP4 = "mp4"; public static final String FILE_MP4 = "mp4";
/**
* 点击推事件
*/
public static final String BUTTON_CLICK = "click";
/////////////////////// ///////////////////////
// 自定义菜单的按钮类型 // 自定义菜单的按钮类型
/////////////////////// ///////////////////////
/** 点击推事件 */ /**
public static final String BUTTON_CLICK = "click"; * 跳转URL
/** 跳转URL */ */
public static final String BUTTON_VIEW = "view"; public static final String BUTTON_VIEW = "view";
/** 扫码推事件 */ /**
* 扫码推事件
*/
public static final String BUTTON_SCANCODE_PUSH = "scancode_push"; public static final String BUTTON_SCANCODE_PUSH = "scancode_push";
/** 扫码推事件且弹出“消息接收中”提示框 */ /**
* 扫码推事件且弹出“消息接收中”提示框
*/
public static final String BUTTON_SCANCODE_WAITMSG = "scancode_waitmsg"; public static final String BUTTON_SCANCODE_WAITMSG = "scancode_waitmsg";
/** 弹出系统拍照发图 */ /**
* 弹出系统拍照发图
*/
public static final String BUTTON_PIC_SYSPHOTO = "pic_sysphoto"; public static final String BUTTON_PIC_SYSPHOTO = "pic_sysphoto";
/** 弹出拍照或者相册发图 */ /**
* 弹出拍照或者相册发图
*/
public static final String BUTTON_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; public static final String BUTTON_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
/** 弹出微信相册发图器 */ /**
* 弹出微信相册发图器
*/
public static final String BUTTON_PIC_WEIXIN = "pic_weixin"; public static final String BUTTON_PIC_WEIXIN = "pic_weixin";
/** 弹出地理位置选择器 */ /**
* 弹出地理位置选择器
*/
public static final String BUTTON_LOCATION_SELECT = "location_select"; public static final String BUTTON_LOCATION_SELECT = "location_select";
/** 下发消息(除文本消息) */ /**
* 下发消息(除文本消息)
*/
public static final String BUTTON_MEDIA_ID = "media_id"; public static final String BUTTON_MEDIA_ID = "media_id";
/** 跳转图文消息URL */ /**
* 跳转图文消息URL
*/
public static final String BUTTON_VIEW_LIMITED = "view_limited"; public static final String BUTTON_VIEW_LIMITED = "view_limited";
/**
* 不弹出授权页面直接跳转只能获取用户openid
*/
public static final String OAUTH2_SCOPE_BASE = "snsapi_base";
/////////////////////// ///////////////////////
// oauth2网页授权的scope // oauth2网页授权的scope
/////////////////////// ///////////////////////
/** 不弹出授权页面直接跳转只能获取用户openid */ /**
public static final String OAUTH2_SCOPE_BASE = "snsapi_base"; * 弹出授权页面可通过openid拿到昵称、性别、所在地。并且即使在未关注的情况下只要用户授权也能获取其信息
/** 弹出授权页面可通过openid拿到昵称、性别、所在地。并且即使在未关注的情况下只要用户授权也能获取其信息 */ */
public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo"; public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo";
/////////////////////// ///////////////////////
// 永久素材类型 // 永久素材类型
/////////////////////// ///////////////////////
@@ -165,4 +171,18 @@ public class WxConsts {
public static final String MATERIAL_VOICE = "voice"; public static final String MATERIAL_VOICE = "voice";
public static final String MATERIAL_IMAGE = "image"; public static final String MATERIAL_IMAGE = "image";
public static final String MATERIAL_VIDEO = "video"; public static final String MATERIAL_VIDEO = "video";
static {
MASS_ST_2_DESC.put(MASS_ST_SUCCESS, "发送成功");
MASS_ST_2_DESC.put(MASS_ST_FAIL, "发送失败");
MASS_ST_2_DESC.put(MASS_ST_涉嫌广告, "涉嫌广告");
MASS_ST_2_DESC.put(MASS_ST_涉嫌政治, "涉嫌政治");
MASS_ST_2_DESC.put(MASS_ST_涉嫌社会, "涉嫌社会");
MASS_ST_2_DESC.put(MASS_ST_涉嫌色情, "涉嫌色情");
MASS_ST_2_DESC.put(MASS_ST_涉嫌违法犯罪, "涉嫌违法犯罪");
MASS_ST_2_DESC.put(MASS_ST_涉嫌欺诈, "涉嫌欺诈");
MASS_ST_2_DESC.put(MASS_ST_涉嫌版权, "涉嫌版权");
MASS_ST_2_DESC.put(MASS_ST_涉嫌互推_互相宣传, "涉嫌互推_互相宣传");
MASS_ST_2_DESC.put(MASS_ST_涉嫌其他, "涉嫌其他");
}
} }

View File

@@ -10,15 +10,16 @@ public interface WxMessageDuplicateChecker {
/** /**
* <h2>公众号的排重方式</h2> * <h2>公众号的排重方式</h2>
* * <p>
* <p>普通消息关于重试的消息排重推荐使用msgid排重。<a href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html">文档参考</a>。</p> * <p>普通消息关于重试的消息排重推荐使用msgid排重。<a href="http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html">文档参考</a>。</p>
* <p>事件消息关于重试的消息排重推荐使用FromUserName + CreateTime 排重。<a href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html">文档参考</a></p> * <p>事件消息关于重试的消息排重推荐使用FromUserName + CreateTime 排重。<a href="http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html">文档参考</a></p>
* * <p>
* <h2>企业号的排重方式</h2> * <h2>企业号的排重方式</h2>
* * <p>
* 官方文档完全没有写,参照公众号的方式排重。 * 官方文档完全没有写,参照公众号的方式排重。
* * <p>
* <p>或者可以采取更简单的方式如果有MsgId就用MsgId排重如果没有就用FromUserName+CreateTime排重</p> * <p>或者可以采取更简单的方式如果有MsgId就用MsgId排重如果没有就用FromUserName+CreateTime排重</p>
*
* @param messageId messageId需要根据上面讲的方式构造 * @param messageId messageId需要根据上面讲的方式构造
* @return 如果是重复消息返回true否则返回false * @return 如果是重复消息返回true否则返回false
*/ */

View File

@@ -46,7 +46,8 @@ public class WxMessageInMemoryDuplicateChecker implements WxMessageDuplicateChec
/** /**
* WxMsgIdInMemoryDuplicateChecker构造函数 * WxMsgIdInMemoryDuplicateChecker构造函数
* @param timeToLive 一个消息ID在内存的过期时间毫秒 *
* @param timeToLive 一个消息ID在内存的过期时间毫秒
* @param clearPeriod 每隔多少周期检查消息ID是否过期毫秒 * @param clearPeriod 每隔多少周期检查消息ID是否过期毫秒
*/ */
public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) { public WxMessageInMemoryDuplicateChecker(Long timeToLive, Long clearPeriod) {

View File

@@ -11,6 +11,10 @@ public class WxAccessToken implements Serializable {
private int expiresIn = -1; private int expiresIn = -1;
public static WxAccessToken fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxAccessToken.class);
}
public String getAccessToken() { public String getAccessToken() {
return accessToken; return accessToken;
} }
@@ -27,8 +31,4 @@ public class WxAccessToken implements Serializable {
this.expiresIn = expiresIn; this.expiresIn = expiresIn;
} }
public static WxAccessToken fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxAccessToken.class);
}
} }

View File

@@ -51,11 +51,11 @@ public class WxJsapiSignature implements Serializable {
} }
public String getAppid() { public String getAppid() {
return appid; return appid;
} }
public void setAppid(String appid) { public void setAppid(String appid) {
this.appid = appid; this.appid = appid;
} }
} }

View File

@@ -1,5 +1,7 @@
package me.chanjar.weixin.common.bean; package me.chanjar.weixin.common.bean;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Serializable; import java.io.Serializable;
@@ -7,12 +9,10 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
/** /**
* 企业号菜单 * 企业号菜单
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class WxMenu implements Serializable { public class WxMenu implements Serializable {
@@ -22,6 +22,22 @@ public class WxMenu implements Serializable {
private WxMenuRule matchRule; private WxMenuRule matchRule;
/**
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*/
public static WxMenu fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMenu.class);
}
/**
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*/
public static WxMenu fromJson(InputStream is) {
return WxGsonBuilder.create().fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class);
}
public List<WxMenuButton> getButtons() { public List<WxMenuButton> getButtons() {
return buttons; return buttons;
} }
@@ -42,27 +58,11 @@ public class WxMenu implements Serializable {
return WxGsonBuilder.create().toJson(this); return WxGsonBuilder.create().toJson(this);
} }
/**
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*/
public static WxMenu fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMenu.class);
}
/**
* 要用 http://mp.weixin.qq.com/wiki/16/ff9b7b85220e1396ffa16794a9d95adc.html 格式来反序列化
* 相比 http://mp.weixin.qq.com/wiki/13/43de8269be54a0a6f64413e4dfa94f39.html 的格式外层多套了一个menu
*/
public static WxMenu fromJson(InputStream is) {
return WxGsonBuilder.create().fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), WxMenu.class);
}
@Override @Override
public String toString() { public String toString() {
return "WxMenu{" + return "WxMenu{" +
"buttons=" + buttons + "buttons=" + buttons +
'}'; '}';
} }
public static class WxMenuButton { public static class WxMenuButton {
@@ -117,12 +117,12 @@ public class WxMenu implements Serializable {
@Override @Override
public String toString() { public String toString() {
return "WxMenuButton{" + return "WxMenuButton{" +
"type='" + type + '\'' + "type='" + type + '\'' +
", name='" + name + '\'' + ", name='" + name + '\'' +
", key='" + key + '\'' + ", key='" + key + '\'' +
", url='" + url + '\'' + ", url='" + url + '\'' +
", subButtons=" + subButtons + ", subButtons=" + subButtons +
'}'; '}';
} }
} }
@@ -194,14 +194,14 @@ public class WxMenu implements Serializable {
@Override @Override
public String toString() { public String toString() {
return "matchrule:{" + return "matchrule:{" +
"tag_id='" + tagId + '\'' + "tag_id='" + tagId + '\'' +
", sex='" + sex + '\'' + ", sex='" + sex + '\'' +
", country" + country + '\'' + ", country" + country + '\'' +
", province" + province + '\'' + ", province" + province + '\'' +
", city" + city + '\'' + ", city" + city + '\'' +
", client_platform_type" + clientPlatformType + '\'' + ", client_platform_type" + clientPlatformType + '\'' +
", language" + language + '\'' + ", language" + language + '\'' +
"}"; "}";
} }
} }

View File

@@ -6,8 +6,8 @@ import java.io.Serializable;
/** /**
* 微信错误码说明,请阅读: <a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">全局返回码说明</a> * 微信错误码说明,请阅读: <a href="http://mp.weixin.qq.com/wiki/10/6380dc743053a91c544ffd2b7c959166.html">全局返回码说明</a>
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class WxError implements Serializable { public class WxError implements Serializable {
@@ -19,6 +19,15 @@ public class WxError implements Serializable {
private String json; private String json;
public static WxError fromJson(String json) {
WxError error = WxGsonBuilder.create().fromJson(json, WxError.class);
return error;
}
public static Builder newBuilder() {
return new Builder();
}
public int getErrorCode() { public int getErrorCode() {
return errorCode; return errorCode;
} }
@@ -43,24 +52,15 @@ public class WxError implements Serializable {
this.json = json; this.json = json;
} }
public static WxError fromJson(String json) {
WxError error = WxGsonBuilder.create().fromJson(json, WxError.class);
return error;
}
@Override @Override
public String toString() { public String toString() {
if(json != null){ if (json != null) {
return json; return json;
} }
return "错误: Code=" + errorCode + ", Msg=" + errorMsg; return "错误: Code=" + errorCode + ", Msg=" + errorMsg;
} }
public static Builder newBuilder(){ public static class Builder {
return new Builder();
}
public static class Builder{
private int errorCode; private int errorCode;
private String errorMsg; private String errorMsg;
@@ -74,7 +74,7 @@ public class WxError implements Serializable {
return this; return this;
} }
public WxError build(){ public WxError build() {
WxError wxError = new WxError(); WxError wxError = new WxError();
wxError.setErrorCode(this.errorCode); wxError.setErrorCode(this.errorCode);
wxError.setErrorMsg(this.errorMsg); wxError.setErrorMsg(this.errorMsg);

View File

@@ -12,6 +12,10 @@ public class WxMediaUploadResult implements Serializable {
private String thumbMediaId; private String thumbMediaId;
private long createdAt; private long createdAt;
public static WxMediaUploadResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class);
}
public String getType() { public String getType() {
return type; return type;
} }
@@ -44,14 +48,10 @@ public class WxMediaUploadResult implements Serializable {
this.thumbMediaId = thumbMediaId; this.thumbMediaId = thumbMediaId;
} }
public static WxMediaUploadResult fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMediaUploadResult.class);
}
@Override @Override
public String toString() { public String toString() {
return "WxUploadResult [type=" + type + ", media_id=" + mediaId + ", thumb_media_id=" + thumbMediaId return "WxUploadResult [type=" + type + ", media_id=" + mediaId + ", thumb_media_id=" + thumbMediaId
+ ", created_at=" + createdAt + "]"; + ", created_at=" + createdAt + "]";
} }
} }

View File

@@ -26,6 +26,6 @@ package me.chanjar.weixin.common.session;
public class Constants { public class Constants {
public static final String Package = "me.chanjar.weixin.common.session"; public static final String Package = "me.chanjar.weixin.common.session";
} }

View File

@@ -8,6 +8,11 @@ public interface InternalSession {
*/ */
WxSession getSession(); WxSession getSession();
/**
* Return the <code>isValid</code> flag for this session.
*/
boolean isValid();
/** /**
* Set the <code>isValid</code> flag for this session. * Set the <code>isValid</code> flag for this session.
* *
@@ -15,11 +20,6 @@ public interface InternalSession {
*/ */
void setValid(boolean isValid); void setValid(boolean isValid);
/**
* Return the <code>isValid</code> flag for this session.
*/
boolean isValid();
/** /**
* Return the session identifier for this session. * Return the session identifier for this session.
*/ */

View File

@@ -7,11 +7,10 @@ public interface InternalSessionManager {
* specified session id (if any); otherwise return <code>null</code>. * specified session id (if any); otherwise return <code>null</code>.
* *
* @param id The session id for the session to be returned * @param id The session id for the session to be returned
* * @throws IllegalStateException if a new session cannot be
* @exception IllegalStateException if a new session cannot be * instantiated for any reason
* instantiated for any reason * @throws java.io.IOException if an input/output error occurs while
* @exception java.io.IOException if an input/output error occurs while * processing this request
* processing this request
*/ */
InternalSession findSession(String id); InternalSession findSession(String id);
@@ -23,10 +22,10 @@ public interface InternalSessionManager {
* <code>null</code>. * <code>null</code>.
* *
* @param sessionId The session id which should be used to create the * @param sessionId The session id which should be used to create the
* new session; if <code>null</code>, a new session id will be * new session; if <code>null</code>, a new session id will be
* generated * generated
* @exception IllegalStateException if a new session cannot be * @throws IllegalStateException if a new session cannot be
* instantiated for any reason * instantiated for any reason
*/ */
InternalSession createSession(String sessionId); InternalSession createSession(String sessionId);
@@ -40,8 +39,8 @@ public interface InternalSessionManager {
/** /**
* Remove this Session from the active Sessions for this Manager. * Remove this Session from the active Sessions for this Manager.
* *
* @param session Session to be removed * @param session Session to be removed
* @param update Should the expiration statistics be updated * @param update Should the expiration statistics be updated
*/ */
void remove(InternalSession session, boolean update); void remove(InternalSession session, boolean update);
@@ -59,6 +58,7 @@ public interface InternalSessionManager {
* @return number of sessions active * @return number of sessions active
*/ */
int getActiveSessions(); int getActiveSessions();
/** /**
* Get a session from the recycled ones or create a new empty one. * Get a session from the recycled ones or create a new empty one.
* The PersistentManager manager does not need to create session data * The PersistentManager manager does not need to create session data
@@ -88,6 +88,7 @@ public interface InternalSessionManager {
* 要和{@link #setBackgroundProcessorDelay(int)}联合起来看 * 要和{@link #setBackgroundProcessorDelay(int)}联合起来看
* 如果把这个数字设置为6默认那么就是说manager要等待 6 * backgroundProcessorDay的时间才会清理过期session * 如果把这个数字设置为6默认那么就是说manager要等待 6 * backgroundProcessorDay的时间才会清理过期session
* </pre> * </pre>
*
* @param processExpiresFrequency the new manager checks frequency * @param processExpiresFrequency the new manager checks frequency
*/ */
void setProcessExpiresFrequency(int processExpiresFrequency); void setProcessExpiresFrequency(int processExpiresFrequency);
@@ -97,6 +98,7 @@ public interface InternalSessionManager {
* Set the manager background processor delay * Set the manager background processor delay
* 设置manager sleep几秒尝试执行一次background操作清理过期session * 设置manager sleep几秒尝试执行一次background操作清理过期session
* </pre> * </pre>
*
* @param backgroundProcessorDelay * @param backgroundProcessorDelay
*/ */
void setBackgroundProcessorDelay(int backgroundProcessorDelay); void setBackgroundProcessorDelay(int backgroundProcessorDelay);
@@ -106,6 +108,7 @@ public interface InternalSessionManager {
* Set the maximum number of active Sessions allowed, or -1 for * Set the maximum number of active Sessions allowed, or -1 for
* no limit. * no limit.
* 设置最大活跃session数默认无限 * 设置最大活跃session数默认无限
*
* @param max The new maximum number of sessions * @param max The new maximum number of sessions
*/ */
void setMaxActiveSessions(int max); void setMaxActiveSessions(int max);

View File

@@ -12,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
applicationSession.session.ise=invalid session state applicationSession.session.ise=invalid session state
applicationSession.value.iae=null value applicationSession.value.iae=null value
fileStore.saving=Saving Session {0} to file {1} fileStore.saving=Saving Session {0} to file {1}

View File

@@ -12,17 +12,68 @@ public class StandardSession implements WxSession, InternalSession {
* The string manager for this package. * The string manager for this package.
*/ */
protected static final StringManager sm = protected static final StringManager sm =
StringManager.getManager(Constants.Package); StringManager.getManager(Constants.Package);
/**
* Type array.
*/
protected static final String EMPTY_ARRAY[] = new String[0];
// ------------------------------ WxSession // ------------------------------ WxSession
protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>(); protected Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
/**
* The session identifier of this Session.
*/
protected String id = null;
/**
* Flag indicating whether this session is valid or not.
*/
protected volatile boolean isValid = false;
/**
* We are currently processing a session expiration, so bypass
* certain IllegalStateException tests. NOTE: This value is not
* included in the serialized version of this object.
*/
protected transient volatile boolean expiring = false;
/**
* The Manager with which this Session is associated.
*/
protected transient InternalSessionManager manager = null;
// ------------------------------ InternalSession
/**
* The time this session was created, in milliseconds since midnight,
* January 1, 1970 GMT.
*/
protected long creationTime = 0L;
/**
* The current accessed time for this session.
*/
protected volatile long thisAccessedTime = creationTime;
/**
* The default maximum inactive interval for Sessions created by
* this Manager.
*/
protected int maxInactiveInterval = 30 * 60;
/**
* The facade associated with this session. NOTE: This value is not
* included in the serialized version of this object.
*/
protected transient StandardSessionFacade facade = null;
/**
* The access count for this session.
*/
protected transient AtomicInteger accessCount = null;
public StandardSession(InternalSessionManager manager) {
this.manager = manager;
this.accessCount = new AtomicInteger();
}
@Override @Override
public Object getAttribute(String name) { public Object getAttribute(String name) {
if (!isValidInternal()) if (!isValidInternal())
throw new IllegalStateException throw new IllegalStateException
(sm.getString("sessionImpl.getAttribute.ise")); (sm.getString("sessionImpl.getAttribute.ise"));
if (name == null) return null; if (name == null) return null;
@@ -33,7 +84,7 @@ public class StandardSession implements WxSession, InternalSession {
public Enumeration<String> getAttributeNames() { public Enumeration<String> getAttributeNames() {
if (!isValidInternal()) if (!isValidInternal())
throw new IllegalStateException throw new IllegalStateException
(sm.getString("sessionImpl.getAttributeNames.ise")); (sm.getString("sessionImpl.getAttributeNames.ise"));
Set<String> names = new HashSet<String>(); Set<String> names = new HashSet<String>();
names.addAll(attributes.keySet()); names.addAll(attributes.keySet());
@@ -45,7 +96,7 @@ public class StandardSession implements WxSession, InternalSession {
// Name cannot be null // Name cannot be null
if (name == null) if (name == null)
throw new IllegalArgumentException throw new IllegalArgumentException
(sm.getString("sessionImpl.setAttribute.namenull")); (sm.getString("sessionImpl.setAttribute.namenull"));
// Null value is the same as removeAttribute() // Null value is the same as removeAttribute()
if (value == null) { if (value == null) {
@@ -56,97 +107,32 @@ public class StandardSession implements WxSession, InternalSession {
// Validate our current state // Validate our current state
if (!isValidInternal()) if (!isValidInternal())
throw new IllegalStateException(sm.getString( throw new IllegalStateException(sm.getString(
"sessionImpl.setAttribute.ise", getIdInternal())); "sessionImpl.setAttribute.ise", getIdInternal()));
attributes.put(name, value); attributes.put(name, value);
} }
@Override @Override
public void removeAttribute(String name) { public void removeAttribute(String name) {
removeAttributeInternal(name); removeAttributeInternal(name);
} }
@Override @Override
public void invalidate() { public void invalidate() {
if (!isValidInternal()) if (!isValidInternal())
throw new IllegalStateException throw new IllegalStateException
(sm.getString("sessionImpl.invalidate.ise")); (sm.getString("sessionImpl.invalidate.ise"));
// Cause this session to expire // Cause this session to expire
expire(); expire();
} }
// ------------------------------ InternalSession
/**
* The session identifier of this Session.
*/
protected String id = null;
/**
* Flag indicating whether this session is valid or not.
*/
protected volatile boolean isValid = false;
/**
* We are currently processing a session expiration, so bypass
* certain IllegalStateException tests. NOTE: This value is not
* included in the serialized version of this object.
*/
protected transient volatile boolean expiring = false;
/**
* The Manager with which this Session is associated.
*/
protected transient InternalSessionManager manager = null;
/**
* Type array.
*/
protected static final String EMPTY_ARRAY[] = new String[0];
/**
* The time this session was created, in milliseconds since midnight,
* January 1, 1970 GMT.
*/
protected long creationTime = 0L;
/**
* The current accessed time for this session.
*/
protected volatile long thisAccessedTime = creationTime;
/**
* The default maximum inactive interval for Sessions created by
* this Manager.
*/
protected int maxInactiveInterval = 30 * 60;
/**
* The facade associated with this session. NOTE: This value is not
* included in the serialized version of this object.
*/
protected transient StandardSessionFacade facade = null;
/**
* The access count for this session.
*/
protected transient AtomicInteger accessCount = null;
public StandardSession(InternalSessionManager manager) {
this.manager = manager;
this.accessCount = new AtomicInteger();
}
@Override @Override
public WxSession getSession() { public WxSession getSession() {
if (facade == null){ if (facade == null) {
facade = new StandardSessionFacade(this); facade = new StandardSessionFacade(this);
} }
return (facade); return (facade);
@@ -161,16 +147,6 @@ public class StandardSession implements WxSession, InternalSession {
return this.isValid; return this.isValid;
} }
/**
* Set the <code>isValid</code> flag for this session.
*
* @param isValid The new value for the <code>isValid</code> flag
*/
@Override
public void setValid(boolean isValid) {
this.isValid = isValid;
}
@Override @Override
public boolean isValid() { public boolean isValid() {
if (!this.isValid) { if (!this.isValid) {
@@ -197,6 +173,16 @@ public class StandardSession implements WxSession, InternalSession {
return this.isValid; return this.isValid;
} }
/**
* Set the <code>isValid</code> flag for this session.
*
* @param isValid The new value for the <code>isValid</code> flag
*/
@Override
public void setValid(boolean isValid) {
this.isValid = isValid;
}
@Override @Override
public String getIdInternal() { public String getIdInternal() {
return (this.id); return (this.id);

View File

@@ -13,16 +13,65 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/ */
public class StandardSessionManager implements WxSessionManager, InternalSessionManager { public class StandardSessionManager implements WxSessionManager, InternalSessionManager {
protected final Logger log = LoggerFactory.getLogger(StandardSessionManager.class);
protected static final StringManager sm = protected static final StringManager sm =
StringManager.getManager(Constants.Package); StringManager.getManager(Constants.Package);
/**
* The descriptive name of this Manager implementation (for logging).
*/
private static final String name = "SessionManagerImpl";
protected final Logger log = LoggerFactory.getLogger(StandardSessionManager.class);
private final Object maxActiveUpdateLock = new Object();
/**
* 后台清理线程是否已经开启
*/
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
// -------------------------------------- InternalSessionManager
/** /**
* The set of currently active Sessions for this Manager, keyed by * The set of currently active Sessions for this Manager, keyed by
* session identifier. * session identifier.
*/ */
protected Map<String, InternalSession> sessions = new ConcurrentHashMap<String, InternalSession>(); protected Map<String, InternalSession> sessions = new ConcurrentHashMap<String, InternalSession>();
/**
* The maximum number of active Sessions allowed, or -1 for no limit.
*/
protected int maxActiveSessions = -1;
/**
* Number of session creations that failed due to maxActiveSessions.
*/
protected int rejectedSessions = 0;
/**
* The default maximum inactive interval for Sessions created by
* this Manager.
*/
protected int maxInactiveInterval = 30 * 60;
// Number of sessions created by this manager
protected long sessionCounter = 0;
protected volatile int maxActive = 0;
/**
* Processing time during session expiration.
*/
protected long processingTime = 0;
/**
* Frequency of the session expiration, and related manager operations.
* Manager operations will be done once for the specified amount of
* backgrondProcess calls (ie, the lower the amount, the most often the
* checks will occur).
*/
protected int processExpiresFrequency = 6;
/**
* background processor delay in seconds
*/
protected int backgroundProcessorDelay = 10;
/**
* Iteration count for background processing.
*/
private int count = 0;
@Override @Override
public WxSession getSession(String sessionId) { public WxSession getSession(String sessionId) {
@@ -33,7 +82,7 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
public WxSession getSession(String sessionId, boolean create) { public WxSession getSession(String sessionId, boolean create) {
if (sessionId == null) { if (sessionId == null) {
throw new IllegalStateException throw new IllegalStateException
(sm.getString("sessionManagerImpl.getSession.ise")); (sm.getString("sessionManagerImpl.getSession.ise"));
} }
InternalSession session = findSession(sessionId); InternalSession session = findSession(sessionId);
@@ -60,64 +109,6 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
return session.getSession(); return session.getSession();
} }
// -------------------------------------- InternalSessionManager
/**
* The descriptive name of this Manager implementation (for logging).
*/
private static final String name = "SessionManagerImpl";
/**
* The maximum number of active Sessions allowed, or -1 for no limit.
*/
protected int maxActiveSessions = -1;
/**
* Number of session creations that failed due to maxActiveSessions.
*/
protected int rejectedSessions = 0;
/**
* The default maximum inactive interval for Sessions created by
* this Manager.
*/
protected int maxInactiveInterval = 30 * 60;
// Number of sessions created by this manager
protected long sessionCounter=0;
protected volatile int maxActive=0;
private final Object maxActiveUpdateLock = new Object();
/**
* Processing time during session expiration.
*/
protected long processingTime = 0;
/**
* Iteration count for background processing.
*/
private int count = 0;
/**
* Frequency of the session expiration, and related manager operations.
* Manager operations will be done once for the specified amount of
* backgrondProcess calls (ie, the lower the amount, the most often the
* checks will occur).
*/
protected int processExpiresFrequency = 6;
/**
* background processor delay in seconds
*/
protected int backgroundProcessorDelay = 10;
/**
* 后台清理线程是否已经开启
*/
private final AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
@Override @Override
public void remove(InternalSession session) { public void remove(InternalSession session) {
remove(session, false); remove(session, false);
@@ -131,7 +122,6 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
} }
@Override @Override
public InternalSession findSession(String id) { public InternalSession findSession(String id) {
@@ -145,15 +135,15 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
public InternalSession createSession(String sessionId) { public InternalSession createSession(String sessionId) {
if (sessionId == null) { if (sessionId == null) {
throw new IllegalStateException throw new IllegalStateException
(sm.getString("sessionManagerImpl.createSession.ise")); (sm.getString("sessionManagerImpl.createSession.ise"));
} }
if ((maxActiveSessions >= 0) && if ((maxActiveSessions >= 0) &&
(getActiveSessions() >= maxActiveSessions)) { (getActiveSessions() >= maxActiveSessions)) {
rejectedSessions++; rejectedSessions++;
throw new TooManyActiveSessionsException( throw new TooManyActiveSessionsException(
sm.getString("sessionManagerImpl.createSession.tmase"), sm.getString("sessionManagerImpl.createSession.tmase"),
maxActiveSessions); maxActiveSessions);
} }
// Recycle or create a Session instance // Recycle or create a Session instance
@@ -216,9 +206,9 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
sessions.put(session.getIdInternal(), session); sessions.put(session.getIdInternal(), session);
int size = getActiveSessions(); int size = getActiveSessions();
if( size > maxActive ) { if (size > maxActive) {
synchronized(maxActiveUpdateLock) { synchronized (maxActiveUpdateLock) {
if( size > maxActive ) { if (size > maxActive) {
maxActive = size; maxActive = size;
} }
} }
@@ -251,19 +241,19 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
long timeNow = System.currentTimeMillis(); long timeNow = System.currentTimeMillis();
InternalSession sessions[] = findSessions(); InternalSession sessions[] = findSessions();
int expireHere = 0 ; int expireHere = 0;
if(log.isDebugEnabled()) if (log.isDebugEnabled())
log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length); log.debug("Start expire sessions {} at {} sessioncount {}", getName(), timeNow, sessions.length);
for (int i = 0; i < sessions.length; i++) { for (int i = 0; i < sessions.length; i++) {
if (sessions[i]!=null && !sessions[i].isValid()) { if (sessions[i] != null && !sessions[i].isValid()) {
expireHere++; expireHere++;
} }
} }
long timeEnd = System.currentTimeMillis(); long timeEnd = System.currentTimeMillis();
if(log.isDebugEnabled()) if (log.isDebugEnabled())
log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere); log.debug("End expire sessions {} processingTime {} expired sessions: {}", getName(), timeEnd - timeNow, expireHere);
processingTime += ( timeEnd - timeNow ); processingTime += (timeEnd - timeNow);
} }

View File

@@ -21,37 +21,34 @@ package me.chanjar.weixin.common.session;
* reached and the server is refusing to create any new sessions. * reached and the server is refusing to create any new sessions.
*/ */
public class TooManyActiveSessionsException public class TooManyActiveSessionsException
extends IllegalStateException extends IllegalStateException {
{ private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
/** /**
* The maximum number of active sessions the server will tolerate. * The maximum number of active sessions the server will tolerate.
*/ */
private final int maxActiveSessions; private final int maxActiveSessions;
/** /**
* Creates a new TooManyActiveSessionsException. * Creates a new TooManyActiveSessionsException.
* *
* @param message A description for the exception. * @param message A description for the exception.
* @param maxActive The maximum number of active sessions allowed by the * @param maxActive The maximum number of active sessions allowed by the
* session manager. * session manager.
*/ */
public TooManyActiveSessionsException(String message, public TooManyActiveSessionsException(String message,
int maxActive) int maxActive) {
{ super(message);
super(message);
maxActiveSessions = maxActive; maxActiveSessions = maxActive;
} }
/** /**
* Gets the maximum number of sessions allowed by the session manager. * Gets the maximum number of sessions allowed by the session manager.
* *
* @return The maximum number of sessions allowed by the session manager. * @return The maximum number of sessions allowed by the session manager.
*/ */
public int getMaxActiveSessions() public int getMaxActiveSessions() {
{ return maxActiveSessions;
return maxActiveSessions; }
}
} }

View File

@@ -7,7 +7,7 @@ public class StringUtils {
/** /**
* <p>Checks if a CharSequence is whitespace, empty ("") or null.</p> * <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
* * <p>
* <pre> * <pre>
* StringUtils.isBlank(null) = true * StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true * StringUtils.isBlank("") = true
@@ -16,9 +16,8 @@ public class StringUtils {
* StringUtils.isBlank(" bob ") = false * StringUtils.isBlank(" bob ") = false
* </pre> * </pre>
* *
* @param cs the CharSequence to check, may be null * @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is null, empty or whitespace * @return {@code true} if the CharSequence is null, empty or whitespace
* @since 2.0
* @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
*/ */
public static boolean isBlank(CharSequence cs) { public static boolean isBlank(CharSequence cs) {
@@ -36,7 +35,7 @@ public class StringUtils {
/** /**
* <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p> * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
* * <p>
* <pre> * <pre>
* StringUtils.isNotBlank(null) = false * StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false * StringUtils.isNotBlank("") = false
@@ -45,10 +44,9 @@ public class StringUtils {
* StringUtils.isNotBlank(" bob ") = true * StringUtils.isNotBlank(" bob ") = true
* </pre> * </pre>
* *
* @param cs the CharSequence to check, may be null * @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is * @return {@code true} if the CharSequence is
* not empty and not null and not whitespace * not empty and not null and not whitespace
* @since 2.0
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence) * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
*/ */
public static boolean isNotBlank(CharSequence cs) { public static boolean isNotBlank(CharSequence cs) {
@@ -57,7 +55,7 @@ public class StringUtils {
/** /**
* <p>Checks if a CharSequence is empty ("") or null.</p> * <p>Checks if a CharSequence is empty ("") or null.</p>
* * <p>
* <pre> * <pre>
* StringUtils.isEmpty(null) = true * StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true * StringUtils.isEmpty("") = true
@@ -65,12 +63,12 @@ public class StringUtils {
* StringUtils.isEmpty("bob") = false * StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false * StringUtils.isEmpty(" bob ") = false
* </pre> * </pre>
* * <p>
* <p>NOTE: This method changed in Lang version 2.0. * <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the CharSequence. * It no longer trims the CharSequence.
* That functionality is available in isBlank().</p> * That functionality is available in isBlank().</p>
* *
* @param cs the CharSequence to check, may be null * @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is empty or null * @return {@code true} if the CharSequence is empty or null
* @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
*/ */
@@ -80,7 +78,7 @@ public class StringUtils {
/** /**
* <p>Checks if a CharSequence is not empty ("") and not null.</p> * <p>Checks if a CharSequence is not empty ("") and not null.</p>
* * <p>
* <pre> * <pre>
* StringUtils.isNotEmpty(null) = false * StringUtils.isNotEmpty(null) = false
* StringUtils.isNotEmpty("") = false * StringUtils.isNotEmpty("") = false
@@ -89,7 +87,7 @@ public class StringUtils {
* StringUtils.isNotEmpty(" bob ") = true * StringUtils.isNotEmpty(" bob ") = true
* </pre> * </pre>
* *
* @param cs the CharSequence to check, may be null * @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is not empty and not null * @return {@code true} if the CharSequence is not empty and not null
* @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
*/ */

View File

@@ -3,24 +3,24 @@ package me.chanjar.weixin.common.util.crypto;
import java.util.ArrayList; import java.util.ArrayList;
public class ByteGroup { public class ByteGroup {
ArrayList<Byte> byteContainer = new ArrayList<Byte>(); ArrayList<Byte> byteContainer = new ArrayList<Byte>();
public byte[] toBytes() { public byte[] toBytes() {
byte[] bytes = new byte[byteContainer.size()]; byte[] bytes = new byte[byteContainer.size()];
for (int i = 0; i < byteContainer.size(); i++) { for (int i = 0; i < byteContainer.size(); i++) {
bytes[i] = byteContainer.get(i); bytes[i] = byteContainer.get(i);
} }
return bytes; return bytes;
} }
public ByteGroup addBytes(byte[] bytes) { public ByteGroup addBytes(byte[] bytes) {
for (byte b : bytes) { for (byte b : bytes) {
byteContainer.add(b); byteContainer.add(b);
} }
return this; return this;
} }
public int size() { public int size() {
return byteContainer.size(); return byteContainer.size();
} }
} }

View File

@@ -16,53 +16,53 @@ import java.util.Arrays;
*/ */
public class PKCS7Encoder { public class PKCS7Encoder {
private static final Charset CHARSET = Charset.forName("utf-8"); private static final Charset CHARSET = Charset.forName("utf-8");
private static final int BLOCK_SIZE = 32; private static final int BLOCK_SIZE = 32;
/** /**
* 获得对明文进行补位填充的字节. * 获得对明文进行补位填充的字节.
* *
* @param count 需要进行填充补位操作的明文字节个数 * @param count 需要进行填充补位操作的明文字节个数
* @return 补齐用的字节数组 * @return 补齐用的字节数组
*/ */
public static byte[] encode(int count) { public static byte[] encode(int count) {
// 计算需要填充的位数 // 计算需要填充的位数
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
if (amountToPad == 0) { if (amountToPad == 0) {
amountToPad = BLOCK_SIZE; amountToPad = BLOCK_SIZE;
} }
// 获得补位所用的字符 // 获得补位所用的字符
char padChr = chr(amountToPad); char padChr = chr(amountToPad);
String tmp = new String(); String tmp = new String();
for (int index = 0; index < amountToPad; index++) { for (int index = 0; index < amountToPad; index++) {
tmp += padChr; tmp += padChr;
} }
return tmp.getBytes(CHARSET); return tmp.getBytes(CHARSET);
} }
/** /**
* 删除解密后明文的补位字符 * 删除解密后明文的补位字符
* *
* @param decrypted 解密后的明文 * @param decrypted 解密后的明文
* @return 删除补位字符后的明文 * @return 删除补位字符后的明文
*/ */
public static byte[] decode(byte[] decrypted) { public static byte[] decode(byte[] decrypted) {
int pad = (int) decrypted[decrypted.length - 1]; int pad = (int) decrypted[decrypted.length - 1];
if (pad < 1 || pad > 32) { if (pad < 1 || pad > 32) {
pad = 0; pad = 0;
} }
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
} }
/** /**
* 将数字转化成ASCII码对应的字符用于对明文进行补码 * 将数字转化成ASCII码对应的字符用于对明文进行补码
* *
* @param a 需要转化的数字 * @param a 需要转化的数字
* @return 转化得到的字符 * @return 转化得到的字符
*/ */
public static char chr(int a) { public static char chr(int a) {
byte target = (byte) (a & 0xFF); byte target = (byte) (a & 0xFF);
return (char) target; return (char) target;
} }
} }

View File

@@ -1,10 +1,10 @@
package me.chanjar.weixin.common.util.crypto; package me.chanjar.weixin.common.util.crypto;
import org.apache.commons.codec.digest.DigestUtils;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
import org.apache.commons.codec.digest.DigestUtils;
/** /**
* Created by Daniel Qian on 14/10/19. * Created by Daniel Qian on 14/10/19.
*/ */
@@ -37,4 +37,4 @@ public class SHA1 {
} }
return DigestUtils.sha1Hex(sb.toString()); return DigestUtils.sha1Hex(sb.toString());
} }
} }

View File

@@ -2,6 +2,10 @@
* 对公众平台发送给公众账号的消息加解密示例代码. * 对公众平台发送给公众账号的消息加解密示例代码.
* *
* @copyright Copyright (c) 1998-2014 Tencent Inc. * @copyright Copyright (c) 1998-2014 Tencent Inc.
* <p>
* 针对org.apache.commons.codec.binary.Base64
* 需要导入架包commons-codec-1.9或commons-codec-1.8等其他版本)
* 官方下载地址http://commons.apache.org/proper/commons-codec/download_codec.cgi
*/ */
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@@ -62,12 +66,51 @@ public class WxCryptUtil {
* @param appidOrCorpid 公众平台appid/corpid * @param appidOrCorpid 公众平台appid/corpid
*/ */
public WxCryptUtil(String token, String encodingAesKey, public WxCryptUtil(String token, String encodingAesKey,
String appidOrCorpid) { String appidOrCorpid) {
this.token = token; this.token = token;
this.appidOrCorpid = appidOrCorpid; this.appidOrCorpid = appidOrCorpid;
this.aesKey = Base64.decodeBase64(encodingAesKey + "="); this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
} }
/**
* 微信公众号支付签名算法(详见:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3)
* @param packageParams 原始参数
* @param signKey 加密Key(即 商户Key)
* @return 签名字符串
*/
public static String createSign(Map<String, String> packageParams,
String signKey) {
SortedMap<String, String> sortedMap = new TreeMap<String, String>();
sortedMap.putAll(packageParams);
List<String> keys = new ArrayList<String>(packageParams.keySet());
Collections.sort(keys);
StringBuffer toSign = new StringBuffer();
for (String key : keys) {
String value = packageParams.get(key);
if (null != value && !"".equals(value) && !"sign".equals(key)
&& !"key".equals(key)) {
toSign.append(key + "=" + value + "&");
}
}
toSign.append("key=" + signKey);
String sign = DigestUtils.md5Hex(toSign.toString()).toUpperCase();
return sign;
}
static String extractEncryptPart(String xml) {
try {
DocumentBuilder db = builderLocal.get();
Document document = db.parse(new InputSource(new StringReader(xml)));
Element root = document.getDocumentElement();
return root.getElementsByTagName("Encrypt").item(0).getTextContent();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** /**
* 将公众平台回复用户的消息加密打包. * 将公众平台回复用户的消息加密打包.
* <ol> * <ol>
@@ -107,7 +150,7 @@ public class WxCryptUtil {
byte[] randomStringBytes = randomStr.getBytes(CHARSET); byte[] randomStringBytes = randomStr.getBytes(CHARSET);
byte[] plainTextBytes = plainText.getBytes(CHARSET); byte[] plainTextBytes = plainText.getBytes(CHARSET);
byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder( byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(
plainTextBytes.length); plainTextBytes.length);
byte[] appIdBytes = appidOrCorpid.getBytes(CHARSET); byte[] appIdBytes = appidOrCorpid.getBytes(CHARSET);
// randomStr + networkBytesOrder + text + appid // randomStr + networkBytesOrder + text + appid
@@ -157,7 +200,7 @@ public class WxCryptUtil {
* @return 解密后的原文 * @return 解密后的原文
*/ */
public String decrypt(String msgSignature, String timeStamp, String nonce, public String decrypt(String msgSignature, String timeStamp, String nonce,
String encryptedXml) { String encryptedXml) {
// 密钥公众账号的app corpSecret // 密钥公众账号的app corpSecret
// 提取密文 // 提取密文
String cipherText = extractEncryptPart(encryptedXml); String cipherText = extractEncryptPart(encryptedXml);
@@ -190,7 +233,7 @@ public class WxCryptUtil {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES"); SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec( IvParameterSpec iv = new IvParameterSpec(
Arrays.copyOfRange(aesKey, 0, 16)); Arrays.copyOfRange(aesKey, 0, 16));
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv); cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
// 使用BASE64对密文进行解码 // 使用BASE64对密文进行解码
@@ -213,9 +256,9 @@ public class WxCryptUtil {
int xmlLength = bytesNetworkOrder2Number(networkOrder); int xmlLength = bytesNetworkOrder2Number(networkOrder);
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength),
CHARSET); CHARSET);
from_appid = new String( from_appid = new String(
Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET); Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -229,33 +272,6 @@ public class WxCryptUtil {
} }
/**
* 微信公众号支付签名算法(详见:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3)
* @param packageParams 原始参数
* @param signKey 加密Key(即 商户Key)
* @return 签名字符串
*/
public static String createSign(Map<String, String> packageParams,
String signKey) {
SortedMap<String, String> sortedMap = new TreeMap<String, String>();
sortedMap.putAll(packageParams);
List<String> keys = new ArrayList<String>(packageParams.keySet());
Collections.sort(keys);
StringBuffer toSign = new StringBuffer();
for (String key : keys) {
String value = packageParams.get(key);
if (null != value && !"".equals(value) && !"sign".equals(key)
&& !"key".equals(key)) {
toSign.append(key + "=" + value + "&");
}
}
toSign.append("key=" + signKey);
String sign = DigestUtils.md5Hex(toSign.toString()).toUpperCase();
return sign;
}
/** /**
* 将一个数字转换成生成4个字节的网络字节序bytes数组 * 将一个数字转换成生成4个字节的网络字节序bytes数组
* *
@@ -308,24 +324,12 @@ public class WxCryptUtil {
* @return 生成的xml字符串 * @return 生成的xml字符串
*/ */
private String generateXml(String encrypt, String signature, String timestamp, private String generateXml(String encrypt, String signature, String timestamp,
String nonce) { String nonce) {
String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n" String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"
+ "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n" + "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"
+ "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n" + "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n"
+ "</xml>"; + "</xml>";
return String.format(format, encrypt, signature, timestamp, nonce); return String.format(format, encrypt, signature, timestamp, nonce);
} }
static String extractEncryptPart(String xml) {
try {
DocumentBuilder db = builderLocal.get();
Document document = db.parse(new InputSource(new StringReader(xml)));
Element root = document.getDocumentElement();
return root.getElementsByTagName("Encrypt").item(0).getTextContent();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} }

View File

@@ -10,17 +10,18 @@ public class FileUtils {
/** /**
* 创建临时文件 * 创建临时文件
*
* @param inputStream * @param inputStream
* @param name 文件名 * @param name 文件名
* @param ext 扩展名 * @param ext 扩展名
* @param tmpDirFile 临时文件夹目录 * @param tmpDirFile 临时文件夹目录
*/ */
public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException { public static File createTmpFile(InputStream inputStream, String name, String ext, File tmpDirFile) throws IOException {
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
File tmpFile; File tmpFile;
if (tmpDirFile == null) { if (tmpDirFile == null) {
tmpFile = File.createTempFile(name, '.' + ext); tmpFile = File.createTempFile(name, '.' + ext);
} else { } else {
tmpFile = File.createTempFile(name, '.' + ext, tmpDirFile); tmpFile = File.createTempFile(name, '.' + ext, tmpDirFile);
} }
@@ -51,9 +52,10 @@ public class FileUtils {
/** /**
* 创建临时文件 * 创建临时文件
*
* @param inputStream * @param inputStream
* @param name 文件名 * @param name 文件名
* @param ext 扩展名 * @param ext 扩展名
*/ */
public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException { public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException {
return createTmpFile(inputStream, name, ext, null); return createTmpFile(inputStream, name, ext, null);

View File

@@ -10,36 +10,42 @@ public interface ApacheHttpClientBuilder {
/** /**
* 构建httpclient实例 * 构建httpclient实例
*
* @return new instance of CloseableHttpClient * @return new instance of CloseableHttpClient
*/ */
CloseableHttpClient build(); CloseableHttpClient build();
/** /**
* 代理服务器地址 * 代理服务器地址
*
* @param httpProxyHost * @param httpProxyHost
*/ */
ApacheHttpClientBuilder httpProxyHost(String httpProxyHost); ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
/** /**
* 代理服务器端口 * 代理服务器端口
*
* @param httpProxyPort * @param httpProxyPort
*/ */
ApacheHttpClientBuilder httpProxyPort(int httpProxyPort); ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
/** /**
* 代理服务器用户名 * 代理服务器用户名
*
* @param httpProxyUsername * @param httpProxyUsername
*/ */
ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername); ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
/** /**
* 代理服务器密码 * 代理服务器密码
*
* @param httpProxyPassword * @param httpProxyPassword
*/ */
ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword); ApacheHttpClientBuilder httpProxyPassword(String httpProxyPassword);
/** /**
* ssl连接socket工厂 * ssl连接socket工厂
*
* @param sslConnectionSocketFactory * @param sslConnectionSocketFactory
*/ */
ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory); ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory);

View File

@@ -94,7 +94,7 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
return this; return this;
} }
public ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory){ public ApacheHttpClientBuilder sslConnectionSocketFactory(SSLConnectionSocketFactory sslConnectionSocketFactory) {
this.sslConnectionSocketFactory = sslConnectionSocketFactory; this.sslConnectionSocketFactory = sslConnectionSocketFactory;
return this; return this;
} }
@@ -103,18 +103,18 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
return idleConnectionMonitorThread; return idleConnectionMonitorThread;
} }
private void prepare(){ private void prepare() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", plainConnectionSocketFactory) .register("http", plainConnectionSocketFactory)
.register("https", sslConnectionSocketFactory) .register("https", sslConnectionSocketFactory)
.build(); .build();
connectionManager = new PoolingHttpClientConnectionManager(registry); connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(maxTotalConn); connectionManager.setMaxTotal(maxTotalConn);
connectionManager.setDefaultMaxPerRoute(maxConnPerHost); connectionManager.setDefaultMaxPerRoute(maxConnPerHost);
connectionManager.setDefaultSocketConfig( connectionManager.setDefaultSocketConfig(
SocketConfig.copy(SocketConfig.DEFAULT) SocketConfig.copy(SocketConfig.DEFAULT)
.setSoTimeout(soTimeout) .setSoTimeout(soTimeout)
.build() .build()
); );
idleConnectionMonitorThread = new IdleConnectionMonitorThread(connectionManager, idleConnTimeout, checkWaitTime); idleConnectionMonitorThread = new IdleConnectionMonitorThread(connectionManager, idleConnTimeout, checkWaitTime);
@@ -122,22 +122,22 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
idleConnectionMonitorThread.start(); idleConnectionMonitorThread.start();
httpClientBuilder = HttpClients.custom() httpClientBuilder = HttpClients.custom()
.setConnectionManager(connectionManager) .setConnectionManager(connectionManager)
.setDefaultRequestConfig( .setDefaultRequestConfig(
RequestConfig.custom() RequestConfig.custom()
.setSocketTimeout(soTimeout) .setSocketTimeout(soTimeout)
.setConnectTimeout(connectionTimeout) .setConnectTimeout(connectionTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout) .setConnectionRequestTimeout(connectionRequestTimeout)
.build() .build()
) )
.setRetryHandler(httpRequestRetryHandler); .setRetryHandler(httpRequestRetryHandler);
if (StringUtils.isNotBlank(httpProxyHost) && StringUtils.isNotBlank(httpProxyUsername)) { if (StringUtils.isNotBlank(httpProxyHost) && StringUtils.isNotBlank(httpProxyUsername)) {
// 使用代理服务器 需要用户认证的代理服务器 // 使用代理服务器 需要用户认证的代理服务器
CredentialsProvider credsProvider = new BasicCredentialsProvider(); CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials( credsProvider.setCredentials(
new AuthScope(httpProxyHost, httpProxyPort), new AuthScope(httpProxyHost, httpProxyPort),
new UsernamePasswordCredentials(httpProxyUsername, httpProxyPassword)); new UsernamePasswordCredentials(httpProxyUsername, httpProxyPassword));
httpClientBuilder.setDefaultCredentialsProvider(credsProvider); httpClientBuilder.setDefaultCredentialsProvider(credsProvider);
} }
@@ -148,7 +148,7 @@ public class DefaultApacheHttpHttpClientBuilder implements ApacheHttpClientBuild
} }
public CloseableHttpClient build() { public CloseableHttpClient build() {
if(!prepared){ if (!prepared) {
prepare(); prepare();
prepared = true; prepared = true;
} }

View File

@@ -1,8 +1,5 @@
package me.chanjar.weixin.common.util.http; package me.chanjar.weixin.common.util.http;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.StatusLine; import org.apache.http.StatusLine;
@@ -10,6 +7,9 @@ import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler; import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamResponseHandler implements ResponseHandler<InputStream> { public class InputStreamResponseHandler implements ResponseHandler<InputStream> {
public static final ResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler(); public static final ResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler();

View File

@@ -18,39 +18,39 @@ import java.io.IOException;
*/ */
public class JoddGetRequestExecutor implements RequestExecutor<String, String> { public class JoddGetRequestExecutor implements RequestExecutor<String, String> {
@Override @Override
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri,
String queryParam) throws WxErrorException, IOException { String queryParam) throws WxErrorException, IOException {
if (queryParam != null) { if (queryParam != null) {
if (uri.indexOf('?') == -1) { if (uri.indexOf('?') == -1) {
uri += '?'; uri += '?';
} }
uri += uri.endsWith("?") ? queryParam : '&' + queryParam; uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
}
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
if (httpProxy != null) {
ProxyInfo proxyInfoObj = new ProxyInfo(
ProxyInfo.ProxyType.HTTP,
httpProxy.getHostName(),
httpProxy.getPort(), "", "");
provider.useProxy(proxyInfoObj);
}
HttpRequest request = HttpRequest.get(uri);
request.method("GET");
request.charset("UTF-8");
HttpResponse response = request.open(provider).send();
response.charset("UTF-8");
String result = response.bodyText();
WxError error = WxError.fromJson(result);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
return result;
} }
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
if (httpProxy != null) {
ProxyInfo proxyInfoObj = new ProxyInfo(
ProxyInfo.ProxyType.HTTP,
httpProxy.getHostName(),
httpProxy.getPort(), "", "");
provider.useProxy(proxyInfoObj);
}
HttpRequest request = HttpRequest.get(uri);
request.method("GET");
request.charset("UTF-8");
HttpResponse response = request.open(provider).send();
response.charset("UTF-8");
String result = response.bodyText();
WxError error = WxError.fromJson(result);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
return result;
}
} }

View File

@@ -18,33 +18,33 @@ import java.io.IOException;
*/ */
public class JoddPostRequestExecutor implements RequestExecutor<String, String> { public class JoddPostRequestExecutor implements RequestExecutor<String, String> {
@Override @Override
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri,
String postEntity) throws WxErrorException, IOException { String postEntity) throws WxErrorException, IOException {
SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider(); SocketHttpConnectionProvider provider = new SocketHttpConnectionProvider();
if (httpProxy != null) { if (httpProxy != null) {
ProxyInfo proxyInfoObj = new ProxyInfo( ProxyInfo proxyInfoObj = new ProxyInfo(
ProxyInfo.ProxyType.HTTP, ProxyInfo.ProxyType.HTTP,
httpProxy.getAddress().getHostAddress(), httpProxy.getAddress().getHostAddress(),
httpProxy.getPort(), "", ""); httpProxy.getPort(), "", "");
provider.useProxy(proxyInfoObj); provider.useProxy(proxyInfoObj);
}
HttpRequest request = HttpRequest.get(uri);
request.method("POST");
request.charset("UTF-8");
request.bodyText(postEntity);
HttpResponse response = request.open(provider).send();
response.charset("UTF-8");
String result = response.bodyText();
WxError error = WxError.fromJson(result);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
return result;
} }
HttpRequest request = HttpRequest.get(uri);
request.method("POST");
request.charset("UTF-8");
request.bodyText(postEntity);
HttpResponse response = request.open(provider).send();
response.charset("UTF-8");
String result = response.bodyText();
WxError error = WxError.fromJson(result);
if (error.getErrorCode() != 0) {
throw new WxErrorException(error);
}
return result;
}
} }

View File

@@ -6,7 +6,6 @@ import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.common.util.fs.FileUtils;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
@@ -21,8 +20,8 @@ import java.util.regex.Pattern;
/** /**
* 下载媒体文件请求执行器请求的参数是String, 返回的结果是File * 下载媒体文件请求执行器请求的参数是String, 返回的结果是File
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> { public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> {
@@ -74,7 +73,7 @@ public class MediaDownloadRequestExecutor implements RequestExecutor<File, Strin
File localFile = FileUtils.createTmpFile(inputStream, name_ext[0], name_ext[1], tmpDirFile); File localFile = FileUtils.createTmpFile(inputStream, name_ext[0], name_ext[1], tmpDirFile);
return localFile; return localFile;
}finally { } finally {
httpGet.releaseConnection(); httpGet.releaseConnection();
} }

View File

@@ -5,7 +5,6 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
@@ -19,8 +18,8 @@ import java.io.IOException;
/** /**
* 上传媒体文件请求执行器请求的参数是File, 返回的结果是String * 上传媒体文件请求执行器请求的参数是File, 返回的结果是String
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUploadResult, File> { public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUploadResult, File> {
@@ -33,10 +32,10 @@ public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUpload
} }
if (file != null) { if (file != null) {
HttpEntity entity = MultipartEntityBuilder HttpEntity entity = MultipartEntityBuilder
.create() .create()
.addBinaryBody("media", file) .addBinaryBody("media", file)
.setMode(HttpMultipartMode.RFC6532) .setMode(HttpMultipartMode.RFC6532)
.build(); .build();
httpPost.setEntity(entity); httpPost.setEntity(entity);
httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString()); httpPost.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
} }
@@ -47,7 +46,7 @@ public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUpload
throw new WxErrorException(error); throw new WxErrorException(error);
} }
return WxMediaUploadResult.fromJson(responseContent); return WxMediaUploadResult.fromJson(responseContent);
}finally { } finally {
httpPost.releaseConnection(); httpPost.releaseConnection();
} }
} }

View File

@@ -1,12 +1,11 @@
package me.chanjar.weixin.common.util.http; package me.chanjar.weixin.common.util.http;
import java.io.IOException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import me.chanjar.weixin.common.exception.WxErrorException; import java.io.IOException;
/** /**
* http请求执行器 * http请求执行器
@@ -17,11 +16,10 @@ import me.chanjar.weixin.common.exception.WxErrorException;
public interface RequestExecutor<T, E> { public interface RequestExecutor<T, E> {
/** /**
*
* @param httpclient 传入的httpClient * @param httpclient 传入的httpClient
* @param httpProxy http代理对象如果没有配置代理则为空 * @param httpProxy http代理对象如果没有配置代理则为空
* @param uri uri * @param uri uri
* @param data 数据 * @param data 数据
* @throws WxErrorException * @throws WxErrorException
* @throws ClientProtocolException * @throws ClientProtocolException
* @throws IOException * @throws IOException

View File

@@ -3,7 +3,6 @@ package me.chanjar.weixin.common.util.http;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
@@ -13,8 +12,8 @@ import java.io.IOException;
/** /**
* 简单的GET请求执行器请求的参数是String, 返回的结果也是String * 简单的GET请求执行器请求的参数是String, 返回的结果也是String
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class SimpleGetRequestExecutor implements RequestExecutor<String, String> { public class SimpleGetRequestExecutor implements RequestExecutor<String, String> {
@@ -39,7 +38,7 @@ public class SimpleGetRequestExecutor implements RequestExecutor<String, String>
throw new WxErrorException(error); throw new WxErrorException(error);
} }
return responseContent; return responseContent;
}finally { } finally {
httpGet.releaseConnection(); httpGet.releaseConnection();
} }
} }

View File

@@ -4,7 +4,6 @@ import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.Consts; import org.apache.http.Consts;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
@@ -15,8 +14,8 @@ import java.io.IOException;
/** /**
* 简单的POST请求执行器请求的参数是String, 返回的结果也是String * 简单的POST请求执行器请求的参数是String, 返回的结果也是String
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class SimplePostRequestExecutor implements RequestExecutor<String, String> { public class SimplePostRequestExecutor implements RequestExecutor<String, String> {
@@ -40,7 +39,7 @@ public class SimplePostRequestExecutor implements RequestExecutor<String, String
throw new WxErrorException(error); throw new WxErrorException(error);
} }
return responseContent; return responseContent;
}finally { } finally {
httpPost.releaseConnection(); httpPost.releaseConnection();
} }
} }

View File

@@ -1,7 +1,5 @@
package me.chanjar.weixin.common.util.http; package me.chanjar.weixin.common.util.http;
import java.io.IOException;
import org.apache.http.Consts; import org.apache.http.Consts;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
@@ -10,10 +8,12 @@ import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler; import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import java.io.IOException;
/** /**
* copy from {@link org.apache.http.impl.client.BasicResponseHandler} * copy from {@link org.apache.http.impl.client.BasicResponseHandler}
* @author Daniel Qian
* *
* @author Daniel Qian
*/ */
public class Utf8ResponseHandler implements ResponseHandler<String> { public class Utf8ResponseHandler implements ResponseHandler<String> {

View File

@@ -15,101 +15,101 @@ import com.google.gson.JsonObject;
public class GsonHelper { public class GsonHelper {
public static boolean isNull(JsonElement element) { public static boolean isNull(JsonElement element) {
return element == null || element.isJsonNull(); return element == null || element.isJsonNull();
} }
public static boolean isNotNull(JsonElement element) { public static boolean isNotNull(JsonElement element) {
return !isNull(element); return !isNull(element);
} }
public static Long getLong(JsonObject json, String property) { public static Long getLong(JsonObject json, String property) {
return getAsLong(json.get(property)); return getAsLong(json.get(property));
} }
public static long getPrimitiveLong(JsonObject json, String property) { public static long getPrimitiveLong(JsonObject json, String property) {
return getAsPrimitiveLong(json.get(property)); return getAsPrimitiveLong(json.get(property));
} }
public static Integer getInteger(JsonObject json, String property) { public static Integer getInteger(JsonObject json, String property) {
return getAsInteger(json.get(property)); return getAsInteger(json.get(property));
} }
public static int getPrimitiveInteger(JsonObject json, String property) { public static int getPrimitiveInteger(JsonObject json, String property) {
return getAsPrimitiveInt(json.get(property)); return getAsPrimitiveInt(json.get(property));
} }
public static Double getDouble(JsonObject json, String property) { public static Double getDouble(JsonObject json, String property) {
return getAsDouble(json.get(property)); return getAsDouble(json.get(property));
} }
public static double getPrimitiveDouble(JsonObject json, String property) { public static double getPrimitiveDouble(JsonObject json, String property) {
return getAsPrimitiveDouble(json.get(property)); return getAsPrimitiveDouble(json.get(property));
} }
public static Float getFloat(JsonObject json, String property) { public static Float getFloat(JsonObject json, String property) {
return getAsFloat(json.get(property)); return getAsFloat(json.get(property));
} }
public static float getPrimitiveFloat(JsonObject json, String property) { public static float getPrimitiveFloat(JsonObject json, String property) {
return getAsPrimitiveFloat(json.get(property)); return getAsPrimitiveFloat(json.get(property));
} }
public static Boolean getBoolean(JsonObject json, String property) { public static Boolean getBoolean(JsonObject json, String property) {
return getAsBoolean(json.get(property)); return getAsBoolean(json.get(property));
} }
public static String getString(JsonObject json, String property) { public static String getString(JsonObject json, String property) {
return getAsString(json.get(property)); return getAsString(json.get(property));
} }
public static String getAsString(JsonElement element) { public static String getAsString(JsonElement element) {
return isNull(element) ? null : element.getAsString(); return isNull(element) ? null : element.getAsString();
} }
public static Long getAsLong(JsonElement element) { public static Long getAsLong(JsonElement element) {
return isNull(element) ? null : element.getAsLong(); return isNull(element) ? null : element.getAsLong();
} }
public static long getAsPrimitiveLong(JsonElement element) { public static long getAsPrimitiveLong(JsonElement element) {
Long r = getAsLong(element); Long r = getAsLong(element);
return r == null ? 0l : r; return r == null ? 0l : r;
} }
public static Integer getAsInteger(JsonElement element) { public static Integer getAsInteger(JsonElement element) {
return isNull(element) ? null : element.getAsInt(); return isNull(element) ? null : element.getAsInt();
} }
public static int getAsPrimitiveInt(JsonElement element) { public static int getAsPrimitiveInt(JsonElement element) {
Integer r = getAsInteger(element); Integer r = getAsInteger(element);
return r == null ? 0 : r; return r == null ? 0 : r;
} }
public static Boolean getAsBoolean(JsonElement element) { public static Boolean getAsBoolean(JsonElement element) {
return isNull(element) ? null : element.getAsBoolean(); return isNull(element) ? null : element.getAsBoolean();
} }
public static boolean getAsPrimitiveBool(JsonElement element) { public static boolean getAsPrimitiveBool(JsonElement element) {
Boolean r = getAsBoolean(element); Boolean r = getAsBoolean(element);
return r != null && r.booleanValue(); return r != null && r.booleanValue();
} }
public static Double getAsDouble(JsonElement element) { public static Double getAsDouble(JsonElement element) {
return isNull(element) ? null : element.getAsDouble(); return isNull(element) ? null : element.getAsDouble();
} }
public static double getAsPrimitiveDouble(JsonElement element) { public static double getAsPrimitiveDouble(JsonElement element) {
Double r = getAsDouble(element); Double r = getAsDouble(element);
return r == null ? 0d : r; return r == null ? 0d : r;
} }
public static Float getAsFloat(JsonElement element) { public static Float getAsFloat(JsonElement element) {
return isNull(element) ? null : element.getAsFloat(); return isNull(element) ? null : element.getAsFloat();
} }
public static float getAsPrimitiveFloat(JsonElement element) { public static float getAsPrimitiveFloat(JsonElement element) {
Float r = getAsFloat(element); Float r = getAsFloat(element);
return r == null ? 0f : r; return r == null ? 0f : r;
} }
} }

View File

@@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
import java.lang.reflect.Type; import java.lang.reflect.Type;
/** /**
*
* @author Daniel Qian * @author Daniel Qian
*
*/ */
public class WxAccessTokenAdapter implements JsonDeserializer<WxAccessToken> { public class WxAccessTokenAdapter implements JsonDeserializer<WxAccessToken> {

View File

@@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.result.WxError;
import java.lang.reflect.Type; import java.lang.reflect.Type;
/** /**
*
* @author Daniel Qian * @author Daniel Qian
*
*/ */
public class WxErrorAdapter implements JsonDeserializer<WxError> { public class WxErrorAdapter implements JsonDeserializer<WxError> {

View File

@@ -2,9 +2,9 @@ package me.chanjar.weixin.common.util.json;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
public class WxGsonBuilder { public class WxGsonBuilder {

View File

@@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import java.lang.reflect.Type; import java.lang.reflect.Type;
/** /**
*
* @author Daniel Qian * @author Daniel Qian
*
*/ */
public class WxMediaUploadResultAdapter implements JsonDeserializer<WxMediaUploadResult> { public class WxMediaUploadResultAdapter implements JsonDeserializer<WxMediaUploadResult> {

View File

@@ -8,22 +8,13 @@
*/ */
package me.chanjar.weixin.common.util.json; package me.chanjar.weixin.common.util.json;
import com.google.gson.JsonArray; import com.google.gson.*;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.bean.WxMenu;
import java.lang.reflect.Type; import java.lang.reflect.Type;
/** /**
*
* @author Daniel Qian * @author Daniel Qian
*
*/ */
public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> { public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> {
@@ -60,15 +51,15 @@ public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializ
return buttonJson; return buttonJson;
} }
protected JsonObject convertToJson(WxMenu.WxMenuRule menuRule){ protected JsonObject convertToJson(WxMenu.WxMenuRule menuRule) {
JsonObject matchRule = new JsonObject(); JsonObject matchRule = new JsonObject();
matchRule.addProperty("tag_id",menuRule.getTagId()); matchRule.addProperty("tag_id", menuRule.getTagId());
matchRule.addProperty("sex",menuRule.getSex()); matchRule.addProperty("sex", menuRule.getSex());
matchRule.addProperty("country",menuRule.getCountry()); matchRule.addProperty("country", menuRule.getCountry());
matchRule.addProperty("province",menuRule.getProvince()); matchRule.addProperty("province", menuRule.getProvince());
matchRule.addProperty("city",menuRule.getCity()); matchRule.addProperty("city", menuRule.getCity());
matchRule.addProperty("client_platform_type",menuRule.getClientPlatformType()); matchRule.addProperty("client_platform_type", menuRule.getClientPlatformType());
matchRule.addProperty("language",menuRule.getLanguage()); matchRule.addProperty("language", menuRule.getLanguage());
return matchRule; return matchRule;
} }

View File

@@ -18,30 +18,24 @@
package me.chanjar.weixin.common.util.res; package me.chanjar.weixin.common.util.res;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Enumeration; import java.util.*;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/** /**
* An internationalization / localization helper class which reduces * An internationalization / localization helper class which reduces
* the bother of handling ResourceBundles and takes care of the * the bother of handling ResourceBundles and takes care of the
* common cases of message formating which otherwise require the * common cases of message formating which otherwise require the
* creation of Object arrays and such. * creation of Object arrays and such.
* * <p>
* <p>The StringManager operates on a package basis. One StringManager * <p>The StringManager operates on a package basis. One StringManager
* per package can be created and accessed via the getManager method * per package can be created and accessed via the getManager method
* call. * call.
* * <p>
* <p>The StringManager will look for a ResourceBundle named by * <p>The StringManager will look for a ResourceBundle named by
* the package name given plus the suffix of "LocalStrings". In * the package name given plus the suffix of "LocalStrings". In
* practice, this means that the localized information will be contained * practice, this means that the localized information will be contained
* in a LocalStrings.properties file located in the package * in a LocalStrings.properties file located in the package
* directory of the classpath. * directory of the classpath.
* * <p>
* <p>Please see the documentation for java.util.ResourceBundle for * <p>Please see the documentation for java.util.ResourceBundle for
* more information. * more information.
* *
@@ -52,152 +46,80 @@ import java.util.ResourceBundle;
*/ */
public class StringManager { public class StringManager {
private static int LOCALE_CACHE_SIZE = 10; private static final Map<String, Map<Locale, StringManager>> managers =
new Hashtable<String, Map<Locale, StringManager>>();
private static int LOCALE_CACHE_SIZE = 10;
/**
* The ResourceBundle for this StringManager.
*/
private final ResourceBundle bundle;
private final Locale locale;
/** /**
* The ResourceBundle for this StringManager. * Creates a new StringManager for a given package. This is a
*/ * private method and all access to it is arbitrated by the
private final ResourceBundle bundle; * static getManager method call so that only one StringManager
private final Locale locale; * per package will be created.
*
/** * @param packageName Name of package to create StringManager for.
* Creates a new StringManager for a given package. This is a */
* private method and all access to it is arbitrated by the private StringManager(String packageName, Locale locale) {
* static getManager method call so that only one StringManager String bundleName = packageName + ".LocalStrings";
* per package will be created. ResourceBundle bnd = null;
* try {
* @param packageName Name of package to create StringManager for. bnd = ResourceBundle.getBundle(bundleName, locale);
*/ } catch (MissingResourceException ex) {
private StringManager(String packageName, Locale locale) { // Try from the current loader (that's the case for trusted apps)
String bundleName = packageName + ".LocalStrings"; // Should only be required if using a TC5 style classloader structure
ResourceBundle bnd = null; // where common != shared != server
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl != null) {
try { try {
bnd = ResourceBundle.getBundle(bundleName, locale); bnd = ResourceBundle.getBundle(bundleName, locale, cl);
} catch( MissingResourceException ex ) { } catch (MissingResourceException ex2) {
// Try from the current loader (that's the case for trusted apps) // Ignore
// Should only be required if using a TC5 style classloader structure
// where common != shared != server
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if( cl != null ) {
try {
bnd = ResourceBundle.getBundle(bundleName, locale, cl);
} catch(MissingResourceException ex2) {
// Ignore
}
}
}
bundle = bnd;
// Get the actual locale, which may be different from the requested one
if (bundle != null) {
Locale bundleLocale = bundle.getLocale();
if (bundleLocale.equals(Locale.ROOT)) {
this.locale = Locale.ENGLISH;
} else {
this.locale = bundleLocale;
}
} else {
this.locale = null;
} }
}
} }
bundle = bnd;
/** // Get the actual locale, which may be different from the requested one
Get a string from the underlying resource bundle or return if (bundle != null) {
null if the String is not found. Locale bundleLocale = bundle.getLocale();
if (bundleLocale.equals(Locale.ROOT)) {
@param key to desired resource String this.locale = Locale.ENGLISH;
@return resource String matching <i>key</i> from underlying } else {
bundle or null if not found. this.locale = bundleLocale;
@throws IllegalArgumentException if <i>key</i> is null. }
*/ } else {
public String getString(String key) { this.locale = null;
if(key == null){
String msg = "key may not have a null value";
throw new IllegalArgumentException(msg);
}
String str = null;
try {
// Avoid NPE if bundle is null and treat it like an MRE
if (bundle != null) {
str = bundle.getString(key);
}
} catch(MissingResourceException mre) {
//bad: shouldn't mask an exception the following way:
// str = "[cannot find message associated with key '" + key +
// "' due to " + mre + "]";
// because it hides the fact that the String was missing
// from the calling code.
//good: could just throw the exception (or wrap it in another)
// but that would probably cause much havoc on existing
// code.
//better: consistent with container pattern to
// simply return null. Calling code can then do
// a null check.
str = null;
}
return str;
} }
}
/** /**
* Get a string from the underlying resource bundle and format * Get the StringManager for a particular package. If a manager for
* it with the given set of arguments. * a package already exists, it will be reused, else a new
* * StringManager will be created and returned.
* @param key *
* @param args * @param packageName The package name
*/ */
public String getString(final String key, final Object... args) { public static final synchronized StringManager getManager(
String value = getString(key); String packageName) {
if (value == null) { return getManager(packageName, Locale.getDefault());
value = key; }
}
MessageFormat mf = new MessageFormat(value); /**
mf.setLocale(locale); * Get the StringManager for a particular package and Locale. If a manager
return mf.format(args, new StringBuffer(), null).toString(); * for a package/Locale combination already exists, it will be reused, else
} * a new StringManager will be created and returned.
*
* @param packageName The package name
* @param locale The Locale
*/
public static final synchronized StringManager getManager(
String packageName, Locale locale) {
/** Map<Locale, StringManager> map = managers.get(packageName);
* Identify the Locale this StringManager is associated with if (map == null) {
*/
public Locale getLocale() {
return locale;
}
// --------------------------------------------------------------
// STATIC SUPPORT METHODS
// --------------------------------------------------------------
private static final Map<String, Map<Locale,StringManager>> managers =
new Hashtable<String, Map<Locale,StringManager>>();
/**
* Get the StringManager for a particular package. If a manager for
* a package already exists, it will be reused, else a new
* StringManager will be created and returned.
*
* @param packageName The package name
*/
public static final synchronized StringManager getManager(
String packageName) {
return getManager(packageName, Locale.getDefault());
}
/**
* Get the StringManager for a particular package and Locale. If a manager
* for a package/Locale combination already exists, it will be reused, else
* a new StringManager will be created and returned.
*
* @param packageName The package name
* @param locale The Locale
*/
public static final synchronized StringManager getManager(
String packageName, Locale locale) {
Map<Locale,StringManager> map = managers.get(packageName);
if (map == null) {
/* /*
* Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE. * Don't want the HashMap to be expanded beyond LOCALE_CACHE_SIZE.
* Expansion occurs when size() exceeds capacity. Therefore keep * Expansion occurs when size() exceeds capacity. Therefore keep
@@ -206,43 +128,113 @@ public class StringManager {
* for removal needs to use one less than the maximum desired size * for removal needs to use one less than the maximum desired size
* *
*/ */
map = new LinkedHashMap<Locale,StringManager>(LOCALE_CACHE_SIZE, 1, true) { map = new LinkedHashMap<Locale, StringManager>(LOCALE_CACHE_SIZE, 1, true) {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(
Map.Entry<Locale,StringManager> eldest) {
return size() > (LOCALE_CACHE_SIZE - 1);
}
};
managers.put(packageName, map);
}
StringManager mgr = map.get(locale); @Override
if (mgr == null) { protected boolean removeEldestEntry(
mgr = new StringManager(packageName, locale); Map.Entry<Locale, StringManager> eldest) {
map.put(locale, mgr); return size() > (LOCALE_CACHE_SIZE - 1);
} }
return mgr; };
managers.put(packageName, map);
} }
/** StringManager mgr = map.get(locale);
* Retrieve the StringManager for a list of Locales. The first StringManager if (mgr == null) {
* found will be returned. mgr = new StringManager(packageName, locale);
* map.put(locale, mgr);
* @param requestedLocales the list of Locales
*
* @return the found StringManager or the default StringManager
*/
public static StringManager getManager(String packageName,
Enumeration<Locale> requestedLocales) {
while (requestedLocales.hasMoreElements()) {
Locale locale = requestedLocales.nextElement();
StringManager result = getManager(packageName, locale);
if (result.getLocale().equals(locale)) {
return result;
}
}
// Return the default
return getManager(packageName);
} }
return mgr;
}
// --------------------------------------------------------------
// STATIC SUPPORT METHODS
// --------------------------------------------------------------
/**
* Retrieve the StringManager for a list of Locales. The first StringManager
* found will be returned.
*
* @param requestedLocales the list of Locales
* @return the found StringManager or the default StringManager
*/
public static StringManager getManager(String packageName,
Enumeration<Locale> requestedLocales) {
while (requestedLocales.hasMoreElements()) {
Locale locale = requestedLocales.nextElement();
StringManager result = getManager(packageName, locale);
if (result.getLocale().equals(locale)) {
return result;
}
}
// Return the default
return getManager(packageName);
}
/**
* Get a string from the underlying resource bundle or return
* null if the String is not found.
*
* @param key to desired resource String
* @return resource String matching <i>key</i> from underlying
* bundle or null if not found.
* @throws IllegalArgumentException if <i>key</i> is null.
*/
public String getString(String key) {
if (key == null) {
String msg = "key may not have a null value";
throw new IllegalArgumentException(msg);
}
String str = null;
try {
// Avoid NPE if bundle is null and treat it like an MRE
if (bundle != null) {
str = bundle.getString(key);
}
} catch (MissingResourceException mre) {
//bad: shouldn't mask an exception the following way:
// str = "[cannot find message associated with key '" + key +
// "' due to " + mre + "]";
// because it hides the fact that the String was missing
// from the calling code.
//good: could just throw the exception (or wrap it in another)
// but that would probably cause much havoc on existing
// code.
//better: consistent with container pattern to
// simply return null. Calling code can then do
// a null check.
str = null;
}
return str;
}
/**
* Get a string from the underlying resource bundle and format
* it with the given set of arguments.
*
* @param key
* @param args
*/
public String getString(final String key, final Object... args) {
String value = getString(key);
if (value == null) {
value = key;
}
MessageFormat mf = new MessageFormat(value);
mf.setLocale(locale);
return mf.format(args, new StringBuffer(), null).toString();
}
/**
* Identify the Locale this StringManager is associated with
*/
public Locale getLocale() {
return locale;
}
} }

View File

@@ -1,7 +1,5 @@
package me.chanjar.weixin.common.util.xml; package me.chanjar.weixin.common.util.xml;
import java.io.Writer;
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
@@ -10,6 +8,8 @@ import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.security.NullPermission; import com.thoughtworks.xstream.security.NullPermission;
import com.thoughtworks.xstream.security.PrimitiveTypePermission; import com.thoughtworks.xstream.security.PrimitiveTypePermission;
import java.io.Writer;
public class XStreamInitializer { public class XStreamInitializer {
public static XStream getInstance() { public static XStream getInstance() {
@@ -22,6 +22,7 @@ public class XStreamInitializer {
protected String SUFFIX_CDATA = "]]>"; protected String SUFFIX_CDATA = "]]>";
protected String PREFIX_MEDIA_ID = "<MediaId>"; protected String PREFIX_MEDIA_ID = "<MediaId>";
protected String SUFFIX_MEDIA_ID = "</MediaId>"; protected String SUFFIX_MEDIA_ID = "</MediaId>";
@Override @Override
protected void writeText(QuickWriter writer, String text) { protected void writeText(QuickWriter writer, String text) {
if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) { if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) {

View File

@@ -8,13 +8,13 @@ import org.testng.annotations.Test;
@Test @Test
public class WxMenuTest { public class WxMenuTest {
@Test(dataProvider="wxReturnMenu") @Test(dataProvider = "wxReturnMenu")
public void testFromJson(String json) { public void testFromJson(String json) {
WxMenu menu = WxMenu.fromJson(json); WxMenu menu = WxMenu.fromJson(json);
Assert.assertEquals(menu.getButtons().size(), 3); Assert.assertEquals(menu.getButtons().size(), 3);
} }
@Test(dataProvider="wxPushMenu") @Test(dataProvider = "wxPushMenu")
public void testToJson(String json) { public void testToJson(String json) {
WxMenu menu = new WxMenu(); WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton(); WxMenuButton button1 = new WxMenuButton();
@@ -81,78 +81,78 @@ public class WxMenuTest {
@DataProvider @DataProvider
public Object[][] wxReturnMenu() { public Object[][] wxReturnMenu() {
Object[][] res = menuJson(); Object[][] res = menuJson();
String json = "{ \"menu\" : " + res[0][0] + " }"; String json = "{ \"menu\" : " + res[0][0] + " }";
return new Object[][] { return new Object[][]{
new Object[] { json } new Object[]{json}
}; };
} }
@DataProvider(name="wxPushMenu") @DataProvider(name = "wxPushMenu")
public Object[][] menuJson() { public Object[][] menuJson() {
String json = String json =
"{" "{"
+"\"button\":[" + "\"button\":["
+"{" + "{"
+"\"type\":\"click\"," + "\"type\":\"click\","
+"\"name\":\"今日歌曲\"," + "\"name\":\"今日歌曲\","
+"\"key\":\"V1001_TODAY_MUSIC\"" + "\"key\":\"V1001_TODAY_MUSIC\""
+"}," + "},"
+"{" + "{"
+"\"type\":\"click\"," + "\"type\":\"click\","
+"\"name\":\"歌手简介\"," + "\"name\":\"歌手简介\","
+"\"key\":\"V1001_TODAY_SINGER\"" + "\"key\":\"V1001_TODAY_SINGER\""
+"}," + "},"
+"{" + "{"
+"\"name\":\"菜单\"," + "\"name\":\"菜单\","
+"\"sub_button\":[" + "\"sub_button\":["
+"{" + "{"
+"\"type\":\"view\"," + "\"type\":\"view\","
+"\"name\":\"搜索\"," + "\"name\":\"搜索\","
+"\"url\":\"http://www.soso.com/\"" + "\"url\":\"http://www.soso.com/\""
+"}," + "},"
+"{" + "{"
+"\"type\":\"view\"," + "\"type\":\"view\","
+"\"name\":\"视频\"," + "\"name\":\"视频\","
+"\"url\":\"http://v.qq.com/\"" + "\"url\":\"http://v.qq.com/\""
+"}," + "},"
+"{" + "{"
+"\"type\":\"click\"," + "\"type\":\"click\","
+"\"name\":\"赞一下我们\"," + "\"name\":\"赞一下我们\","
+"\"key\":\"V1001_GOOD\"" + "\"key\":\"V1001_GOOD\""
+"}" + "}"
+"]" + "]"
+"}" + "}"
+"]" + "]"
+"}"; + "}";
return new Object[][] { return new Object[][]{
new Object[] { json } new Object[]{json}
}; };
} }
@DataProvider(name = "wxAddConditionalMenu") @DataProvider(name = "wxAddConditionalMenu")
public Object[][] addConditionalMenuJson(){ public Object[][] addConditionalMenuJson() {
String json = String json =
"{" "{"
+"\"button\":[" + "\"button\":["
+"{" + "{"
+"\"type\":\"click\"," + "\"type\":\"click\","
+"\"name\":\"今日歌曲\"," + "\"name\":\"今日歌曲\","
+"\"key\":\"V1001_TODAY_MUSIC\"" + "\"key\":\"V1001_TODAY_MUSIC\""
+"}" + "}"
+"]," + "],"
+"\"matchrule\":{" + "\"matchrule\":{"
+"\"group_id\":\"2\"," + "\"group_id\":\"2\","
+"\"sex\":\"1\"," + "\"sex\":\"1\","
+"\"country\":\"中国\"," + "\"country\":\"中国\","
+"\"province\":\"广东\"," + "\"province\":\"广东\","
+"\"city\":\"广州\"," + "\"city\":\"广州\","
+"\"client_platform_type\":\"2\"," + "\"client_platform_type\":\"2\","
+"\"language\":\"zh_CN\"" + "\"language\":\"zh_CN\""
+"}" + "}"
+"}"; + "}";
return new Object[][]{ return new Object[][]{
new Object[]{json} new Object[]{json}
}; };
} }

View File

@@ -10,8 +10,8 @@ public class SessionTest {
@DataProvider @DataProvider
public Object[][] getSessionManager() { public Object[][] getSessionManager() {
return new Object[][] { return new Object[][]{
new Object[] { new StandardSessionManager() } new Object[]{new StandardSessionManager()}
}; };
} }

View File

@@ -8,7 +8,7 @@ import org.testng.annotations.Test;
public class WxMessageInMemoryDuplicateCheckerTest { public class WxMessageInMemoryDuplicateCheckerTest {
public void test() throws InterruptedException { public void test() throws InterruptedException {
Long[] msgIds = new Long[] { 1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l }; Long[] msgIds = new Long[]{1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l};
WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000l, 1000l); WxMessageInMemoryDuplicateChecker checker = new WxMessageInMemoryDuplicateChecker(2000l, 1000l);
// 第一次检查 // 第一次检查

View File

@@ -69,7 +69,7 @@ public class WxCryptUtilTest {
} }
public void testValidateSignatureError() throws ParserConfigurationException, SAXException, public void testValidateSignatureError() throws ParserConfigurationException, SAXException,
IOException { IOException {
try { try {
WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId); WxCryptUtil pc = new WxCryptUtil(token, encodingAesKey, appId);
String afterEncrpt = pc.encrypt(replyMsg); String afterEncrpt = pc.encrypt(replyMsg);