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

news2024/12/27 10:35:17

之前对接的打印和导出是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("&", "&");
                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 握手
     */
    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
        LogUtils.WriteDebugLog("新客户端接入:" + conn.getRemoteSocketAddress());
        allSockets.add(conn);
    }

    /**
     * 断开连接
     * @param conn 连接
     * @param code 代码
     * @param reason 原因
     * @param remote 是否远程
     */
    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
        LogUtils.WriteDebugLog("客户端断开:" + conn.getRemoteSocketAddress());
        allSockets.remove(conn);
    }

    /**
     * 收到消息
     * @param conn 连接
     * @param message 消息
     */
    @Override
    public 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 异常
     */
    @Override
    public void onError(WebSocket conn, Exception ex) {
        LogUtils.WriteExceptionLog("发生错误:" + conn.getRemoteSocketAddress(),ex);
    }

    /**
     * 启动事件
     */
    @Override
    public 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="";

    @Override
    public 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
     */
    @Override
    public 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.coloradmin.cn/o/1273636.html

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

相关文章

Echarts大屏可视化_04 横向柱状图模块的引入和开发

模块的引入 1.寻找官方示例引入 ECharts官方实例入口 2.引入示例 ECharts 示例 可从这里直接进入 标题、提示信息、图例都不需要所以直接删掉 <div class"column"><div class"panel bar2"><h2>柱状图-技能掌握</h2><div cla…

项目动态 | 十一月重点上线项目集锦

武清联创商会 【应用场景】商协会资源对接服务平台&#xff1b; 【核心功能】 l 利用资源对接系统&#xff0c;用户可在平台内发布自己的人脉信息、个性化标签&#xff0c;通过对接获得收益&#xff0c;实现人脉增值&#xff1b; l 利用信息发布系统&#xff0c;用户可直观…

UEFI与ESKII源代码分析

这是一本未出版的电子书&#xff0c;是UEFI BIOS从业者的非常重要的参考书籍。需要的朋友可以联系我。

微服务实战系列之EhCache

前言 书接前文&#xff0c;继续深耕。上一篇博主对Redis进行了入门级介绍&#xff0c;大体知道了Redis可以干什么以及怎么使用它。 今日博主继续带着大家学习如何使用EhCache&#xff0c;这是一款基于Java的缓存框架。 微服务实战系列之Redis微服务实战系列之Cache微服务实战…

主成分分析例题 (多元统计分析期末复习)

例一 给定X的协差阵&#xff0c;对其进行主成分分析, &#xff08;1&#xff09;求出每个主成分的贡献率&#xff1b; &#xff08;2&#xff09;求出每个原始变量的信息提取率&#xff1b; 解&#xff1a;对于主成分分析的题&#xff0c;一般来说&#xff0c;题目给定一个协方…

mybatis关于namespace以及id以及Mapper接口命名的说明(了解)

1、建库建表 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIMARY KEY(emp_id) );INSERT INTO t_emp(emp_name,emp_salary) VALUES("tom",200.33); INSERT INTO…

使用Jetty编写RESTful接口

一、依赖 <!--Jetty服务器的核心依赖项&#xff0c;用于创建和管理服务器。--><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-server</artifactId><version>9.4.43.v20210629</version></dependency…

Linux scatterlist 详解

源码基于&#xff1a;Linux 5.4 约定&#xff1a; 芯片架构&#xff1a;ARM64内存架构&#xff1a;UMACONFIG_ARM64_VA_BITS&#xff1a;39CONFIG_ARM64_PAGE_SHIFT&#xff1a;12CONFIG_PGTABLE_LEVELS &#xff1a;3 0. 前言 之前在《Linux DMA... 零拷贝》博文分享了DMA 技…

程序员养生之道

程序员养生之道——如何保持健康的生活方式 摘要&#xff1a; 随着互联网行业的快速发展&#xff0c;越来越多的人选择从事程序员这个职业。然而&#xff0c;长时间的工作和高强度的压力容易导致程序员出现亚健康状况&#xff0c;如头发稀疏、视力下降、肥胖等问题。因此&#…

字节大佬整理测试用例编写规范

