From b6ec2485c929496bf16c01efa34b03a20b47be8f Mon Sep 17 00:00:00 2001 From: jinyu Date: Fri, 15 May 2015 12:51:19 +0800 Subject: [PATCH] =?UTF-8?q?weixin4j-server:=E6=B6=88=E6=81=AF=E6=8B=A6?= =?UTF-8?q?=E6=88=AA=E5=99=A8=E5=92=8C=E5=A4=84=E7=90=86=E5=99=A8=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=B3=9B=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGE.md | 4 + weixin4j-server/CHANGE.md | 6 +- .../dispatcher/MessageHandlerExecutor.java | 11 +- .../dispatcher/WeixinMessageAdapter.java | 69 +++++++++++ .../dispatcher/WeixinMessageDispatcher.java | 9 +- .../weixin4j/handler/BlankMessageHandler.java | 11 +- .../weixin4j/handler/DebugMessageHandler.java | 22 ++-- .../handler/MessageHandlerAdapter.java | 28 ++++- .../handler/WeixinMessageHandler.java | 6 +- .../MessageInterceptorAdapter.java | 45 +++++-- .../interceptor/WeixinMessageInterceptor.java | 19 ++- .../message/event/MenuPhotoEventMessage.java | 10 +- .../weixin4j/request/WeixinMessage.java | 38 +----- .../weixin4j/request/WeixinRequest.java | 116 ++++++++---------- .../weixin4j/socket/WeixinMessageDecoder.java | 31 ++--- .../weixin4j/socket/WeixinRequestHandler.java | 30 ++--- .../socket/WeixinResponseEncoder.java | 2 +- .../server/test/MessageServerStartup.java | 32 ++--- 18 files changed, 283 insertions(+), 206 deletions(-) create mode 100644 weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageAdapter.java diff --git a/CHANGE.md b/CHANGE.md index fca03f62..c1402f89 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -280,3 +280,7 @@ * 2015-05-13 + **weixin4j-server**: 新增了许多被动消息类型 + +* 2015-05-15 + + + **weixin4j-server**: 消息拦截器和处理器支持泛型 diff --git a/weixin4j-server/CHANGE.md b/weixin4j-server/CHANGE.md index 2213005b..effc0e53 100644 --- a/weixin4j-server/CHANGE.md +++ b/weixin4j-server/CHANGE.md @@ -28,4 +28,8 @@ * 2015-05-13 - + 新增了许多被动消息类型 \ No newline at end of file + + 新增了许多被动消息类型 + +* 2015-05-15 + + + **weixin4j-server**: 消息拦截器和处理器支持泛型 \ No newline at end of file diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/MessageHandlerExecutor.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/MessageHandlerExecutor.java index ac45263a..18481c02 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/MessageHandlerExecutor.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/MessageHandlerExecutor.java @@ -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); diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageAdapter.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageAdapter.java new file mode 100644 index 00000000..94bbc936 --- /dev/null +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageAdapter.java @@ -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 { + /** + * 消息类集合 + */ + private static final Map, Unmarshaller> unmarshallerMap; + + static { + unmarshallerMap = new HashMap, 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; + } +} diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java index 485c6c10..837c80ff 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/dispatcher/WeixinMessageDispatcher.java @@ -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) { diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/BlankMessageHandler.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/BlankMessageHandler.java index 59bba354..b3d152e8 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/BlankMessageHandler.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/BlankMessageHandler.java @@ -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; } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/DebugMessageHandler.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/DebugMessageHandler.java index 25410587..ac3c86d6 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/DebugMessageHandler.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/DebugMessageHandler.java @@ -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); } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/MessageHandlerAdapter.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/MessageHandlerAdapter.java index 73b4baed..1ca6b422 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/MessageHandlerAdapter.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/MessageHandlerAdapter.java @@ -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 extends WeixinMessageAdapter + 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; + } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/WeixinMessageHandler.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/WeixinMessageHandler.java index 49e2edfc..cf0da879 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/WeixinMessageHandler.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/handler/WeixinMessageHandler.java @@ -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; } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/MessageInterceptorAdapter.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/MessageInterceptorAdapter.java index a803caaf..bd30451c 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/MessageInterceptorAdapter.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/MessageInterceptorAdapter.java @@ -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 extends + WeixinMessageAdapter 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; } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/WeixinMessageInterceptor.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/WeixinMessageInterceptor.java index 565d115e..b31c3950 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/WeixinMessageInterceptor.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/interceptor/WeixinMessageInterceptor.java @@ -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; } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/message/event/MenuPhotoEventMessage.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/message/event/MenuPhotoEventMessage.java index 791eb0aa..66657a87 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/message/event/MenuPhotoEventMessage.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/message/event/MenuPhotoEventMessage.java @@ -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 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 + "]"; diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinMessage.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinMessage.java index dec597a2..38377762 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinMessage.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinMessage.java @@ -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; diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java index b236f2ce..ed180e18 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/request/WeixinRequest.java @@ -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 diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java index 38d3b779..1f020286 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinMessageDecoder.java @@ -44,8 +44,6 @@ public class WeixinMessageDecoder extends protected void decode(ChannelHandlerContext ctx, FullHttpRequest req, List 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> 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)); } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java index 64463732..1de9e435 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinRequestHandler.java @@ -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 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); } } diff --git a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java index 523bc5a1..c4af7aeb 100644 --- a/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java +++ b/weixin4j-server/src/main/java/com/foxinmy/weixin4j/socket/WeixinResponseEncoder.java @@ -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(""); content.append(String.format("", nonce)); diff --git a/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessageServerStartup.java b/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessageServerStartup.java index ecca0e0b..df6f355a 100644 --- a/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessageServerStartup.java +++ b/weixin4j-server/src/test/java/com/foxinmy/weixin4j/server/test/MessageServerStartup.java @@ -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() { @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(); } }