新增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
|
||||
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