diff --git a/.gitignore b/.gitignore index 744289df..82e5c637 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ # Project exclude paths -/target/ \ No newline at end of file +/target/ +/.idea/ diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java index 10891a30..05151ffe 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMaTemplateMsgSender.java @@ -87,7 +87,7 @@ private static WxMaInMemoryConfig wxMaConfigStorage() { //空闲链接的检测周期(单位ms) clientBuilder.setCheckWaitTime(60000); //每路最大连接数 - clientBuilder.setMaxConnPerHost(App.config.getMaxThreadPool()); + clientBuilder.setMaxConnPerHost(App.config.getMaxThreadPool() * 2); //连接池最大连接数 clientBuilder.setMaxTotalConn(App.config.getMaxThreadPool() * 2); //HttpClient请求时使用的User Agent diff --git a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java index a8e9e537..a4a929bc 100644 --- a/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java +++ b/src/main/java/com/fangxuele/tool/push/logic/msgsender/WxMpTemplateMsgSender.java @@ -83,7 +83,7 @@ private static WxMpInMemoryConfigStorage wxMpConfigStorage() { //空闲链接的检测周期(单位ms) clientBuilder.setCheckWaitTime(60000); //每路最大连接数 - clientBuilder.setMaxConnPerHost(App.config.getMaxThreadPool()); + clientBuilder.setMaxConnPerHost(App.config.getMaxThreadPool() * 2); //连接池最大连接数 clientBuilder.setMaxTotalConn(App.config.getMaxThreadPool() * 2); //HttpClient请求时使用的User Agent diff --git a/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java b/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java index 53adf81c..5346461f 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java +++ b/src/main/java/com/fangxuele/tool/push/ui/UiConsts.java @@ -16,7 +16,7 @@ public class UiConsts { * 软件名称,版本 */ public final static String APP_NAME = "WePush"; - public final static String APP_VERSION = "v_3.3.0_190608"; + public final static String APP_VERSION = "v_3.4.0_190619"; /** * 主窗口图标-大 diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/msg/KefuPriorityMsgForm.java b/src/main/java/com/fangxuele/tool/push/ui/form/msg/KefuPriorityMsgForm.java index 88ceca59..4b6e8fea 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/msg/KefuPriorityMsgForm.java +++ b/src/main/java/com/fangxuele/tool/push/ui/form/msg/KefuPriorityMsgForm.java @@ -43,7 +43,7 @@ public static void init(String msgName) { String kefuMsgType = tMsgKefuPriority.getKefuMsgType(); KefuMsgForm.kefuMsgForm.getMsgKefuMsgTypeComboBox().setSelectedItem(kefuMsgType); if ("文本消息".equals(kefuMsgType)) { - KefuMsgForm.kefuMsgForm.getMsgKefuMsgTitleTextField().setText(tMsgKefuPriority.getContent()); + KefuMsgForm.kefuMsgForm.getContentTextArea().setText(tMsgKefuPriority.getContent()); } else if ("图文消息".equals(kefuMsgType)) { KefuMsgForm.kefuMsgForm.getMsgKefuMsgTitleTextField().setText(tMsgKefuPriority.getTitle()); } @@ -53,7 +53,7 @@ public static void init(String msgName) { KefuMsgForm.switchKefuMsgType(kefuMsgType); - MpTemplateMsgForm.initTemplateDataTable(); + MpTemplateMsgForm.selectedMsgTemplateId = tMsgKefuPriority.getTemplateId(); // 模板消息Data表 List templateDataList = templateDataMapper.selectByMsgTypeAndMsgId(MessageTypeEnum.KEFU_PRIORITY_CODE, msgId); String[] headerNames = {"Name", "Value", "Color", "操作"}; @@ -80,6 +80,7 @@ public static void init(String msgName) { } else { KefuMsgForm.switchKefuMsgType("图文消息"); } + MpTemplateMsgForm.initTemplateList(); } public static void save(String msgName) { @@ -103,6 +104,7 @@ public static void save(String msgName) { String templateId = MpTemplateMsgForm.mpTemplateMsgForm.getMsgTemplateIdTextField().getText(); String templateUrl = MpTemplateMsgForm.mpTemplateMsgForm.getMsgTemplateUrlTextField().getText(); String kefuMsgType = Objects.requireNonNull(KefuMsgForm.kefuMsgForm.getMsgKefuMsgTypeComboBox().getSelectedItem()).toString(); + String kefuMsgContent = KefuMsgForm.kefuMsgForm.getContentTextArea().getText(); String kefuMsgTitle = KefuMsgForm.kefuMsgForm.getMsgKefuMsgTitleTextField().getText(); String kefuPicUrl = KefuMsgForm.kefuMsgForm.getMsgKefuPicUrlTextField().getText(); String kefuDesc = KefuMsgForm.kefuMsgForm.getMsgKefuDescTextField().getText(); @@ -120,7 +122,7 @@ public static void save(String msgName) { tMsgKefuPriority.setMaAppid(templateMiniAppid); tMsgKefuPriority.setMaPagePath(templateMiniPagePath); tMsgKefuPriority.setKefuMsgType(kefuMsgType); - tMsgKefuPriority.setContent(kefuMsgTitle); + tMsgKefuPriority.setContent(kefuMsgContent); tMsgKefuPriority.setTitle(kefuMsgTitle); tMsgKefuPriority.setImgUrl(kefuPicUrl); tMsgKefuPriority.setDescribe(kefuDesc); diff --git a/src/main/java/com/fangxuele/tool/push/ui/form/msg/MpTemplateMsgForm.java b/src/main/java/com/fangxuele/tool/push/ui/form/msg/MpTemplateMsgForm.java index a6bc2b59..cb50f10d 100644 --- a/src/main/java/com/fangxuele/tool/push/ui/form/msg/MpTemplateMsgForm.java +++ b/src/main/java/com/fangxuele/tool/push/ui/form/msg/MpTemplateMsgForm.java @@ -90,11 +90,6 @@ public class MpTemplateMsgForm { */ public static String selectedMsgTemplateId; - /** - * (选择模板ComboBox)所选模板对应的模板ID - */ - public static String selectedComboBoxTemplateId; - /** * 是否需要监听模板列表ComboBox */ @@ -143,16 +138,10 @@ public MpTemplateMsgForm() { templateListComboBox.addItemListener(e -> { if (needListenTemplateListComboBox && e.getStateChange() == ItemEvent.SELECTED) { clearAllField(); - int index = mpTemplateMsgForm.getTemplateListComboBox().getSelectedIndex(); - String templateId = ""; - if (templateList != null && templateList.size() > 0) { - templateId = templateList.get(index).getTemplateId(); - } - selectedComboBoxTemplateId = templateId; - fillWxTemplateContentToField(templateId); + fillWxTemplateContentToField(); } }); - autoFillButton.addActionListener(e -> autoFillTemplateDataTable(selectedComboBoxTemplateId)); + autoFillButton.addActionListener(e -> autoFillTemplateDataTable()); refreshTemplateListButton.addActionListener(e -> { initTemplateList(); initTemplateDataTable(); @@ -229,14 +218,7 @@ public static void initTemplateList() { mpTemplateMsgForm.getTemplateListComboBox().setSelectedIndex(selectedIndex); - if (templateList != null && templateList.size() > 0) { - selectedComboBoxTemplateId = templateList.get(0).getTemplateId(); - } - if (selectedMsgTemplateId != null) { - selectedComboBoxTemplateId = selectedMsgTemplateId; - } - - fillWxTemplateContentToField(selectedComboBoxTemplateId); + fillWxTemplateContentToField(); } catch (Exception e) { log.error(e.toString()); } @@ -260,11 +242,9 @@ public static List getTemplateParams(String templateContent) { /** * 根据模板id填充模板列表中对应的WxTemplate内容到表单 - * - * @param templateId */ - public static void fillWxTemplateContentToField(String templateId) { - WxMpTemplate wxMpTemplate = templateMap.get(templateId); + public static void fillWxTemplateContentToField() { + WxMpTemplate wxMpTemplate = templateList.get(mpTemplateMsgForm.getTemplateListComboBox().getSelectedIndex()); if (wxMpTemplate != null) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("-----------模板ID-----------\n").append(wxMpTemplate.getTemplateId()).append("\n"); @@ -278,12 +258,10 @@ public static void fillWxTemplateContentToField(String templateId) { /** * 自动填充模板数据Table - * - * @param templateId templateId */ - private static void autoFillTemplateDataTable(String templateId) { - if (templateId != null && templateMap != null) { - WxMpTemplate wxMpTemplate = templateMap.get(templateId); + private static void autoFillTemplateDataTable() { + if (templateList != null) { + WxMpTemplate wxMpTemplate = templateList.get(mpTemplateMsgForm.getTemplateListComboBox().getSelectedIndex()); if (wxMpTemplate != null) { initTemplateDataTable(); DefaultTableModel tableModel = (DefaultTableModel) mpTemplateMsgForm.getTemplateMsgDataTable() diff --git a/src/main/resources/version_summary.json b/src/main/resources/version_summary.json index 7d5028f4..3f2e9791 100644 --- a/src/main/resources/version_summary.json +++ b/src/main/resources/version_summary.json @@ -1,5 +1,5 @@ { - "currentVersion": "v_3.3.0_190608", + "currentVersion": "v_3.4.0_190619", "versionIndex": { "v_1.1.0_170701": "0", "v_1.2.0_170831": "1", @@ -25,7 +25,8 @@ "v_3.1.0_190524": "21", "v_3.2.0_190601": "22", "v_3.2.1_190603": "23", - "v_3.3.0_190608": "24" + "v_3.3.0_190608": "24", + "v_3.4.0_190619": "25" }, "versionDetailList": [ { @@ -152,6 +153,11 @@ "version": "v_3.3.0_190608", "title": "微信相关消息支持使用http代理+优化连接池+全局帮助", "log": "● 增加全局帮助对话框\n● 版本更新对话框优化,避免更新日志过多显示不下\n● 根据屏幕DPI自动初始化字号\n● 短信编辑form调整\n● 优化微信相关消息发送时连接获取超时的问题\n● 微信相关消息类型增加Http代理设置\n● 第一次安装时增加字号大小设置引导\n● 消息编辑深度梳理大规模重构\n" + }, + { + "version": "v_3.4.0_190619", + "title": "自动获取微信公众号可选模板+模板参数自动填充", + "log": "● 自动获取微信公众号可选模板\n● 模板参数自动填充\n● 客服消息文本类型输入区域优化\n● UI调整,消息编辑可见范围不受屏幕分辨率限制\n● 增加空跑帮助提示\n● 消息发送器解耦,新增消息加工器策略,大幅提高消息加工性能\n● push相关流程深度梳理和大规模重构\n● UI细节调整,增加累计推送量展示\n" } ] } \ No newline at end of file diff --git a/src/test/java/com/fangxuele/tool/push/util/CommonTest.java b/src/test/java/com/fangxuele/tool/push/util/CommonTest.java index 704a942c..32df8c82 100644 --- a/src/test/java/com/fangxuele/tool/push/util/CommonTest.java +++ b/src/test/java/com/fangxuele/tool/push/util/CommonTest.java @@ -1,9 +1,32 @@ package com.fangxuele.tool.push.util; +import cn.hutool.core.thread.ThreadUtil; import cn.hutool.extra.mail.MailAccount; import cn.hutool.extra.mail.MailUtil; +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.HttpResponseException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.concurrent.FutureCallback; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.apache.http.nio.IOControl; +import org.apache.http.nio.client.methods.AsyncCharConsumer; +import org.apache.http.nio.client.methods.HttpAsyncMethods; +import org.apache.http.nio.protocol.HttpAsyncRequestProducer; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; import org.junit.Test; +import java.io.IOException; +import java.nio.CharBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + /** *
  * 通用测试
