feat(0): [java]-[wcferry-mvn]-架构调整

This commit is contained in:
chandler 2024-09-30 23:22:55 +08:00
parent 12029ebba0
commit fed590cdc6
6 changed files with 109 additions and 308 deletions

View File

@ -1,17 +0,0 @@
package com.iamteer;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
@Data
@Order(100)
public class BussinessContext {
private Client client;
}

View File

@ -0,0 +1,94 @@
package com.iamteer.config;
import javax.annotation.Resource;
import com.iamteer.handle.WechatSocketClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import lombok.extern.slf4j.Slf4j;
/**
* 配置类-注入微信客户端
*
* @author chandler
* @date 2024-09-30 12:21
*/
@Slf4j
@Configuration
public class WechatConfiguration {
@Resource
private WcferryProperties properties;
@Bean
public WechatSocketClient client() {
log.debug("测试:端口:{},地址:{}", properties.getSocketPort(), properties.getDllPath());
// 连接远程 RPC
// Client client = new Client("127.0.0.1", 10086);
// 本地启动 RPC
// Client client = new Client(); // 默认 10086 端口
// Client client = new Client(10088,true); // 也可以指定端口
WechatSocketClient wechatSocketClient = new WechatSocketClient(properties.getSocketPort(), properties.getDllPath());
// 是否已登录
// log.info("isLogin: {}", client.isLogin());
// 登录账号 wxid
// log.info("wxid: {}", client.getSelfWxid());
// 消息类型
// log.info("message types: {}", client.getMsgTypes());
// 所有联系人包括群聊公众号好友
// client.printContacts(client.getContacts());
// 获取数据库
log.info("dbs: {}", wechatSocketClient.getDbNames());
// 获取数据库下的表
String db = "MicroMsg.db";
// log.info("tables in {}: {}", db, client.getDbTables(db));
// 发送文本消息aters 是要 @ wxid多个用逗号分隔消息里@的数量要与aters里的数量对应
// client.sendText("Hello", "filehelper", "");
// client.sendText("Hello @某人1 @某人2", "xxxxxxxx@chatroom", "wxid_xxxxxxxxxxxxx1,wxid_xxxxxxxxxxxxx2");
// 发送图片消息图片必须要存在
// client.sendImage("C:\\Projs\\WeChatFerry\\TEQuant.jpeg", "filehelper");
// 发送文件消息文件必须要存在
// client.sendFile("C:\\Projs\\WeChatFerry\\README.MD", "filehelper");
String xml =
"<?xml version=\"1.0\"?><msg><appmsg appid=\"\" sdkver=\"0\"><title>叮当药房24小时服务28分钟送药到家</title><des>叮当快药首家承诺范围内28分钟送药到家叮当快药核心区域内7*24小时全天候服务送药上门叮当快药官网为您提供快捷便利正品低价安全放心的购药、送药服务体验。</des><action>view</action><type>33</type><showtype>0</showtype><content /><url>https://mp.weixin.qq.com/mp/waerrpage?appid=wxc2edadc87077fa2a&amp;type=upgrade&amp;upgradetype=3#wechat_redirect</url><dataurl /><lowurl /><lowdataurl /><recorditem /><thumburl /><messageaction /><md5>7f6f49d301ebf47100199b8a4fcf4de4</md5><extinfo /><sourceusername>gh_c2b88a38c424@app</sourceusername><sourcedisplayname>叮当快药 药店送药到家夜间买药</sourcedisplayname><commenturl /><appattach><totallen>0</totallen><attachid /><emoticonmd5></emoticonmd5><fileext>jpg</fileext><filekey>da0e08f5c7259d03da150d5e7ca6d950</filekey><cdnthumburl>3057020100044b30490201000204e4c0232702032f4ef20204a6bace6f02046401f62d042430326337303430352d333734332d343362652d623335322d6233333566623266376334620204012400030201000405004c537600</cdnthumburl><aeskey>0db26456caf243fbd4efb99058a01d66</aeskey><cdnthumbaeskey>0db26456caf243fbd4efb99058a01d66</cdnthumbaeskey><encryver>1</encryver><cdnthumblength>61558</cdnthumblength><cdnthumbheight>100</cdnthumbheight><cdnthumbwidth>100</cdnthumbwidth></appattach><weappinfo><pagepath>pages/index/index.html</pagepath><username>gh_c2b88a38c424@app</username><appid>wxc2edadc87077fa2a</appid><version>197</version><type>2</type><weappiconurl>http://wx.qlogo.cn/mmhead/Q3auHgzwzM4727n0NQ0ZIPQPlfp15m1WLsnrXbo1kLhFGcolgLyc0A/96</weappiconurl><appservicetype>0</appservicetype><shareId>1_wxc2edadc87077fa2a_29177e9a9b918cb9e75964f80bb8f32e_1677849476_0</shareId></weappinfo><websearch /></appmsg><fromusername>wxid_eob5qfcrv4zd22</fromusername><scene>0</scene><appinfo><version>1</version><appname /></appinfo><commenturl /></msg>";
// client.sendXml("filehelper", xml, "", 0x21);
// 发送表情消息gif 必须要存在
// client.sendEmotion("C:\\Projs\\WeChatFerry\\emo.gif", "filehelper");
// 接收消息并调用 printWxMsg 处理
wechatSocketClient.enableRecvMsg(100);
Thread thread = new Thread(new Runnable() {
public void run() {
while (wechatSocketClient.getIsReceivingMsg()) {
wechatSocketClient.printWxMsg(wechatSocketClient.getMsg());
}
}
});
thread.start();
// client.diableRecvMsg(); // 需要停止时调用
wechatSocketClient.keepRunning();
new Thread(new Runnable() {
public void run() {
wechatSocketClient.keepRunning();
}
}).start();
return wechatSocketClient;
}
}

