打印元素绘制协议Java实现

我一直提倡的面向接口和约定编程,而打印元素绘制协议一直是我推荐的打印实现方式,我以前只是强调按打印元素绘制协议输出数据就行了,有实现程序按协议控制打印,说是可以用任何语言实现客户端程序而不影响打印业务,那么这次就用Java实现打印元素绘制协议,来感受一下按协议编程的魅力吧。

打印设计请参照打印设计

首先以前的M都由虚拟M层替代了,这个就是访问地址
在这里插入图片描述

然后实现Java调用虚拟M逻辑,客户端通过此逻辑调虚拟M拿到符合打印元素绘制协议的数据

package JRTPrintDraw.WebService;

import javax.net.ssl.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.HashMap;

import JRTPrintDraw.WebService.Parameters;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * 请求Webservice得到数据
 */
public class WebGetData {

    /**
     * 调用虚拟M方法得到数据
     *
     * @param Address   地址
     * @param ClassName 类名
     * @param FuncName  方法名
     * @param Param     参数
     * @param Session   会话
     * @return
     * @throws Exception
     */
    public static String GetData(String Address, String ClassName, String FuncName, Parameters Param, String Session) throws Exception {
        System.out.println("ClassName:" + ClassName);
        System.out.println("FuncName:" + FuncName);
        String result = "";
        DealNullPara(Param);
        String paraStr = "Method=GetData&ClassName=" + ClassName + "&FuncName=" + FuncName + "&Param=" + URLEncoder.encode(JRTPrintDraw.JsonDealUtil.Object2Json(Param), "UTF-8") + "&Session=" + URLEncoder.encode(Session, "UTF-8");

        try {
            //返回接受的数据
            result = GetHttpStr(Address, paraStr);
            //调用报错了
            if (!result.contains("<Response>")) {
                result = "<Response><SQLResult><SQL><FunRet></FunRet></SQL></SQLResult><RetVal>-1</RetVal><Error>" + result + "</Error><Node></Node><RowCount>0</RowCount></Response>";
            }
        } catch (Exception ex) {
            result += ",异常信息:" + ex.getMessage() + ",调用:" + ClassName + "," + FuncName + "," + Param + "," + Session;
        }
        return DealXmlToJson(result);
    }

    /**
     * 把xml处理成json串
     *
     * @param xmlStr
     * @return
     * @throws Exception
     */
    private static String DealXmlToJson(String xmlStr) throws Exception {
        System.out.println("返回串:" + xmlStr);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(new InputSource(new StringReader(xmlStr)));
        // 获得根节点
        Element rootElement = document.getDocumentElement();
        // 获得根节点下的所有子节点
        NodeList childs = rootElement.getChildNodes();
        HashMap dataMap = new HashMap();
        String ResultName = "";
        for (int i = 0; i < childs.getLength(); i++) {
            // 由于节点多种类型,而一般我们需要处理的是元素节点
            Node childNode = childs.item(i);
            // 元素节点就是非空的子节点,也就是还有孩子的子节点
            if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) childNode;

                dataMap.put(childElement.getNodeName(), childElement.getTextContent());
                //不是对象配置元素就忽略
                if (childElement.getNodeName().equals("Node")) {
                    ResultName = childElement.getTextContent() + "Result";
                }
            }
        }
        String Error = dataMap.get("Error").toString();
        if (!Error.isEmpty()) {
            System.out.println("异常:" + Error);
            throw new Exception(Error);
        }
        String ResType = dataMap.get("ResType").toString();
        System.out.println("数据串:" + dataMap.get(ResultName).toString());
        return dataMap.get(ResultName).toString();
    }


    /// <summary>
    /// 处理空参数
    /// </summary>
    /// <param name="Param"></param>
    private static void DealNullPara(Parameters Param) {
        if (Param.P0 == null) {
            Param.P0 = "";
        }
        if (Param.P1 == null) {
            Param.P1 = "";
        }
        if (Param.P2 == null) {
            Param.P2 = "";
        }
        if (Param.P3 == null) {
            Param.P3 = "";
        }
        if (Param.P4 == null) {
            Param.P4 = "";
        }
        if (Param.P5 == null) {
            Param.P5 = "";
        }
        if (Param.P6 == null) {
            Param.P6 = "";
        }
        if (Param.P7 == null) {
            Param.P7 = "";
        }
        if (Param.P8 == null) {
            Param.P8 = "";
        }
        if (Param.P9 == null) {
            Param.P9 = "";
        }
        if (Param.P10 == null) {
            Param.P10 = "";
        }
        if (Param.P11 == null) {
            Param.P11 = "";
        }
        if (Param.P12 == null) {
            Param.P12 = "";
        }
        if (Param.P13 == null) {
            Param.P13 = "";
        }
        if (Param.P14 == null) {
            Param.P14 = "";
        }
    }

    /**
     * 从http下载文本
     *
     * @param url  url
     * @param para 参数
     * @return 文本串
     * @throws Exception
     */
    private static String GetHttpStr(String url, String para) throws Exception {
        byte[] bytes = para.getBytes("UTF-8");

        //忽略证书
        if (url.contains("https://")) {
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }
            };

            // Install the all-trusting trust manager
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // Create all-trusting host name verifier
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };
        }

        URL u = new URL(url);
        HttpURLConnection http = (HttpURLConnection) u.openConnection();
        http.setAllowUserInteraction(true);
        http.setDoOutput(Boolean.TRUE);
        http.setDoInput(Boolean.TRUE);
        http.setUseCaches(false);
        http.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
        http.setInstanceFollowRedirects(false);
        http.setRequestMethod("POST");
        http.connect();

        OutputStream outputStream = http.getOutputStream();
        outputStream.write(bytes);
        outputStream.flush();
        outputStream.close();

        InputStream is = http.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder stringBuilder = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            stringBuilder.append(line + System.lineSeparator());
        }
        return stringBuilder.toString();
    }
}

