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>();
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_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_KF_CREATE_SESSION = "kf_create_session"; // 客服接入会话
public static final String EVT_KF_CLOSE_SESSION = "kf_close_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_THUMB = "thumb";
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_AMR = "amr";
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_SCANCODE_PUSH = "scancode_push";
/** 扫码推事件且弹出“消息接收中”提示框 */
/**
* 扫码推事件且弹出消息接收中提示框
*/
public static final String BUTTON_SCANCODE_WAITMSG = "scancode_waitmsg";
/** 弹出系统拍照发图 */
/**
* 弹出系统拍照发图
*/
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_WEIXIN = "pic_weixin";
/** 弹出地理位置选择器 */
/**
* 弹出地理位置选择器
*/
public static final String BUTTON_LOCATION_SELECT = "location_select";
/** 下发消息(除文本消息) */
/**
* 下发消息除文本消息
*/
public static final String BUTTON_MEDIA_ID = "media_id";
/** 跳转图文消息URL */
/**
* 跳转图文消息URL
*/
public static final String BUTTON_VIEW_LIMITED = "view_limited";
/**
* 不弹出授权页面直接跳转只能获取用户openid
*/
public static final String OAUTH2_SCOPE_BASE = "snsapi_base";
///////////////////////
// oauth2网页授权的scope
///////////////////////
/** 不弹出授权页面直接跳转只能获取用户openid */
public static final String OAUTH2_SCOPE_BASE = "snsapi_base";
/** 弹出授权页面可通过openid拿到昵称、性别、所在地。并且即使在未关注的情况下只要用户授权也能获取其信息 */
/**
* 弹出授权页面可通过openid拿到昵称性别所在地并且即使在未关注的情况下只要用户授权也能获取其信息
*/
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_IMAGE = "image";
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>
*
* <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>
* <h2>企业号的排重方式</h2>
*
* <p>
* 官方文档完全没有写参照公众号的方式排重
*
* <p>
* <p>或者可以采取更简单的方式如果有MsgId就用MsgId排重如果没有就用FromUserName+CreateTime排重</p>
*
* @param messageId messageId需要根据上面讲的方式构造
* @return 如果是重复消息返回true否则返回false
*/

View File

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

View File

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

View File

