HTML5服务器推送事件(Server-sent-event)

HTML5服务器推送事件(Server-sent-event) 在前端开发中,实现界面推送的方式,这里大概总结下三种方式 轮询(ajax),比较耗费服务器资源。COMET方式(COMET 技术并不是 HTML 5 ) websocket 双向数据推送,灵活,功能强大 Server-sent-event(简称SSE),单项数据推送(Server-sent Events 规范是 HTML 5 规范的一个组成部分) 这里我们只讨论SSE SSE的本质:严格地说,HTTP协议无法做到服务器主动推送信息。但是有一种变通的发光法,就是服务器向客户端声明,接下来要发送的是流信息,也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断的发送过来。这是客户端不会关闭连接,会一直等待服务器发过来的数据流,视频播放就是这样的例子。本质上这种通信就是以流信息的方式,完成一次用时很长的下载。 SSE就是利用这种机制,使用流信息想浏览器推送信息。它基于HTTP协议,除了IE/Edge,其他浏览器都支持 闲谈 在Web开发中,浏览器和服务器之间使用请求/响应的交互模式。浏览器发出请求,服务器根据请求来生成响应。这种交互方式,服务器端产生数据变化后不能及时的通知给浏览,只能在浏览器下次请求的时候,才能获取(对于某些对数据实时性要求很高的应用,这种延迟是不能接受的)。 使用浏览器原生的EventSource对象的一个比较大的问题是IE并不支持(为实现在IE上COMET或轮询,第二种使用polyfill技术) SSE的客户端API部署在EventSource对象上,使用之前检测浏览器是否支持SSE if(typeof(EventSource)!=="undefined") { // 浏览器支持 Server-Sent // 一些代码..... } else { // 浏览器不支持 Server-Sent.. } var source = new EventSource(url); // url可以在当前网址同域,也可以跨域,跨域时可以指定第二个参数withCredentials 表示是否一起发送Cookies > > EventSource的readyState 表明连接的当前状态,该属性只读 > > * 0: 相当于常量EventSource.CONNECTIONG 表示连接还未建立,或者断线正在重连 > * 1:相当于常量EventSource.OPEN 表示连接已经建立,可以接受数据 > * 2:相当于常量EventSource.CLOSED 表示连接已断,且不会重连 ### Server-sent Events {#toc_2} > Server-sent Events 规范是 HTML 5 规范的一个组成部分,该规范比较简单,主要由两部分组成: > > 第一部分:服务器端与浏览器之间的通讯协议 > > 第二部分:浏览器端可以提供JavaScript中使用EventSource对象。 > > 通讯协议是基于纯文本的简单协议 > > 服务器端响应的内容类型为:text/event-stream,响应文本内容可以看成是一个事件流,有不同的事件组成。 > > 每个事件由类型和数据两个部分组成,同时每个事件可以有一个可选的标识符。不同事件的内容之间通过仅包含回车符和换行符的空行来分隔。每个事件的数据可能由多行组成。 > > 清单1 > > > ``` `data: first event data: second event id: 100 event: myevent data: third event id: 101 : this is a comment data: fourth event data: fourth event continue ` 每个事件之间通过空行来分隔。对于每行来说,冒号(:)前面表示的该行的类型,冒号后面则是对应的值。 ...

2020年8月19日 · 8 分钟 · 天边的星星

adb常用命令

adb常用命令 1.adb devices , 获取设备列表及设备状态(adb -s 设备号 其他指令 adb -s devicel install xxx.apk) 2.adb get-state , 获取设备的状态 3.adb install 用于安装(此时需要用 -r 参数来重新安装。) 4.adb uninstall 用于卸载(adb uninstall 后面带的是应用的包名,而不是应用名。adb uninstall -k 表示保留数据) 5.adb shell pm list packages –f (查看系统所有应用的包名) 6.adb push 命令将PC机上的文件推到 DLT-RK3288 机器上; 7.adb pull 命令将DLT-RK3288机器上的文件拉到PC机上; { 例如: adb push d:/new.txt /sdcard/ 将D盘下new.txt文件 推到内部存储器 adb pull /sdcard/new.txt d:\ 将DLT-RK3288 内部存储器根目录下的new.txt 拉到D盘 } adb shell pm list package Package Manager , 可以用获取到一些安装在 Android 设备上得应用信息 -s:列出系统应用 -f:列出应用包名及对应的apk名及存放位置 9.adb shell { 通过adb shell 命令,就可以进入设备或者模拟器的shell环境了,在这个Linux shell中,我们就可以执行各种Linux命令了。 如果只想执行一条shell命令,就可以采用:adb shell [shell_command],在实际使用中,经常与grep或findstr一起使用,起到过滤作用,查看自己需要的关键信息。 常见命令: 如 ls, cd, rm, mkdir, touch, pwd, cp, mv, ifconfig, netstat, ping, ps, top等,进入adb shell即可执行,与linux相似 } 10.adb logcat { 一.在cmd窗口查看手机的Log日志 `有时候我们在手机程序上的日志要在其他地方调试,然后要看里面的Log日志。在cmd窗口中输入如下命令: //格式1:打印默认日志数据 ...

2020年8月13日 · 4 分钟 · 天边的星星

Spring boot 自定义处理404 500等

Spring boot 自定义处理404 500等 有时候我们会遇到一些问题,需要我们自定义一些异常,例如404、403、502、500等,我们这里就说说Springboot 修改自定义这些。 处理方式一 我们重写ErrorController接口,重写handleError方法 `import javax.servlet.http.HttpServletRequest; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MainsiteErrorController implements ErrorController{ @RequestMapping("/error") public ModelAndView handleError(HttpServletRequest request,HttpServletResponse response){ //获取statusCode:401,404,500 //Integer statusCode = (Integer) request.getAttribute(“javax.servlet.error.status_code”); Integer statusCode =response.getStatus(); ModelAndView model = new ModelAndView(); if(statusCode == 401){ model.setViewName(“401.html”); }else if(statusCode == 404){ model.setViewName(“404.html”); }else if(statusCode == 403){ model.setViewName(“403.html”); }else{ model.setViewName(“500.html”); } return model; } @Override public String getErrorPath() { return “/error”; } ...

2020年8月12日 · 2 分钟 · 天边的星星

Gitea 安装配置及使用

Gitea 安装配置 在很多时候,我们希望有自己的git仓库管理,把我们隐私的一点点工程,放在里面。大家也可以去使用目前网上免费的,例如 github、gitee 、gitlab、 coding.net、gogs、gitea等 Centos 安装Gitea 下载gitea wget -O gitea https://dl.gitea.io/gitea/1.12.1/gitea-1.12.1-linux-amd64 下载下来的gitea是没有 执行权限的,我们需要给他执行权限 chmod a+x gitea 复制gitea到 /usr/log/bin 方便我们之间执行 cp gitea /usr/local/bin/ 执行 启动 gitea web 根据gitea 页面信息,进行初始化配置,配置最后所在文件地址 cat /usr/local/bin/custom/conf/app.ini 如果需要后台运行 使用 nohup gitea >/dev/null 2>&1 & 命令 完成 开心的使用Gitea吧 通过 ps -ef |grep gitea |grep -v “grep”|wc -l 查询是否运行 返回1 表示运行 通过 ps -ef |grep gitea |grep -v “grep” 查询具体的执行信息

2020年7月7日 · 1 分钟 · 天边的星星

PDF转图片

PDF转图片 在开发过程中,我们遇到PDF 转图片的需求,这里主要介绍下Java(Apache pdfbox) Java Apache PdfBox使用 首先我们要引入Apache Pdfbox的包 gradle compile ‘org.apache.pdfbox:pdfbox:2.0.14’ maven <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.14</version> </dependency> > > 接下来几行代码搞定 > > ``` ` import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; public class App { public static void main(String[] args) { Long currentTimeMillis = System.currentTimeMillis(); File dir = new File("."); File[] filesList = dir.listFiles(); if (filesList != null) { for (File file : filesList) { if (file.isFile() && getFileExtension(file.getName()).equalsIgnoreCase("pdf")) { convert(file); } } } long diff = System.currentTimeMillis() - currentTimeMillis; System.out.print(diff); } private static String getFileExtension(String fileName) { if (fileName == null || fileName.equals("")) return "undefined"; int dotIndex = fileName.lastIndexOf("."); return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1); } private static void convert(File sourceFile) { try { String destinationDir = sourceFile.getName().replace(".pdf", "") + "/"; // converted images from pdf document are saved here File destinationFile = new File(destinationDir); if (!destinationFile.exists()) { boolean fileCreated = destinationFile.mkdir(); if (fileCreated) System.out.println("Folder Created -> "+ destinationFile.getAbsolutePath()); } if (sourceFile.exists()) { System.out.println("Images copied to Folder: "+ destinationFile.getName()); PDDocument document = PDDocument.load(sourceFile); PDPageTree pdPageTree = document.getDocumentCatalog().getPages(); System.out.println("Total files to be converted -> "+ pdPageTree.getCount()); PDFRenderer pdfRenderer = new PDFRenderer(document); String fileName = sourceFile.getName().replace(".pdf", ""); int pageNumber = 1; for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage image = pdfRenderer.renderImageWithDPI(page, 150, ImageType.RGB); File outputFile = new File(destinationDir + fileName +"_"+ pageNumber +".jpg"); System.out.println("Image Created -> "+ outputFile.getName()); ImageIO.write(image, "jpg", outputFile); pageNumber++; } document.close(); System.out.println("Converted Images are saved at -> "+ destinationFile.getAbsolutePath()); } else { System.err.println(sourceFile.getName() +" File not exists"); } } catch (Exception e) { e.printStackTrace(); } } } ` 这里主要使用了BufferedImage与ImageIO输出图片,通Pdfbox获取到PDF的内容 ...

2020年6月30日 · 2 分钟 · 天边的星星

MySql函数使用

select DATE_FORMAT(NOW(),’%Y-%m-%d %T’) — 日期格式化 2020-06-30 11:03:26 select DATE_FORMAT(NOW(),’%Y-%c’) — 日期格式化 2020-6 select YEAR(NOW()) — 获取年2020 select DAY(NOW()) — 获取日30 select FLOOR(25.96) — 向下取整 25 select UNIX_TIMESTAMP(‘2020-06-30’) — 获取时间戳 1593446400 select CONCAT(‘zhang’,’-‘,’dong’,’-‘,’ling’) — 字符串拼接zhang-dong-ling select MOD(89,9) — 取余 8

2020年6月30日 · 1 分钟 · 天边的星星

Spring boot 集成ElasticSearch

Spring boot 集成ElasticSearch * [第一步Spring boot集成ELasticSearch][2] * [第二步Spring boot中配置ElasticSearch][3] * [第三步 创建操作的实体Bean(我创建的是UserItemBean)][4] * [第四步 使用ElasticSearch的API进行测试][5] Spring boot 集成ElasticSearch 第一步Spring boot集成ELasticSearch `<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> &lt;dependency&gt; &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt; &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt; &lt;scope&gt;test&lt;/scope&gt; &lt;exclusions&gt; &lt;exclusion&gt; &lt;groupId&gt;org.junit.vintage&lt;/groupId&gt; &lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt; &lt;/exclusion&gt; &lt;/exclusions&gt; &lt;/dependency&gt; &lt;dependency&gt; &lt;groupId&gt;com.alibaba&lt;/groupId&gt; &lt;artifactId&gt;fastjson&lt;/artifactId&gt; &lt;version&gt;1.2.68&lt;/version&gt; &lt;/dependency&gt; </dependencies> ` > > Spring boot集成ElasticSearch主要依赖 > > ``` `spring-boot-starter-data-elasticsearch ` 这里需要大家特别注意自己使用的ElasticSearch的版本 是否和自己的版本一致 我这里是使用的最新的ElasticSearch 7.8.0 需要配置版本 &lt;properties&gt; &lt;java.version&gt;1.8&lt;/java.version&gt; &lt;elasticsearch.version&gt;7.8.0&lt;/elasticsearch.version&gt; &lt;/properties&gt; ### 第二步Spring boot中配置ElasticSearch {#toc_2} > 创建一个<mark>ElasticSearchConfig</mark>的类,配置在下ElasticSearch的高级客户端api > > ``` `import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Elasticsearch 配置 */ @Configuration public class ElasticSearchConfig { @Bean public RestHighLevelClient restHighLevelClient(){//配置rest客户端 RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("192.168.1.187", 9200, "http"))); return client; } } ` 注意:这里可以配置多个ElasticSearch 只需要创建多个HttpPost即可 ...

2020年6月28日 · 4 分钟 · 天边的星星

window postMessage使用Demo

使用window.open进行postmessage处理 打开新页面和监听界面的界面 `&lt;!DOCTYPE html> &lt;html lang="en"> &lt;head> &lt;meta charset="UTF-8"> &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"> &lt;title>Document&lt;/title> &lt;/head> 我是监听界面 &lt;body> &lt;script> window.onload = function(){ console.log("onload finish"); if(window.addEventListener){ console.log("onload addEventListener"); window.addEventListener('message', function (e) { console.log("addEventListener我监听到了"); // if (e.data.act == 'response') { // alert(e.data.msg.answer); // } else { // alert('未定义的消息: ' + e.data.act); // } console.log(e.data); }); }else{ window.attachEvent('onmessage', function (e) { console.log("attachEvent我监听到了"); // if (e.data.act == 'response') { // alert(e.data.msg.answer); // } else { // alert('未定义的消息: ' + e.data.act); // } console.log(e.data); }); } } var popup = window.open("indexopen.html"); popup.onload = function(){ // popup.postMessage("hello there!", "*"); console.log("popup 设置监听"); popup.addEventListener('message', function (e) { console.log("popup addEventListener我监听到了"); console.log(e.data); },false); popup.mydataFunction = function(){ console.log("自定义的函数!"); } } &lt;/script> &lt;/body> &lt;/html>` 子界面及发送postmessage界面 ...

2020年6月21日 · 2 分钟 · 天边的星星

ELK日志分析系统搭建

ELK 是Elasticsearch, Logstash,Kibana三个组件的首字母组合,这种方案最初的做法是:使用Logstash 去服务上采集日志文件, 然后做一些过滤处理后发送给 Elasticsearch, 在Elasticsearch中创建相应的索引,由Kibana提供统计分析的页面访问。但是Logstash 本身资源消耗较大,如果把它放到业务系统的服务器上会对系统造成不小的影响,一般的做法采用beats来替代(beats是一个更轻量级的收集器),参考如下图-1,此外也会有在数据量比较大时引入消息队列来环节组件压力。 详细的关于各组件的介绍建议参考Elastic 提供的官方文档 (图-1) (图-2) 本文将基于上图-2的架构来介绍ELK日志系统的搭建。由于环境限制,这里各组件均部署在同一服务器上。 1)搭建elasticsearch elasticsearch的下载安装配置在所有组件中相对是最复杂的,但是它依然可以很简单的按照如下几个步骤顺利完成: ① 官网下载地址 :https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.1.1-linux-x86_64.tar.gz ② 解压之后配置 elasticsearch-7.1.1/config/elasticsearch.yml 文件,如下 [][1] # ---------------------------------- Cluster ----------------------------------- # 指定集群名 cluster.name: customer-service # ------------------------------------ Node ------------------------------------ # 在集群名为customer-service 的集群下的 node-1 节点 node.name: node-1 # ---------------------------------- Network ----------------------------------- # 开启本质之外的网络访问 network.host: 0.0.0.0 # --------------------------------- Discovery ---------------------------------- # 定义初始主机点 cluster.initial_master_nodes: ["node-1"] ```<figure class="wp-block-image"> [![复制代码](https://common.cnblogs.com/images/copycode.gif)][1]</figure> ③ 启动elasticsearch&nbsp; (处于安全考虑 elasticsearch 只能非root用户启动,需要将elasticsearch解压文件切换所属用户)&nbsp; 解压路径下 ./bin/elasticsearch ...

2020年6月20日 · 2 分钟 · 天边的星星

Itext html转PDF,解决中文不显示与样式问题

`package com.zdltech.test.pdf; import com.lowagie.text.pdf.BaseFont; import org.xhtmlrenderer.pdf.ITextFontResolver; import org.xhtmlrenderer.pdf.ITextRenderer; import java.io.*; public class PDFUtils6 { /** * 获取对应pageName的html内容(生产环境java -jar直接run) */ private static String getHtmlByPageName2(String filePath) throws IOException { // /BOOT-INF/classes/templates/dashboard.html // 返回读取指定资源的输入流 InputStream is = new FileInputStream(new File(filePath)); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String s = ""; StringBuffer sb = new StringBuffer(); while ((s = br.readLine()) != null) { sb.append(s).append("\n"); } return sb.toString(); } /** * 将HTML转成PD格式的文件。html文件的格式比较严格 * @param htmlFile * @param pdfFile * @throws Exception */ // &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> public static void html2pdf(String htmlFile, String pdfFile) throws Exception { // step 1 String url = new File(htmlFile).toURI().toURL().getPath(); System.out.println(url); // step 2 OutputStream os = new FileOutputStream(pdfFile); ITextRenderer renderer = new ITextRenderer(); String result = getHtmlByPageName2(url); // System.out.println(result.substring(1)); System.out.println(result); renderer.setDocumentFromString(result); // renderer.setDocumentFromString(result.substring(1)); // renderer.setDocumentFromString(getXmlString()); // renderer.setDocument(url); // step 3 解决中文支持 ITextFontResolver fontResolver = renderer.getFontResolver(); if("linux".equals(getCurrentOperatingSystem())){ fontResolver.addFont("/Users/jason/Desktop/test/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); }else{ fontResolver.addFont("/Users/jason/Desktop/test/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); fontResolver.addFont("/Users/jason/Desktop/test/simkai.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); } renderer.layout(); renderer.createPDF(os); os.close(); System.out.println("create pdf done!!"); } public static String getCurrentOperatingSystem(){ String os = System.getProperty("os.name").toLowerCase(); System.out.println("---------当前操作系统是-----------" + os); return os; } public static String getXmlString() { String xmlString="&lt;!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" + "&lt;html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "&lt;head>\n" + " &lt;meta charset=\"UTF-8\"/>\n" + " &lt;title>Hello World&lt;/title>\n" + "\t&lt;style>\n" + "\t table.table-separate th{\n" + " font-weight:bold;\n" + " font-size:14px;\n" + " border-top:1px solid #F3EDE9 !important;\n" + " }\n" + " table.table-separate td{\n" + " padding: 13px 0;\n" + " font-weight:100;\n" + " }\n" + " .table-separate td.tit{\n" + " background-color: #f4f9fe;\n" + " font-weight:normal;\n" + " padding:22px 0;\n" + " width:15%;\n" + " }\n" + " .table-separate td.cont{\n" + " text-align: left;\n" + " padding:16px 22px;\n" + " width:85%;\n" + " line-height:175%;\n" + " }\n" + " .table-separate.no-border th{\n" + " border:none;\n" + " text-align: left;\n" + " }\n" + " .table-separate.no-border td{\n" + " text-align: left;\n" + " border:none;\n" + " }\n" + "\t@page {\n" + "\tsize:210mm 297mm;//纸张大小A4\n" + "\tmargin: 0.25in;\n" + "\t-fs-flow-bottom: \"footer\";\n" + "\t-fs-flow-left: \"left\";\n" + "\t-fs-flow-right: \"right\";\n" + "\tborder: thin solid black;\n" + "\tpadding: 1em;\n" + "\t}\n" + "\t#footer {\n" + "\tfont-size: 90%; font-style: italic;\n" + "\tposition: absolute; top: 0; left: 0;\n" + "\t-fs-move-to-flow: \"footer\";\n" + "\t}\n" + "\t#pagenumber:before {\n" + "\tcontent: counter(page);\n" + "\t}\n" + "\t#pagecount:before {content: counter(pages);\n" + "\t}\n" + "\ttable {\n" + "\t\t\tborder-collapse: collapse;\n" + "\t\t\ttable-layout: fixed;\n" + "\t\t\tword-break:break-all;\n" + "\t\t\tfont-size: 10px;\n" + "\t\t\twidth: 100%;\n" + "\t\t\ttext-align: center;\n" + "\t}\n" + "\ttd {\n" + "\t\tword-break:break-all;\n" + "\t\tword-wrap : break-word;\n" + "\t}\n" + "\t&lt;/style>\n" + "\t&lt;/head>\n" + "&lt;body style = \"font-family: SimSun;\">\n" + "&lt;div id=\"footer\" style=\"\"> Page &lt;span id=\"pagenumber\"/> of &lt;span id=\"pagecount\"/> &lt;/div>\n" + "&lt;div id=\"main\">\n" + " &lt;div style=\"max-width:600px;margin:0 auto;padding:10px;\">\n" + " &lt;div style=\"text-align: center; padding: 5mm 0;\">\n" + " &lt;div style=\"font-weight: bold; font-size: 30px;\"> HI Fudi&amp;More&lt;/div>\n" + " &lt;div> THANK YOU FOR SHOPPING WITH Fudi&amp;More!&lt;/div>\n" + " &lt;/div>\n" + " &lt;div style=\"border: 1px solid black; background-color: #f8f8f8; padding: 4mm;\">\n" + " &lt;div style=\"font-size: 17px; font-weight: bold; border-bottom: 1px solid black; padding-bottom: 5mm;\"> ORDER DETAILS&lt;/div>\n" + " &lt;div style=\"padding-top: 10px;\">\n" + " &lt;div>&lt;strong>Order:&nbsp;&lt;/strong>D-8C2Y Placed on 29/09/2019 10:04&lt;/div>\n" + " &lt;div>&lt;strong>Carrier:&nbsp;&lt;/strong>Delivery&lt;/div>\n" + " &lt;div>&lt;strong>Payment:&nbsp;&lt;/strong>Cash Payment&lt;/div>\n" + " &lt;/div>\n" + " &lt;/div>\n" + " &lt;div style=\"margin-top: 4mm;\">\n" + " &lt;table class=\"table-separate\" cellpadding=\"0\" cellspacing=\"0\" style=\"max-width:600px;margin:0 auto;padding:10px;\">\n" + " &lt;thead>\n" + " &lt;tr style=\"text-align: center; height: 40px;\">\n" + " &lt;th style=\"width: 90px; background-color: #f8f8f8; border-top: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;\">\n" + " Reference\n" + " &lt;/th>\n" + " &lt;th colspan=\"2\" style=\"background-color: #f8f8f8; border-top: 1px solid black; border-right: 1px solid black;\">Product&lt;/th>\n" + " &lt;th style=\"width: 110px; background-color: #f8f8f8; border-top: 1px solid black; border-right: 1px solid black;\">Unit price&lt;/th>\n" + " &lt;th style=\"width: 80px; background-color: #f8f8f8; border-top: 1px solid black; border-right: 1px solid black;\">Quantity&lt;/th>\n" + " &lt;th style=\"width: 90px; background-color: #f8f8f8; border-top: 1px solid black; border-right: 1px solid black;\">Total price&lt;/th>\n" + " &lt;/tr>\n" + " &lt;/thead>\n" + " &lt;tbody>\n" + " &lt;tr style=\"text-align: center; \">\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;\">\n" + " Main\n" + " &lt;/td>\n" + " &lt;td colspan=\"2\"\n" + " style=\"border-top: 1px solid black; border-bottom:1px solid black; border-right: 1px solid black; text-align: left; padding: 010px;\">\n" + " SweetSour Chicken\n" + " &lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro; 7.00&lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">1&lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro; 7.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;tr style=\"text-align: center; \">\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;\">\n" + " Main\n" + " &lt;/td>\n" + " &lt;td colspan=\"2\"\n" + " style=\"border-top: 1px solid black; border-bottom:1px solid black; border-right: 1px solid black; text-align: left; padding: 010px;\">\n" + " Black Bean Stir Fry\n" + " &lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro; 9.00&lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">1&lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro; 9.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;tr style=\"text-align: center; \">\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;\">\n" + " Pizzas\n" + " &lt;/td>\n" + " &lt;td colspan=\"2\"\n" + " style=\"border-top: 1px solid black; border-bottom:1px solid black; border-right: 1px solid black; text-align: left; padding: 010px;\">\n" + " Test Design Your Own 8\" Pizza\n" + " &lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro; 6.00&lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">1&lt;/td>\n" + " &lt;td style=\"border-top: 1px solid black; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro; 6.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;/tbody>\n" + " &lt;tfoot>\n" + " &lt;tr style=\"text-align: center; height: 8mm;\">\n" + " &lt;td colspan=\"5\"\n" + " style=\"text-align: right; width: 90px; background-color: #f8f8f8; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; padding: 0 10px;\">\n" + " Item:\n" + " &lt;/td>\n" + " &lt;td style=\"background-color: #f8f8f8; border-bottom: 1px solid black; border-right: 1px solid black;\">3&lt;/td>\n" + " &lt;/tr>\n" + " &lt;tr style=\"text-align: center; height: 8mm;\">\n" + " &lt;td colspan=\"5\"\n" + " style=\"text-align: right; width: 90px; background-color: #f8f8f8; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; padding: 0 10px;\">\n" + " Subtotal:\n" + " &lt;/td>\n" + " &lt;td style=\"background-color: #f8f8f8; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro;24.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;tr style=\"text-align: center; height: 8mm;\">\n" + " &lt;td colspan=\"5\"\n" + " style=\"text-align: right; width: 90px; background-color: #f8f8f8; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; padding: 0 10px;\">\n" + " Deliver Fee:\n" + " &lt;/td>\n" + " &lt;td style=\"background-color: #f8f8f8; border-bottom: 1px solid black; border-right: 1px solid black;\">+&euro;2.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;tr style=\"text-align: center; height: 8mm;\">\n" + " &lt;td colspan=\"5\"\n" + " style=\"text-align: right; width: 90px; background-color: #f8f8f8; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; padding: 0 10px;\">\n" + " Discount:\n" + " &lt;/td>\n" + " &lt;td style=\"background-color: #f8f8f8; border-bottom: 1px solid black; border-right: 1px solid black;\">-&euro;0.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;tr style=\"text-align: center; height: 8mm;\">\n" + " &lt;td colspan=\"5\"\n" + " style=\"text-align: right; width: 90px; background-color: #f8f8f8; border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; padding: 0 10px;\">\n" + " Total:\n" + " &lt;/td>\n" + " &lt;td style=\"background-color: #f8f8f8; border-bottom: 1px solid black; border-right: 1px solid black;\">&euro;24.00&lt;/td>\n" + " &lt;/tr>\n" + " &lt;/tfoot>\n" + " &lt;/table>\n" + " &lt;/div>\n" + " &lt;div>\n" + " &lt;div style=\"border: 1px solid black; background-color: #f8f8f8; padding:5mm; margin-top: 5mm;\">\n" + " &lt;div style=\"font-size: 17px; font-weight: bold; border-bottom: 1px solid black; padding-bottom: 15px;\"> DELIVERY ADDRESS&lt;/div>\n" + " &lt;div style=\"padding-top: 10px;\">\n" + " &lt;div>&lt;strong>guan&lt;/strong> &#9742; &lt;strong>13656690321&lt;/strong>&lt;/div>\n" + " &lt;div> 1024/ Edenhall,ModelFarmRd,Cork,爱尔兰,A 2048&lt;/div>\n" + " &lt;/div>\n" + " &lt;/div>\n" + " &lt;/div>\n" + " &lt;div style=\"font-size: 13px;\">&lt;p>You can review your order and download your invoice from the \"&lt;a target=\"_blank\"\n" + " href=\"http://www.fudiandmore.ie/#/FudiIndex/Order1\">Order\n" + " history&lt;/a>\"section of your customer account by clicking \"&lt;a target=\"_blank\" href=\"http://www.fudiandmore.ie/#/FudiIndex/Personalcenter1\">My\n" + " account&lt;/a>\" on ourshop.&lt;/p>&lt;/div>\n" + " &lt;hr style=\"border-width: 5px;\"/>\n" + " &lt;div> Fudi,More powered by &lt;a target=\"_blank\" href=\"http://www.fudiandmore.ie\">A2BLiving&lt;/a>&lt;/div>\n" + " &lt;/div>\n" + "&lt;/div>\n" + "&lt;/body>\n" + "&lt;/html>"; StringBuffer stringBuffer=new StringBuffer(); return xmlString; } public static void main(String&#91;] args) { // String htmlFile = "/home/lbj/sign.jsp"; // String pdfFile = "/home/lbj/sign.pdf"; String htmlFile = "/Users/jason/Desktop/test/aaa/aaa.html"; // String htmlFile = "/Users/jason/Desktop/test/pdftest.html"; String pdfFile = "/Users/jason/Desktop/test/pdftest30.pdf"; try { PDFUtils6.html2pdf(htmlFile, pdfFile); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } ` `&lt;dependency> &lt;groupId>com.itextpdf&lt;/groupId> &lt;artifactId>itextpdf&lt;/artifactId> &lt;version>5.5.9&lt;/version> &lt;/dependency> &lt;dependency> &lt;groupId>com.itextpdf.tool&lt;/groupId> &lt;artifactId>xmlworker&lt;/artifactId> &lt;version>5.5.9&lt;/version> &lt;/dependency> &lt;dependency> &lt;groupId>com.itextpdf&lt;/groupId> &lt;artifactId>itext-asian&lt;/artifactId> &lt;version>5.2.0&lt;/version> &lt;/dependency> &lt;dependency> &lt;groupId>org.xhtmlrenderer&lt;/groupId> &lt;artifactId>flying-saucer-pdf-itext5&lt;/artifactId> &lt;version>9.0.3&lt;/version> &lt;/dependency>` `&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> &lt;html lang="en" xmlns="http://www.w3.org/1999/xhtml"> &lt;head> &lt;meta charset="UTF-8" /> &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> &lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> &lt;meta http-equiv="X-UA-Compatible" content="IE=9" /> &lt;meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> &lt;style> @page { size: A4; margin: 0; } body{ zoom:0.8; transform: scale(0.8); } .fontSize16 { font-size: 16px !important; } .cllor3B7 { color: #3B76B5 !important; } .posAbsolute { position: absolute !important; } .posRelative { position: relative !important; } .textAlignLeft { text-align: left } .textAlignRight { text-align: right } .voucher_body { /* position: relative;width: 954px;height: 424px;margin-left: -477px;margin-top: -212px;top: 50%;left: 50%; */ position: relative; } .voucher { position: relative; width: 954px; height: 424px; background-size: 82% 82% !important; z-index: 999; } .printBtn { position: absolute; left: 50%; margin-left: -100px !important; } .voucherPrint { position: fixed; width: 954px; height: 424px; top: 50%; left: 50%; transform: translate(-50%, -50%); background: initial !important; z-index: 99999; display: none; } .voucherPDF { position: fixed; width: 954px; height: 424px; top: 50%; left: 50%; transform: translate(-50%, -50%); background: initial !important; z-index: 999999; display: none; } .openBg { background: url('https://www.zchfax.com/data/temp/0_15723304043.jpg') no-repeat !important; } .openBg2 { background: url('/Users/jason/Desktop/test/aaa/open@2x.png') no-repeat !important; } .financingBg { background: url('financing@2x.png') no-repeat !important; } .trasterBg { background: url('transter@2x.png') no-repeat !important; } .vouStatus { left: 124px; top: 65px; } .vouStatus>span { color: #EA2A41 !important; } .voucher .voNumber { right: 25%; top: 50px; color: #EA2A41 !important; } .voucher .voNumber2 { left: 120px; bottom: 16px; color: #EA2A41 !important; } .voucherContent .gsName { top: 98px; } .voucherContent .skName { top: 98px; } .voucherDer { width: 296px; } .voucherContent .openDer { width: 288px; } .voucherContent .shNumber { top: 129px; } .voucherContent .shNumber2 { top: 129px; } .voucherContent .moneyNumber { top: 169px; } .moneyALL { right: 23.5%; top: 184px; height: 30px; width: 296px; } /* width: 100%; height: 100%; */ .monyList { width: 100%; height: 100%; align-items: center; } .monyList>div { float: left; width: 8.33%; height: 30px; padding: 5px 0; text-align: center; color: #3B76B5 !important; } .voucherContent .openDate { top: 209px; } .voucherContent .openEleName { top: 241px; } .voucherContent .payDate { top: 209px; } .voucherContent .voucherLeft { left: 124px; } .voucherContent .voucherRight { right: 121px; } &lt;/style> &lt;/head> &lt;body style="font-family: SimSun;line-height:1;font-size:10.0pt;"> &lt;div class="textAlignCenter masking_alt" id="forPrint"> &lt;div class="voucher openBg office"> &lt;div class="voucherDer vouStatus textAlignLeft voucherLeft fontSize16 posAbsolute">&lt;span>已签收&lt;/span>&lt;/div> &lt;p class="voNumber fontSize16 posAbsolute">BL20200615101522932&lt;/p> &lt;div class="voucherContent"> &lt;div class="gsName voucherDer posAbsolute textAlignLeft voucherLeft">&lt;span class="fontSize16 cllor3B7">泽诚控股有限公司&lt;/span>&lt;/div> &lt;div class="skName posAbsolute textAlignLeft voucherDer voucherRight">&lt;span class="fontSize16 cllor3B7">陕西泽诚置业有限公司&lt;/span>&lt;/div> &lt;div class="shNumber posAbsolute textAlignLeft voucherDer voucherLeft">&lt;span class="fontSize16 color2B2">91610132MA6X53QN7L&lt;/span>&lt;/div> &lt;div class="shNumber2 posAbsolute textAlignLeft voucherDer voucherRight">&lt;span class="fontSize16 color2B2">8351515313513852&lt;/span>&lt;/div> &lt;div class="moneyNumber posAbsolute textAlignLeft openDer voucherLeft">&lt;span class="fontSize16 cllor3B7">(大写)伍拾万元&lt;/span>&lt;/div> &lt;div class="moneyALL posAbsolute textAlignLeft"> &lt;div class="monyList"> &lt;div class="moneyOne">&lt;/div> &lt;div class="moneyOne">&lt;/div> &lt;div class="moneyOne">&lt;/div> &lt;div class="moneyOne">$&lt;/div> &lt;div class="moneyOne">6&lt;/div> &lt;div class="moneyOne">0&lt;/div> &lt;div class="moneyOne">5&lt;/div> &lt;div class="moneyOne">0&lt;/div> &lt;div class="moneyOne">0&lt;/div> &lt;div class="moneyOne">0&lt;/div> &lt;div class="moneyOne">0&lt;/div> &lt;div class="moneyOne">0&lt;/div> &lt;/div> &lt;/div> &lt;div class="openDate posAbsolute textAlignLeft voucherDer voucherLeft">&lt;span class="fontSize16 cllor3B7">2020-06-15&lt;/span>&lt;/div> &lt;div class="openEleName posAbsolute textAlignLeft voucherDer voucherLeft">&lt;span class="fontSize16 cllor3B7">&lt;/span>&lt;/div> &lt;div class="payDate posAbsolute textAlignLeft voucherDer voucherRight">&lt;span class="fontSize16 cllor3B7">2025-06-30&lt;/span>&lt;/div> &lt;/div> &lt;div class="fontSize16 posAbsolute voNumber2 textAlignLeft voucherDer">&lt;span>&lt;/span>&lt;/div> &lt;/div> &lt;/div> &lt;/body> &lt;/html>` 这就完了.直接运行没问题。还有比如 & 在正文中的要转义 & 要不然报错,格式一定要正确,</>结束符一定要有,标准也要有 ...

2020年6月19日 · 10 分钟 · 天边的星星