Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
|
38ee383033 | |
|
afea000336 | |
|
84fe5afc62 | |
|
23063b0d9c | |
|
b29961b0bf | |
|
b0701543b1 | |
|
c192fcf954 | |
|
bd95bbb11b | |
|
9b1138d62a | |
|
8f0175641f | |
|
79da72c6ea | |
|
e9a6312913 | |
|
f6a4717dac | |
|
0091075137 | |
|
40e1932f0c | |
|
3bec2895b1 |
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
14
pom.xml
14
pom.xml
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>org.aohe</groupId>
|
||||
<artifactId>sane-service</artifactId>
|
||||
<version>0.2.6</version>
|
||||
<version>0.3.4</version>
|
||||
|
||||
<name>aohe-sane-service</name>
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
|||
<dependency>
|
||||
<groupId>org.java-websocket</groupId>
|
||||
<artifactId>Java-WebSocket</artifactId>
|
||||
<version>1.5.3</version>
|
||||
<version>1.5.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.formdev</groupId>
|
||||
|
@ -71,6 +71,12 @@
|
|||
<version>3.4.1</version>
|
||||
<classifier>no-natives</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.sanyarnd</groupId>
|
||||
<artifactId>app-locker</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.formdev</groupId>-->
|
||||
<!-- <artifactId>flatlaf</artifactId>-->
|
||||
|
@ -145,8 +151,10 @@
|
|||
<generateInstaller>true</generateInstaller>
|
||||
<administratorRequired>false</administratorRequired>
|
||||
<platform>linux</platform>
|
||||
<displayName>奥诃影像扫描控件</displayName>
|
||||
<description>奥诃公司为影像 WEB 应用开发的 USB 扫描仪连接驱动,请搭配 WEB 产品使用。</description>
|
||||
<linuxConfig>
|
||||
<generateAppImage>true</generateAppImage>
|
||||
<!-- <generateAppImage>true</generateAppImage>-->
|
||||
<generateDeb>true</generateDeb>
|
||||
<generateRpm>true</generateRpm>
|
||||
<wrapJar>true</wrapJar>
|
||||
|
|
|
@ -1,30 +1,43 @@
|
|||
package org.aohe;
|
||||
|
||||
import com.formdev.flatlaf.FlatDarculaLaf;
|
||||
import io.github.sanyarnd.applocker.AppLocker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aohe.core.sane.utils.SaneSessionUtils;
|
||||
import org.aohe.core.swing.MainWindow;
|
||||
import org.aohe.core.swing.NewWindow;
|
||||
import org.aohe.core.utils.CommandUtils;
|
||||
import org.aohe.core.utils.SystemUtils;
|
||||
import org.aohe.core.web.SocketFactory;
|
||||
import com.formdev.flatlaf.FlatLightLaf;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@Slf4j
|
||||
public class Main {
|
||||
|
||||
private static final String JAVA_IO_TMPDIR = System.getProperty("java.io.tmpdir");
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
log.info(" 当前系统类型: {}", SystemUtils.getOsName());
|
||||
AppLocker locker = AppLocker.create("aoheSaneServiceLock").setPath( Path.of(JAVA_IO_TMPDIR) ).build();
|
||||
try {
|
||||
//启动锁,只允许启动一个
|
||||
locker.lock();
|
||||
|
||||
//设置窗口主题
|
||||
//FlatLightLaf.setup();
|
||||
UIManager.setLookAndFeel(new FlatLightLaf());
|
||||
UIManager.setLookAndFeel(new FlatDarculaLaf());
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (Exception ex) {
|
||||
log.error("应用已经启动,当前进程退出。",ex);
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
//初始化其他资源
|
||||
init();
|
||||
SwingUtilities.invokeLater(() -> new MainWindow().setVisible(true));
|
||||
SwingUtilities.invokeLater(() -> new NewWindow().setVisible(true));
|
||||
|
||||
}
|
||||
|
||||
|
@ -47,4 +60,6 @@ public class Main {
|
|||
log.info("socket 服务已关闭 ");
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -142,13 +142,13 @@ public class SaneSessionUtils {
|
|||
try {
|
||||
saneDevice.open();
|
||||
BufferedImage bufferedImage = saneDevice.acquireImage();
|
||||
File file = FileUtil.createTempFile("sane","png",true);
|
||||
File file = FileUtil.createTempFile("sane-",".png",true);
|
||||
ImageIO.write(bufferedImage, "png", file);
|
||||
return file;
|
||||
} catch (IOException | SaneException e) {
|
||||
throw new RuntimeException(e);
|
||||
}finally {
|
||||
if(saneDevice != null){
|
||||
if(saneDevice != null && saneDevice.isOpen()){
|
||||
saneDevice.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package org.aohe.core.swing;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aohe.core.utils.CommandUtils;
|
||||
import org.aohe.core.web.SocketFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class MainWindow extends JFrame {
|
||||
|
@ -55,6 +57,7 @@ public class MainWindow extends JFrame {
|
|||
startButton.addActionListener(e -> {
|
||||
startButton.setEnabled(false);
|
||||
stopButton.setEnabled(true);
|
||||
CommandUtils.killUsedPort("8997");
|
||||
initSocket();
|
||||
setView("服务已打开...");
|
||||
serviceStatus = true;
|
||||
|
@ -125,6 +128,11 @@ public class MainWindow extends JFrame {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean checkPort(String port){
|
||||
List<CommandUtils.LsofInfo> lsofInfos = CommandUtils.findPort(port);
|
||||
return !lsofInfos.isEmpty();
|
||||
}
|
||||
|
||||
public static void setView(String msg){
|
||||
if(logTextArea != null){
|
||||
logTextArea.append(msg +"\n");
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
package org.aohe.core.swing;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aohe.core.web.SocketFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
@Slf4j
|
||||
public class NewWindow extends JFrame {
|
||||
|
||||
private static JTextArea logTextArea;
|
||||
|
||||
private static final JLabel textField = new JLabel();
|
||||
|
||||
public NewWindow() {
|
||||
// 设置窗口标题
|
||||
setTitle("扫描前端");
|
||||
|
||||
// 设置默认的关闭操作
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
// 设置窗口大小
|
||||
setSize(400, 300);
|
||||
|
||||
// 居中显示窗口
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
// 初始化UI组件
|
||||
initializeComponents();
|
||||
}
|
||||
|
||||
private void initializeComponents() {
|
||||
|
||||
textField.setForeground(Color.GRAY);
|
||||
textField.setText("服务状态:启动中...");
|
||||
|
||||
//初始化连接服务
|
||||
initSocket();
|
||||
|
||||
// 示例:添加一个按钮,点击时向文本区域添加日志信息
|
||||
JButton stopButton = new JButton("退出");
|
||||
stopButton.setEnabled(true);
|
||||
stopButton.addActionListener(e -> {
|
||||
stopButton.setEnabled(false);
|
||||
logTextArea.append("关闭服务中...\n");
|
||||
//开个新线程关闭,防止主UI线程卡死
|
||||
new Thread( () ->{
|
||||
stopSocket();
|
||||
//关闭任务
|
||||
sleep(1000);
|
||||
textField.setForeground(Color.RED);
|
||||
textField.setText("服务状态:关闭");
|
||||
sleep(100);
|
||||
System.exit(0);
|
||||
} ).start();
|
||||
});
|
||||
|
||||
getContentPane().add(textField, BorderLayout.NORTH);
|
||||
|
||||
getContentPane().add(stopButton, BorderLayout.SOUTH);
|
||||
|
||||
}
|
||||
|
||||
public void setView(String view){
|
||||
getLogTextArea().append(view + "\n");
|
||||
}
|
||||
|
||||
public static void setStaticView(String view){
|
||||
if(logTextArea != null){
|
||||
logTextArea.append(view + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
public void initSocket() {
|
||||
if(SocketFactory.start()){
|
||||
setView("socket 服务启动成功");
|
||||
textField.setForeground(Color.GREEN);
|
||||
textField.setText("服务状态:启动");
|
||||
}else{
|
||||
setView("socket 服务启动失败");
|
||||
setView("请检查8997端口是否被占用,或是否重复打开此程序");
|
||||
setView("应用退出中...");
|
||||
new Thread( () -> {
|
||||
sleep(5000);
|
||||
System.exit(0);
|
||||
} ).start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopSocket() {
|
||||
try {
|
||||
if(SocketFactory.stop()){
|
||||
setView("服务停止成功");
|
||||
}else{
|
||||
setView("服务停止失败");
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
log.info("服务关闭");
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public JTextArea getLogTextArea(){
|
||||
if(logTextArea == null){
|
||||
initLogTextArea();
|
||||
}
|
||||
return logTextArea;
|
||||
}
|
||||
|
||||
public void initLogTextArea(){
|
||||
// 在这里添加你的组件初始化代码
|
||||
// 创建一个JTextArea用于显示日志
|
||||
logTextArea = new JTextArea();
|
||||
logTextArea.setEditable(false); // 设置为不可编辑
|
||||
logTextArea.setEnabled(false);
|
||||
|
||||
// 将JTextArea放入JScrollPane中以支持滚动
|
||||
JScrollPane scrollPane = new JScrollPane(logTextArea);
|
||||
|
||||
// 将JScrollPane添加到窗口中
|
||||
getContentPane().add(scrollPane, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public static void sleep(long m){
|
||||
try {
|
||||
Thread.sleep(m);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ package org.aohe.core.utils;
|
|||
|
||||
import cn.hutool.core.util.RuntimeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -59,4 +61,60 @@ public class CommandUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void killUsedPort(String port){
|
||||
List<LsofInfo> lsofInfos = findPort(port);
|
||||
for(LsofInfo lsofInfo : lsofInfos){
|
||||
log.info(" pro kill begin {}", lsofInfo);
|
||||
destroy(lsofInfo.getPid());
|
||||
}
|
||||
}
|
||||
|
||||
public static List<LsofInfo> findPort(String port){
|
||||
String exec = StrUtil.format("lsof -i:{}",port);
|
||||
String s = execForStrUtf8Sudo(exec);
|
||||
log.info(s);
|
||||
return parseCommandOutput(s);
|
||||
}
|
||||
|
||||
public static void destroy(String pid){
|
||||
String exec = StrUtil.format("kill -9 {}",pid);
|
||||
String s = execForStrUtf8Sudo(exec);
|
||||
log.info(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* lsof 格式化
|
||||
* @param output s
|
||||
* @return list
|
||||
*/
|
||||
public static List<LsofInfo> parseCommandOutput(String output) {
|
||||
List<LsofInfo> processInfos = new ArrayList<>();
|
||||
String[] lines = output.split("\n");
|
||||
if(lines.length <= 1){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
for (int i = 1 ; i < lines.length ; i ++) {
|
||||
//从第一行开始
|
||||
String[] parts = lines[i].trim().split("\\s+");
|
||||
if (parts.length < 6) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
LsofInfo processInfo = new LsofInfo();
|
||||
processInfo.setPid(parts[1]);
|
||||
processInfo.setType(parts[4]);
|
||||
|
||||
processInfos.add(processInfo);
|
||||
}
|
||||
|
||||
return processInfos;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public static class LsofInfo {
|
||||
private String pid;
|
||||
private String type;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
package org.aohe.core.utils;
|
||||
|
||||
import cn.hutool.core.net.Ipv4Util;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import org.aohe.core.sane.utils.SaneSessionUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class SystemUtils {
|
||||
|
||||
|
|
|
@ -11,12 +11,6 @@ import java.net.UnknownHostException;
|
|||
@Slf4j
|
||||
public class SocketFactory {
|
||||
|
||||
/**
|
||||
* -- GETTER --
|
||||
* get 方法
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Getter
|
||||
private static SocketServer socketServer;
|
||||
|
||||
|
@ -31,6 +25,7 @@ public class SocketFactory {
|
|||
private static SocketServer getSocket() throws UnknownHostException {
|
||||
log.info("Create Socket ...");
|
||||
socketServer = new SocketServer(8997);
|
||||
socketServer.setReuseAddr(true);
|
||||
return socketServer;
|
||||
}
|
||||
|
||||
|
@ -40,9 +35,10 @@ public class SocketFactory {
|
|||
public static boolean start() {
|
||||
try {
|
||||
getSocket().start();
|
||||
} catch (UnknownHostException e) {
|
||||
} catch (Exception e){
|
||||
return false;
|
||||
}
|
||||
log.info("socket ReuseAddr status {}", socketServer.isReuseAddr());
|
||||
log.info("socket 已启动");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.aohe.core.result.R;
|
|||
import org.aohe.core.sane.SaneOperational;
|
||||
|
||||
import org.aohe.core.sane.utils.SaneSessionUtils;
|
||||
import org.aohe.core.swing.NewWindow;
|
||||
import org.aohe.core.utils.SystemUtils;
|
||||
import org.java_websocket.WebSocket;
|
||||
import org.java_websocket.handshake.ClientHandshake;
|
||||
|
@ -65,6 +66,14 @@ public class SocketServer extends WebSocketServer {
|
|||
// websocket
|
||||
log.error( "System error ", ex );
|
||||
}
|
||||
if(ex instanceof java.net.BindException){
|
||||
//无法绑定接口
|
||||
NewWindow.setStaticView("端口绑定失败,请检查端口占用,程序退出中...");
|
||||
new Thread( ()->{
|
||||
NewWindow.sleep(3000);
|
||||
System.exit(0);
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!-- 日志存放路径 -->
|
||||
<property name="log.path" value="${HOME}/Logs/ScanService"/>
|
||||
<property name="log.path" value="${HOME}/logs/ScanService"/>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
|
||||
|
||||
|
|
Loading…
Reference in New Issue