@ -1,5 +1,7 @@
package me.chanjar.weixin.common.bean;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
@ -7,12 +9,10 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
/**
* 企业号菜单
* @author Daniel Qian
*
* @author Daniel Qian
*/
public class WxMenu implements Serializable {
@ -22,6 +22,22 @@ public class WxMenu implements Serializable {
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() {
return buttons;
}
@ -42,22 +58,6 @@ public class WxMenu implements Serializable {
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
public String toString() {
return "WxMenu{" +

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,9 +13,60 @@ public class StandardSession implements WxSession, InternalSession {
*/
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* Type array.
*/
protected static final String EMPTY_ARRAY[] = new String[0];
// ------------------------------ WxSession
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
public Object getAttribute(String name) {
@ -62,13 +113,11 @@ public class StandardSession implements WxSession, InternalSession {
}
@Override
public void removeAttribute(String name) {
removeAttributeInternal(name);
}
@Override
public void invalidate() {
if (!isValidInternal())
@ -80,69 +129,6 @@ public class StandardSession implements WxSession, InternalSession {
}
// ------------------------------ 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
public WxSession getSession() {
@ -161,16 +147,6 @@ public class StandardSession implements WxSession, InternalSession {
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
public boolean isValid() {
if (!this.isValid) {
@ -197,6 +173,16 @@ public class StandardSession implements WxSession, InternalSession {
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
public String getIdInternal() {
return (this.id);

View File

@ -13,16 +13,65 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class StandardSessionManager implements WxSessionManager, InternalSessionManager {
protected final Logger log = LoggerFactory.getLogger(StandardSessionManager.class);
protected static final StringManager sm =
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
* session identifier.
*/
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
public WxSession getSession(String sessionId) {
@ -60,64 +109,6 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
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
public void remove(InternalSession session) {
remove(session, false);
@ -131,7 +122,6 @@ public class StandardSessionManager implements WxSessionManager, InternalSession
}
@Override
public InternalSession findSession(String id) {

View File

@ -21,8 +21,7 @@ package me.chanjar.weixin.common.session;
* reached and the server is refusing to create any new sessions.
*/
public class TooManyActiveSessionsException
extends IllegalStateException
{
extends IllegalStateException {
private static final long serialVersionUID = 1L;
/**
@ -38,8 +37,7 @@ public class TooManyActiveSessionsException
* session manager.
*/
public TooManyActiveSessionsException(String message,
int maxActive)
{
int maxActive) {
super(message);
maxActiveSessions = maxActive;
@ -50,8 +48,7 @@ public class TooManyActiveSessionsException
*
* @return The maximum number of sessions allowed by the session manager.
*/
public int getMaxActiveSessions()
{
public int getMaxActiveSessions() {
return maxActiveSessions;
}
}

View File

@ -7,7 +7,7 @@ public class StringUtils {
/**
* <p>Checks if a CharSequence is whitespace, empty ("") or null.</p>
*
* <p>
* <pre>
* StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true
@ -18,7 +18,6 @@ public class StringUtils {
*
* @param cs the CharSequence to check, may be null
* @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)
*/
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>
* <pre>
* StringUtils.isNotBlank(null) = false
* StringUtils.isNotBlank("") = false
@ -48,7 +47,6 @@ public class StringUtils {
* @param cs the CharSequence to check, may be null
* @return {@code true} if the CharSequence is
* not empty and not null and not whitespace
* @since 2.0
* @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
*/
public static boolean isNotBlank(CharSequence cs) {
@ -57,7 +55,7 @@ public class StringUtils {
/**
* <p>Checks if a CharSequence is empty ("") or null.</p>
*
* <p>
* <pre>
* StringUtils.isEmpty(null) = true
* StringUtils.isEmpty("") = true
@ -65,7 +63,7 @@ public class StringUtils {
* StringUtils.isEmpty("bob") = false
* StringUtils.isEmpty(" bob ") = false
* </pre>
*
* <p>
* <p>NOTE: This method changed in Lang version 2.0.
* It no longer trims the CharSequence.
* That functionality is available in isBlank().</p>
@ -80,7 +78,7 @@ public class StringUtils {
/**
* <p>Checks if a CharSequence is not empty ("") and not null.</p>
*
* <p>
* <pre>
* StringUtils.isNotEmpty(null) = false
* StringUtils.isNotEmpty("") = false

View File

@ -1,10 +1,10 @@
package me.chanjar.weixin.common.util.crypto;
import org.apache.commons.codec.digest.DigestUtils;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import org.apache.commons.codec.digest.DigestUtils;
/**
* Created by Daniel Qian on 14/10/19.
*/

View File

@ -2,6 +2,10 @@
* 对公众平台发送给公众账号的消息加解密示例代码.
*
* @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
*/
// ------------------------------------------------------------------------
@ -68,6 +72,45 @@ public class WxCryptUtil {
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>
@ -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数组
*
@ -316,16 +332,4 @@ public class WxCryptUtil {
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,6 +10,7 @@ public class FileUtils {
/**
* 创建临时文件
*
* @param inputStream
* @param name 文件名
* @param ext 扩展名
@ -51,6 +52,7 @@ public class FileUtils {
/**
* 创建临时文件
*
* @param inputStream
* @param name 文件名
* @param ext 扩展名

View File

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

View File

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

View File

@ -6,7 +6,6 @@ import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.common.util.fs.FileUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
@ -21,8 +20,8 @@ import java.util.regex.Pattern;
/**
* 下载媒体文件请求执行器请求的参数是String, 返回的结果是File
* @author Daniel Qian
*
* @author Daniel Qian
*/
public class MediaDownloadRequestExecutor implements RequestExecutor<File, String> {

View File

@ -5,7 +5,6 @@ import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
@ -19,8 +18,8 @@ import java.io.IOException;
/**
* 上传媒体文件请求执行器请求的参数是File, 返回的结果是String
* @author Daniel Qian
*
* @author Daniel Qian
*/
public class MediaUploadRequestExecutor implements RequestExecutor<WxMediaUploadResult, File> {

View File

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

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.exception.WxErrorException;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
@ -13,8 +12,8 @@ import java.io.IOException;
/**
* 简单的GET请求执行器请求的参数是String, 返回的结果也是String
* @author Daniel Qian
*
* @author Daniel Qian
*/
public class SimpleGetRequestExecutor implements RequestExecutor<String, String> {

View File

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

View File

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

View File

@ -14,9 +14,7 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
import java.lang.reflect.Type;
/**
*
* @author Daniel Qian
*
*/
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;
/**
*
* @author Daniel Qian
*
*/
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.GsonBuilder;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
public class WxGsonBuilder {

View File

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

View File

@ -8,22 +8,13 @@
*/
package me.chanjar.weixin.common.util.json;
import com.google.gson.JsonArray;
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 com.google.gson.*;
import me.chanjar.weixin.common.bean.WxMenu;
import java.lang.reflect.Type;
/**
*
* @author Daniel Qian
*
*/
public class WxMenuGsonAdapter implements JsonSerializer<WxMenu>, JsonDeserializer<WxMenu> {

View File

@ -18,30 +18,24 @@
package me.chanjar.weixin.common.util.res;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.*;
/**
* An internationalization / localization helper class which reduces
* the bother of handling ResourceBundles and takes care of the
* common cases of message formating which otherwise require the
* creation of Object arrays and such.
*
* <p>
* <p>The StringManager operates on a package basis. One StringManager
* per package can be created and accessed via the getManager method
* call.
*
* <p>
* <p>The StringManager will look for a ResourceBundle named by
* the package name given plus the suffix of "LocalStrings". In
* practice, this means that the localized information will be contained
* in a LocalStrings.properties file located in the package
* directory of the classpath.
*
* <p>
* <p>Please see the documentation for java.util.ResourceBundle for
* more information.
*
@ -52,8 +46,9 @@ import java.util.ResourceBundle;
*/
public class StringManager {
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.
*/
@ -101,13 +96,90 @@ public class StringManager {
}
/**
Get a string from the underlying resource bundle or return
null if the String is not found.
* 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());
}
@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.
/**
* 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.
* Expansion occurs when size() exceeds capacity. Therefore keep
* size at or below capacity.
* removeEldestEntry() executes after insertion therefore the test
* for removal needs to use one less than the maximum desired size
*
*/
map = new LinkedHashMap<Locale, StringManager>(LOCALE_CACHE_SIZE, 1, true) {
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);
if (mgr == null) {
mgr = new StringManager(packageName, locale);
map.put(locale, mgr);
}
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) {
@ -165,84 +237,4 @@ public class StringManager {
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.
* Expansion occurs when size() exceeds capacity. Therefore keep
* size at or below capacity.
* removeEldestEntry() executes after insertion therefore the test
* for removal needs to use one less than the maximum desired size
*
*/
map = new LinkedHashMap<Locale,StringManager>(LOCALE_CACHE_SIZE, 1, true) {
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);
if (mgr == null) {
mgr = new StringManager(packageName, locale);
map.put(locale, mgr);
}
return mgr;
}
/**
* 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);
}
}

View File

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