目录 1.1目的 1.2使用范围 二 测试用例编写原则 2.1系统性 2.2连贯性 2.3全面性 2.4正确性 2.5符合正常业务惯例 2.6仿真性 2.7容错性&#xff08;健壮性&#xff09; 三 测试用例设计方法 3.1 等价类划分法&#xff1a; 3.2 边界值分析法&#xff1a; 3.3 因果图…

python简单通讯录

代码&#xff1a; # 定义联系人类 class Contact:def __init__(self, name, phone, street, city, province, postcode):self.name nameself.phone phoneself.street streetself.city cityself.province provinceself.postcode postcodedef __str__(self):return f"…

shell编程系列(6)-使用Sort进行数据排序

文章目录 前言使用Sort命令文本排序sort命令的选项如下&#xff1a;基本排序对单个指定列进行排序对多个指定列进行排序删除重复的行 结语 前言 shell脚本通常用作一些自动化的操作&#xff0c;但是在有些场景下例如科研运算&#xff0c;有时候会产生大量的运算结果文件&#…

学习记录PCL-1 通过哈希表进行三维点云的虚拟格网划分

直接对整个场景的点云进行特征提取&#xff0c;效果很差&#xff0c;因此通过划分区域格网进行划分。格网划分有很多种方式&#xff0c;在这里尝试使用哈希表进行格网链接&#xff0c;后续通过在每个格网内基于点云特征进行提取。 参考博客&#xff1a; 点云侠的PCL 点云分块_p…

揭示堆叠自动编码器的强大功能 - 最新深度学习技术

简介 在不断发展的人工智能和机器学习领域&#xff0c;深度学习技术由于其处理复杂和高维数据的能力而获得了巨大的普及。在各种深度学习模型中&#xff0c;堆叠自动编码器[1]作为一种多功能且强大的工具脱颖而出&#xff0c;用于特征学习、降维和数据表示。本文探讨了堆叠式自…

影视网站影视介绍评论网站

基于Boostrap的响应式电影网站影视网站移动技术应用开发一、考核要求1、考核内容本课程的成绩主要依据平时表现、文档、答辩&#xff08;设计讲解、操作演示等&#xff09;等方面评定。运用所学知识&#xff0c;独立设计并开发一个影视介绍评论网站&#xff0c;具体要求如下&am…

凯旋泥巴佬正式全面亮相,Triumph TF 250-X

之前给大家曝光过凯旋将要进军越野车领域&#xff0c;并且发动机和车架都已经造出来了&#xff0c;还要去参加赛事想要获得比赛的荣誉和名次&#xff0c;就在今日凯旋的一台越野车TF 250-X正式亮相&#xff0c;售价9995美元。 这是凯旋真正意义上的第一台竞赛级越野车&#xff…

特征选择的方法:包裹法之递归特征消除

1.递归特征消除法的基本原理 递归特征消除法是一种贪婪的优化算法&#xff0c;致力于通过反复创建模型的方式找到性能最佳的特征子集。 首先将筛选的K个特征作为初始特征子集&#xff0c;开展机器学习计算得到每个特征的重要性&#xff0c;利用交叉验证方法得到初始特征子集的…

智慧水务系统在流域水环境规划中起到什么作用?

智慧水务系统在流域水环境规划中扮演着越来越重要的角色。作为一款集信息化、自动化、智能化、智慧化于一体的水务管理系统&#xff0c;智慧水务系统不仅能够提高水环境规划的效率&#xff0c;还能为水资源的保护和利用提供有力支持。 在流域水环境规划中&#xff0c;智慧水务系…

Windows10设置定时提醒

文章目录 Windows10设置定时提醒创建提醒文件新建文本文档修改文件编码和后缀双击测试 创建文件夹创建任务测试运行 Windows10设置定时提醒 创建提醒文件 新建文本文档 修改文件编码和后缀 双击测试 创建文件夹 创建任务 创建触发器 选择程序 测试运行 弹窗正常

16.Oracle数据库Row_number() over()函数排序使用方法

1.原始数据(部分) SELECT * FROM SCOTT.EMP ; 2.使用Row_number() over() 函数,排序 SELECT EMPNO,ENAME,SAL,DEPTNO,Row_number() over( order by sal) rs FROM SCOTT.EMP ; 根据工资排序并添加序号 3.使用Row_number() over() 函数,分组并排序 SELECT EMPNO,ENAME,SAL,DEPTN…