From 083147c2702448aa76489e11dd8e420d0d35cd68 Mon Sep 17 00:00:00 2001 From: "jy.hu" Date: Mon, 27 Oct 2014 11:18:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5netty=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=B9=B6=E6=94=AF=E6=8C=81=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=88=86=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/foxinmy/weixin4j/README.md | 3 + .../weixin4j/action/AbstractAction.java | 53 ++++++++++++ .../com/foxinmy/weixin4j/action/Action.java | 26 ++++++ .../foxinmy/weixin4j/action/BlankAction.java | 23 +++++ .../foxinmy/weixin4j/action/DebugAction.java | 23 +++++ .../foxinmy/weixin4j/action/ImageAction.java | 18 ++++ .../foxinmy/weixin4j/action/LinkAction.java | 18 ++++ .../weixin4j/action/LocationAction.java | 18 ++++ .../com/foxinmy/weixin4j/action/README.md | 1 + .../weixin4j/action/SignatureAction.java | 47 ++++++++++ .../foxinmy/weixin4j/action/TextAction.java | 22 +++++ .../foxinmy/weixin4j/action/VideoAction.java | 18 ++++ .../foxinmy/weixin4j/action/VoiceAction.java | 18 ++++ .../foxinmy/weixin4j/action/WeixinAction.java | 18 ++++ .../weixin4j/action/event/LocationAction.java | 21 +++++ .../weixin4j/action/event/MassSendAction.java | 21 +++++ .../action/event/MenuClickAction.java | 21 +++++ .../action/event/MenuLocationAction.java | 21 +++++ .../action/event/MenuPhotoAction.java | 23 +++++ .../weixin4j/action/event/MenuScanAction.java | 22 +++++ .../weixin4j/action/event/MenuViewAction.java | 21 +++++ .../foxinmy/weixin4j/action/event/README.md | 1 + .../weixin4j/action/event/ScanAction.java | 21 +++++ .../action/event/SubscribeAction.java | 21 +++++ .../action/event/TemplateSendAction.java | 22 +++++ .../action/event/UnsubscribeAction.java | 21 +++++ .../java/com/foxinmy/weixin4j/api/README.md | 1 + .../com/foxinmy/weixin4j/api/token/README.md | 1 + .../java/com/foxinmy/weixin4j/http/README.md | 1 + .../com/foxinmy/weixin4j/msg/event/README.md | 1 + .../foxinmy/weixin4j/msg/event/menu/README.md | 1 + .../com/foxinmy/weixin4j/msg/in/README.md | 1 + .../com/foxinmy/weixin4j/msg/model/README.md | 1 + .../com/foxinmy/weixin4j/msg/notify/README.md | 1 + .../com/foxinmy/weixin4j/msg/out/README.md | 1 + .../com/foxinmy/weixin4j/server/README.md | 1 + .../weixin4j/server/WeixinActionMapping.java | 48 +++++++++++ .../weixin4j/server/WeixinServerHandler.java | 86 +++++++++++++++++++ .../server/WeixinServerInitializer.java | 24 ++++++ .../server/WeixinServiceBootstrap.java | 53 ++++++++++++ .../foxinmy/weixin4j/server/netty.properties | 2 + .../com/foxinmy/weixin4j/spider/MpWeixin.java | 5 ++ .../com/foxinmy/weixin4j/spider/README.md | 3 + .../java/com/foxinmy/weixin4j/type/README.md | 1 + .../com/foxinmy/weixin4j/util/ClassUtil.java | 56 ++++++++++++ .../com/foxinmy/weixin4j/util/RandomUtil.java | 76 ++++++++++++++++ .../java/com/foxinmy/weixin4j/xml/README.md | 1 + .../weixin4j/test/msg/MessagePush.java | 49 +++++++++++ 48 files changed, 956 insertions(+) create mode 100644 src/main/java/com/foxinmy/weixin4j/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/action/AbstractAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/Action.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/BlankAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/DebugAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/ImageAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/LinkAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/LocationAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/action/SignatureAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/TextAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/VideoAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/VoiceAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/WeixinAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/LocationAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/MassSendAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/MenuClickAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/MenuLocationAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/MenuPhotoAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/MenuScanAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/MenuViewAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/ScanAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/SubscribeAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/TemplateSendAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/action/event/UnsubscribeAction.java create mode 100644 src/main/java/com/foxinmy/weixin4j/api/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/api/token/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/http/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/msg/event/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/msg/event/menu/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/msg/in/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/msg/model/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/msg/notify/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/msg/out/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/server/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/server/WeixinActionMapping.java create mode 100644 src/main/java/com/foxinmy/weixin4j/server/WeixinServerHandler.java create mode 100644 src/main/java/com/foxinmy/weixin4j/server/WeixinServerInitializer.java create mode 100644 src/main/java/com/foxinmy/weixin4j/server/WeixinServiceBootstrap.java create mode 100644 src/main/java/com/foxinmy/weixin4j/server/netty.properties create mode 100644 src/main/java/com/foxinmy/weixin4j/spider/MpWeixin.java create mode 100644 src/main/java/com/foxinmy/weixin4j/spider/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/type/README.md create mode 100644 src/main/java/com/foxinmy/weixin4j/util/ClassUtil.java create mode 100644 src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java create mode 100644 src/main/java/com/foxinmy/weixin4j/xml/README.md create mode 100644 src/test/java/com/foxinmy/weixin4j/test/msg/MessagePush.java diff --git a/src/main/java/com/foxinmy/weixin4j/README.md b/src/main/java/com/foxinmy/weixin4j/README.md new file mode 100644 index 00000000..1720ea24 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/README.md @@ -0,0 +1,3 @@ +config.properties包含了app跟接口url信息 + +WeixinProxy类为接口调用入口 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/action/AbstractAction.java b/src/main/java/com/foxinmy/weixin4j/action/AbstractAction.java new file mode 100644 index 00000000..a1301dbb --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/AbstractAction.java @@ -0,0 +1,53 @@ +package com.foxinmy.weixin4j.action; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.dom4j.DocumentException; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.util.MessageUtil; +import com.foxinmy.weixin4j.xml.XStream; + +/** + * 继承的类需实现execute(M inMessage) + * + * @className AbstractAction + * @author jy + * @date 2014年10月12日 + * @since JDK 1.7 + * @see + */ +public abstract class AbstractAction implements + WeixinAction { + + public abstract String execute(M inMessage); + + @SuppressWarnings("unchecked") + @Override + public String execute(String msg) throws DocumentException { + BaseMessage message = MessageUtil.xml2msg(msg); + if (message == null) { + Class messageClass = getGenericType(); + XStream xstream = new XStream(); + xstream.ignoreUnknownElements(); + xstream.autodetectAnnotations(true); + xstream.processAnnotations(messageClass); + xstream.alias("xml", messageClass); + return execute(xstream.fromXML(msg, messageClass)); + } + return execute((M) message); + } + + @SuppressWarnings("unchecked") + private Class getGenericType() { + Class clazz = null; + 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/src/main/java/com/foxinmy/weixin4j/action/Action.java b/src/main/java/com/foxinmy/weixin4j/action/Action.java new file mode 100644 index 00000000..671894d5 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/Action.java @@ -0,0 +1,26 @@ +package com.foxinmy.weixin4j.action; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +/** + * 标注 + * @className Action + * @author jy + * @date 2014年10月12日 + * @since JDK 1.7 + * @see + */ +public @interface Action { + + MessageType msgType(); + + EventType[] eventType() default {}; +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/BlankAction.java b/src/main/java/com/foxinmy/weixin4j/action/BlankAction.java new file mode 100644 index 00000000..fb047971 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/BlankAction.java @@ -0,0 +1,23 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.BaseMessage; + +/** + * 返回空白消息 + * + * @className BlankAction + * @author jy.hu + * @date 2014年10月2日 + * @since JDK 1.7 + * @see + */ +public abstract class BlankAction extends + AbstractAction { + + private final String BLANK = ""; + + @Override + public String execute(M message) { + return BLANK; + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/DebugAction.java b/src/main/java/com/foxinmy/weixin4j/action/DebugAction.java new file mode 100644 index 00000000..7214618e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/DebugAction.java @@ -0,0 +1,23 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.BaseMessage; +import com.foxinmy.weixin4j.msg.TextMessage; + +/** + * 显示调试信息 + * + * @className DebugAction + * @author jy + * @date 2014年10月8日 + * @since JDK 1.7 + * @see + */ +public abstract class DebugAction extends + AbstractAction { + + @Override + public String execute(M message) { + BaseMessage response = new TextMessage(message.toString(), message); + return response.toXml(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/ImageAction.java b/src/main/java/com/foxinmy/weixin4j/action/ImageAction.java new file mode 100644 index 00000000..b6786947 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/ImageAction.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.in.ImageMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 图片消息响应 + * + * @className ImageAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.in.ImageMessage + */ +@Action(msgType = MessageType.image) +public class ImageAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/LinkAction.java b/src/main/java/com/foxinmy/weixin4j/action/LinkAction.java new file mode 100644 index 00000000..e4bac378 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/LinkAction.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.in.LinkMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 链接消息响应 + * + * @className LinkAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.in.LinkMessage + */ +@Action(msgType = MessageType.link) +public class LinkAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/LocationAction.java b/src/main/java/com/foxinmy/weixin4j/action/LocationAction.java new file mode 100644 index 00000000..a47c7d8e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/LocationAction.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.in.LocationMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 地理位置响应 + * + * @className LocationAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.in.LocationMessage + */ +@Action(msgType = MessageType.location) +public class LocationAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/README.md b/src/main/java/com/foxinmy/weixin4j/action/README.md new file mode 100644 index 00000000..c0b75a62 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/README.md @@ -0,0 +1 @@ +普通消息类型对应的Action \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/action/SignatureAction.java b/src/main/java/com/foxinmy/weixin4j/action/SignatureAction.java new file mode 100644 index 00000000..81cb9e34 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/SignatureAction.java @@ -0,0 +1,47 @@ +package com.foxinmy.weixin4j.action; + +import io.netty.handler.codec.http.QueryStringDecoder; + +import java.util.List; +import java.util.Map; + +import org.dom4j.DocumentException; + +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.util.ConfigUtil; +import com.foxinmy.weixin4j.util.MessageUtil; + +/** + * 用于校验消息安全性 + * + * @className SignatureAction + * @author jy + * @date 2014年10月24日 + * @since JDK 1.7 + * @see + */ +@Action(msgType = MessageType.signature) +public class SignatureAction implements WeixinAction { + + @Override + public String execute(String uri) throws DocumentException { + String[] paths = uri.split("\\?"); + if (paths == null || paths.length < 2) { + return ""; + } + QueryStringDecoder queryDecoder = new QueryStringDecoder(paths[1], + false); + Map> parameters = queryDecoder.parameters(); + String echostr = parameters.containsKey("echostr") ? parameters.get( + "echostr").get(0) : null; + String timestamp = parameters.containsKey("timestamp") ? parameters + .get("timestamp").get(0) : null; + String nonce = parameters.containsKey("nonce") ? parameters + .get("nonce").get(0) : null; + String signature = parameters.containsKey("signature") ? parameters + .get("signature").get(0) : null; + String token = ConfigUtil.getValue("app_token"); + return MessageUtil.signature(token, echostr, timestamp, nonce, + signature); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/TextAction.java b/src/main/java/com/foxinmy/weixin4j/action/TextAction.java new file mode 100644 index 00000000..17a126d9 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/TextAction.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.TextMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 文字消息响应 + * + * @className TextAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.TextMessage + */ +@Action(msgType = MessageType.text) +public class TextAction extends AbstractAction { + + @Override + public String execute(TextMessage inMessage) { + return new TextMessage("Hello World!", inMessage).toXml(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/VideoAction.java b/src/main/java/com/foxinmy/weixin4j/action/VideoAction.java new file mode 100644 index 00000000..c4067914 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/VideoAction.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.in.VideoMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 视频消息响应 + * + * @className VideoAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.in.VideoMessage + */ +@Action(msgType = MessageType.video) +public class VideoAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/VoiceAction.java b/src/main/java/com/foxinmy/weixin4j/action/VoiceAction.java new file mode 100644 index 00000000..3ab2865f --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/VoiceAction.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.action; + +import com.foxinmy.weixin4j.msg.in.VoiceMessage; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 语音消息响应 + * + * @className VoiceAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.in.VoiceMessage + */ +@Action(msgType = MessageType.voice) +public class VoiceAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/WeixinAction.java b/src/main/java/com/foxinmy/weixin4j/action/WeixinAction.java new file mode 100644 index 00000000..5006341b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/WeixinAction.java @@ -0,0 +1,18 @@ +package com.foxinmy.weixin4j.action; + +import org.dom4j.DocumentException; + +/** + * 消息处理接口 + * + * @className Action + * @author jy.hu + * @date 2014年10月2日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.action.AbstractAction + * @see com.foxinmy.weixin4j.action.BlankAction + * @see com.foxinmy.weixin4j.action.DebugAction + */ +public interface WeixinAction { + public String execute(String msg) throws DocumentException; +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/LocationAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/LocationAction.java new file mode 100644 index 00000000..2f9af320 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/LocationAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.LocationEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 上报地理位置后触发 + * + * @className LocationAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.LocationEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.location }) +public class LocationAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/MassSendAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/MassSendAction.java new file mode 100644 index 00000000..9a71973b --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/MassSendAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.MassEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 群发消息发送动作完成后触发 + * + * @className MassSendAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.MassEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.massendjobfinish }) +public class MassSendAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/MenuClickAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/MenuClickAction.java new file mode 100644 index 00000000..34d699c9 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/MenuClickAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 菜单点击click事件时触发 + * + * @className MenuClickAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.click }) +public class MenuClickAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/MenuLocationAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/MenuLocationAction.java new file mode 100644 index 00000000..75712bb4 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/MenuLocationAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 菜单发送地理位置时触发 + * + * @className MenuLocationAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.menu.MenuLocationEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.location_select }) +public class MenuLocationAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/MenuPhotoAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/MenuPhotoAction.java new file mode 100644 index 00000000..84ffeded --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/MenuPhotoAction.java @@ -0,0 +1,23 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 菜单发送图片时触发 + * + * @className MenuPhotoAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.menu.MenuPhotoEventMessage + */ +@Action(msgType = MessageType.event, eventType = { + EventType.pic_photo_or_album, EventType.pic_sysphoto, + EventType.pic_weixin }) +public class MenuPhotoAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/MenuScanAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/MenuScanAction.java new file mode 100644 index 00000000..37a1b32e --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/MenuScanAction.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 菜单扫描时触发 + * + * @className MenuScanAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.menu.MenuScanEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.scancode_push, + EventType.scancode_waitmsg }) +public class MenuScanAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/MenuViewAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/MenuViewAction.java new file mode 100644 index 00000000..46eb1b7a --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/MenuViewAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 菜单点击view事件时触发 + * + * @className MenuViewAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.menu.MenuEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.view }) +public class MenuViewAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/README.md b/src/main/java/com/foxinmy/weixin4j/action/event/README.md new file mode 100644 index 00000000..c48619b3 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/README.md @@ -0,0 +1 @@ +事件消息类型对应的Action \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/ScanAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/ScanAction.java new file mode 100644 index 00000000..723991d2 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/ScanAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.ScanEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 扫描事件时触发 + * + * @className ScanAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.scan }) +public class ScanAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/SubscribeAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/SubscribeAction.java new file mode 100644 index 00000000..d6e5cb85 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/SubscribeAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 关注时触发 + * + * @className SubscribeAction + * @author jy + * @date 2014年10月9日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.subscribe }) +public class SubscribeAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/TemplateSendAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/TemplateSendAction.java new file mode 100644 index 00000000..349efc77 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/TemplateSendAction.java @@ -0,0 +1,22 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 模板消息发送动作完成时触发 + * + * @className TemplateSendAction + * @author jy + * @date 2014年10月10日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.TemplatesendjobfinishMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.templatesendjobfinish }) +public class TemplateSendAction extends + DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/action/event/UnsubscribeAction.java b/src/main/java/com/foxinmy/weixin4j/action/event/UnsubscribeAction.java new file mode 100644 index 00000000..64b5f63d --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/action/event/UnsubscribeAction.java @@ -0,0 +1,21 @@ +package com.foxinmy.weixin4j.action.event; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.DebugAction; +import com.foxinmy.weixin4j.msg.event.ScribeEventMessage; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; + +/** + * 取消关注时触发 + * + * @className UnsubscribeAction + * @author jy + * @date 2014年10月10日 + * @since JDK 1.7 + * @see com.foxinmy.weixin4j.msg.event.ScanEventMessage + */ +@Action(msgType = MessageType.event, eventType = { EventType.unsubscribe }) +public class UnsubscribeAction extends DebugAction { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/api/README.md b/src/main/java/com/foxinmy/weixin4j/api/README.md new file mode 100644 index 00000000..deac1dcf --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/README.md @@ -0,0 +1 @@ +API的实现 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/api/token/README.md b/src/main/java/com/foxinmy/weixin4j/api/token/README.md new file mode 100644 index 00000000..d674ea9f --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/api/token/README.md @@ -0,0 +1 @@ +Token的实现 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/http/README.md b/src/main/java/com/foxinmy/weixin4j/http/README.md new file mode 100644 index 00000000..c47f8468 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/http/README.md @@ -0,0 +1 @@ +基于HttpClient封装的针对微信API的HttpRequest \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/README.md b/src/main/java/com/foxinmy/weixin4j/msg/event/README.md new file mode 100644 index 00000000..08852002 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/README.md @@ -0,0 +1 @@ +事件消息 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/msg/event/menu/README.md b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/README.md new file mode 100644 index 00000000..f04f4575 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/event/menu/README.md @@ -0,0 +1 @@ +底部菜单消息 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/msg/in/README.md b/src/main/java/com/foxinmy/weixin4j/msg/in/README.md new file mode 100644 index 00000000..e8725f39 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/in/README.md @@ -0,0 +1 @@ +微信push过来的消息 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/msg/model/README.md b/src/main/java/com/foxinmy/weixin4j/msg/model/README.md new file mode 100644 index 00000000..e710f5c1 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/model/README.md @@ -0,0 +1 @@ +不同的消息类型中的模型 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/msg/notify/README.md b/src/main/java/com/foxinmy/weixin4j/msg/notify/README.md new file mode 100644 index 00000000..f6831d23 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/notify/README.md @@ -0,0 +1 @@ +客服消息 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/msg/out/README.md b/src/main/java/com/foxinmy/weixin4j/msg/out/README.md new file mode 100644 index 00000000..04955923 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/msg/out/README.md @@ -0,0 +1 @@ +回复消息 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/server/README.md b/src/main/java/com/foxinmy/weixin4j/server/README.md new file mode 100644 index 00000000..b14d4f53 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/server/README.md @@ -0,0 +1 @@ +微信服务netty启动类 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/server/WeixinActionMapping.java b/src/main/java/com/foxinmy/weixin4j/server/WeixinActionMapping.java new file mode 100644 index 00000000..0e0da1b1 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/server/WeixinActionMapping.java @@ -0,0 +1,48 @@ +package com.foxinmy.weixin4j.server; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.foxinmy.weixin4j.action.Action; +import com.foxinmy.weixin4j.action.WeixinAction; +import com.foxinmy.weixin4j.type.EventType; +import com.foxinmy.weixin4j.type.MessageType; +import com.foxinmy.weixin4j.util.ClassUtil; + +public class WeixinActionMapping { + private final Map actionMap; + + public WeixinActionMapping() { + actionMap = new HashMap(); + Set> weixinActions = ClassUtil.getClasses(WeixinAction.class + .getPackage()); + for (Class clazz : weixinActions) { + Action action = clazz.getAnnotation(Action.class); + if (action == null) { + continue; + } + WeixinAction weixinAction = null; + try { + weixinAction = (WeixinAction) clazz.newInstance(); + } catch (Exception e) { + continue; + } + MessageType msgType = action.msgType(); + EventType[] eventTypes = action.eventType(); + if (eventTypes != null && eventTypes.length > 0) { + for (EventType e : eventTypes) { + actionMap.put( + (msgType.name() + "_" + e.name()).toLowerCase(), + weixinAction); + } + continue; + } + actionMap.put(msgType.name().toLowerCase(), weixinAction); + } + } + + public WeixinAction getAction(String key) { + return actionMap.get(key.toLowerCase()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/server/WeixinServerHandler.java b/src/main/java/com/foxinmy/weixin4j/server/WeixinServerHandler.java new file mode 100644 index 00000000..ff9d9391 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/server/WeixinServerHandler.java @@ -0,0 +1,86 @@ +package com.foxinmy.weixin4j.server; + +import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION; +import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH; +import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; +import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE; +import static io.netty.handler.codec.http.HttpResponseStatus.OK; +import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.codec.http.DefaultFullHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpHeaders.Values; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; + +import java.nio.charset.StandardCharsets; + +import org.dom4j.DocumentException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.foxinmy.weixin4j.action.WeixinAction; +import com.foxinmy.weixin4j.util.MessageUtil; + +public class WeixinServerHandler extends ChannelInboundHandlerAdapter { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final WeixinActionMapping weixinActionMapping; + + public WeixinServerHandler(WeixinActionMapping weixinActionMapping) { + this.weixinActionMapping = weixinActionMapping; + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) { + ctx.flush(); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) + throws DocumentException { + if (msg instanceof FullHttpRequest) { + FullHttpRequest req = (FullHttpRequest) msg; + if (HttpHeaders.is100ContinueExpected(req)) { + ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE)); + return; + } + String xmlMsg = req.content().toString(StandardCharsets.UTF_8); + log.info("\n=================message in=================\n{}", + xmlMsg); + String key = MessageUtil.getMappingKey(xmlMsg); + WeixinAction action = weixinActionMapping.getAction(key); + if (action == null) { + ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, + HttpResponseStatus.NOT_FOUND)); + return; + } + String content = action.execute(xmlMsg); + log.info("\n=================message out=================\n{}", + content); + FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, + OK, Unpooled.copiedBuffer(content, StandardCharsets.UTF_8)); + response.headers().set(CONTENT_TYPE, "text/plain;charset=utf-8"); + response.headers().set(CONTENT_LENGTH, + response.content().readableBytes()); + if (!HttpHeaders.isKeepAlive(req)) { + ctx.write(response).addListener(ChannelFutureListener.CLOSE); + } else { + response.headers().set(CONNECTION, Values.KEEP_ALIVE); + ctx.write(response); + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/server/WeixinServerInitializer.java b/src/main/java/com/foxinmy/weixin4j/server/WeixinServerInitializer.java new file mode 100644 index 00000000..0211b471 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/server/WeixinServerInitializer.java @@ -0,0 +1,24 @@ +package com.foxinmy.weixin4j.server; + +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; + +public class WeixinServerInitializer extends ChannelInitializer { + + private final WeixinActionMapping weixinActionMapping; + + public WeixinServerInitializer() { + this.weixinActionMapping = new WeixinActionMapping(); + } + + @Override + protected void initChannel(SocketChannel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(new HttpServerCodec()); + pipeline.addLast(new HttpObjectAggregator(65536)); + pipeline.addLast(new WeixinServerHandler(weixinActionMapping)); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/server/WeixinServiceBootstrap.java b/src/main/java/com/foxinmy/weixin4j/server/WeixinServiceBootstrap.java new file mode 100644 index 00000000..9915eda1 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/server/WeixinServiceBootstrap.java @@ -0,0 +1,53 @@ +package com.foxinmy.weixin4j.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LoggingHandler; + +import java.util.ResourceBundle; + +/** + * 微信服务启动程序 + * + * @className WeixinBootstrap + * @author jy + * @date 2014年10月12日 + * @since JDK 1.7 + * @see + */ +public final class WeixinServiceBootstrap { + + private final static int port; + private final static int workerThreads; + static { + ResourceBundle config = ResourceBundle + .getBundle("com.foxinmy.weixin4j.server.netty"); + port = Integer.parseInt(config.getString("port")); + workerThreads = Integer.parseInt(config.getString("workerThreads")); + } + + public static void main(String[] args) { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + EventLoopGroup workerGroup = new NioEventLoopGroup(workerThreads); + try { + ServerBootstrap b = new ServerBootstrap(); + b.option(ChannelOption.SO_BACKLOG, 1024); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler()) + .childHandler(new WeixinServerInitializer()); + Channel ch = b.bind(port).sync().channel(); + System.err.println("weixin server startup OK:" + port); + ch.closeFuture().sync(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/server/netty.properties b/src/main/java/com/foxinmy/weixin4j/server/netty.properties new file mode 100644 index 00000000..184e4c9f --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/server/netty.properties @@ -0,0 +1,2 @@ +port=8090 +workerThreads=20 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/spider/MpWeixin.java b/src/main/java/com/foxinmy/weixin4j/spider/MpWeixin.java new file mode 100644 index 00000000..edd5f2b4 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/spider/MpWeixin.java @@ -0,0 +1,5 @@ +package com.foxinmy.weixin4j.spider; + +public final class MpWeixin { + +} diff --git a/src/main/java/com/foxinmy/weixin4j/spider/README.md b/src/main/java/com/foxinmy/weixin4j/spider/README.md new file mode 100644 index 00000000..7588d21d --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/spider/README.md @@ -0,0 +1,3 @@ +模拟微信公众平台登陆 + +(模拟登录|启用开发者模式|修改服务器配置|修改回调地址|创建自定义菜单....more) \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/type/README.md b/src/main/java/com/foxinmy/weixin4j/type/README.md new file mode 100644 index 00000000..2798d9f8 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/type/README.md @@ -0,0 +1 @@ +消息类型、事件类型等枚举 \ No newline at end of file diff --git a/src/main/java/com/foxinmy/weixin4j/util/ClassUtil.java b/src/main/java/com/foxinmy/weixin4j/util/ClassUtil.java new file mode 100644 index 00000000..48725281 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/ClassUtil.java @@ -0,0 +1,56 @@ +package com.foxinmy.weixin4j.util; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.URL; +import java.util.HashSet; +import java.util.Set; + +import com.foxinmy.weixin4j.action.WeixinAction; + +public class ClassUtil { + + public static Set> getClasses(Package _package) { + ClassLoader classLoader = Thread.currentThread() + .getContextClassLoader(); + String subPath = _package.getName().replace(".", File.separator); + URL fullPath = classLoader.getResource(subPath); + File dir = new File(fullPath.getPath()); + return findClasses(dir, _package.getName()); + } + + private static Set> findClasses(File dir, String packageName) { + Set> classes = new HashSet>(); + File[] files = dir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File file, String name) { + return file.isDirectory() || file.getName().endsWith(".class"); + } + }); + for (File file : files) { + if (file.isDirectory()) { + classes.addAll(findClasses(file, + packageName + "." + file.getName())); + } else { + try { + Class clazz = Class.forName(packageName + "." + + file.getName().replace(".class", "")); + if (clazz.isInterface()) { + continue; + } + classes.add(clazz); + } catch (ClassNotFoundException e) { + ; + } + + } + } + return classes; + } + + public static void main(String[] args) throws ClassNotFoundException, + IOException, InstantiationException, IllegalAccessException { + System.out.println(getClasses(WeixinAction.class.getPackage())); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java b/src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java new file mode 100644 index 00000000..d19c962a --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java @@ -0,0 +1,76 @@ +package com.foxinmy.weixin4j.util; + +import java.util.Random; +import java.util.UUID; + +/** + * 随机码工具类 + * @className RandomUtil + * @author jy + * @date 2014年10月22日 + * @since JDK 1.7 + * @see + */ +public class RandomUtil { + + private static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static final String LETTERCHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static final String NUMBERCHAR = "0123456789"; + + // 返回一个定长的随机字符串(包含数字和大小写字母) + public static String generateString(int length) { + StringBuilder sb = new StringBuilder(length); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length()))); + } + return sb.toString(); + } + + // 返回一个定长的随机纯数字字符串(只包含数字) + public static String generateStringByNumberChar(int length) { + StringBuilder sb = new StringBuilder(length); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(NUMBERCHAR.charAt(random.nextInt(NUMBERCHAR.length()))); + } + return sb.toString(); + } + + // 返回一个定长的随机纯字母字符串(只包含大小写字母) + public static String generateStringByLetterCharr(int length) { + StringBuilder sb = new StringBuilder(length); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(LETTERCHAR.charAt(random.nextInt(LETTERCHAR.length()))); + } + return sb.toString(); + } + + // 返回一个定长的随机纯大写字母字符串(只包含大小写字母) + public static String generateLowerString(int length) { + return generateStringByLetterCharr(length).toLowerCase(); + } + + // 返回一个定长的随机纯小写字母字符串(只包含大小写字母) + public static String generateUpperString(int length) { + return generateStringByLetterCharr(length).toUpperCase(); + } + + /** + * 随机获取UUID字符串(无中划线) + * + * @return UUID字符串 + */ + public static String getUUID() { + String uuid = UUID.randomUUID().toString(); + return uuid.substring(0, 8) + uuid.substring(9, 13) + + uuid.substring(14, 18) + uuid.substring(19, 23) + + uuid.substring(24); + } + + public static void main(String[] args) { + System.out.println(System.nanoTime()); + System.out.println(System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/foxinmy/weixin4j/xml/README.md b/src/main/java/com/foxinmy/weixin4j/xml/README.md new file mode 100644 index 00000000..cfc071f6 --- /dev/null +++ b/src/main/java/com/foxinmy/weixin4j/xml/README.md @@ -0,0 +1 @@ +添加支持 \ No newline at end of file diff --git a/src/test/java/com/foxinmy/weixin4j/test/msg/MessagePush.java b/src/test/java/com/foxinmy/weixin4j/test/msg/MessagePush.java new file mode 100644 index 00000000..122dc5be --- /dev/null +++ b/src/test/java/com/foxinmy/weixin4j/test/msg/MessagePush.java @@ -0,0 +1,49 @@ +package com.foxinmy.weixin4j.test.msg; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ResourceBundle; + +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + +import com.foxinmy.weixin4j.exception.WeixinException; + +public class MessagePush { + + private HttpClient httpClient; + private final HttpPost httpPost; + + public MessagePush() { + this.httpClient = new DefaultHttpClient(); + ResourceBundle config = ResourceBundle + .getBundle("com.foxinmy.weixin4j.server.netty"); + httpPost = new HttpPost(); + httpPost.setURI(URI.create(String.format("http://localhost:%s", + Integer.parseInt(config.getString("port"))))); + } + + public String push(String xml) throws WeixinException, IOException { + httpPost.setEntity(new StringEntity(xml, StandardCharsets.UTF_8)); + HttpResponse httpResponse = httpClient.execute(httpPost); + StatusLine statusLine = httpResponse.getStatusLine(); + + int status = statusLine.getStatusCode(); + if (status != HttpStatus.SC_OK) { + throw new WeixinException(status, "request fail"); + } + if (status == HttpStatus.SC_MOVED_PERMANENTLY + || status == HttpStatus.SC_MOVED_TEMPORARILY) { + throw new WeixinException(status, "uri moved"); + } + return EntityUtils.toString(httpResponse.getEntity(), + StandardCharsets.UTF_8); + } +}