From 4d0a511186e3fe86ccdfa8d695074b5650a3f453 Mon Sep 17 00:00:00 2001 From: JianGuo Date: Wed, 27 Nov 2024 17:18:32 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=8E=BB=E6=8E=89socket=E7=9A=84=E6=B3=A8?= =?UTF-8?q?=E9=87=8Afeat(show):=20=E6=B7=BB=E5=8A=A0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=89=98=E7=9B=98=E7=A8=8B=E5=BA=8F=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20UI=20=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 TrayFrame 和 TrayFrameUtf8 类实现系统托盘功能- 更新 Main 类以使用新的系统托盘程序 - 引入 FlatDarculaLaf 样式以改善 UI 外观- 重构 Operational 类,使用 Lombok 日志替代 StaticLog - 更新 SocketServer 类,使用 Lombok 日志替代 StaticLog - 新增 SocketUtils 类以管理 SocketServer 实例 --- pom.xml | 19 +- src/main/java/org/aohe/Main.java | 46 +- .../java/org/aohe/control/Operational.java | 475 +++++++++--------- src/main/java/org/aohe/show/TrayFrame.java | 105 ++++ .../java/org/aohe/show/TrayFrameUtf8.java | 143 ++++++ src/main/java/org/aohe/web/SocketServer.java | 17 +- src/main/java/org/aohe/web/SocketUtils.java | 34 ++ src/main/resources/ah.png | Bin 0 -> 2794 bytes 8 files changed, 558 insertions(+), 281 deletions(-) create mode 100644 src/main/java/org/aohe/show/TrayFrame.java create mode 100644 src/main/java/org/aohe/show/TrayFrameUtf8.java create mode 100644 src/main/java/org/aohe/web/SocketUtils.java create mode 100644 src/main/resources/ah.png diff --git a/pom.xml b/pom.xml index 6e87b2b..252f4bd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.aohe twain-service - 0.1.1 + 0.1.2 8 @@ -48,6 +48,23 @@ jna-platform 4.5.1 + + com.formdev + flatlaf + 3.4.1 + no-natives + + + org.slf4j + slf4j-api + 2.0.13 + + + org.slf4j + slf4j-simple + 2.0.13 + + diff --git a/src/main/java/org/aohe/Main.java b/src/main/java/org/aohe/Main.java index 4711236..2f584fd 100644 --- a/src/main/java/org/aohe/Main.java +++ b/src/main/java/org/aohe/Main.java @@ -1,29 +1,17 @@ -//package org.aohe; -// -//import lombok.extern.slf4j.Slf4j; -//import org.aohe.web.SocketServer; -// -//import java.io.BufferedReader; -//import java.io.IOException; -//import java.io.InputStreamReader; -// -//@Slf4j -//public class Main { -// public static void main(String[] args) throws IOException, InterruptedException { -// int port = 8997; // 843 flash policy port -// -// SocketServer s = new SocketServer(port); -// s.start(); -// System.out.println("ChatServer started on port: " + s.getPort()); -// -// BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in)); -// while (true) { -// String in = sysin.readLine(); -// s.broadcast(in); -// if (in.equals("exit")) { -// s.stop(1000); -// break; -// } -// } -// } -//} \ No newline at end of file +package org.aohe; + +import com.formdev.flatlaf.FlatDarculaLaf; +import lombok.extern.slf4j.Slf4j; +import org.aohe.show.TrayFrame; +import org.aohe.show.TrayFrameUtf8; + +import javax.swing.*; + +@Slf4j +public class Main { + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(new FlatDarculaLaf()); + log.info("启动成功"); + new TrayFrameUtf8().initSystemTrayUTF8(); + } +} \ No newline at end of file diff --git a/src/main/java/org/aohe/control/Operational.java b/src/main/java/org/aohe/control/Operational.java index 34a332e..f32ea2b 100644 --- a/src/main/java/org/aohe/control/Operational.java +++ b/src/main/java/org/aohe/control/Operational.java @@ -1,242 +1,235 @@ -//package org.aohe.control; -// -//import cn.hutool.core.codec.Base64; -//import cn.hutool.core.lang.Console; -//import cn.hutool.log.Log; -//import cn.hutool.log.LogFactory; -//import cn.hutool.log.StaticLog; -//import com.alibaba.fastjson2.JSONObject; -//import org.aohe.core.twain.*; -//import org.aohe.exceptions.TwainException; -//import org.aohe.result.R; -//import org.aohe.scan.Source; -//import org.aohe.scan.SourceManager; -// -//import java.io.File; -//import java.util.*; -// -//public class Operational { -// -// private static final Log log = LogFactory.get(); -// -// private static TwainScanner scanner = null; -// -// public static String selectOperational(String path) { -// JSONObject json = JSONObject.parse(path); -// -// //操作符 -// String function = json.getString("function"); -// -// //参数符 -// JSONObject param = json.getJSONObject("params"); -// -// R r = R.ok(); -// try { -// if("001001".equals(function)){ -// //获取扫描仪列表 -// r = getDevices(); -// } else if ("001002".equals(function)) { -// //选择扫描仪 -// r = setScanner(param.getString("scannerId")); -// }else if ("001003".equals(function)){ -// //获取扫描仪操作符列表 -// r = getDeviceOperations(); -// }else if ("001004".equals(function)){ -// //r = setDeviceOperations(); -// }else if ("001007".equals(function)){ -// r = setDeviceOperations(param); -// }else if ("001008".equals(function)){ -// r = startScan(param.getString("scannerId")); -// }else if ("001012".equals(function)){ -// closeTwSource(); -// }else if ("001013".equals(function)){ -// closeTwSource(); -// }else if ("001015".equals(function)){ -// r = startScan(param.getString("scannerId"),true); -// }else if ("001016".equals(function)){ -// r = startScan(param.getString("scannerId"),true); -// } -// } catch (TwainException e) { -// StaticLog.error("获取驱动列表失败"); -// StaticLog.error(e); -// throw new RuntimeException(e); -// } catch (InterruptedException e) { -// StaticLog.error("选择驱动失败"); -// StaticLog.error(e); -// throw new RuntimeException(e); -// } -// -// return r.toJsonStr(); +package org.aohe.control; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.lang.Console; +import com.alibaba.fastjson2.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.aohe.core.twain.*; +import org.aohe.exceptions.TwainException; +import org.aohe.result.R; +import org.aohe.scan.Source; + +import java.io.File; +import java.util.*; + +@Slf4j +public class Operational { + + + private static TwainScanner scanner = null; + + public static String selectOperational(String path) { + JSONObject json = JSONObject.parse(path); + + //操作符 + String function = json.getString("function"); + + //参数符 + JSONObject param = json.getJSONObject("params"); + + R r = R.ok(); + try { + if("001001".equals(function)){ + //获取扫描仪列表 + r = getDevices(); + } else if ("001002".equals(function)) { + //选择扫描仪 + r = setScanner(param.getString("scannerId")); + }else if ("001003".equals(function)){ + //获取扫描仪操作符列表 + r = getDeviceOperations(); + }else if ("001004".equals(function)){ + //r = setDeviceOperations(); + }else if ("001007".equals(function)){ + r = setDeviceOperations(param); + }else if ("001008".equals(function)){ + r = startScan(param.getString("scannerId")); + }else if ("001012".equals(function)){ + closeTwSource(); + }else if ("001013".equals(function)){ + closeTwSource(); + }else if ("001015".equals(function)){ + r = startScan(param.getString("scannerId"),true); + }else if ("001016".equals(function)){ + r = startScan(param.getString("scannerId"),true); + } + } catch (TwainException e) { + log.error("获取驱动列表失败"); + log.error(e.getMessage()); + throw new RuntimeException(e); + } catch (InterruptedException e) { + log.error("选择驱动失败"); + log.error(e.getMessage()); + throw new RuntimeException(e); + } + + return r.toJsonStr(); + } + + /** + * 001001 + * 获取连接到当前终端的所有扫描仪并返回设备的SN号 + * + * @return R + */ + public static R getDevices () throws TwainException { + return R.ok(TwainSource.getProductNamesToList()); + } + + /** + * 001002 + * 选中某一获取到的扫描仪 + * @return R -> success + */ + public static R setScanner(String name) throws TwainException, InterruptedException { + if(name == null || name.isEmpty()){ + return R.fail("扫描仪名字为空"); + } + + TwainScanner.getScanner().select(name); + Twain.getSourceManager().selectSource(name); + + return R.ok(); + } + + /** + * 001003 + * 获取当前选中扫描仪可配置的项 + * @return + */ + public static R getDeviceOperations() throws TwainException { + + try{ + TwainSource twainSource = openTwSource(); + TwainCapability[] capabilities = twainSource.getCapabilities(); + + + Map> map = new HashMap<>(); + for (TwainCapability cap : capabilities){ + List list = new ArrayList<>(); + + String key = Twain.getMapCapCodeToName().get(cap.cap); + String formatKey = String.format("0x%04x", cap.cap); + + list.add(key); + list.add(formatKey); + + map.put(key,list); + } + return R.ok(map); + }finally { + closeTwSource(); + } + + + + + + } + + /** + * 001004 + * 设置或修改当前选中扫描仪某一配置项的能力值 + * DPI --> double + * 色彩模式 color 0,1,2 -> 黑白,灰度,彩色 + * 进纸模式 paper true,false -> 自动,手动 + * @param map 参数和值 + * @return R + */ + public static R setDeviceOperations(JSONObject map){ + try { + TwainSource twainSource = Twain.getSourceManager().getSource(); + // 先约定为三种参数 DPI,色彩模式,进纸模式 + if(map.get("dpi") !=null){ + twainSource.setResolution(map.getDouble("dpi")); + } + if(map.get("color") !=null){ + twainSource.setCapability(Twain.ICAP_PIXELTYPE, map.getInteger("color")); + } + if(map.get("paper") !=null){ + twainSource.setCapability(Twain.CAP_FEEDERENABLED, map.getBooleanValue("paper")); + } + } catch (TwainException e) { + throw new RuntimeException(e); + } + return R.ok(); + } + + /** + * 001008 + * 当前扫描仪启动扫描 + * @param name 扫描仪名称 + * @return R + * @throws TwainException default error + */ + public static R startScan(String name) throws TwainException { + return startScan(name, false); + } + + /** + * 001008 + * 当前扫描仪启动扫描 + * @param name 扫描仪名称 + * @param systemUI 是否使用打印机自带UI + * @return R + * @throws TwainException default error + */ + public static R startScan(String name, boolean systemUI ) throws TwainException { + Source source = new Source(); + source.setName(name); + source.setSystemUI(systemUI); + List fileList = source.scan(); + List base64Files = new ArrayList<>(); + for (File file : fileList){ + base64Files.add(Base64.encode(file)); + } + return R.ok(base64Files); + } + +// public static void main(String[] args) throws TwainException, InterruptedException { +// List list = (List) getDevices().getData(); +// System.out.println(list.get(0)); +// R r = setScanner(list.get(0)); +// //System.out.println(getDeviceOperations()); +// System.out.println(startScan(list.get(0), false)); +// ; // } -// -// /** -// * 001001 -// * 获取连接到当前终端的所有扫描仪并返回设备的SN号 -// * -// * @return R -// */ -// public static R getDevices () throws TwainException { -// return R.ok(TwainSource.getProductNamesToList()); -// } -// -// /** -// * 001002 -// * 选中某一获取到的扫描仪 -// * @return R -> success -// */ -// public static R setScanner(String name) throws TwainException, InterruptedException { -// if(name == null || name.isEmpty()){ -// return R.fail("扫描仪名字为空"); -// } -// -// TwainScanner.getScanner().select(name); -// Twain.getSourceManager().selectSource(name); -// -// return R.ok(); -// } -// -// public static void main(String[] args) throws TwainException { -// System.out.println(TwainScanner.getScanner().getDeviceNames()); -// } -// -// /** -// * 001003 -// * 获取当前选中扫描仪可配置的项 -// * @return -// */ -// public static R getDeviceOperations() throws TwainException { -// -// try{ -// TwainSource twainSource = openTwSource(); -// TwainCapability[] capabilities = twainSource.getCapabilities(); -// -// -// Map> map = new HashMap<>(); -// for (TwainCapability cap : capabilities){ -// List list = new ArrayList<>(); -// -// String key = Twain.getMapCapCodeToName().get(cap.cap); -// String formatKey = String.format("0x%04x", cap.cap); -// -// list.add(key); -// list.add(formatKey); -// -// map.put(key,list); -// } -// return R.ok(map); -// }finally { -// closeTwSource(); -// } -// -// -// -// -// -// } -// -// /** -// * 001004 -// * 设置或修改当前选中扫描仪某一配置项的能力值 -// * DPI --> double -// * 色彩模式 color 0,1,2 -> 黑白,灰度,彩色 -// * 进纸模式 paper true,false -> 自动,手动 -// * @param map 参数和值 -// * @return R -// */ -// public static R setDeviceOperations(JSONObject map){ -// try { -// TwainSource twainSource = Twain.getSourceManager().getSource(); -// // 先约定为三种参数 DPI,色彩模式,进纸模式 -// if(map.get("dpi") !=null){ -// twainSource.setResolution(map.getDouble("dpi")); -// } -// if(map.get("color") !=null){ -// twainSource.setCapability(Twain.ICAP_PIXELTYPE, map.getInteger("color")); -// } -// if(map.get("paper") !=null){ -// twainSource.setCapability(Twain.CAP_FEEDERENABLED, map.getBooleanValue("paper")); -// } -// } catch (TwainException e) { -// throw new RuntimeException(e); -// } -// return R.ok(); -// } -// -// /** -// * 001008 -// * 当前扫描仪启动扫描 -// * @param name 扫描仪名称 -// * @return R -// * @throws TwainException default error -// */ -// public static R startScan(String name) throws TwainException { -// return startScan(name, false); -// } -// -// /** -// * 001008 -// * 当前扫描仪启动扫描 -// * @param name 扫描仪名称 -// * @param systemUI 是否使用打印机自带UI -// * @return R -// * @throws TwainException default error -// */ -// public static R startScan(String name, boolean systemUI ) throws TwainException { -// Source source = new Source(); -// source.setName(name); -// source.setSystemUI(systemUI); -// List fileList = source.scan(); -// List base64Files = new ArrayList<>(); -// for (File file : fileList){ -// base64Files.add(Base64.encode(file)); -// } -// return R.ok(base64Files); -// } -// -//// public static void main(String[] args) throws TwainException, InterruptedException { -//// List list = (List) getDevices().getData(); -//// System.out.println(list.get(0)); -//// R r = setScanner(list.get(0)); -//// //System.out.println(getDeviceOperations()); -//// System.out.println(startScan(list.get(0), false)); -//// ; -//// } -// -// -// /** -// * 打开接口 -// * @return twSource -// * @throws TwainException 默认错误 -// */ -// public static TwainSource openTwSource() throws TwainException { -// TwainSource twainSource = Twain.getSourceManager().getSource(); -// -// if(twainSource.getState() != 4){ -// //打开接口 -// Twain.getSourceManager().openSource(); -// } -// return twainSource; -// } -// -// /** -// * 关闭接口 -// * @throws TwainException 默认错误 -// */ -// public static void closeTwSource() throws TwainException { -// TwainSource twainSource = Twain.getSourceManager().getSource(); -// twainSource.close(); -// } -// -// public void getSetting(Integer i) throws TwainException { -// -// try{ -// TwainSource twainSource = openTwSource(); -// TwainCapability tc = twainSource.getCapability(i); -// Console.log(tc.getItems()); -// } catch (TwainException e) { -// throw new RuntimeException(e); -// } finally { -// closeTwSource(); -// } -// } -//} + + + /** + * 打开接口 + * @return twSource + * @throws TwainException 默认错误 + */ + public static TwainSource openTwSource() throws TwainException { + TwainSource twainSource = Twain.getSourceManager().getSource(); + + if(twainSource.getState() != 4){ + //打开接口 + Twain.getSourceManager().openSource(); + } + return twainSource; + } + + /** + * 关闭接口 + * @throws TwainException 默认错误 + */ + public static void closeTwSource() throws TwainException { + TwainSource twainSource = Twain.getSourceManager().getSource(); + twainSource.close(); + } + + public void getSetting(Integer i) throws TwainException { + + try{ + TwainSource twainSource = openTwSource(); + TwainCapability tc = twainSource.getCapability(i); + Console.log(tc.getItems()); + } catch (TwainException e) { + throw new RuntimeException(e); + } finally { + closeTwSource(); + } + } +} diff --git a/src/main/java/org/aohe/show/TrayFrame.java b/src/main/java/org/aohe/show/TrayFrame.java new file mode 100644 index 0000000..d06864f --- /dev/null +++ b/src/main/java/org/aohe/show/TrayFrame.java @@ -0,0 +1,105 @@ +package org.aohe.show; + +import cn.hutool.core.io.resource.ResourceUtil; +import org.aohe.web.SocketUtils; + +import javax.swing.*; +import java.awt.*; + +public class TrayFrame { + + public void create() throws Exception { + //创建Socket连接,默认是执行了start操作 + SocketUtils.start(8997); + + // 确保事件调度线程(EDT)创建和显示GUI + SwingUtilities.invokeLater(() -> { + // 检查系统是否支持系统托盘 + if (!SystemTray.isSupported()) { + System.out.println("系统托盘不被支持"); + return; + } + + // 获取系统托盘实例 + SystemTray tray = SystemTray.getSystemTray(); + + // 创建一个图像,作为托盘图标 + + Image image = Toolkit.getDefaultToolkit().getImage(ResourceUtil.getResource("ah.png").getFile()); + + // 创建一个弹出菜单 + PopupMenu popup = new PopupMenu(); + + // 创建菜单项 + MenuItem aboutItem = new MenuItem("About"); + //CheckboxMenuItem cb1 = new CheckboxMenuItem("Enable Message"); // 使用CheckboxMenuItem替换JCheckBoxMenuItem + MenuItem exitItem = new MenuItem("Exit"); + MenuItem startServiceItem = new MenuItem("Start Service"); + MenuItem stopServiceItem = new MenuItem("Stop Service"); + + // 初始化按钮状态 + startServiceItem.setEnabled(false); + stopServiceItem.setEnabled(true); + + // 将菜单项添加到弹出菜单 + popup.add(aboutItem); + //popup.add(cb1); + popup.addSeparator(); + popup.add(startServiceItem); + popup.add(stopServiceItem); + popup.addSeparator(); + popup.add(exitItem); + + // 创建托盘图标 + TrayIcon trayIcon = new TrayIcon(image, "Scan Tray Program", popup); + + // 设置托盘图标大小 + trayIcon.setImageAutoSize(true); + + // 添加托盘图标到系统托盘 + try { + tray.add(trayIcon); + } catch (AWTException e) { + System.out.println("无法添加托盘图标"); + return; + } + + // 添加事件监听器 + aboutItem.addActionListener(e -> JOptionPane.showMessageDialog(null, "AoHe 的扫描托盘程序")); + +// cb1.addItemListener(e -> { +// if (cb1.getState()) { +// System.out.println("通知已启用"); +// } else { +// System.out.println("通知已禁用"); +// } +// }); + + startServiceItem.addActionListener(e -> { + try { + SocketUtils.start(8997); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + startServiceItem.setEnabled(false); + stopServiceItem.setEnabled(true); + System.out.println("服务已启动"); + }); + + stopServiceItem.addActionListener(e -> { + SocketUtils.safeStop(); + startServiceItem.setEnabled(true); + stopServiceItem.setEnabled(false); + System.out.println("服务已停止"); + }); + + exitItem.addActionListener(e -> { + tray.remove(trayIcon); + SocketUtils.safeStop(); + System.exit(0); + }); + }); + } + +} + diff --git a/src/main/java/org/aohe/show/TrayFrameUtf8.java b/src/main/java/org/aohe/show/TrayFrameUtf8.java new file mode 100644 index 0000000..47fdb00 --- /dev/null +++ b/src/main/java/org/aohe/show/TrayFrameUtf8.java @@ -0,0 +1,143 @@ +package org.aohe.show; + +import cn.hutool.core.io.resource.ResourceUtil; +import com.formdev.flatlaf.FlatDarculaLaf; +import lombok.extern.slf4j.Slf4j; +import org.aohe.web.SocketUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; + +/** + * 中文系统托盘弹出菜单不乱码。 + */ +@Slf4j +public class TrayFrameUtf8 { + + public static void initSystemTrayUTF8() throws MalformedURLException { + SocketUtils.start(8997); + //使用 JDialog 作为 JPopupMenu 载体 + JDialog jDialog = new JDialog(); + //关闭 JDialog 的装饰器 + jDialog.setUndecorated(true); + //jDialog 作为 JPopupMenu 载体不需要多大的 size + jDialog.setSize(1, 1); + + //创建 JPopupMenu + //重写 firePopupMenuWillBecomeInvisible + //消失后将绑定的组件一起消失 + JPopupMenu jPopupMenu = new JPopupMenu() { + @Override + public void firePopupMenuWillBecomeInvisible() { + jDialog.setVisible(false); + //log.info("JPopupMenu 不可见时绑定载体组件 jDialog 也不可见"); + } + }; + jPopupMenu.setSize(100, 30); + + //添加菜单选项 + // JMenuItem exit = new JMenuItem(getUTF8String("退出")); + JMenuItem exit = new JMenuItem("退出"); + exit.addActionListener(e -> { + log.info("点击了退出选项"); + System.exit(0); + }); + // JMenuItem showMainFrame = new JMenuItem(getUTF8String("显示主窗体")); + JMenuItem showMainFrame = new JMenuItem("关于"); + showMainFrame.addActionListener(e -> { + log.info("关于系统"); + JOptionPane.showMessageDialog(null, "AoHe 的扫描托盘程序"); + //显示窗口 + }); + + JMenuItem startServiceItem = new JMenuItem("启动服务"); + JMenuItem stopServiceItem = new JMenuItem("停止服务"); + startServiceItem.setEnabled(false); + stopServiceItem.setEnabled(true); + startServiceItem.addActionListener(e ->{ + try { + SocketUtils.start(8997); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + startServiceItem.setEnabled(false); + stopServiceItem.setEnabled(true); + log.info("服务已启动"); + } + ); + stopServiceItem.addActionListener(e -> { + SocketUtils.safeStop(); + startServiceItem.setEnabled(true); + stopServiceItem.setEnabled(false); + log.info("服务已停止"); + }); + + + jPopupMenu.add(startServiceItem); + jPopupMenu.add(stopServiceItem); + + jPopupMenu.add(showMainFrame); + jPopupMenu.add(exit); + + Image image = Toolkit.getDefaultToolkit().getImage(ResourceUtil.getResource("ah.png").getFile()); + // 创建系统托盘图标 + TrayIcon trayIcon = new TrayIcon(image, "Scan Program For AH"); + // 自动调整系统托盘图标大小 + trayIcon.setImageAutoSize(true); + + // 给托盘图标添加鼠标监听 + trayIcon.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + //左键点击 + if (e.getButton() == 1) { + //显示窗口 + } else if (e.getButton() == 3 && e.isPopupTrigger()) { + // 右键点击弹出 JPopupMenu 绑定的载体以及 JPopupMenu + jDialog.setLocation(e.getX() + 5, e.getY() + 5 - jPopupMenu.getHeight()); + // 显示载体 + jDialog.setVisible(true); + // 在载体的 0,0 处显示对话框 + jPopupMenu.show(jDialog, 0, 0); + } + } + }); + // 添加托盘图标到系统托盘 + systemTrayAdd(trayIcon); + } + + /** + * 添加托盘图标到系统托盘中。 + * + * @param trayIcon 系统托盘图标。 + */ + private static void systemTrayAdd(TrayIcon trayIcon) { + // 将托盘图标添加到系统的托盘实例中 + SystemTray tray = SystemTray.getSystemTray(); + try { + tray.add(trayIcon); + } catch (AWTException ex) { + ex.printStackTrace(); + } + } + + /** + * 字符串转 UTF-8 字符串 + * + * @param str 要转换的字符串 + * @return UTF-8 编码的字符串 + */ + private static String getUTF8String(String str) { + try { + return new String(str.getBytes("UTF-8"), "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } +} + diff --git a/src/main/java/org/aohe/web/SocketServer.java b/src/main/java/org/aohe/web/SocketServer.java index ac1fd91..a7eb58e 100644 --- a/src/main/java/org/aohe/web/SocketServer.java +++ b/src/main/java/org/aohe/web/SocketServer.java @@ -1,9 +1,6 @@ package org.aohe.web; - -import cn.hutool.log.Log; -import cn.hutool.log.LogFactory; -import cn.hutool.log.StaticLog; +import lombok.extern.slf4j.Slf4j; import org.aohe.result.R; import org.java_websocket.WebSocket; import org.java_websocket.handshake.ClientHandshake; @@ -14,10 +11,9 @@ import java.net.UnknownHostException; import static org.aohe.control.Operational.selectOperational; +@Slf4j public class SocketServer extends WebSocketServer { - private static final Log log = LogFactory.get(); - public SocketServer(int port) throws UnknownHostException { super(new InetSocketAddress(port)); } @@ -31,24 +27,25 @@ public class SocketServer extends WebSocketServer { //conn.send("Welcome to the server!"); // This method sends a message to the new client //broadcast("new connection: " + handshake.getResourceDescriptor()); // This method sends a message to all clients connected //System.out.println(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!"); - StaticLog.info("ws用户已连接"); + log.info("ws用户已连接"); } @Override public void onClose(WebSocket conn, int code, String reason, boolean remote) { - StaticLog.info("ws用户关闭连接"); + log.info("ws用户关闭连接"); //这里执行关闭扫描仪连接 } @Override public void onMessage(WebSocket conn, String message) { - StaticLog.info("用户发送了数据:\n"+message); + log.info("用户发送了数据:\n {}", message); conn.send(selectOperational(message)); } @Override public void onError(WebSocket conn, Exception ex) { ex.printStackTrace(); + log.info(ex.getMessage()); if (conn != null) { conn.send(R.fail("error").toJsonStr()); //绑定不到就退出 @@ -61,7 +58,7 @@ public class SocketServer extends WebSocketServer { @Override public void onStart() { - System.out.println("Server started!"); + log.info("Server started!"); setConnectionLostTimeout(0); setConnectionLostTimeout(100); diff --git a/src/main/java/org/aohe/web/SocketUtils.java b/src/main/java/org/aohe/web/SocketUtils.java new file mode 100644 index 0000000..a44e4f8 --- /dev/null +++ b/src/main/java/org/aohe/web/SocketUtils.java @@ -0,0 +1,34 @@ +package org.aohe.web; + +import java.net.UnknownHostException; + +public class SocketUtils { + private static SocketServer server; + + public SocketUtils() throws Exception { + } + + public static SocketServer get() { + return server; + } + + public static void start(int port) { + try { + server = new SocketServer(port); + server.start(); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } + + public static void safeStop() { + if(server != null){ + try { + server.stop(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/src/main/resources/ah.png b/src/main/resources/ah.png new file mode 100644 index 0000000000000000000000000000000000000000..b225fdabc29dcdc8009352df343bef6856a4bd36 GIT binary patch literal 2794 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