打印元素绘制协议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 managerSSLContext sc = SSLContext.getInstance("SSL");sc.init(null, trustAllCerts, new java.security.SecureRandom());HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());// Create all-trusting host name verifierHostnameVerifier 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*/@Overridepublic 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#丑陋很多,也得忍着把实现了
相关文章:

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

js 处理编译器html 包含img的标签并设置width
var imgElements document.getElementsByTagName(img); for (let imgElement of imgElements) { //1.如果有style属性,去掉style属性中的width属性和height属性 if (imgElement.hasAttribute(st…...

同旺科技 分布式数字温度传感器 -- OPC Servers测试
内附链接 1、数字温度传感器 主要特性有: ● 支持PT100 / PT1000 两种铂电阻; ● 支持 2线 / 3线 / 4线 制接线方式; ● 支持5V~17V DC电源供电; ● 支持电源反接保护; ● 支持通讯波特率1200bps、2…...

php获取过去一段的时间范围
在 PHP 中获取过去一周的时间,你可以使用 DateTime 和 DateInterval 类。这里是一个示例代码,展示如何获取从今天起算的过去一周(7天)的日期: // 当前日期 $today new DateTime();// 设置日期为一周前 $oneWeekAgo …...

张三、如花、王婆带你了解Shell命令以及运行原理
文章目录 前言概述张三、王婆、如花的故事Shell命令以及运行原理后记 前言 Linux严格意义上说的是一个操作系统,我们称之为“核心(kernel)“ ,但我们一般用户,不能直接使用kernel。而是通过kernel的“外壳”程序&…...

redis介绍和安装、redis普通连接和连接池、字符串类型、hash类型、列表类型列表类型
文章目录 redis介绍和安装安装步骤启动,连接 redis普通连接和连接池普通连接连接池 redis字符串类型redis hash类型redis列表类型 redis介绍和安装 redis 什么? 数据库就是个存数据的地方:只是不同数据库数据组织,存放形式不一样…...

集成开发环境PyCharm的使用【侯小啾python领航计划系列(三)】
集成开发环境 PyCharm 的使用【侯小啾python领航计划系列(三)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…...

Flink(九)【时间语义与水位线】
前言 2023-12-02-20:05,终于写完啦,最近状态不错。刚写完又收到了她的消息哈哈哈哈,开心。 再去全力打拼一次,奋战一场,就算最后打了败仗也无所谓,至少你留下了足迹。 《解忧杂货店》 1、时间语义 …...

torch中的随机数种子
如何在torch生成随机数时,设置随机种子,要求每次调用生成的随机数都一样 在 PyTorch 中,可以使用 torch.manual_seed(seed) 函数设置随机种子,以确保每次运行代码时生成的随机数都一样。 以下是一个示例代码,展示了如…...

C 标准库 <math.h>
C 标准库 <math.h> C <math.h>头文件声明了一组函数来执行数学运算,例如:sqrt()计算平方根,log()查找数字的自然对数,等等。 math.h 头文件定义了各种数学函数和一个宏。在这个库中所有可用的函数都带有一个 double…...

一篇带你串通数据结构
文章目录 导论数据结构的定义数据结构在计算机科学中的重要性为什么学习数据结构很重要 1、基本概念1.1、数据、数据元素和数据项的概念1.2、数据对象与数据结构的关系1.3、逻辑结构与物理结构 2、线性结构2.1、数组2.2、链表2.3、栈2.4、队列 3、非线性结构3.1、树3.2、图 4、…...

网络篇---第九篇
系列文章目录 文章目录 系列文章目录前言一、说说TCP/IP四层网络模型二、说说域名解析详细过程?三、 IP 地址分为几类,每类都代表什么,私网是哪些?四、说说TCP 如何保证可靠性的?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家…...

Python基础学习快速入门
文章目录 Number变量String字符串Def函数Class类List列表Tuple元组Dictionary字典Set集合值与引用类型if条件控制Loop循环 Number变量 python直接赋值,不需要定义变量类型。不需要**,逗号结尾符 使用print**直接进行输出 #赋值 a 1.0 print(a)a 7 print(a)p…...

C语言-预处理与库
预处理、动态库、静态库 1. 声明与定义分离 一个源文件对应一个头文件 注意: 头文件名以 .h 作为后缀头文件名要与对应的原文件名 一致 例: 源文件:01_code.c #include <stdio.h> int num01 10; int num02 20; void add(int a, in…...

王道数据结构课后代码题p40 9.给定一个带表头结点的单链表,写出算法 : 按递增次序输出单链表中各结点的数据元素并释放结点 (c语言代码实现)
本题代码如下(有注释) void delete_min(linklist* head) {while ((*head)->next ! NULL)//循环到只剩下头节点{lnode* pre *head;//pre为元素最小结点的前驱结点指针lnode* p (*head)->next;//p为工作指针lnode* q;//指向被删除的结点while (p-…...

对系统的 Go 版本进行升级
方法一 直接升级系统的 Go 版本 注意以下操作仅适用于:amd64 架构的 Centos 系统。如果需要适配其他架构,需要自行编写代码实现。 手动执行: # 显示当前版本 go version # 查看环境变量 cat /etc/profile # 进入 go 的安装目录,…...

【从删库到跑路 | MySQL总结篇】事务详细介绍
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】🎈 本专栏旨在分享学习MySQL的一点学习心得,欢迎大家在评论区讨论💌 目录 一、事务…...

七牛云1024创建节-赛后有感
距离比赛结束已经过去快半个月时间,七牛云又发起了有奖征文的活动,正好借此机会记录一下自己参加这次比赛的经历,感受和一些比赛的心得。 如何了解到的比赛信息 其实我很早就开始关注七牛云了,最早是在今年二三月的时候…...

CSS 选择器优先级,!important 也会被覆盖?
目录 1,重要性2,专用性3,源代码顺序 CSS 属性值的计算过程中。其中第2步层叠冲突只是简单说明了下,这篇文章来详细介绍。 层叠冲突更广泛的被称为 CSS选择器优先级计算。 为什么叫层叠冲突,可以理解为 CSS 是 Cascadi…...

关于src别名的配置之tsconfig.json配置
tsconfig.json {"compilerOptions": {"baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录"paths": { //路径映射,相对于baseUrl"/*": ["src/*"] }} } ① "baseUrl": &…...

Mybatis如何执行批量操作
文章目录 Mybatis如何执行批量操作使用foreach标签 使用ExecutorType.BATCH如何获取生成的主键 Mybatis如何执行批量操作 使用foreach标签 foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach标签的属性主要有item,index&…...

LeetCode 1094. 拼车:优先队列
【LetMeFly】1094.拼车:优先队列 力扣题目链接:https://leetcode.cn/problems/car-pooling/ 车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向) 给定整数 capacity 和一个数组…...

项目开发维护技术文档(总结梳理)
目录 一、项目背景 二、架构设计 1.技术栈 2.架构图 3.代码结构 三、模块划分 1.用户模块 2.商品模块 四、开发规范 1.命名规范 2.代码格式 3.版本控制 五、部署流程 1.环境要求 2.部署流程 六、问题解决 1.数据库连接异常 2.Redis缓存失效 七、参考资料 项…...

01_学习使用javax_ws_rs_上传文件
文章目录 1 前言2 Maven 依赖3 上传接口4 如何解析 MultipartFormDataInput5 结语 1 前言 使用 Spring MVC 来处理文件上传,想必是大家耳熟能详的了,如下代码: ResponseBody PostMapping("/upload") public String upload(Request…...

MFC 发布CLXHHandleEngine动态库1.0.0.0版本
第一版发布以下功能,此项目使用VS2013创建,项目配置包括Unicode的Mdd,md与多字节版本: //MFC Grid表格 #include "../MFCGridCtrl/GridCtrl.h" //使用AES与Base64加密解密可以与java中的AES加解密衔接 //AES加密解密 #include &q…...

MicroPython 基于microdot框架搭建网页服务器
MicroPython 基于microdot框架搭建网页服务器 简介简单demo 简介 Microdot是一个极简的Python web框架,灵感来自于Flask,它被设计用来运行在资源有限的系统上,如微控制器。它运行在标准的Python和MicroPython上。 API参考microdot 资源下载m…...

FL Studio21.2汉化永久中文语言包
FL Studio21.2这款软件在国内被广泛使用,因此又被称为"水果"。它提供音符编辑器,可以针对作曲者的要求编辑出不同音律的节奏,例如鼓、镲、锣、钢琴、笛、大提琴、筝、扬琴等等任何乐器的节奏律动。此外,它还提供了方便快…...

Glide结合OkHttp保证短信验证接口携带图形验证码接口返回Cookie值去做网络请求
一、实现效果 二、步骤 注意:仅展示核心部分代码 1、导入依赖 api com.github.bumptech.glide:glide:4.10.0 kapt com.github.bumptech.glide:compiler:4.10.0 api com.squareup.okhttp3:okhttp:3.11.0 api com.squareup.okhttp3:logging-interceptor:3.11.02、自…...

怎样用Ajax提交from表单并接收其中的json数据
怎样用Ajax提交表单并接收其中的json数据 需求:实现点击按钮后,数据以表单形式提交至服务器,并接收来自服务器的返回数据。过程中页面不刷新。 AJAX 不是新的编程语言,而是一种使用现有标准的新方法。AJAX 是与服务器交换数据并…...

【动态规划】LeetCode-746LCR 088.使用最小花费爬楼梯
🎈算法那些事专栏说明:这是一个记录刷题日常的专栏,每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目,在这立下Flag🚩 🏠个人主页:Jammingpro 📕专栏链接&…...