weixin4j-server:消息拦截器和处理器支持泛型
This commit is contained in:
parent
33d5addc18
commit
b6ec2485c9
@ -280,3 +280,7 @@
|
||||
* 2015-05-13
|
||||
|
||||
+ **weixin4j-server**: 新增了许多被动消息类型
|
||||
|
||||
* 2015-05-15
|
||||
|
||||
+ **weixin4j-server**: 消息拦截器和处理器支持泛型
|
||||
|
||||
@ -28,4 +28,8 @@
|
||||
|
||||
* 2015-05-13
|
||||
|
||||
+ 新增了许多被动消息类型
|
||||
+ 新增了许多被动消息类型
|
||||
|
||||
* 2015-05-15
|
||||
|
||||
+ **weixin4j-server**: 消息拦截器和处理器支持泛型
|
||||
@ -8,7 +8,6 @@ import org.slf4j.LoggerFactory;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
@ -49,7 +48,7 @@ public class MessageHandlerExecutor {
|
||||
return messageHandler;
|
||||
}
|
||||
|
||||
public boolean applyPreHandle(WeixinRequest request, WeixinMessage message)
|
||||
public boolean applyPreHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
if (messageInterceptors != null) {
|
||||
for (int i = 0; i < messageInterceptors.length; i++) {
|
||||
@ -66,7 +65,7 @@ public class MessageHandlerExecutor {
|
||||
}
|
||||
|
||||
public void applyPostHandle(WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message) throws WeixinException {
|
||||
String message) throws WeixinException {
|
||||
if (messageInterceptors == null) {
|
||||
return;
|
||||
}
|
||||
@ -77,8 +76,8 @@ public class MessageHandlerExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
public void triggerAfterCompletion(WeixinRequest request,
|
||||
WeixinMessage message, WeixinException ex) throws WeixinException {
|
||||
public void triggerAfterCompletion(WeixinRequest request, String message,
|
||||
WeixinException exception) throws WeixinException {
|
||||
if (messageInterceptors == null) {
|
||||
return;
|
||||
}
|
||||
@ -86,7 +85,7 @@ public class MessageHandlerExecutor {
|
||||
WeixinMessageInterceptor interceptor = messageInterceptors[i];
|
||||
try {
|
||||
interceptor.afterCompletion(context, request, message,
|
||||
messageHandler, ex);
|
||||
messageHandler, exception);
|
||||
} catch (WeixinException e) {
|
||||
logger.error(
|
||||
"MessageInterceptor.afterCompletion threw exception", e);
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
package com.foxinmy.weixin4j.dispatcher;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.util.Consts;
|
||||
|
||||
public abstract class WeixinMessageAdapter<M> {
|
||||
/**
|
||||
* 消息类集合
|
||||
*/
|
||||
private static final Map<Class<?>, Unmarshaller> unmarshallerMap;
|
||||
|
||||
static {
|
||||
unmarshallerMap = new HashMap<Class<?>, Unmarshaller>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected M messageRead(String message) throws WeixinException {
|
||||
try {
|
||||
Class<?> clazz = resolveMessageClass();
|
||||
Source source = new StreamSource(new ByteArrayInputStream(
|
||||
message.getBytes(Consts.UTF_8)));
|
||||
JAXBElement<?> jaxbElement = getUnmarshaller().unmarshal(source,
|
||||
clazz);
|
||||
return (M) jaxbElement.getValue();
|
||||
} catch (JAXBException e) {
|
||||
throw new WeixinException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Unmarshaller getUnmarshaller() throws WeixinException {
|
||||
Class<?> mineClass = resolveMessageClass();
|
||||
Unmarshaller unmarshaller = unmarshallerMap.get(mineClass);
|
||||
if (unmarshaller == null) {
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(mineClass);
|
||||
unmarshaller = jaxbContext.createUnmarshaller();
|
||||
unmarshallerMap.put(mineClass, unmarshaller);
|
||||
} catch (JAXBException e) {
|
||||
throw new WeixinException(e);
|
||||
}
|
||||
}
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
protected Class<?> resolveMessageClass() {
|
||||
Class<?> clazz = WeixinMessage.class;
|
||||
Type type = getClass().getGenericSuperclass();
|
||||
if (type instanceof ParameterizedType) {
|
||||
ParameterizedType ptype = ((ParameterizedType) type);
|
||||
Type[] args = ptype.getActualTypeArguments();
|
||||
clazz = (Class<?>) args[0];
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,6 @@ import com.foxinmy.weixin4j.bean.BeanFactory;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.util.ClassUtil;
|
||||
@ -65,7 +64,7 @@ public class WeixinMessageDispatcher {
|
||||
}
|
||||
|
||||
public void doDispatch(final ChannelHandlerContext context,
|
||||
final WeixinRequest request, final WeixinMessage message)
|
||||
final WeixinRequest request, final String message)
|
||||
throws WeixinException {
|
||||
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context,
|
||||
request, message);
|
||||
@ -94,14 +93,14 @@ public class WeixinMessageDispatcher {
|
||||
}
|
||||
|
||||
protected void noHandlerFound(ChannelHandlerContext ctx,
|
||||
WeixinRequest request, WeixinMessage message) {
|
||||
WeixinRequest request, String message) {
|
||||
ctx.writeAndFlush(HttpUtil.createHttpResponse(null, NOT_FOUND, null))
|
||||
.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
protected MessageHandlerExecutor getHandlerExecutor(
|
||||
ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinMessage message) throws WeixinException {
|
||||
ChannelHandlerContext context, WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
WeixinMessageHandler messageHandler = null;
|
||||
WeixinMessageHandler[] messageHandlers = getMessageHandlers();
|
||||
if (messageHandlers == null) {
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.BlankResponse;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
public class BlankMessageHandler extends MessageHandlerAdapter {
|
||||
public class BlankMessageHandler implements WeixinMessageHandler {
|
||||
|
||||
public final static BlankMessageHandler global = new BlankMessageHandler();
|
||||
|
||||
@ -15,7 +14,13 @@ public class BlankMessageHandler extends MessageHandlerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message)
|
||||
public boolean canHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
return BlankResponse.global;
|
||||
}
|
||||
|
||||
@ -1,23 +1,27 @@
|
||||
package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.TextResponse;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
public class DebugMessageHandler extends MessageHandlerAdapter {
|
||||
public class DebugMessageHandler implements WeixinMessageHandler {
|
||||
|
||||
public static final DebugMessageHandler global = new DebugMessageHandler();
|
||||
|
||||
private DebugMessageHandler(){
|
||||
|
||||
|
||||
private DebugMessageHandler() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message)
|
||||
public boolean canHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
return new TextResponse(String.format("%s,%s", request,
|
||||
message));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
return new TextResponse(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,32 @@
|
||||
package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageAdapter;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
public abstract class MessageHandlerAdapter implements WeixinMessageHandler {
|
||||
public abstract class MessageHandlerAdapter<M> extends WeixinMessageAdapter<M>
|
||||
implements WeixinMessageHandler {
|
||||
|
||||
private M message;
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message) {
|
||||
return true;
|
||||
public boolean canHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
this.message = super.messageRead(message);
|
||||
return canHandle0(request, message, this.message);
|
||||
}
|
||||
|
||||
public abstract boolean canHandle0(WeixinRequest request, String message,
|
||||
M m) throws WeixinException;
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, String message)
|
||||
throws WeixinException {
|
||||
return doHandle0(request, message, this.message);
|
||||
}
|
||||
|
||||
public abstract WeixinResponse doHandle0(WeixinRequest request,
|
||||
String message, M m) throws WeixinException;
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
@ -25,7 +24,8 @@ public interface WeixinMessageHandler {
|
||||
* 微信消息
|
||||
* @return
|
||||
*/
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message);
|
||||
public boolean canHandle(WeixinRequest request, String message)
|
||||
throws WeixinException;
|
||||
|
||||
/**
|
||||
* 处理请求
|
||||
@ -36,6 +36,6 @@ public interface WeixinMessageHandler {
|
||||
* 微信消息
|
||||
* @return
|
||||
*/
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message)
|
||||
public WeixinResponse doHandle(WeixinRequest request, String message)
|
||||
throws WeixinException;
|
||||
}
|
||||
|
||||
@ -2,33 +2,60 @@ package com.foxinmy.weixin4j.interceptor;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageAdapter;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
public abstract class MessageInterceptorAdapter implements
|
||||
WeixinMessageInterceptor {
|
||||
/**
|
||||
* 消息拦截适配
|
||||
*
|
||||
* @className MessageInterceptorAdapter
|
||||
* @author jy
|
||||
* @date 2015年5月14日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public abstract class MessageInterceptorAdapter<M> extends
|
||||
WeixinMessageAdapter<M> implements WeixinMessageInterceptor {
|
||||
|
||||
private M message;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message,
|
||||
WeixinRequest request, final String message,
|
||||
WeixinMessageHandler handler) throws WeixinException {
|
||||
return true;
|
||||
this.message = super.messageRead(message);
|
||||
return preHandle0(context, request, this.message, handler);
|
||||
}
|
||||
|
||||
public abstract boolean preHandle0(ChannelHandlerContext context,
|
||||
WeixinRequest request, M message, WeixinMessageHandler handler)
|
||||
throws WeixinException;
|
||||
|
||||
@Override
|
||||
public void postHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler)
|
||||
throws WeixinException {
|
||||
WeixinRequest request, WeixinResponse response, String message,
|
||||
WeixinMessageHandler handler) throws WeixinException {
|
||||
postHandle0(context, request, response, message, this.message, handler);
|
||||
}
|
||||
|
||||
public abstract void postHandle0(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response, String message,
|
||||
M m, WeixinMessageHandler handler) throws WeixinException;
|
||||
|
||||
@Override
|
||||
public void afterCompletion(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message,
|
||||
WeixinRequest request, String message,
|
||||
WeixinMessageHandler handler, WeixinException exception)
|
||||
throws WeixinException {
|
||||
afterCompletion0(context, request, message, this.message, handler,
|
||||
exception);
|
||||
}
|
||||
|
||||
public abstract void afterCompletion0(ChannelHandlerContext context,
|
||||
WeixinRequest request, String message, M m,
|
||||
WeixinMessageHandler handler, WeixinException exception)
|
||||
throws WeixinException;
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
@ -22,7 +21,7 @@ public interface WeixinMessageInterceptor {
|
||||
/**
|
||||
* 执行handler前
|
||||
*
|
||||
* @param ctx
|
||||
* @param context
|
||||
* 通道环境
|
||||
* @param request
|
||||
* 微信请求
|
||||
@ -33,14 +32,14 @@ public interface WeixinMessageInterceptor {
|
||||
* @return 返回true执行下一个拦截器
|
||||
* @throws WeixinException
|
||||
*/
|
||||
boolean preHandle(ChannelHandlerContext ctx, WeixinRequest request,
|
||||
WeixinMessage message, WeixinMessageHandler handler)
|
||||
boolean preHandle(ChannelHandlerContext context, WeixinRequest request,
|
||||
String message, WeixinMessageHandler handler)
|
||||
throws WeixinException;
|
||||
|
||||
/**
|
||||
* 执行handler后
|
||||
*
|
||||
* @param ctx
|
||||
* @param context
|
||||
* 通道环境
|
||||
* @param request
|
||||
* 微信请求
|
||||
@ -52,14 +51,14 @@ public interface WeixinMessageInterceptor {
|
||||
* 消息处理器
|
||||
* @throws WeixinException
|
||||
*/
|
||||
void postHandle(ChannelHandlerContext ctx, WeixinRequest request,
|
||||
WeixinResponse response, WeixinMessage message,
|
||||
void postHandle(ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinResponse response, String message,
|
||||
WeixinMessageHandler handler) throws WeixinException;
|
||||
|
||||
/**
|
||||
* 全部执行后
|
||||
*
|
||||
* @param ctx
|
||||
* @param context
|
||||
* 通道环境
|
||||
* @param request
|
||||
* 微信请求
|
||||
@ -71,7 +70,7 @@ public interface WeixinMessageInterceptor {
|
||||
* 执行异常
|
||||
* @throws WeixinException
|
||||
*/
|
||||
void afterCompletion(ChannelHandlerContext ctx, WeixinRequest request,
|
||||
WeixinMessage message, WeixinMessageHandler handler,
|
||||
void afterCompletion(ChannelHandlerContext context, WeixinRequest request,
|
||||
String message, WeixinMessageHandler handler,
|
||||
WeixinException exception) throws WeixinException;
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlElementWrapper;
|
||||
|
||||
/**
|
||||
* 弹出拍照或者相册发图的事件推送(pic_sysphoto|pic_photo_or_album|pic_weixin)
|
||||
@ -53,7 +53,8 @@ public class MenuPhotoEventMessage extends MenuEventMessage {
|
||||
/**
|
||||
* 图片列表
|
||||
*/
|
||||
@XmlElement(name = "PicList")
|
||||
@XmlElementWrapper(name = "PicList")
|
||||
@XmlElement(name = "item")
|
||||
private List<PictureItem> items;
|
||||
|
||||
public int getCount() {
|
||||
@ -79,7 +80,6 @@ public class MenuPhotoEventMessage extends MenuEventMessage {
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement(name = "item")
|
||||
public static class PictureItem implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7636697449096645590L;
|
||||
@ -90,6 +90,10 @@ public class MenuPhotoEventMessage extends MenuEventMessage {
|
||||
@XmlElement(name = "PicMd5Sum")
|
||||
private String md5;
|
||||
|
||||
public String getMd5() {
|
||||
return md5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PictureItem [md5=" + md5 + "]";
|
||||
|
||||
@ -3,7 +3,6 @@ package com.foxinmy.weixin4j.request;
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* 基本被动消息
|
||||
@ -14,7 +13,6 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement(name = "xml")
|
||||
public class WeixinMessage implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7761192742840031607L;
|
||||
@ -22,27 +20,33 @@ public class WeixinMessage implements Serializable {
|
||||
/**
|
||||
* 开发者微信号
|
||||
*/
|
||||
@XmlElement(name = "ToUserName")
|
||||
private String toUserName;
|
||||
/**
|
||||
* 发送方账号 即用户的openid
|
||||
*/
|
||||
@XmlElement(name = "FromUserName")
|
||||
private String fromUserName;
|
||||
/**
|
||||
* 消息创建时间 系统毫秒数
|
||||
*/
|
||||
@XmlElement(name = "CreateTime")
|
||||
private long createTime;
|
||||
/**
|
||||
* 消息类型
|
||||
*
|
||||
*/
|
||||
@XmlElement(name = "MsgType")
|
||||
private String msgType;
|
||||
/**
|
||||
* 消息ID 可用于排重
|
||||
*/
|
||||
@XmlElement(name = "MsgId")
|
||||
private long msgId;
|
||||
/**
|
||||
* 企业号独有的应用ID
|
||||
*/
|
||||
@XmlElement(name = "AgentID")
|
||||
private String agentId;
|
||||
|
||||
public WeixinMessage() {
|
||||
@ -57,56 +61,26 @@ public class WeixinMessage implements Serializable {
|
||||
return toUserName;
|
||||
}
|
||||
|
||||
@XmlElement(name = "ToUserName")
|
||||
public void setToUserName(String toUserName) {
|
||||
this.toUserName = toUserName;
|
||||
}
|
||||
|
||||
public String getFromUserName() {
|
||||
return fromUserName;
|
||||
}
|
||||
|
||||
@XmlElement(name = "FromUserName")
|
||||
public void setFromUserName(String fromUserName) {
|
||||
this.fromUserName = fromUserName;
|
||||
}
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
@XmlElement(name = "CreateTime")
|
||||
public void setCreateTime(long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
@XmlElement(name = "MsgType")
|
||||
public void setMsgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public long getMsgId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
@XmlElement(name = "MsgId")
|
||||
public void setMsgId(long msgId) {
|
||||
this.msgId = msgId;
|
||||
}
|
||||
|
||||
public String getAgentId() {
|
||||
return agentId;
|
||||
}
|
||||
|
||||
@XmlElement(name = "AgentID")
|
||||
public void setAgentId(String agentId) {
|
||||
this.agentId = agentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
||||
@ -17,17 +17,10 @@ public class WeixinRequest implements Serializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = -9157395300510879866L;
|
||||
|
||||
// 以下字段是加密方式为「安全模式」时的参数
|
||||
/**
|
||||
* 加密后的内容
|
||||
* 请求的方式
|
||||
*/
|
||||
private String encryptContent;
|
||||
/**
|
||||
* 加密类型
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.type.EncryptType
|
||||
*/
|
||||
private EncryptType encryptType;
|
||||
private String method;
|
||||
|
||||
// 以下字段每次被动消息时都会带上
|
||||
/**
|
||||
@ -50,85 +43,72 @@ public class WeixinRequest implements Serializable, Cloneable {
|
||||
* AES模式下消息签名
|
||||
*/
|
||||
private String msgSignature;
|
||||
|
||||
/**
|
||||
* 加密类型(POST时存在)
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.type.EncryptType
|
||||
*/
|
||||
private EncryptType encryptType;
|
||||
|
||||
/**
|
||||
* xml消息明文主体
|
||||
*/
|
||||
private String originalContent;
|
||||
|
||||
/**
|
||||
* 请求的方式
|
||||
* xml消息密文主体(AES时存在)
|
||||
*/
|
||||
private String method;
|
||||
private String encryptContent;
|
||||
|
||||
public String getEncryptContent() {
|
||||
return encryptContent;
|
||||
}
|
||||
|
||||
public void setEncryptContent(String encryptContent) {
|
||||
this.encryptContent = encryptContent;
|
||||
}
|
||||
|
||||
public EncryptType getEncryptType() {
|
||||
return encryptType;
|
||||
}
|
||||
|
||||
public void setEncryptType(EncryptType encryptType) {
|
||||
public WeixinRequest(String method, EncryptType encryptType,
|
||||
String echoStr, String timeStamp, String nonce, String signature,
|
||||
String msgSignature, String originalContent, String encryptContent) {
|
||||
this.method = method;
|
||||
this.encryptType = encryptType;
|
||||
}
|
||||
|
||||
public String getEchoStr() {
|
||||
return echoStr;
|
||||
}
|
||||
|
||||
public void setEchoStr(String echoStr) {
|
||||
this.echoStr = echoStr;
|
||||
}
|
||||
|
||||
public String getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public void setTimeStamp(String timeStamp) {
|
||||
this.timeStamp = timeStamp;
|
||||
}
|
||||
|
||||
public String getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
public void setNonce(String nonce) {
|
||||
this.nonce = nonce;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public String getMsgSignature() {
|
||||
return msgSignature;
|
||||
}
|
||||
|
||||
public void setMsgSignature(String msgSignature) {
|
||||
this.msgSignature = msgSignature;
|
||||
}
|
||||
|
||||
public String getOriginalContent() {
|
||||
return originalContent;
|
||||
}
|
||||
|
||||
public void setOriginalContent(String originalContent) {
|
||||
this.originalContent = originalContent;
|
||||
this.encryptContent = encryptContent;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
public String getEchoStr() {
|
||||
return echoStr;
|
||||
}
|
||||
|
||||
public String getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public String getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public String getMsgSignature() {
|
||||
return msgSignature;
|
||||
}
|
||||
|
||||
public EncryptType getEncryptType() {
|
||||
return encryptType;
|
||||
}
|
||||
|
||||
public String getOriginalContent() {
|
||||
return originalContent;
|
||||
}
|
||||
|
||||
public String getEncryptContent() {
|
||||
return encryptContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -44,8 +44,6 @@ public class WeixinMessageDecoder extends
|
||||
protected void decode(ChannelHandlerContext ctx, FullHttpRequest req,
|
||||
List<Object> out) throws WeixinException {
|
||||
String content = req.content().toString(Consts.UTF_8);
|
||||
WeixinRequest message = new WeixinRequest();
|
||||
message.setMethod(req.getMethod().name());
|
||||
QueryStringDecoder queryDecoder = new QueryStringDecoder(req.getUri(),
|
||||
true);
|
||||
log.info("\n=================receive request=================");
|
||||
@ -53,40 +51,35 @@ public class WeixinMessageDecoder extends
|
||||
log.info("{}", req.getUri());
|
||||
log.info("{}", content);
|
||||
Map<String, List<String>> parameters = queryDecoder.parameters();
|
||||
String encryptType = parameters.containsKey("encrypt_type") ? parameters
|
||||
.get("encrypt_type").get(0) : EncryptType.RAW.name();
|
||||
message.setEncryptType(EncryptType.valueOf(encryptType.toUpperCase()));
|
||||
EncryptType encryptType = parameters.containsKey("encrypt_type") ? EncryptType
|
||||
.valueOf(parameters.get("encrypt_type").get(0).toUpperCase())
|
||||
: EncryptType.RAW;
|
||||
String echoStr = parameters.containsKey("echostr") ? parameters.get(
|
||||
"echostr").get(0) : "";
|
||||
message.setEchoStr(echoStr);
|
||||
String timeStamp = parameters.containsKey("timestamp") ? parameters
|
||||
.get("timestamp").get(0) : "";
|
||||
message.setTimeStamp(timeStamp);
|
||||
String nonce = parameters.containsKey("nonce") ? parameters
|
||||
.get("nonce").get(0) : "";
|
||||
message.setNonce(nonce);
|
||||
String signature = parameters.containsKey("signature") ? parameters
|
||||
.get("signature").get(0) : "";
|
||||
message.setSignature(signature);
|
||||
String msgSignature = parameters.containsKey("msg_signature") ? parameters
|
||||
.get("msg_signature").get(0) : "";
|
||||
message.setMsgSignature(msgSignature);
|
||||
String originalContent = content;
|
||||
String encryptContent = null;
|
||||
if (!content.isEmpty()) {
|
||||
if (message.getEncryptType() == EncryptType.AES) {
|
||||
if (encryptType == EncryptType.AES) {
|
||||
if (StringUtil.isBlank(aesToken.getAesKey())
|
||||
|| StringUtil.isBlank(aesToken.getAppid())) {
|
||||
throw new WeixinException(
|
||||
"AESEncodingKey or AppId not be null in AES mode");
|
||||
}
|
||||
String encryptContent = EncryptMessageHandler.parser(content);
|
||||
message.setEncryptContent(encryptContent);
|
||||
message.setOriginalContent(MessageUtil.aesDecrypt(
|
||||
aesToken.getAppid(), aesToken.getAesKey(),
|
||||
encryptContent));
|
||||
} else {
|
||||
message.setOriginalContent(content);
|
||||
encryptContent = EncryptMessageHandler.parser(content);
|
||||
originalContent = MessageUtil.aesDecrypt(aesToken.getAppid(),
|
||||
aesToken.getAesKey(), encryptContent);
|
||||
}
|
||||
}
|
||||
out.add(message);
|
||||
out.add(new WeixinRequest(req.getMethod().name(), encryptType, echoStr,
|
||||
timeStamp, nonce, signature, msgSignature, originalContent,
|
||||
encryptContent));
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,8 +11,11 @@ import io.netty.handler.codec.http.HttpMethod;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -23,7 +26,6 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.ClassUtil;
|
||||
import com.foxinmy.weixin4j.util.Consts;
|
||||
import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
@ -44,17 +46,11 @@ public class WeixinRequestHandler extends
|
||||
|
||||
private final AesToken aesToken;
|
||||
private final WeixinMessageDispatcher messageDispatcher;
|
||||
private final JAXBContext jaxbContext;
|
||||
|
||||
public WeixinRequestHandler(AesToken aesToken,
|
||||
WeixinMessageDispatcher messageDispatcher) throws WeixinException {
|
||||
this.aesToken = aesToken;
|
||||
this.messageDispatcher = messageDispatcher;
|
||||
try {
|
||||
jaxbContext = JAXBContext.newInstance(WeixinMessage.class);
|
||||
} catch (JAXBException e) {
|
||||
throw new WeixinException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||
@ -112,12 +108,16 @@ public class WeixinRequestHandler extends
|
||||
.addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
WeixinMessage weixinMessage = null;
|
||||
final String message = request.getOriginalContent();
|
||||
WeixinMessage weixinMessage;
|
||||
try {
|
||||
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
|
||||
weixinMessage = (WeixinMessage) jaxbUnmarshaller
|
||||
.unmarshal(new ByteArrayInputStream(request
|
||||
.getOriginalContent().getBytes(Consts.UTF_8)));
|
||||
Unmarshaller unmarshaller = JAXBContext.newInstance(
|
||||
WeixinMessage.class).createUnmarshaller();
|
||||
Source source = new StreamSource(new ByteArrayInputStream(
|
||||
message.getBytes()));
|
||||
JAXBElement<WeixinMessage> jaxbElement = unmarshaller.unmarshal(
|
||||
source, WeixinMessage.class);
|
||||
weixinMessage = jaxbElement.getValue();
|
||||
} catch (JAXBException e) {
|
||||
throw new WeixinException(e);
|
||||
}
|
||||
@ -129,10 +129,6 @@ public class WeixinRequestHandler extends
|
||||
ctx.channel().attr(Consts.ACCOUNTOPENID_KEY)
|
||||
.set(weixinMessage.getToUserName());
|
||||
}
|
||||
final WeixinRequest cloneRequest = (WeixinRequest) ClassUtil
|
||||
.deepClone(request);
|
||||
final WeixinMessage cloneMessage = (WeixinMessage) ClassUtil
|
||||
.deepClone(weixinMessage);
|
||||
messageDispatcher.doDispatch(ctx, cloneRequest, cloneMessage);
|
||||
messageDispatcher.doDispatch(ctx, request, message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ public class WeixinResponseEncoder extends
|
||||
aesToken.getAesKey(), content.toString());
|
||||
String msgSignature = MessageUtil.signature(
|
||||
aesToken.getToken(), nonce, timestamp, encrtypt);
|
||||
content.delete(0, content.length() - 1);
|
||||
content.delete(0, content.length());
|
||||
content.append("<xml>");
|
||||
content.append(String.format("<Nonce><![CDATA[%s]]></Nonce>",
|
||||
nonce));
|
||||
|
||||
@ -5,10 +5,10 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.BlankMessageHandler;
|
||||
import com.foxinmy.weixin4j.handler.DebugMessageHandler;
|
||||
import com.foxinmy.weixin4j.handler.MessageHandlerAdapter;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.interceptor.MessageInterceptorAdapter;
|
||||
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.message.TextMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.TextResponse;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
@ -57,18 +57,18 @@ public class MessageServerStartup {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void test3() throws WeixinException {
|
||||
// 回复文本消息
|
||||
WeixinMessageHandler messageHandler = new WeixinMessageHandler() {
|
||||
// 文本消息回复
|
||||
WeixinMessageHandler messageHandler = new MessageHandlerAdapter<TextMessage>() {
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request,
|
||||
WeixinMessage message) throws WeixinException {
|
||||
return new TextResponse("HelloWorld!");
|
||||
public boolean canHandle0(WeixinRequest request, String message,
|
||||
TextMessage m) throws WeixinException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request,
|
||||
WeixinMessage message) {
|
||||
return message.getMsgType().equals("text");
|
||||
public WeixinResponse doHandle0(WeixinRequest request,
|
||||
String message, TextMessage m) throws WeixinException {
|
||||
return new TextResponse("HelloWorld!");
|
||||
}
|
||||
};
|
||||
// 当消息类型为文本(text)时回复「HelloWorld」, 否则回复调试消息
|
||||
@ -85,26 +85,26 @@ public class MessageServerStartup {
|
||||
|
||||
public void test5() throws WeixinException {
|
||||
// 拦截所有请求
|
||||
WeixinMessageInterceptor interceptor = new MessageInterceptorAdapter() {
|
||||
WeixinMessageInterceptor interceptor = new WeixinMessageInterceptor() {
|
||||
@Override
|
||||
public boolean preHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message,
|
||||
WeixinRequest request, String message,
|
||||
WeixinMessageHandler handler) throws WeixinException {
|
||||
context.write(new TextResponse("所有消息被拦截了!"));
|
||||
context.writeAndFlush(new TextResponse("所有消息被拦截了!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler)
|
||||
String message, WeixinMessageHandler handler)
|
||||
throws WeixinException {
|
||||
System.err.println("preHandle返回为true,执行handler后");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message,
|
||||
WeixinRequest request, String message,
|
||||
WeixinMessageHandler handler, WeixinException exception)
|
||||
throws WeixinException {
|
||||
System.err.println("请求处理完毕");
|
||||
@ -115,6 +115,6 @@ public class MessageServerStartup {
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws WeixinException {
|
||||
new MessageServerStartup().test5();
|
||||
new MessageServerStartup().test1();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user