新增ws实现打印调用
This commit is contained in:
parent
3c9095bff4
commit
676c135121
@ -0,0 +1,22 @@
|
|||||||
|
package com.goeing.printserver.main.domain.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class WebSocketMessageDTO {
|
||||||
|
|
||||||
|
// 消息内容
|
||||||
|
private String payload;
|
||||||
|
|
||||||
|
// 消息时间戳
|
||||||
|
private LocalDateTime timestamp;
|
||||||
|
|
||||||
|
// 消息类型(可选)
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
//请求id
|
||||||
|
private String requestId;
|
||||||
|
|
||||||
|
}
|
||||||
213
src/main/java/com/goeing/printserver/main/sse/PrinterClient.java
Normal file
213
src/main/java/com/goeing/printserver/main/sse/PrinterClient.java
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package com.goeing.printserver.main.sse;
|
||||||
|
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.goeing.printserver.main.PrintController;
|
||||||
|
import com.goeing.printserver.main.domain.dto.WebSocketMessageDTO;
|
||||||
|
import com.goeing.printserver.main.domain.request.PrintRequest;
|
||||||
|
import jakarta.websocket.*;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
|
||||||
|
import javax.print.PrintService;
|
||||||
|
import java.awt.print.PrinterJob;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ClientEndpoint
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class PrinterClient implements ApplicationRunner {
|
||||||
|
private Session session;
|
||||||
|
@Value("${print.printer.id}")
|
||||||
|
private String printerId;
|
||||||
|
@Value("${print.websocket.url}")
|
||||||
|
private String serverUri;
|
||||||
|
@Value("${print.websocket.apiKey}")
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
private final ScheduledExecutorService reconnectExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
private final ScheduledExecutorService heartbeatExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
private boolean isConnecting = false;
|
||||||
|
|
||||||
|
// 无参构造函数,由Spring管理
|
||||||
|
public PrinterClient() {
|
||||||
|
// 构造函数不做连接操作,在run方法中进行连接
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
log.info("WebSocket连接已建立");
|
||||||
|
isConnecting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnMessage
|
||||||
|
public void onMessage(String message, Session session) {
|
||||||
|
log.info("收到消息: {}", message);
|
||||||
|
try {
|
||||||
|
// 解析消息
|
||||||
|
WebSocketMessageDTO webSocketMessageDTO = JSON.parseObject(message, WebSocketMessageDTO.class);
|
||||||
|
String type = webSocketMessageDTO.getType();
|
||||||
|
|
||||||
|
if ("print".equals(type)) {
|
||||||
|
String payload = webSocketMessageDTO.getPayload();
|
||||||
|
PrintRequest printRequest = JSONUtil.toBean(payload, PrintRequest.class);
|
||||||
|
PrintController bean = SpringUtil.getBean(PrintController.class);
|
||||||
|
|
||||||
|
|
||||||
|
// 处理打印任务
|
||||||
|
log.info("收到打印任务: {}, ", printRequest);
|
||||||
|
|
||||||
|
try {
|
||||||
|
bean.print(printRequest);
|
||||||
|
log.info("打印任务完成: {}", printRequest.getFileUrl());
|
||||||
|
|
||||||
|
Map<String,String> map = new HashMap<>();
|
||||||
|
map.put("status", "success");
|
||||||
|
map.put("msg", "");
|
||||||
|
|
||||||
|
webSocketMessageDTO.setType("RESPONSE");
|
||||||
|
webSocketMessageDTO.setPayload(JSONUtil.toJsonStr(map));
|
||||||
|
session.getBasicRemote().sendText(JSONUtil.toJsonStr(webSocketMessageDTO));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("打印失败: {}", printRequest.getFileUrl(), e);
|
||||||
|
// 发送打印失败消息
|
||||||
|
String errorMsg = e.getMessage();
|
||||||
|
if (errorMsg == null) {
|
||||||
|
errorMsg = "未知错误";
|
||||||
|
} else {
|
||||||
|
// 转义JSON特殊字符
|
||||||
|
errorMsg = errorMsg.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String,String> map = new HashMap<>();
|
||||||
|
map.put("status", "fail");
|
||||||
|
map.put("msg", errorMsg);
|
||||||
|
webSocketMessageDTO.setType("RESPONSE");
|
||||||
|
webSocketMessageDTO.setPayload(JSONUtil.toJsonStr(map));
|
||||||
|
|
||||||
|
session.getBasicRemote().sendText(JSONUtil.toJsonStr(webSocketMessageDTO));
|
||||||
|
}
|
||||||
|
} else if ("heartbeat_ack".equals(type)) {
|
||||||
|
// 心跳响应,可以记录最后一次心跳时间
|
||||||
|
log.debug("收到心跳响应");
|
||||||
|
}else if ("printerList".equals(type)) {
|
||||||
|
|
||||||
|
PrintService[] printServices = PrinterJob.lookupPrintServices();
|
||||||
|
Set<String> collect = Arrays.stream(printServices).map(PrintService::getName).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
List<String> collect1 = collect.stream().sorted().collect(Collectors.toList());
|
||||||
|
|
||||||
|
webSocketMessageDTO.setType("RESPONSE");
|
||||||
|
webSocketMessageDTO.setPayload(JSONUtil.toJsonStr(collect1));
|
||||||
|
session.getBasicRemote().sendText(JSONUtil.toJsonStr(webSocketMessageDTO));
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理消息失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClose
|
||||||
|
public void onClose(Session session, CloseReason closeReason) {
|
||||||
|
log.warn("WebSocket连接关闭: {}", closeReason.getReasonPhrase());
|
||||||
|
this.session = null;
|
||||||
|
// 安排重连任务
|
||||||
|
scheduleReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnError
|
||||||
|
public void onError(Session session, Throwable throwable) {
|
||||||
|
log.error("WebSocket连接发生错误", throwable);
|
||||||
|
this.session = null;
|
||||||
|
|
||||||
|
// 安排重连任务
|
||||||
|
scheduleReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接到WebSocket服务器
|
||||||
|
*/
|
||||||
|
private void connect() {
|
||||||
|
if (isConnecting || (session != null && session.isOpen())) {
|
||||||
|
return; // 已经连接或正在连接中
|
||||||
|
}
|
||||||
|
String tempUrl = serverUri+"?printerId="+printerId+"&apiKey="+apiKey;
|
||||||
|
|
||||||
|
isConnecting = true;
|
||||||
|
try {
|
||||||
|
log.info("正在连接到WebSocket服务器: {}", tempUrl);
|
||||||
|
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
|
||||||
|
// 设置连接超时时间
|
||||||
|
container.setDefaultMaxSessionIdleTimeout(60000);
|
||||||
|
container.connectToServer(this, new URI(tempUrl));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("连接到WebSocket服务器失败", e);
|
||||||
|
isConnecting = false;
|
||||||
|
// 连接失败,安排重连
|
||||||
|
scheduleReconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动心跳机制
|
||||||
|
*/
|
||||||
|
private void startHeartbeat() {
|
||||||
|
heartbeatExecutor.scheduleAtFixedRate(() -> {
|
||||||
|
if (session != null && session.isOpen()) {
|
||||||
|
try {
|
||||||
|
session.getBasicRemote().sendText("{\"type\":\"heartbeat\"}");
|
||||||
|
log.debug("发送心跳");
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("发送心跳失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 30, 30, TimeUnit.SECONDS);
|
||||||
|
log.info("心跳机制已启动");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安排重连任务
|
||||||
|
*/
|
||||||
|
private void scheduleReconnect() {
|
||||||
|
reconnectExecutor.schedule(() -> {
|
||||||
|
log.info("尝试重新连接到WebSocket服务器...");
|
||||||
|
connect();
|
||||||
|
}, 5, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭连接和资源
|
||||||
|
*/
|
||||||
|
@PreDestroy
|
||||||
|
public void shutdown() {
|
||||||
|
log.info("正在关闭WebSocket客户端...");
|
||||||
|
if (session != null) {
|
||||||
|
try {
|
||||||
|
session.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("关闭WebSocket连接失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reconnectExecutor.shutdownNow();
|
||||||
|
heartbeatExecutor.shutdownNow();
|
||||||
|
log.info("WebSocket客户端已关闭");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
// 应用启动后连接到WebSocket服务器
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,6 @@
|
|||||||
spring.application.name=goeingPrintServer
|
spring.application.name=goeingPrintServer
|
||||||
server.port=9090
|
server.port=9090
|
||||||
|
print.websocket.url=ws://127.0.0.1:8080/print-websocket
|
||||||
|
print.printer.id=123456
|
||||||
|
print.websocket.apiKey=519883ab-3677-ce4b-59ba-7263870d0a26
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user