然后实现打印元素绘制协议,这里把打印和绘图逻辑进行了分离,因为绘图逻辑后面还会给网站的在线打印预览用
在这里插入图片描述

在这里插入图片描述
按元素类型绘制
在这里插入图片描述

在这里插入图片描述

绘图与打印结合

package Monitor.Print;

import JRTPrintDraw.DrawConvert;
import JRTPrintDraw.DrawElement;
import JRTPrintDraw.JRTPrintDrawProtocol;
import JRTPrintDraw.JsonDealUtil;
import JRTPrintDraw.WebService.Parameters;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.MediaTray;
import java.awt.*;
import java.awt.print.*;
import java.util.ArrayList;
import java.util.List;

public class PrintProtocol implements Printable {
    /**
     * 纸张名称
     */
    private String PageName;

    /**
     * 打印句柄
     */
    private JRTPrintDrawProtocol printHandeler=null;

    /**
     * 得到打印机
     * @param printerName
     * @return
     */
    public static PrintService GetPrinter(String printerName) {

        DocFlavor psInFormat = DocFlavor.INPUT_STREAM.AUTOSENSE;
        HashPrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
        PrintService printService[] = PrintServiceLookup.lookupPrintServices(psInFormat, pras);
        PrintService myPrinter = null;
        //遍历所有打印机如果没有选择打印机或找不到该打印机则调用默认打印机
        for (PrintService printService2 : printService) {
            String svcName = printService2.toString();
            if (svcName.contains(printerName)) {
                myPrinter = printService2;
                break;
            }
        }
        if (myPrinter == null) {
            myPrinter = PrintServiceLookup.lookupDefaultPrintService();
            return myPrinter;
        }
        return myPrinter;
    }

