JRT和检验共用的打印层实现

之前对接的打印和导出是C#实现的,如果要完全Java化就需要用Java把打印元素绘制协议用Java实现,这次介绍实现主体搭建,最终使JRT达到完全信创和跨平台目标。到这篇后,所有的Java难题都解决完毕,几天到几周之内就可以把打印元素绘制协议完全实现,实现看着很快。至此可以一马平川的用Java了,没有M,一样可以领先,哈哈哈哈,框架完全体快出来了。

首先抽取消息处理接口

package Monitor.Msg;import org.java_websocket.WebSocket;/*** 抽取的处理前端传来的消息接口,不同类型的消息处理实现此接口从而实现不同的功能*/
public interface IMessageDeal {/*** 处理消息* @param socket 套接字,可以获得id,发送消息给socket* @param message 约定#分割的第一位描述消息类型,收到的消息内容* @return 是否继续往后传递消息,true是,false否*/public boolean DealMessage(WebSocket socket, String message);
}

然后实现打印消息处理

package Monitor.Msg;
import Monitor.Util.LogUtils;
import javafx.scene.control.Alert;
import org.java_websocket.WebSocket;/*** 处理打印消息*/
public class MessagePrintDeal implements Monitor.Msg.IMessageDeal {/*** 处理消息* @param socket 套接字,可以获得id,发送消息给socket* @param message 约定#分割的第一位描述消息类型,收到的消息内容* @return 是否继续往后传递消息,true是,false否*/public boolean DealMessage(WebSocket socket, String message){LogUtils.WriteDebugLog("识别以print#开头的消息");//识别打印消息if (message.split("#")[0].equals("print")){LogUtils.WriteDebugLog("确定为打印消息,准备处理");int index = message.indexOf('#');String msg = message.substring(index + 1);String[] arrMsg = msg.split("@");//报告打印消息直接处理,不驱动exe,提高速度if (arrMsg.length > 5 && (!arrMsg[4].contains("PDF#")) && (arrMsg[0].equals("iMedicalLIS://0") || arrMsg[0].equals("iMedicalLIS://1")) && (!arrMsg[4].equals("ReportView"))){String cmdLine = msg.substring(14);String[] tmpStrings = cmdLine.split((char)64+"");String printFlag = tmpStrings[0];String connectString = tmpStrings[1].replace("&", "&amp;");String rowids = tmpStrings[2];String userCode = tmpStrings[3];//PrintOut:打印  PrintPreview打印预览String printType = tmpStrings[4];//参数模块名称(LIS工作站,DOC医生,SELF自助,OTH其它)String paramList = tmpStrings[5];String clsName = "";String funName = "";if (tmpStrings.length >= 8){clsName = tmpStrings[6];funName = tmpStrings[7];}//没传报告主键退出if (rowids == "" && printType != "ReportView"){javafx.application.Platform.runLater(()->{Alert alert = new Alert(Alert.AlertType.INFORMATION);alert.setTitle("提示");alert.setHeaderText("打印参数异常");alert.setContentText("未传入报告主键");alert.showAndWait();});return true;};String ip = "";String hostName = "";String mac = "";paramList = paramList + "^HN" + hostName + "^IP" + ip + "^MAC" + mac;//printFlag  0:打印所有报告 1:循环打印每一份报告if (printFlag.substring(0, 1).equals("0")){Monitor.Print.PrintProtocol reportPrint = new Monitor.Print.PrintProtocol(rowids, userCode, paramList, connectString, printType, clsName, funName);}else{String[] tmpRowids = rowids.split((char)94+"");for (int i = 0; i < tmpRowids.length; i++){rowids = tmpRowids[i];if (rowids != ""){Monitor.Print.PrintProtocol reportPrint = new Monitor.Print.PrintProtocol(rowids, userCode, paramList, connectString, printType, clsName, funName);}}}}return false;}LogUtils.WriteDebugLog("不是打印消息,传递消息链");return true;}
}

然后实现Websockt对接消息、

package Monitor.Websocket;import Monitor.Util.LogUtils;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import Monitor.Msg.IMessageDeal;import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;public class WebsocketServer extends WebSocketServer {/*** 存所有套接字*/private static List<WebSocket> allSockets = new ArrayList<>();/*** 处理消息链对象*/public List<IMessageDeal> LinkList=new ArrayList<>();/*** 构造函数* @param port*/public WebsocketServer(int port) {super(new InetSocketAddress(port));Monitor.Util.LogUtils.WriteDebugLog("启动Websockt在"+port);}/*** 打开链接* @param conn 连接* @param handshake 握手*/@Overridepublic void onOpen(WebSocket conn, ClientHandshake handshake) {LogUtils.WriteDebugLog("新客户端接入:" + conn.getRemoteSocketAddress());allSockets.add(conn);}/*** 断开连接* @param conn 连接* @param code 代码* @param reason 原因* @param remote 是否远程*/@Overridepublic void onClose(WebSocket conn, int code, String reason, boolean remote) {LogUtils.WriteDebugLog("客户端断开:" + conn.getRemoteSocketAddress());allSockets.remove(conn);}/*** 收到消息* @param conn 连接* @param message 消息*/@Overridepublic void onMessage(WebSocket conn, String message) {System.out.println("收到消息:" + conn.getRemoteSocketAddress() + ": " + message);LogUtils.WriteDebugLog("#WS消息服务准备调用消息链...");try{if (LinkList.size() > 0){for(IMessageDeal deal:LinkList){LogUtils.WriteDebugLog("#WS调用:" + deal.getClass().getName() + "...");boolean ret = deal.DealMessage(conn, message);LogUtils.WriteDebugLog("#WS调用:" + deal.getClass().getName() + "结束...");//返回false不传递消息了if (ret == false){LogUtils.WriteDebugLog("#WS消息链不继续传递消息...");break;}}}LogUtils.WriteDebugLog("#WS消息服务调用消息链结束...");}catch (Exception ex){LogUtils.WriteExceptionLog("#WS消息服务调用消息链异常", ex);}}/*** 发生错误* @param conn 连接* @param ex 异常*/@Overridepublic void onError(WebSocket conn, Exception ex) {LogUtils.WriteExceptionLog("发生错误:" + conn.getRemoteSocketAddress(),ex);}/*** 启动事件*/@Overridepublic void onStart() {}}

包装log4j

package Monitor.Util;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class LogUtils {//调试日志static final Logger loggerDebug = LoggerFactory.getLogger("Debug");/*** 书写调试日志* @param message 日志内容*/public static void WriteDebugLog(String message){loggerDebug.error(message);}/*** 书写异常日志* @param message 描述* @param exception 异常*/public static void WriteExceptionLog(String message, Exception exception){loggerDebug.error(message, exception);}}

实现exe程序

package Monitor;import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import Monitor.Websocket.WebsocketServer;
import Monitor.Msg.MessagePrintDeal;import java.net.URL;
import java.nio.file.Paths;public class Main extends Application {// 创建一个TextArea控件TextArea textInfo = new TextArea();//日志路径String logPath="";@Overridepublic void start(Stage primaryStage) throws Exception{String projectPath = System.getProperty("user.dir");Monitor.Util.LogUtils.WriteDebugLog("项目路径:" + projectPath);URL url = Main.class.getResource("");String bashPath = url.getPath();Monitor.Util.LogUtils.WriteDebugLog("程序路径:"+bashPath);//日志路径logPath= Paths.get(projectPath,"logs","Debug.log").toString();// 设置文本自动换行textInfo.setWrapText(true);Monitor.Util.LogUtils.WriteDebugLog("启动Websockt");WebsocketServer server=new WebsocketServer(8082);MessagePrintDeal printDeal=new MessagePrintDeal();server.LinkList.add(printDeal);server.start();SplitPane splitPane = new SplitPane();splitPane.setOrientation(Orientation.VERTICAL);// 刷新日志按钮Button btnRefresh = new Button("刷新日志");btnRefresh.setOnMouseClicked(e -> {RefreshLogs();});btnRefresh.setPrefHeight(30);// 清空日志按钮Button btnDelete = new Button("清空日志");btnDelete.setOnMouseClicked(e -> {DeleteLogs();});btnDelete.setPrefHeight(30);HBox top  = new HBox(20,btnRefresh,btnDelete);top.setPadding(new Insets(5,5,5,5));top.setPrefHeight(40);top.setMaxHeight(40);HBox bottom = new HBox(textInfo);textInfo.prefWidthProperty().bind(bottom.widthProperty());RefreshLogs();//VBox left = new VBox(new Label("left"));//VBox center = new VBox(new Label("center"));//VBox right = new VBox(new Label("right"));//SplitPane splitPane1 = new SplitPane();//splitPane1.getItems().setAll(left,center,right);splitPane.getItems().addAll(top, bottom);Scene scene = new Scene(splitPane);//primaryStage.setScene(scene);//Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));//primaryStage.setTitle("JRTClient");primaryStage.setOnCloseRequest(event -> {try {server.stop();}catch (Exception ex){}});primaryStage.setScene(scene);primaryStage.setMaximized(true);primaryStage.show();}/*** 刷新日志*/public void RefreshLogs(){try {textInfo.setText(Monitor.Util.TxtUtil.ReadTextStr(logPath));}catch (Exception ex){}}/*** 清空日志*/public void DeleteLogs(){try {Monitor.Util.TxtUtil.WriteText2File(logPath,"");textInfo.setText("");}catch (Exception ex){}}public static void main(String[] args) {launch(args);}
}

实现打印画图类

package Monitor.Print;import java.awt.*;
import java.awt.print.*;public class PrintProtocol implements Printable {/*** 按打印元素绘制协议实现打印* @param rowids 数据主键* @param userCode 用户* @param paramList 参数* @param connectString 连接串* @param printFlag 打印标识* @param className 调用类名* @param funcName 方法名称*/public PrintProtocol(String rowids, String userCode, String paramList, String connectString, String printFlag, String className, String funcName){try {// 通俗理解就是书、文档Book book = new Book();// 设置成竖打PageFormat pf = new PageFormat();pf.setOrientation(PageFormat.PORTRAIT);// 通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。Paper paper = new Paper();// 设置纸张大小为 A4 大小(210 mm × 297 mm)double width = 827;double height = 1169;double margin = 10.0;paper.setSize(width, height);paper.setImageableArea(margin, margin, width - 2 * margin, height - 2 * margin);pf.setPaper(paper);book.append(this, pf,2);// 获取打印服务对象PrinterJob job = PrinterJob.getPrinterJob();// 设置打印类job.setPageable(book);job.print();} catch (PrinterException e) {e.printStackTrace();}}/*** 安逸画图* @param graphics* @param pageFormat* @param pageIndex* @return* @throws PrinterException*/@Overridepublic int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {// 转换成Graphics2D 拿到画笔Graphics2D g2 = (Graphics2D) graphics;// 设置打印颜色为黑色g2.setColor(Color.black);//打印起点坐标double x = pageFormat.getImageableX();double y = pageFormat.getImageableY();if(pageIndex==0) {//设置打印字体(字体名称、样式和点大小)(字体名称可以是物理或者逻辑名称)Font font = new Font("宋体", Font.BOLD, 14);// 设置字体g2.setFont(font);//字体高度float heigth = font.getSize2D();g2.drawString("Java打印测试", (float) 10, 10);font = new Font("宋体", Font.BOLD, 12);// 设置字体g2.setFont(font);// 字体高度heigth = font.getSize2D();g2.drawString("张联珠", (float) 10, 60);g2.drawString("1890075****", (float) 10, 90);g2.drawString("张联珠", 10, 120);g2.drawString("0947809", 120, 120);font = new Font("宋体", Font.BOLD, 12);g2.setFont(font);heigth = font.getSize2D();g2.drawString("湖南长沙", 10, 150);g2.drawString("pageIndex:" + pageIndex, 10, 180);return PAGE_EXISTS;}else if(pageIndex==1) {//设置打印字体(字体名称、样式和点大小)(字体名称可以是物理或者逻辑名称)Font font = new Font("宋体", Font.BOLD, 14);// 设置字体g2.setFont(font);//字体高度float heigth = font.getSize2D();g2.drawString("Java打印测试", (float) 10, 10);font = new Font("宋体", Font.BOLD, 12);// 设置字体g2.setFont(font);// 字体高度heigth = font.getSize2D();g2.drawString("张联珠", (float) 10, 60);g2.drawString("18900752521", (float) 10, 90);g2.drawString("张联珠", 10, 120);g2.drawString("0947809", 120, 120);font = new Font("宋体", Font.BOLD, 12);g2.setFont(font);heigth = font.getSize2D();g2.drawString("湖南长沙", 10, 150);g2.drawString("第2页" , 10, 180);return PAGE_EXISTS;}else{return NO_SUCH_PAGE;}}
}

测试
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/185549.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(二进制、八进制、十进制、十六进制)的进制转换

整型有4种进制形式&#xff1a; 1.十进制&#xff1a; 都是以0-9这九个数字组成&#xff0c;不能以0开头。 2.二进制&#xff1a; 由0和1两个数字组成。 3.八进制&#xff1a; 由0-7数字组成&#xff0c;为了区分与其他进制的数字区别&#xff0c;开头都是以0开始。 4.十六进制…

聚类算法的算法原理

聚类算法是机器学习中常用的一种无监督学习方法&#xff0c;其主要目标是将数据集划分为具有相似特征的组或簇。这种算法在数据挖掘、模式识别、社交网络分析等领域有着广泛的应用。聚类算法的核心思想是通过计算数据点之间的相似度或距离&#xff0c;将相似的数据点聚集在一起…

WordPress 粘贴图片上传插件

找了很久&#xff0c;发现一款不错的插件&#xff0c;允许我们直接粘贴图片文件并且上传到媒体库。以前的插件上传后媒体库不会显示&#xff0c;这个要显示。 启用后编辑器会有一个图标&#xff0c;如果开启&#xff0c;那么久可以截图后直接粘贴了。 学习资料源代码&#xf…

TR转发路由器测评—云企业网实现跨地域跨VPC的网络互通测评实战【阿里云产品测评】

文章目录 一.转发路由器 Transit Router 测评1.1 准备阶段1.2 本文测评收获1.3 什么是云企业网实例、转发路由器实例和云数据传输服务 二.使用云企业网实现跨地域跨VPC的网络互通2.2 **测试连通性**2.3 网络拓扑如下&#xff1a; 心得&#xff1a;总结&#xff1a; 声明&#x…

基于SpringBoot房屋租赁系统

摘 要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&#xff0c;成本低等优点。 因此&#xff0c;构建符…

JSON.stringify方法详解 后端接受JSON数据格式

1、方法定义&#xff1a;JSON.stringify(value, replacer, space) 参数说明&#xff1a; value&#xff1a;js对象 replacer&#xff1a;替换对象&#xff0c;可以是一个方法、对象或数组&#xff0c;将value按照替换规则展示。 space&#xff1a;填充参数&#xff0c;可以是数…

Python排序算法大比拼:快速排序 VS 归并排序

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 快速排序和归并排序是两种常见的排序算法&#xff0c;在Python中有着重要的应用。本文将深入探讨这两种算法的原理和实现&#xff0c;并提供丰富的示例代码来说明它们的工作方式。 快速排序算法 def quicksort…

NSSCTF第13页(3)

[FSCTF 2023]巴巴托斯&#xff01; 看见个输入路径&#xff0c;打了半天没进去&#xff0c;php伪协议也打不进去&#xff0c; 用dirsearch扫一下 看了半天才看出来&#xff0c;那串英文 Access Denied! I love FSCTF Browser 是要用FSCTF浏览器&#xff0c;改一下ua头就行了…

数字图像处理(实践篇)十二 基于小波变换的图像降噪

目录 一 基于小波变换的图像降噪 &#xff08;1&#xff09;小波变换基本理论 &#xff08;2&#xff09;小波分析在图像处理中的应用 &#xff08;3&#xff09;小波变换原理 &#xff08;4&#xff09;小波降噪原理 &#xff08;5&#xff09;小波降噪算法的实现 &…

vsVode C++开发远程虚拟机工程配置

在使用VS Code进行C/C的开发过程中&#xff0c;有三个至关重要的配置文件&#xff0c;分别是 tasks.json, launch.json 和 c_cpp_properties.json 1. tasks.json tasks.json 是在 vscode 中辅助程序编译的模块&#xff0c;可以代你执行类似于在命令行输入 “gcc hello.c -o h…

解决webpack打包生成gz格式css/js文件没法在nginx使用的问题--全网唯一正确

本文绝对是全网解决这个问题唯一正确的文章&#xff0c;没有之一&#xff01; 很多人都说开启nginx gzip压缩&#xff0c;这些人完全是胡说八道&#xff01;你们到底懂不懂叫gzip压缩啊&#xff1f;&#xff01; 不信你就试试&#xff0c;如果css/js只有gz文件&#xff0c;ng…

排序分析(Ordination analysis)及R实现

在生态学、统计学和生物学等领域&#xff0c;排序分析是一种用于探索和展示数据结构的多元统计技术。这种分析方法通过将多维数据集中的样本或变量映射到低维空间&#xff0c;以便更容易理解和可视化数据之间的关系。排序分析常用于研究物种组成、生态系统结构等生态学和生物学…

中伟视界:AI盒子中的报警预录像功能能解决什么问题?实现原理是怎样的?

现代社会智能安防已成为各行各业的重要一环&#xff0c;而AI盒子中的报警预录像功能更是智能安防的一大利器。这一功能能够解决很多安防方面的难题&#xff0c;其实现原理更是技术创新的体现。 首先&#xff0c;让我们来看看AI盒子中的报警预录像功能能解决哪些问题。在传统的安…

Prosys OPC Client连接OPC DA

Prosys OPC Client连接OPC DA Prosys OPC 客户端将帮助排除 OPC 连接故障并测试 OPC 服务器。 您可以读写数据、浏览服务器以及导出和导入地址空间。 OPC 客户端轻巧、快速且易于使用。 支持 OPC DA 1.0a 和 OPC DA 2.05a 官方地址: https://www.prosysopc.com/products/opc-…

《开箱元宇宙》:Madballs 解锁炫酷新境界,人物化身系列大卖

你是否曾想过&#xff0c;元宇宙是如何融入世界上最具代表性的品牌和名人的战略中的&#xff1f;在本期的《开箱元宇宙》 系列中&#xff0c;我们与 Madballs 的战略顾问 Derek Roberto 一起聊聊 Madballs 如何在 90 分钟内售罄 2,000 个人物化身系列&#xff0c;以及是什么原…

4.7-容器网络之host和none

这一节我们来看一下docker中的另外两种网络&#xff0c;host和none。 docker network inspect none 于是就看到Containers, 里面包含了一个test1 表示这个容器连接到了none。

陈嘉庚慈善践行与卓顺发的大爱传承

陈嘉庚慈善践行&#xff0c;了解陈嘉庚后人与卓顺发的大爱传承。 2023年11月25日,卓顺发太平绅士以及陈家后人在分享他们对慈善领域见解的过程中,特别强调了慈善在促进社会和谐以及推动社会进步方面的关键作用。同时,他们深入探讨了如何在当今社会中继续传扬和实践家国情怀以及…

清理docker Build Cache缓存文件

使用docker构建镜像&#xff0c;发现docker的overlay2文件会越来越大。 使用命令查看docker系统占用资源&#xff1a; docker system df 可以看到已经占用了26.7GB&#xff0c;清理这个缓存 docker builder prune 再次查看&#xff0c;已经没有缓存了&#xff0c;清理成功。 …

Linux基础操作二:Linux系统介绍

1、系统启动过程 Linux系统的启动过程并不是大家想象中的那么复杂&#xff0c;其过程可以分为5个阶段&#xff1a; 内核的引导。运行 init。系统初始化。建立终端 。用户登录系统。 1.1、内核引导 当计算机打开电源后&#xff0c;首先是BIOS开机自检&#xff0c;按照BIOS中…

固态继电器的分类:揭秘热门趋势

固态继电器(SSR)已成为现代电子和自动化系统不可或缺的一部分&#xff0c;与传统电磁继电器相比具有众多优势。随着技术的进步&#xff0c;SSR的分类不断发展&#xff0c;催生了令人兴奋的趋势和创新。在本文中&#xff0c;我们将探讨SSR分类的最新趋势&#xff0c;阐明该领域的…