@@ -16,13 +39,189 @@ public class CommonTest {
     @Test
     public void test() {
         MailAccount account = new MailAccount();
-        account.setHost("smtp.yeah.net");
+        account.setHost("smtp.163.com");
         account.setPort(25);
         account.setAuth(true);
-        account.setFrom("hutool@yeah.net");
-        account.setUser("hutool");
-        account.setPass("q1w2e3");
+        account.setFrom("rememberber@163.com");
+        account.setUser("rememberber");
+        account.setPass("885995zyf163");
+
+
+        for (int i = 0; i < 20; i++) {
+            ThreadUtil.execute(new Runnable() {
+                @Override
+                public void run() {
+                    MailUtil.send(account, "rememberber@163.com", "测试", "邮件来自Hutool测试", false);
+                }
+            });
+        }
+
+        ThreadUtil.safeSleep(10000);
+    }
+
+    /**
+     * HttpAsyncClient Official Quick Start
+     */
+    @Test
+    public void testAsyncHttpClient() {
+        CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
+        try {
+            // Start the client
+            httpclient.start();
+
+            // Execute request
+            final HttpGet request1 = new HttpGet("http://www.apache.org/");
+            Future future = httpclient.execute(request1, null);
+            // and wait until a response is received
+            HttpResponse response1 = future.get();
+            System.out.println(request1.getRequestLine() + "->" + response1.getStatusLine());
+
+            // One most likely would want to use a callback for operation result
+            final CountDownLatch latch1 = new CountDownLatch(1);
+            final HttpGet request2 = new HttpGet("http://www.apache.org/");
+            httpclient.execute(request2, new FutureCallback() {
+
+                public void completed(final HttpResponse response2) {
+                    latch1.countDown();
+                    System.out.println(request2.getRequestLine() + "->" + response2.getStatusLine());
+                }
+
+                public void failed(final Exception ex) {
+                    latch1.countDown();
+                    System.out.println(request2.getRequestLine() + "->" + ex);
+                }
+
+                public void cancelled() {
+                    latch1.countDown();
+                    System.out.println(request2.getRequestLine() + " cancelled");
+                }
+
+            });
+            latch1.await();
+
+            // In real world one most likely would also want to stream
+            // request and response body content
+            final CountDownLatch latch2 = new CountDownLatch(1);
+            final HttpGet request3 = new HttpGet("http://www.apache.org/");
+            HttpAsyncRequestProducer producer3 = HttpAsyncMethods.create(request3);
+            AsyncCharConsumer consumer3 = new AsyncCharConsumer() {
+
+                HttpResponse response;
+
+                @Override
+                protected void onResponseReceived(final HttpResponse response) {
+                    this.response = response;
+                }
+
+                @Override
+                protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
+                    // Do something useful
+                }
+
+                @Override
+                protected void releaseResources() {
+                }
+
+                @Override
+                protected HttpResponse buildResult(final HttpContext context) {
+                    return this.response;
+                }
+
+            };
+            httpclient.execute(producer3, consumer3, new FutureCallback() {
+
+                public void completed(final HttpResponse response3) {
+                    latch2.countDown();
+                    System.out.println(request3.getRequestLine() + "->" + response3.getStatusLine());
+                }
+
+                public void failed(final Exception ex) {
+                    latch2.countDown();
+                    System.out.println(request3.getRequestLine() + "->" + ex);
+                }
+
+                public void cancelled() {
+                    latch2.countDown();
+                    System.out.println(request3.getRequestLine() + " cancelled");
+                }
+
+            });
+            latch2.await();
+
+        } catch (InterruptedException | ExecutionException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                httpclient.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Test
+    public void myAsyncHttpClientTest() {
+        CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
+        try {
+            // Start the client
+            httpclient.start();
+
+            // One most likely would want to use a callback for operation result
+            final CountDownLatch latch1 = new CountDownLatch(1);
+            final HttpPost request2 = new HttpPost("http://localhost:9000/qian/api/test/lucky?msg=asdf");
+            System.err.println(SqliteUtil.nowDateForSqlite() + "开始 " + System.currentTimeMillis());
+            httpclient.execute(request2, new FutureCallback() {
+
+                public void completed(final HttpResponse response2) {
+                    System.err.println("完成1 " + SqliteUtil.nowDateForSqlite());
+                    latch1.countDown();
+                    System.err.println(latch1.getCount());
+                    System.err.println("完成2 " + SqliteUtil.nowDateForSqlite());
+                    try {
+                        System.err.println(handleResponse(response2));
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                    System.out.println(request2.getRequestLine() + "->" + response2.getStatusLine());
+                }
+
+                public void failed(final Exception ex) {
+                    System.err.println("failed1 " + SqliteUtil.nowDateForSqlite());
+                    latch1.countDown();
+                    System.err.println(latch1.getCount());
+                    System.err.println("failed2 " + SqliteUtil.nowDateForSqlite());
+                    System.out.println(request2.getRequestLine() + "->" + ex);
+                }
+
+                public void cancelled() {
+                    latch1.countDown();
+                    System.out.println(request2.getRequestLine() + " cancelled");
+                }
+
+            });
+            System.err.println(SqliteUtil.nowDateForSqlite() + "结束1 " + System.currentTimeMillis());
+            latch1.await();
+            System.err.println(SqliteUtil.nowDateForSqlite() + "结束2 " + System.currentTimeMillis());
+            System.err.println(latch1.getCount());
+
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                httpclient.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
 
-        MailUtil.send(account, "rememberber@163.com", "测试", "邮件来自Hutool测试", false);
+    public String handleResponse(final HttpResponse response) throws IOException {
+        final StatusLine statusLine = response.getStatusLine();
+        final HttpEntity entity = response.getEntity();
+        if (statusLine.getStatusCode() >= 300) {
+            EntityUtils.consume(entity);
+            throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
+        }
+        return entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8);
     }
 }