    /**
     * 按打印元素绘制协议实现打印
     * @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) throws Exception{
        try {
            Parameters para=new Parameters();
            para.P0=rowids;
            para.P1=userCode;
            para.P2=paramList;
            para.P3=rowids;
            String json=JRTPrintDraw.WebService.WebGetData.GetData(connectString,className,funcName,para,"");
            System.out.println("打印数据:"+json);
            List<DrawElement> elementList= JsonDealUtil.Json2List(json,new DrawElement());
            System.out.println("转换List");
            // 通俗理解就是书、文档
            Book book = new Book();
            printHandeler=new JRTPrintDrawProtocol();
            int pageNum=printHandeler.JRTPrintDrawInit(elementList);
            System.out.println("页数:"+pageNum);
            // 获取打印服务对象
            PrinterJob job = PrinterJob.getPrinterJob();
            // 设置打印类
            job.setPageable(book);
            //设置成竖打
            PageFormat pf = new PageFormat();
            pf.setOrientation(PageFormat.PORTRAIT);
            boolean hasSetPaper=false;
            //控制打印机的数据
            if(elementList.get(0).PrintType.contains("PRINTER"))
            {
                DrawElement dr=elementList.get(0);
                //打印机名称
                String tPrinterName = elementList.get(0).PrintFlag;
                //选择打印机
                if(tPrinterName!=null&&!tPrinterName.isEmpty())
                {
                    PrintService printService=GetPrinter(tPrinterName);
                    job.setPrintService(printService);
                }

                //设置打印机其他参数
                if(dr.PrintType.equals("PRINTER"))
                {
                    //设置打印机宽度
                    int PrinterWidth = DrawConvert.ToInt32(dr.PrintWidth);
                    //设置打印机高度
                    int PrinterHeight = DrawConvert.ToInt32(dr.PrintHeight);
                    printHandeler.WriteLog("PRINTER得到纸张宽高:" + PrinterWidth + " " + PrinterHeight);
                    //页面名称
                    PageName = dr.DataField;
                    //停靠
                    String ReportLayout = dr.PrintAlignment;
                    printHandeler.WriteLog("PRINTER得打印机名称:" + tPrinterName);
                    //指定打印机送纸来源
                    int iPaperSource = DrawConvert.ToInt32(dr.PrintFont);
                    if (ReportLayout == "Landscape")
                    {
                        pf.setOrientation(PageFormat.LANDSCAPE);
                        printHandeler.WriteLog("PRINTER旋转纸张:Landscape");
                    }
                    //宽高大于0就控制
                    if(PrinterWidth>0&&PrinterHeight>0)
                    {
                        //通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。
                        Paper paper = new Paper();
                        // 设置纸张大小为 A4 大小(210 mm × 297 mm)
                        int width = PrinterWidth;
                        int height = PrinterHeight;
                        //旋转
                        if (ReportLayout == "Landscape") {
                            int tmp=width;
                            width=height;
                            height=tmp;
                        }
                        double margin = 0;
                        paper.setSize(width, height);
                        paper.setImageableArea(margin, margin, width - 2 * margin, height - 2 * margin);
                        pf.setPaper(paper);
                        hasSetPaper=true;

                    }
                }
            }
            if(hasSetPaper==false)
            {
                Paper paper = new Paper();
                // 设置纸张大小为 A4 大小(210 mm × 297 mm)
                int width = 794;
                int height = 1123;
                double margin = 0;
                paper.setSize(width, height);
                paper.setImageableArea(margin, margin, width - 2 * margin, height - 2 * margin);
                pf.setPaper(paper);
            }
            book.append(this, pf,pageNum);
            if(printFlag.contains("PrintPreview"))
            {
                System.out.println("打印设置");
                job.print();
            }
            else
            {
                System.out.println("打印");
                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;
        if(printHandeler!=null)
        {
            try {
                int drawOneRet=printHandeler.DrawOnePage(g2, pageIndex);
                System.out.println(pageIndex+":"+drawOneRet);
                return drawOneRet;
            }
            catch (Exception ex)
            {
                if(ex.getCause()!=null)
                {
                    printHandeler.WriteLog(ex.getCause().getMessage());
                }
                else
                {
                    printHandeler.WriteLog(ex.getMessage());
                }
                ex.printStackTrace();
                return 1;
            }
        }
        return 1;
    }
}

这样就实现了Java的打印层,只要按打印元素绘制协议打印的业务不需要改就能话环境执行了

C#的效果
在这里插入图片描述

Java的效果
在这里插入图片描述

打磨好之后再把导出Excel实现了就基本实现JRT的最终目标了,导出一样的实现的有导出协议,我一般不直接写死业务,到时候开发换Linux都没毛病了,实现可以用任何语言都行,为啥打印也有Java呢,因为成本,不可能客户端程序再用一套编程语言实现,增加维护和开发成本,虽然写的比C#丑陋很多,也得忍着把实现了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《opencv实用探索·八》图像模糊之均值滤波简单理解

1、前言 什么是噪声&#xff1f; 该像素与周围像素的差别非常大&#xff0c;导致从视觉上就能看出该像素无法与周围像素组成可识别的图像信息&#xff0c;降低了整个图像的质量。这种“格格不入”的像素就被称为图像的噪声。如果图像中的噪声都是随机的纯黑像素或者纯白像素&am…

【动态规划】LeetCode-91.解码方法

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

leetcode-160-相交链表(C语言实现)

题目&#xff1a; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;…

Leetcode226. 翻转二叉树

文章目录 题目介绍题目分析解题思路边界条件&#xff1a;节点为空时返回空子问题&#xff1a;交换左右子节点 整体代码 题目介绍 题目分析 题目要求我们将树中每个节点的左右子节点全部交换,最后返回交换后的树的根节点。 解题思路 这题是比较常见的递归&#xff0c;直接找边…

LangChain 18 LangSmith监控评估Agent并创建对应的数据库

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

最多不一定最好,只有适合的才是最好的!电脑的内存多大才是合理的

RAM&#xff0c;或称随机存取存储器&#xff0c;是最好的笔记本电脑和最好的电脑最重要的组成部分之一。硬盘驱动器&#xff08;HDD&#xff09;或固态驱动器&#xff08;SSD&#xff09;存储可以被视为电脑的长期内存&#xff0c;内存是其短期内存。内存可以跟踪后台运行的应用…

背包9讲系列2-完全背包问题

一、前言 又到周末了&#xff0c;这几天可以腾出时间来把背包系列的其他内容好好肝一肝&#xff0c;本次介绍的是完全背包问题&#xff0c;之前的系列内容请查看&#xff1a; 背包9讲系列1-01背包问题 二、完全背包 2.1 问题描述 有n个物品和一个容量为capacity的背包&…

误用STM32串口发送标志位 “USART_FLAG_TXE” “USART_FLAG_TC”造成的BUG

当你使用串口发送数据时是否出现过这样的情况&#xff1a; 1.发送时第一个字节丢失。 2.发送时出现莫名的字节丢失。 3.各种情况字节丢失。 1.先了解一下串口发送的流程图&#xff08;手动描绘&#xff09;&#xff1a; 可以假想USART_FLAG_TXE是用于检测"弹仓"&…

C++11——initializer_list

initializer_list的简介 initializer_list是C11新出的一个类型&#xff0c;正如类型的简介所说&#xff0c;initializer_list一般用于作为构造函数的参数&#xff0c;来让我们更方便赋值 但是光看这些&#xff0c;我们还是不知道initializer_list到底是个什么类型&#xff0c;…

关于标准库中的vector - (涉及迭代器失效,深浅拷贝,构造函数,内置类型构造函数,匿名对象)

目录 关于vector vector中的常见接口 vector常见接口的实现 迭代器失效 关于深浅拷贝 关于vector 关于vector的文档介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元…

零售数字化“逆熵”的6项原则和8种能力建设|ShopeX徐礼昭

作者&#xff1a;徐礼昭 来源&#xff1a;《三体零售逆熵法则》节选 旧的规则与秩序被打破&#xff0c;无序成为常态 新时代洪流裹挟冲击着传统零售 无序带来的“熵增”侵蚀企业生命 所有人都在不确定性中寻找确定 数字化如何助力企业铸就「反熵增」神器&#xff1f; 如何…

【交换排序 简单选择排序 堆排序 归并排序】

文章目录 交换排序简单选择排序堆排序归并排序 交换排序 冒泡排序的算法分析&#xff1a; 冒泡排序最好的时间复杂度是O&#xff08;n&#xff09;冒泡排序最好的时间复杂度是O&#xff08;n平方&#xff09;冒泡排序平均时间复杂度为O&#xff08;n的平方&#xff09;冒泡排…

spring boot定时器实现定时同步数据

文章目录 目录 文章目录 前言 一、依赖和目录结构 二、使用步骤 2.1 两个数据源的不同引用配置 2.2 对应的mapper 2.3 定时任务处理 总结 前言 一、依赖和目录结构 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifa…

无线物理层安全学习

文章目录 3.17到3.203.85到3.88 3.17到3.20 3.85到3.88

#计算机毕业设计#微信小程序#社区团购#小猪优选

小猪优选 简介 类似于美团优选&#xff0c;多多买菜等线上平台。 是一套社区团购的项目&#xff0c;是依托真实社区的一种区域化、小众化、本地化、网络化的团购形式&#xff0c;同事也是一种生鲜商品流通的新零售模式。 背景&#xff1a; 社区团购是真实具名团体的一种互…

电脑提示mfc100u.dll缺失如何解决?分享有效的5个解决方法

由于各种原因&#xff0c;电脑可能会出现一些问题&#xff0c;其中之一就是电脑提示mfc100u.dll的错误。这个问题可能会导致电脑无法正常运行某些程序或功能。为了解决这个问题&#xff0c;我将分享验证有效的五个修复方法&#xff0c;帮助大家恢复电脑的正常运行。 首先&#…

SALib敏感性分析入门实践笔记

1. 敏感性分析 敏感性分析是指从定量分析的角度研究有关因素发生某种变化对某一个或一组关键指标影响程度的一种不确定分析技术。 其实质是通过逐一改变相关变量数值的方法来解释关键指标受这些因素变动影响大小的规律。 敏感性因素一般可选择主要参数&#xff08;如销售收入、…

Redis数据结构之跳表

跳表是一种有序的数据结构&#xff0c;它通过在每个节点中维持多个指向其他节点的指针&#xff0c;从而达到快速访问节点的目的。其核心思想就是通过建立多级索引来实现空间换时间。 在Redis中&#xff0c;使用跳表作为Zset的一种底层实现之一&#xff0c;这也是跳表在Redis中的…

IO延迟引起的虚拟机故障排查

vmware 虚拟机连上之后总感觉非常卡&#xff0c;查看CPU 内存资源使用率是正常的。 message 日志有cpu卡住的报错 NMI watchdog: BUG: soft lockup - CPU#8 stuck for 23s! [container-31451:45878]下面分析是什么导致的服务器cpu卡住。 1、打开prometheus&#xff0c;观察服务…

CSS新手入门笔记整理:CSS图片样式

图片大小 语法 width:像素值; height:像素值; 图片边框&#xff1a;border 语法 边框&#xff1a;宽度值 样式值 颜色值&#xff1b; border:1px solid red; 图片对齐 水平对齐&#xff1a;text-align 语法 text-align:取值; 属性值 说明 left 左对齐(默认值) cent…