引入netty服务模块并支持消息分发
This commit is contained in:
parent
0cc69cff01
commit
083147c270
3
src/main/java/com/foxinmy/weixin4j/README.md
Normal file
3
src/main/java/com/foxinmy/weixin4j/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
config.properties包含了app跟接口url信息
|
||||||
|
|
||||||
|
WeixinProxy类为接口调用入口
|
||||||
@ -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<M extends BaseMessage> 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<M> 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<M> getGenericType() {
|
||||||
|
Class<M> clazz = null;
|
||||||
|
Type type = getClass().getGenericSuperclass();
|
||||||
|
if (type instanceof ParameterizedType) {
|
||||||
|
ParameterizedType ptype = ((ParameterizedType) type);
|
||||||
|
Type[] args = ptype.getActualTypeArguments();
|
||||||
|
clazz = (Class<M>) args[0];
|
||||||
|
}
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/com/foxinmy/weixin4j/action/Action.java
Normal file
26
src/main/java/com/foxinmy/weixin4j/action/Action.java
Normal file
@ -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 {};
|
||||||
|
}
|
||||||
23
src/main/java/com/foxinmy/weixin4j/action/BlankAction.java
Normal file
23
src/main/java/com/foxinmy/weixin4j/action/BlankAction.java
Normal file
@ -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<M extends BaseMessage> extends
|
||||||
|
AbstractAction<M> {
|
||||||
|
|
||||||
|
private final String BLANK = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(M message) {
|
||||||
|
return BLANK;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/main/java/com/foxinmy/weixin4j/action/DebugAction.java
Normal file
23
src/main/java/com/foxinmy/weixin4j/action/DebugAction.java
Normal file
@ -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<M extends BaseMessage> extends
|
||||||
|
AbstractAction<M> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(M message) {
|
||||||
|
BaseMessage response = new TextMessage(message.toString(), message);
|
||||||
|
return response.toXml();
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/main/java/com/foxinmy/weixin4j/action/ImageAction.java
Normal file
18
src/main/java/com/foxinmy/weixin4j/action/ImageAction.java
Normal file
@ -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<ImageMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
18
src/main/java/com/foxinmy/weixin4j/action/LinkAction.java
Normal file
18
src/main/java/com/foxinmy/weixin4j/action/LinkAction.java
Normal file
@ -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<LinkMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<LocationMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
1
src/main/java/com/foxinmy/weixin4j/action/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/action/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
普通消息类型对应的Action
|
||||||
@ -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<String, List<String>> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/main/java/com/foxinmy/weixin4j/action/TextAction.java
Normal file
22
src/main/java/com/foxinmy/weixin4j/action/TextAction.java
Normal file
@ -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<TextMessage> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(TextMessage inMessage) {
|
||||||
|
return new TextMessage("Hello World!", inMessage).toXml();
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/main/java/com/foxinmy/weixin4j/action/VideoAction.java
Normal file
18
src/main/java/com/foxinmy/weixin4j/action/VideoAction.java
Normal file
@ -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<VideoMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
18
src/main/java/com/foxinmy/weixin4j/action/VoiceAction.java
Normal file
18
src/main/java/com/foxinmy/weixin4j/action/VoiceAction.java
Normal file
@ -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<VoiceMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
18
src/main/java/com/foxinmy/weixin4j/action/WeixinAction.java
Normal file
18
src/main/java/com/foxinmy/weixin4j/action/WeixinAction.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
@ -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<LocationEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<MassEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<MenuEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<MenuLocationEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<MenuPhotoEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<MenuScanEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<MenuEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
事件消息类型对应的Action
|
||||||
@ -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<ScanEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<ScribeEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<TemplatesendjobfinishMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -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<ScribeEventMessage> {
|
||||||
|
|
||||||
|
}
|
||||||
1
src/main/java/com/foxinmy/weixin4j/api/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/api/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
API的实现
|
||||||
1
src/main/java/com/foxinmy/weixin4j/api/token/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/api/token/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Token的实现
|
||||||
1
src/main/java/com/foxinmy/weixin4j/http/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/http/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
基于HttpClient封装的针对微信API的HttpRequest
|
||||||
1
src/main/java/com/foxinmy/weixin4j/msg/event/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/msg/event/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
事件消息
|
||||||
@ -0,0 +1 @@
|
|||||||
|
底部菜单消息
|
||||||
1
src/main/java/com/foxinmy/weixin4j/msg/in/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/msg/in/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
微信push过来的消息
|
||||||
1
src/main/java/com/foxinmy/weixin4j/msg/model/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/msg/model/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
不同的消息类型中的模型
|
||||||
1
src/main/java/com/foxinmy/weixin4j/msg/notify/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/msg/notify/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
客服消息
|
||||||
1
src/main/java/com/foxinmy/weixin4j/msg/out/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/msg/out/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
回复消息
|
||||||
1
src/main/java/com/foxinmy/weixin4j/server/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/server/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
微信服务netty启动类
|
||||||
@ -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<String, WeixinAction> actionMap;
|
||||||
|
|
||||||
|
public WeixinActionMapping() {
|
||||||
|
actionMap = new HashMap<String, WeixinAction>();
|
||||||
|
Set<Class<?>> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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<SocketChannel> {
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
port=8090
|
||||||
|
workerThreads=20
|
||||||
5
src/main/java/com/foxinmy/weixin4j/spider/MpWeixin.java
Normal file
5
src/main/java/com/foxinmy/weixin4j/spider/MpWeixin.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.foxinmy.weixin4j.spider;
|
||||||
|
|
||||||
|
public final class MpWeixin {
|
||||||
|
|
||||||
|
}
|
||||||
3
src/main/java/com/foxinmy/weixin4j/spider/README.md
Normal file
3
src/main/java/com/foxinmy/weixin4j/spider/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
模拟微信公众平台登陆
|
||||||
|
|
||||||
|
(模拟登录|启用开发者模式|修改服务器配置|修改回调地址|创建自定义菜单....more)
|
||||||
1
src/main/java/com/foxinmy/weixin4j/type/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/type/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
消息类型、事件类型等枚举
|
||||||
56
src/main/java/com/foxinmy/weixin4j/util/ClassUtil.java
Normal file
56
src/main/java/com/foxinmy/weixin4j/util/ClassUtil.java
Normal file
@ -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<Class<?>> 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<Class<?>> findClasses(File dir, String packageName) {
|
||||||
|
Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
76
src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java
Normal file
76
src/main/java/com/foxinmy/weixin4j/util/RandomUtil.java
Normal file
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/main/java/com/foxinmy/weixin4j/xml/README.md
Normal file
1
src/main/java/com/foxinmy/weixin4j/xml/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
添加<![CDATA[]>支持
|
||||||
49
src/test/java/com/foxinmy/weixin4j/test/msg/MessagePush.java
Normal file
49
src/test/java/com/foxinmy/weixin4j/test/msg/MessagePush.java
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user