Compare commits
No commits in common. "191c6dfce76986f240197244031cbe00618dfdec" and "5978de5534ed8a49f72f899ecddd7727c6a8be95" have entirely different histories.
191c6dfce7
...
5978de5534
@ -8,7 +8,6 @@ import com.goeing.printserver.main.domain.request.PrintRequest;
|
|||||||
import com.goeing.printserver.main.service.PrintQueueService;
|
import com.goeing.printserver.main.service.PrintQueueService;
|
||||||
import com.goeing.printserver.main.service.PrintService;
|
import com.goeing.printserver.main.service.PrintService;
|
||||||
import com.goeing.printserver.main.utils.PdfPrinter;
|
import com.goeing.printserver.main.utils.PdfPrinter;
|
||||||
import com.goeing.printserver.main.ws.PrinterClient;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -16,12 +15,13 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
// 使用完全限定名称避免与自定义PrintService接口冲突
|
// 使用完全限定名称避免与自定义PrintService接口冲突
|
||||||
import java.awt.print.PrinterJob;
|
import java.awt.print.PrinterJob;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -36,7 +36,7 @@ public class PrintController implements PrintService {
|
|||||||
private PrintServerConfig config;
|
private PrintServerConfig config;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PrinterClient printerClient;
|
private com.goeing.printserver.main.sse.PrinterClient printerClient;
|
||||||
|
|
||||||
private final String rootPath = System.getProperty("java.io.tmpdir") + File.separator + "goeingprint" + File.separator + "pdfTemp";
|
private final String rootPath = System.getProperty("java.io.tmpdir") + File.separator + "goeingprint" + File.separator + "pdfTemp";
|
||||||
|
|
||||||
@ -107,51 +107,6 @@ public class PrintController implements PrintService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空打印队列
|
|
||||||
*
|
|
||||||
* @return 清空结果
|
|
||||||
*/
|
|
||||||
@DeleteMapping("queue/clear")
|
|
||||||
public Map<String, Object> clearQueue() {
|
|
||||||
int clearedCount = printQueueService.clearQueue();
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
result.put("success", true);
|
|
||||||
result.put("clearedCount", clearedCount);
|
|
||||||
result.put("message", "队列已清空,共清空 " + clearedCount + " 个任务");
|
|
||||||
result.put("timestamp", System.currentTimeMillis());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消单个任务
|
|
||||||
*
|
|
||||||
* @param taskId 任务ID
|
|
||||||
* @return 取消结果
|
|
||||||
*/
|
|
||||||
@DeleteMapping("queue/task/{taskId}")
|
|
||||||
public Map<String, Object> cancelTask(@PathVariable String taskId) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
try {
|
|
||||||
boolean cancelled = printQueueService.cancelTask(taskId);
|
|
||||||
if (cancelled) {
|
|
||||||
result.put("success", true);
|
|
||||||
result.put("message", "任务已取消");
|
|
||||||
result.put("taskId", taskId);
|
|
||||||
} else {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "未找到指定任务");
|
|
||||||
result.put("taskId", taskId);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "取消任务失败: " + e.getMessage());
|
|
||||||
result.put("taskId", taskId);
|
|
||||||
}
|
|
||||||
result.put("timestamp", System.currentTimeMillis());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索打印任务
|
* 搜索打印任务
|
||||||
*
|
*
|
||||||
@ -190,13 +145,7 @@ public class PrintController implements PrintService {
|
|||||||
taskMap.put("fileName", extractFileName(task.getFileUrl()));
|
taskMap.put("fileName", extractFileName(task.getFileUrl()));
|
||||||
taskMap.put("printer", task.getPrinter());
|
taskMap.put("printer", task.getPrinter());
|
||||||
taskMap.put("status", task.getStatus());
|
taskMap.put("status", task.getStatus());
|
||||||
// 格式化创建时间为 yyyy-MM-dd HH:mm:ss
|
taskMap.put("createTime", task.getQueuedTime());
|
||||||
if (task.getQueuedTime() != null) {
|
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
||||||
taskMap.put("createTime", task.getQueuedTime().format(formatter));
|
|
||||||
} else {
|
|
||||||
taskMap.put("createTime", "N/A");
|
|
||||||
}
|
|
||||||
taskMap.put("fileUrl", task.getFileUrl());
|
taskMap.put("fileUrl", task.getFileUrl());
|
||||||
return taskMap;
|
return taskMap;
|
||||||
})
|
})
|
||||||
|
|||||||
@ -20,19 +20,13 @@ public class LogbackConfig {
|
|||||||
public void registerAppender() {
|
public void registerAppender() {
|
||||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||||
|
|
||||||
// 将 Spring 管理的 appender 关联到 Logback 的上下文
|
// // 添加 appender 到 root logger
|
||||||
memoryLogAppender.setContext(context);
|
|
||||||
|
|
||||||
// / 添加 appender 到 root logger(供其它包使用)
|
|
||||||
Logger rootLogger = context.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
Logger rootLogger = context.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||||
rootLogger.addAppender(memoryLogAppender);
|
rootLogger.addAppender(memoryLogAppender);
|
||||||
|
|
||||||
// 同时添加到 com.goeing.printserver 包级 logger(该 logger 配置了 additivity=false)
|
|
||||||
Logger appLogger = context.getLogger("com.goeing.printserver");
|
|
||||||
appLogger.addAppender(memoryLogAppender);
|
|
||||||
|
|
||||||
// 启动 appender
|
|
||||||
memoryLogAppender.start();
|
memoryLogAppender.start();
|
||||||
|
|
||||||
|
// 可选:也加到你的包 logger
|
||||||
|
// Logger appLogger = context.getLogger("com.goeing.printserver");
|
||||||
|
// appLogger.addAppender(memoryLogAppender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,7 +4,6 @@ import com.goeing.printserver.main.domain.bo.PrintOption;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -41,27 +40,16 @@ public class PrintTask {
|
|||||||
*/
|
*/
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
map.put("fileUrl", fileUrl);
|
map.put("fileUrl", fileUrl);
|
||||||
map.put("printerName", printer);
|
map.put("printerName", printer);
|
||||||
map.put("status", status);
|
map.put("status", status);
|
||||||
|
map.put("queuedTime", queuedTime);
|
||||||
// 格式化时间字段
|
|
||||||
if (queuedTime != null) {
|
|
||||||
map.put("queuedTime", queuedTime.format(formatter));
|
|
||||||
} else {
|
|
||||||
map.put("queuedTime", "N/A");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startTime != null) {
|
if (startTime != null) {
|
||||||
map.put("startTime", startTime.format(formatter));
|
map.put("startTime", startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endTime != null) {
|
if (endTime != null) {
|
||||||
map.put("endTime", endTime.format(formatter));
|
map.put("endTime", endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,7 +12,6 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -64,7 +63,6 @@ public class PrintQueueService {
|
|||||||
* 打印任务内部类,封装打印请求和WebSocket会话
|
* 打印任务内部类,封装打印请求和WebSocket会话
|
||||||
*/
|
*/
|
||||||
private static class PrintTask {
|
private static class PrintTask {
|
||||||
private final String id;
|
|
||||||
private final PrintRequest printRequest;
|
private final PrintRequest printRequest;
|
||||||
private final WebSocketMessageDTO messageDTO;
|
private final WebSocketMessageDTO messageDTO;
|
||||||
private final Session session;
|
private final Session session;
|
||||||
@ -74,7 +72,6 @@ public class PrintQueueService {
|
|||||||
private String status; // queued, processing, completed, failed
|
private String status; // queued, processing, completed, failed
|
||||||
|
|
||||||
public PrintTask(PrintRequest printRequest, WebSocketMessageDTO messageDTO, Session session) {
|
public PrintTask(PrintRequest printRequest, WebSocketMessageDTO messageDTO, Session session) {
|
||||||
this.id = "TASK_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000);
|
|
||||||
this.printRequest = printRequest;
|
this.printRequest = printRequest;
|
||||||
this.messageDTO = messageDTO;
|
this.messageDTO = messageDTO;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
@ -82,10 +79,6 @@ public class PrintQueueService {
|
|||||||
this.status = "queued";
|
this.status = "queued";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrintRequest getPrintRequest() {
|
public PrintRequest getPrintRequest() {
|
||||||
return printRequest;
|
return printRequest;
|
||||||
}
|
}
|
||||||
@ -128,28 +121,16 @@ public class PrintQueueService {
|
|||||||
|
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
map.put("id", id);
|
|
||||||
map.put("fileUrl", printRequest.getFileUrl());
|
map.put("fileUrl", printRequest.getFileUrl());
|
||||||
map.put("printerName", printRequest.getPrinterName());
|
map.put("printerName", printRequest.getPrinterName());
|
||||||
map.put("status", status);
|
map.put("status", status);
|
||||||
|
map.put("queuedTime", queuedTime);
|
||||||
// 格式化时间字段
|
|
||||||
if (queuedTime != null) {
|
|
||||||
map.put("queuedTime", queuedTime.format(formatter));
|
|
||||||
} else {
|
|
||||||
map.put("queuedTime", "N/A");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startTime != null) {
|
if (startTime != null) {
|
||||||
map.put("startTime", startTime.format(formatter));
|
map.put("startTime", startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endTime != null) {
|
if (endTime != null) {
|
||||||
map.put("endTime", endTime.format(formatter));
|
map.put("endTime", endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,7 +212,6 @@ public class PrintQueueService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 执行打印
|
// 执行打印
|
||||||
// Thread.sleep(20000L);
|
|
||||||
printService.print(printRequest);
|
printService.print(printRequest);
|
||||||
log.info("打印任务完成: {}", printRequest.getFileUrl());
|
log.info("打印任务完成: {}", printRequest.getFileUrl());
|
||||||
|
|
||||||
@ -370,43 +350,6 @@ public class PrintQueueService {
|
|||||||
return maxQueueSize;
|
return maxQueueSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 清空打印队列
|
|
||||||
* 注意:此操作不会影响当前正在处理的任务
|
|
||||||
*
|
|
||||||
* @return 清空的任务数量
|
|
||||||
*/
|
|
||||||
public int clearQueue() {
|
|
||||||
int clearedCount = printQueue.size();
|
|
||||||
printQueue.clear();
|
|
||||||
log.info("打印队列已清空,共清空 {} 个任务", clearedCount);
|
|
||||||
return clearedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消指定任务
|
|
||||||
* @param taskId 任务ID
|
|
||||||
* @return 是否成功取消
|
|
||||||
*/
|
|
||||||
public boolean cancelTask(String taskId) {
|
|
||||||
// 检查当前任务
|
|
||||||
if (currentTask != null && taskId.equals(currentTask.getId())) {
|
|
||||||
log.info("取消当前正在执行的任务: {}", taskId);
|
|
||||||
currentTask.setStatus("cancelled");
|
|
||||||
currentTask = null;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从队列中移除任务
|
|
||||||
boolean removed = printQueue.removeIf(task -> taskId.equals(task.getId()));
|
|
||||||
if (removed) {
|
|
||||||
log.info("成功从队列中取消任务: {}", taskId);
|
|
||||||
} else {
|
|
||||||
log.warn("未找到要取消的任务: {}", taskId);
|
|
||||||
}
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取历史服务实例
|
* 获取历史服务实例
|
||||||
*
|
*
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package com.goeing.printserver.main.ws;
|
package com.goeing.printserver.main.sse;
|
||||||
|
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -21,7 +21,6 @@ import java.net.URI;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -33,12 +32,9 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
private final PrintServerConfig config;
|
private final PrintServerConfig config;
|
||||||
private Session session;
|
private Session session;
|
||||||
|
|
||||||
|
private final ScheduledExecutorService reconnectExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
private final ScheduledExecutorService heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
|
private final ScheduledExecutorService heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
private final ScheduledExecutorService connectionMonitor = Executors.newSingleThreadScheduledExecutor();
|
private boolean isConnecting = false;
|
||||||
private volatile ScheduledFuture<?> heartbeatTask;
|
|
||||||
private volatile boolean isConnecting = false;
|
|
||||||
private int reconnectAttempts = 0;
|
|
||||||
private static final int MAX_RECONNECT_ATTEMPTS = 10;
|
|
||||||
|
|
||||||
// 构造函数,注入PrintQueueService和PrintServerConfig
|
// 构造函数,注入PrintQueueService和PrintServerConfig
|
||||||
public PrinterClient(@Lazy PrintQueueService printQueueService, PrintServerConfig config) {
|
public PrinterClient(@Lazy PrintQueueService printQueueService, PrintServerConfig config) {
|
||||||
@ -52,8 +48,6 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
this.session = session;
|
this.session = session;
|
||||||
log.info("WebSocket连接已建立");
|
log.info("WebSocket连接已建立");
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
reconnectAttempts = 0; // 重置重连计数
|
|
||||||
startHeartbeat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnMessage
|
@OnMessage
|
||||||
@ -95,18 +89,10 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
PrintService[] printServices = PrinterJob.lookupPrintServices();
|
PrintService[] printServices = PrinterJob.lookupPrintServices();
|
||||||
Set<String> collect = Arrays.stream(printServices).map(PrintService::getName).collect(Collectors.toSet());
|
Set<String> collect = Arrays.stream(printServices).map(PrintService::getName).collect(Collectors.toSet());
|
||||||
|
|
||||||
List<String> printerList = collect.stream().sorted().collect(Collectors.toList());
|
List<String> collect1 = collect.stream().sorted().collect(Collectors.toList());
|
||||||
|
|
||||||
// 获取设置中的默认打印机
|
|
||||||
String defaultPrinter = config.getDefaultPrinter();
|
|
||||||
|
|
||||||
// 构建响应对象
|
|
||||||
Map<String, Object> response = new HashMap<>();
|
|
||||||
response.put("printerList", printerList);
|
|
||||||
response.put("defaultPrinter", defaultPrinter);
|
|
||||||
|
|
||||||
webSocketMessageDTO.setType("RESPONSE");
|
webSocketMessageDTO.setType("RESPONSE");
|
||||||
webSocketMessageDTO.setPayload(JSONUtil.toJsonStr(response));
|
webSocketMessageDTO.setPayload(JSONUtil.toJsonStr(collect1));
|
||||||
session.getBasicRemote().sendText(JSONUtil.toJsonStr(webSocketMessageDTO));
|
session.getBasicRemote().sendText(JSONUtil.toJsonStr(webSocketMessageDTO));
|
||||||
} else if ("queueStatus".equals(type)) {
|
} else if ("queueStatus".equals(type)) {
|
||||||
// 返回当前打印队列状态
|
// 返回当前打印队列状态
|
||||||
@ -139,22 +125,25 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
public void onClose(Session session, CloseReason closeReason) {
|
public void onClose(Session session, CloseReason closeReason) {
|
||||||
log.warn("WebSocket连接关闭: {}", closeReason.getReasonPhrase());
|
log.warn("WebSocket连接关闭: {}", closeReason.getReasonPhrase());
|
||||||
this.session = null;
|
this.session = null;
|
||||||
// 连接监控器会自动处理重连
|
// 安排重连任务
|
||||||
|
scheduleReconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnError
|
@OnError
|
||||||
public void onError(Session session, Throwable throwable) {
|
public void onError(Session session, Throwable throwable) {
|
||||||
log.error("WebSocket连接发生错误", throwable);
|
log.error("WebSocket连接发生错误", throwable);
|
||||||
this.session = null;
|
this.session = null;
|
||||||
// 连接监控器会自动处理重连
|
|
||||||
|
// 安排重连任务
|
||||||
|
scheduleReconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接到WebSocket服务器
|
* 连接到WebSocket服务器
|
||||||
*/
|
*/
|
||||||
private void connect() {
|
private void connect() {
|
||||||
if (isConnecting) {
|
if (isConnecting || (session != null && session.isOpen())) {
|
||||||
return; // 正在连接中
|
return; // 已经连接或正在连接中
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从配置对象中获取最新的连接参数
|
// 从配置对象中获取最新的连接参数
|
||||||
@ -162,11 +151,6 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
String printerId = config.getPrinterId();
|
String printerId = config.getPrinterId();
|
||||||
String apiKey = config.getApiKey();
|
String apiKey = config.getApiKey();
|
||||||
|
|
||||||
if (serverUri == null || serverUri.trim().isEmpty()) {
|
|
||||||
log.warn("WebSocket URL未配置,跳过连接");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加调试日志
|
// 添加调试日志
|
||||||
log.info("当前配置 - WebSocket URL: {}, PrinterId: {}, ApiKey: {}", serverUri, printerId, apiKey);
|
log.info("当前配置 - WebSocket URL: {}, PrinterId: {}, ApiKey: {}", serverUri, printerId, apiKey);
|
||||||
|
|
||||||
@ -181,8 +165,9 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
container.connectToServer(this, new URI(tempUrl));
|
container.connectToServer(this, new URI(tempUrl));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("连接到WebSocket服务器失败", e);
|
log.error("连接到WebSocket服务器失败", e);
|
||||||
} finally {
|
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
|
// 连接失败,安排重连
|
||||||
|
scheduleReconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,63 +175,27 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
* 启动心跳机制
|
* 启动心跳机制
|
||||||
*/
|
*/
|
||||||
private void startHeartbeat() {
|
private void startHeartbeat() {
|
||||||
// 取消之前的心跳任务
|
heartbeatExecutor.scheduleAtFixedRate(() -> {
|
||||||
if (heartbeatTask != null && !heartbeatTask.isCancelled()) {
|
|
||||||
heartbeatTask.cancel(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
heartbeatTask = heartbeatExecutor.scheduleAtFixedRate(() -> {
|
|
||||||
if (session != null && session.isOpen()) {
|
if (session != null && session.isOpen()) {
|
||||||
try {
|
try {
|
||||||
session.getBasicRemote().sendText("{\"type\":\"heartbeat\"}");
|
session.getBasicRemote().sendText("{\"type\":\"heartbeat\"}");
|
||||||
log.debug("发送心跳");
|
log.debug("发送心跳");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.debug("发送心跳失败", e);
|
log.error("发送心跳失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 30, 20, TimeUnit.SECONDS);
|
}, 30, 30, TimeUnit.SECONDS);
|
||||||
log.info("心跳机制已启动");
|
log.info("心跳机制已启动");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动连接监控
|
* 安排重连任务
|
||||||
*/
|
*/
|
||||||
private void startConnectionMonitor() {
|
private void scheduleReconnect() {
|
||||||
connectionMonitor.scheduleWithFixedDelay(() -> {
|
reconnectExecutor.schedule(() -> {
|
||||||
try {
|
log.info("尝试重新连接到WebSocket服务器...");
|
||||||
checkAndReconnect();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("连接监控任务执行失败", e);
|
|
||||||
}
|
|
||||||
}, 10, 20, TimeUnit.SECONDS); // 每10秒检查一次
|
|
||||||
|
|
||||||
log.info("连接监控已启动,每10秒检查一次连接状态");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查连接状态并在需要时重连
|
|
||||||
*/
|
|
||||||
private void checkAndReconnect() {
|
|
||||||
if (isConnected()) {
|
|
||||||
// 连接正常,重置重连计数
|
|
||||||
reconnectAttempts = 0;
|
|
||||||
log.debug("WebSocket连接状态正常");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isConnecting) {
|
|
||||||
log.debug("正在连接中,跳过此次检查");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
||||||
log.error("重连次数已达上限({}次),停止重连", MAX_RECONNECT_ATTEMPTS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("检测到连接断开,开始重连...(第{}次尝试)", reconnectAttempts + 1);
|
|
||||||
reconnectAttempts++;
|
|
||||||
connect();
|
connect();
|
||||||
|
}, 5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,16 +204,6 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
@PreDestroy
|
@PreDestroy
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
log.info("正在关闭WebSocket客户端...");
|
log.info("正在关闭WebSocket客户端...");
|
||||||
|
|
||||||
// 取消心跳任务
|
|
||||||
if (heartbeatTask != null && !heartbeatTask.isCancelled()) {
|
|
||||||
heartbeatTask.cancel(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 停止连接监控和心跳
|
|
||||||
connectionMonitor.shutdownNow();
|
|
||||||
heartbeatExecutor.shutdownNow();
|
|
||||||
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
try {
|
try {
|
||||||
session.close();
|
session.close();
|
||||||
@ -272,6 +211,8 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
log.error("关闭WebSocket连接失败", e);
|
log.error("关闭WebSocket连接失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
reconnectExecutor.shutdownNow();
|
||||||
|
heartbeatExecutor.shutdownNow();
|
||||||
log.info("WebSocket客户端已关闭");
|
log.info("WebSocket客户端已关闭");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,12 +221,6 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
*/
|
*/
|
||||||
public void reconnect() {
|
public void reconnect() {
|
||||||
log.info("配置已更改,重新连接WebSocket服务器...");
|
log.info("配置已更改,重新连接WebSocket服务器...");
|
||||||
|
|
||||||
// 停止旧的心跳任务
|
|
||||||
if (heartbeatTask != null && !heartbeatTask.isCancelled()) {
|
|
||||||
heartbeatTask.cancel(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session != null && session.isOpen()) {
|
if (session != null && session.isOpen()) {
|
||||||
try {
|
try {
|
||||||
session.close();
|
session.close();
|
||||||
@ -295,10 +230,6 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
}
|
}
|
||||||
session = null;
|
session = null;
|
||||||
isConnecting = false;
|
isConnecting = false;
|
||||||
|
|
||||||
// 重置重连计数
|
|
||||||
reconnectAttempts = 0;
|
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,8 +270,6 @@ public class PrinterClient implements ApplicationRunner {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) {
|
public void run(ApplicationArguments args) {
|
||||||
// 启动连接监控
|
|
||||||
startConnectionMonitor();
|
|
||||||
// 应用启动后连接到WebSocket服务器
|
// 应用启动后连接到WebSocket服务器
|
||||||
connect();
|
connect();
|
||||||
}
|
}
|
||||||
@ -2,12 +2,15 @@ package com.goeing.printserver.main.utils;
|
|||||||
|
|
||||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
import ch.qos.logback.core.AppenderBase;
|
import ch.qos.logback.core.AppenderBase;
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内存日志追加器,用于缓存日志到内存中
|
* 内存日志追加器,用于缓存日志到内存中
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
package com.goeing.printserver.main.utils;
|
package com.goeing.printserver.main.utils;// src/main/java/com/example/printer/PdfPrinter.java
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.goeing.printserver.main.domain.bo.PrintOption;
|
import com.goeing.printserver.main.domain.bo.PrintOption;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
|
import org.apache.pdfbox.printing.PDFPageable;
|
||||||
import org.apache.pdfbox.printing.Orientation;
|
import org.apache.pdfbox.printing.Orientation;
|
||||||
import org.apache.pdfbox.printing.PDFPrintable;
|
import org.apache.pdfbox.printing.PDFPrintable;
|
||||||
import org.apache.pdfbox.printing.Scaling;
|
import org.apache.pdfbox.printing.Scaling;
|
||||||
@ -29,10 +31,6 @@ public class PdfPrinter {
|
|||||||
|
|
||||||
private static final Map<String, MediaSizeName> PAPER_SIZES = new HashMap<>();
|
private static final Map<String, MediaSizeName> PAPER_SIZES = new HashMap<>();
|
||||||
|
|
||||||
// 装订边距常量(英寸)
|
|
||||||
private static final double BINDING_MARGIN_LEFT = 0.5; // 左装订额外边距
|
|
||||||
private static final double BINDING_MARGIN_TOP = 0.5; // 顶装订额外边距
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
PAPER_SIZES.put("Letter", MediaSizeName.NA_LETTER); // 8.5" × 11"
|
PAPER_SIZES.put("Letter", MediaSizeName.NA_LETTER); // 8.5" × 11"
|
||||||
PAPER_SIZES.put("Legal", MediaSizeName.NA_LEGAL); // 8.5" × 14"
|
PAPER_SIZES.put("Legal", MediaSizeName.NA_LEGAL); // 8.5" × 14"
|
||||||
@ -79,7 +77,9 @@ public class PdfPrinter {
|
|||||||
|
|
||||||
String color = option.getColor();
|
String color = option.getColor();
|
||||||
//如果是封面彩打 那么要把封面和 内容分开打印 就做两个打印任务 先打封面 再打内容
|
//如果是封面彩打 那么要把封面和 内容分开打印 就做两个打印任务 先打封面 再打内容
|
||||||
if ("Cover Letter Color Only".equals(color)) {
|
if (color.equalsIgnoreCase("Cover Letter Color Only")){
|
||||||
|
|
||||||
|
|
||||||
PDDocument cover = new PDDocument();
|
PDDocument cover = new PDDocument();
|
||||||
cover.addPage(document.getPage(0));
|
cover.addPage(document.getPage(0));
|
||||||
cover.close();
|
cover.close();
|
||||||
@ -87,7 +87,7 @@ public class PdfPrinter {
|
|||||||
PDDocument content = new PDDocument();
|
PDDocument content = new PDDocument();
|
||||||
for (int i = 0; i < document.getNumberOfPages(); i++) {
|
for (int i = 0; i < document.getNumberOfPages(); i++) {
|
||||||
//第一页是封面
|
//第一页是封面
|
||||||
if (i == 0) {
|
if (i==0){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
content.addPage(document.getPage(i));
|
content.addPage(document.getPage(i));
|
||||||
@ -99,10 +99,7 @@ public class PdfPrinter {
|
|||||||
option.setColor("black & white");
|
option.setColor("black & white");
|
||||||
setPageStyle(content, job, option);
|
setPageStyle(content, job, option);
|
||||||
|
|
||||||
} else {
|
}else {
|
||||||
if (StrUtil.containsIgnoreCase(color,"color")){
|
|
||||||
option.setColor("color");
|
|
||||||
}
|
|
||||||
//全部打印
|
//全部打印
|
||||||
setPageStyle(document, job, option);
|
setPageStyle(document, job, option);
|
||||||
}
|
}
|
||||||
@ -268,8 +265,8 @@ public class PdfPrinter {
|
|||||||
// 获取边距(默认为0.5英寸)
|
// 获取边距(默认为0.5英寸)
|
||||||
double marginInches = option.getMargin();
|
double marginInches = option.getMargin();
|
||||||
|
|
||||||
// 创建并返回Paper对象,考虑装订选项
|
// 创建并返回Paper对象
|
||||||
return createPaper(dimensions[0], dimensions[1], marginInches, option.getPosition());
|
return createPaper(dimensions[0], dimensions[1], marginInches);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -385,52 +382,22 @@ public class PdfPrinter {
|
|||||||
*
|
*
|
||||||
* @param width 纸张宽度(点)
|
* @param width 纸张宽度(点)
|
||||||
* @param height 纸张高度(点)
|
* @param height 纸张高度(点)
|
||||||
* @param marginInches 基础边距(英寸)
|
* @param marginInches 边距(英寸)
|
||||||
* @param bindingOption 装订选项
|
|
||||||
* @return 配置好的Paper对象
|
* @return 配置好的Paper对象
|
||||||
*/
|
*/
|
||||||
private static Paper createPaper(double width, double height, double marginInches, String bindingOption) {
|
private static Paper createPaper(double width, double height, double marginInches) {
|
||||||
Paper paper = new Paper();
|
Paper paper = new Paper();
|
||||||
paper.setSize(width, height);
|
paper.setSize(width, height);
|
||||||
|
|
||||||
// 计算各边的边距,考虑装订选项
|
|
||||||
double leftMargin = marginInches;
|
|
||||||
double topMargin = marginInches;
|
|
||||||
double rightMargin = marginInches;
|
|
||||||
double bottomMargin = marginInches;
|
|
||||||
|
|
||||||
// 根据装订选项调整边距
|
|
||||||
if (bindingOption != null) {
|
|
||||||
switch (bindingOption) {
|
|
||||||
case "Left":
|
|
||||||
leftMargin += BINDING_MARGIN_LEFT;
|
|
||||||
break;
|
|
||||||
case "Top":
|
|
||||||
topMargin += BINDING_MARGIN_TOP;
|
|
||||||
break;
|
|
||||||
case "Staple":
|
|
||||||
leftMargin += BINDING_MARGIN_LEFT;
|
|
||||||
topMargin += BINDING_MARGIN_TOP;
|
|
||||||
break;
|
|
||||||
case "None":
|
|
||||||
default:
|
|
||||||
// 不调整边距
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将边距从英寸转换为点
|
// 将边距从英寸转换为点
|
||||||
double leftMarginPoints = leftMargin * 72;
|
double marginPoints = marginInches * 72;
|
||||||
double topMarginPoints = topMargin * 72;
|
|
||||||
double rightMarginPoints = rightMargin * 72;
|
|
||||||
double bottomMarginPoints = bottomMargin * 72;
|
|
||||||
|
|
||||||
// 设置可打印区域
|
// 设置可打印区域
|
||||||
paper.setImageableArea(
|
paper.setImageableArea(
|
||||||
leftMarginPoints,
|
marginPoints,
|
||||||
topMarginPoints,
|
marginPoints,
|
||||||
width - leftMarginPoints - rightMarginPoints,
|
width - 2 * marginPoints,
|
||||||
height - topMarginPoints - bottomMarginPoints
|
height - 2 * marginPoints
|
||||||
);
|
);
|
||||||
|
|
||||||
return paper;
|
return paper;
|
||||||
|
|||||||
@ -42,8 +42,8 @@
|
|||||||
</logger>
|
</logger>
|
||||||
|
|
||||||
<!-- Spring Boot 相关日志 -->
|
<!-- Spring Boot 相关日志 -->
|
||||||
<logger name="org.springframework" level="WARN" />
|
<logger name="org.springframework" level="INFO" />
|
||||||
<logger name="org.springframework.web" level="WARN" />
|
<logger name="org.springframework.web" level="DEBUG" />
|
||||||
|
|
||||||
<!-- Hibernate 相关日志 -->
|
<!-- Hibernate 相关日志 -->
|
||||||
<logger name="org.hibernate" level="WARN" />
|
<logger name="org.hibernate" level="WARN" />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user