View File

@ -1,4 +1,4 @@
package com.iamteer;
package com.iamteer.handle;
import java.nio.ByteBuffer;
import java.util.Arrays;
@ -34,9 +34,9 @@ import io.sisu.nng.pair.Pair1Socket;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Client {
public class WechatSocketClient {
private static final Logger logger = LoggerFactory.getLogger(Client.class);
private static final Logger logger = LoggerFactory.getLogger(WechatSocketClient.class);
private static final int BUFFER_SIZE = 16 * 1024 * 1024; // 16M
private Socket cmdSocket = null;
private Socket msgSocket = null;
@ -52,15 +52,15 @@ public class Client {
private int port;
private String dllPath;
public Client() {
public WechatSocketClient() {
this(DEFAULT_HOST, PORT, false, DEFAULT_DLL_PATH);
}
public Client(int port, String dllPath) {
public WechatSocketClient(int port, String dllPath) {
this(DEFAULT_HOST, port, false, dllPath);
}
public Client(String host, int port, boolean debug, String dllPath) {
public WechatSocketClient(String host, int port, boolean debug, String dllPath) {
this.host = host;
this.port = port;
this.dllPath = dllPath;

View File

@ -1,105 +0,0 @@
package com.iamteer.runner;
import javax.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.iamteer.BussinessContext;
import com.iamteer.Client;
import com.iamteer.config.WcferryProperties;
import lombok.extern.slf4j.Slf4j;
/**
* 启动回调-调用微信
*
* @author chandler
* @date 2024-09-21 12:21
*/
@Slf4j
@Component
@Order(101)
public class WechatRunner implements ApplicationRunner {
@Resource
private WcferryProperties properties;
@Resource
private BussinessContext bussinessContext;
public WechatRunner(BussinessContext bussinessContext) {
this.bussinessContext = bussinessContext;
}
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(">>>服务启动第一个开始执行的任务<<<<");
runWechat();
}
private void runWechat() {
log.debug("测试:端口:{},地址:{}", properties.getSocketPort(), properties.getDllPath());
// 连接远程 RPC
// Client client = new Client("127.0.0.1", 10086);
// 本地启动 RPC
// Client client = new Client(); // 默认 10086 端口
// Client client = new Client(10088,true); // 也可以指定端口
Client client = new Client(properties.getSocketPort(), properties.getDllPath());
bussinessContext.setClient(client); // 默认 10086 端口
// 是否已登录
// log.info("isLogin: {}", client.isLogin());
// 登录账号 wxid
// log.info("wxid: {}", client.getSelfWxid());
// 消息类型
// log.info("message types: {}", client.getMsgTypes());
// 所有联系人包括群聊公众号好友
// client.printContacts(client.getContacts());
// 获取数据库
log.info("dbs: {}", client.getDbNames());
// 获取数据库下的表
String db = "MicroMsg.db";
// log.info("tables in {}: {}", db, client.getDbTables(db));
// 发送文本消息aters 是要 @ wxid多个用逗号分隔消息里@的数量要与aters里的数量对应
// client.sendText("Hello", "filehelper", "");
// client.sendText("Hello @某人1 @某人2", "xxxxxxxx@chatroom", "wxid_xxxxxxxxxxxxx1,wxid_xxxxxxxxxxxxx2");
// 发送图片消息图片必须要存在
// client.sendImage("C:\\Projs\\WeChatFerry\\TEQuant.jpeg", "filehelper");
// 发送文件消息文件必须要存在
// client.sendFile("C:\\Projs\\WeChatFerry\\README.MD", "filehelper");
String xml =
"<?xml version=\"1.0\"?><msg><appmsg appid=\"\" sdkver=\"0\"><title>叮当药房24小时服务28分钟送药到家</title><des>叮当快药首家承诺范围内28分钟送药到家叮当快药核心区域内7*24小时全天候服务送药上门叮当快药官网为您提供快捷便利正品低价安全放心的购药、送药服务体验。</des><action>view</action><type>33</type><showtype>0</showtype><content /><url>https://mp.weixin.qq.com/mp/waerrpage?appid=wxc2edadc87077fa2a&amp;type=upgrade&amp;upgradetype=3#wechat_redirect</url><dataurl /><lowurl /><lowdataurl /><recorditem /><thumburl /><messageaction /><md5>7f6f49d301ebf47100199b8a4fcf4de4</md5><extinfo /><sourceusername>gh_c2b88a38c424@app</sourceusername><sourcedisplayname>叮当快药 药店送药到家夜间买药</sourcedisplayname><commenturl /><appattach><totallen>0</totallen><attachid /><emoticonmd5></emoticonmd5><fileext>jpg</fileext><filekey>da0e08f5c7259d03da150d5e7ca6d950</filekey><cdnthumburl>3057020100044b30490201000204e4c0232702032f4ef20204a6bace6f02046401f62d042430326337303430352d333734332d343362652d623335322d6233333566623266376334620204012400030201000405004c537600</cdnthumburl><aeskey>0db26456caf243fbd4efb99058a01d66</aeskey><cdnthumbaeskey>0db26456caf243fbd4efb99058a01d66</cdnthumbaeskey><encryver>1</encryver><cdnthumblength>61558</cdnthumblength><cdnthumbheight>100</cdnthumbheight><cdnthumbwidth>100</cdnthumbwidth></appattach><weappinfo><pagepath>pages/index/index.html</pagepath><username>gh_c2b88a38c424@app</username><appid>wxc2edadc87077fa2a</appid><version>197</version><type>2</type><weappiconurl>http://wx.qlogo.cn/mmhead/Q3auHgzwzM4727n0NQ0ZIPQPlfp15m1WLsnrXbo1kLhFGcolgLyc0A/96</weappiconurl><appservicetype>0</appservicetype><shareId>1_wxc2edadc87077fa2a_29177e9a9b918cb9e75964f80bb8f32e_1677849476_0</shareId></weappinfo><websearch /></appmsg><fromusername>wxid_eob5qfcrv4zd22</fromusername><scene>0</scene><appinfo><version>1</version><appname /></appinfo><commenturl /></msg>";
// client.sendXml("filehelper", xml, "", 0x21);
// 发送表情消息gif 必须要存在
// client.sendEmotion("C:\\Projs\\WeChatFerry\\emo.gif", "filehelper");
// 接收消息并调用 printWxMsg 处理
client.enableRecvMsg(100);
Thread thread = new Thread(new Runnable() {
public void run() {
while (client.getIsReceivingMsg()) {
client.printWxMsg(client.getMsg());
}
}
});
thread.start();
// client.diableRecvMsg(); // 需要停止时调用
client.keepRunning();
}
}

View File

@ -2,11 +2,12 @@ package com.iamteer.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.iamteer.BussinessContext;
import com.iamteer.handle.WechatSocketClient;
import com.iamteer.service.TestService;
import com.iamteer.utils.SpringContextHolderUtil;
import lombok.extern.slf4j.Slf4j;
@ -20,16 +21,17 @@ import lombok.extern.slf4j.Slf4j;
@Service
public class TestServiceImpl implements TestService {
@Resource
private WechatSocketClient wechatSocketClient;
@Override
public Boolean isLogin() {
BussinessContext bussinessContext = SpringContextHolderUtil.getBean(BussinessContext.class);
boolean flag = bussinessContext.getClient().isLogin();
boolean flag = wechatSocketClient.isLogin();
log.info("flag:{}", flag);
List<String> list = bussinessContext.getClient().getDbNames();
List<String> list = wechatSocketClient.getDbNames();
log.info("list:{}", list);
return flag;
return false;
}
}

View File

@ -1,173 +0,0 @@
package com.iamteer.utils;
import java.util.Map;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
/**
* Spring 工具类
*
* @author chandler
* @date 2023-03-30 11:05:49
*/
@Slf4j
@Service
@Lazy(false)
public class SpringContextHolderUtil implements ApplicationContextAware, DisposableBean {
/**
* 上下文对象实例
*/
private static ApplicationContext applicationContext = null;
/**
* 获取applicationContext-取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return applicationContext;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextHolderUtil.applicationContext = applicationContext;
}
/**
* 通过name获取Bean-从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
checkApplicationContext();
if (applicationContext.containsBean(name)) {
return (T)applicationContext.getBean(name);
}
return null;
}
/**
* 通过class获取Bean-从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
checkApplicationContext();
return applicationContext.getBean(requiredType);
}
/**
* 通过name,以及Clazz返回指定的Bean
*/
public static <T> T getBean(String name, Class<T> requiredType) {
return getApplicationContext().getBean(name, requiredType);
}
/**
* 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBeanOfType(Class<T> clazz) {
checkApplicationContext();
return (T)applicationContext.getBeansOfType(clazz);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
if (log.isDebugEnabled()) {
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
/**
* 发布事件
*
* @param event
*/
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
@SneakyThrows
public void destroy() {
SpringContextHolderUtil.clearHolder();
}
public static synchronized void registerSingletonBean(String beanName, Class clzz, Map<String, Object> original) {
checkApplicationContext();
DefaultListableBeanFactory beanFactory =
(DefaultListableBeanFactory)SpringContextHolderUtil.getApplicationContext().getAutowireCapableBeanFactory();
if (beanFactory.containsBean(beanName)) {
removeBean(beanName);
}
GenericBeanDefinition definition = new GenericBeanDefinition();
// 类class
definition.setBeanClass(clzz);
// 属性赋值
definition.setPropertyValues(new MutablePropertyValues(original));
// 注册到spring上下文
beanFactory.registerBeanDefinition(beanName, definition);
}
public static synchronized void registerSingletonBean(String beanName, Object obj, Map<String, Object> original) {
checkApplicationContext();
DefaultListableBeanFactory beanFactory =
(DefaultListableBeanFactory)SpringContextHolderUtil.getApplicationContext().getAutowireCapableBeanFactory();
if (beanFactory.containsBean(beanName)) {
removeBean(beanName);
}
GenericBeanDefinition definition = new GenericBeanDefinition();
// 类class
definition.setBeanClass(obj.getClass());
// 属性赋值
definition.setPropertyValues(new MutablePropertyValues(original));
// 注册到spring上下文
beanFactory.registerBeanDefinition(beanName, definition);
}
public static synchronized void registerSingletonBean(String beanName, Object obj) {
registerSingletonBean(beanName, obj, JSONObject.parseObject(JSON.toJSONString(obj), Map.class));
}
/**
* 删除spring中管理的bean
*
* @param beanName
*/
public static void removeBean(String beanName) {
ApplicationContext ctx = SpringContextHolderUtil.getApplicationContext();
DefaultListableBeanFactory acf = (DefaultListableBeanFactory)ctx.getAutowireCapableBeanFactory();
if (acf.containsBean(beanName)) {
acf.removeBeanDefinition(beanName);
}
}
private static void checkApplicationContext() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextUtil");
}
}
}