Java之生成条形码、PDF、HTML FreeMarker之根据模型
关于Java生成HTML,可参考我的这篇文章:FreeMarker之根据模型生成HTML代码 当然了,该篇文章也会给你很多启发,比如,根据html生成html,大家不要小看这个,著名的WordPress博客文章,本质上就是这个机制,每发表一篇文章相当于新生成的一个HTML,内容不一样,样式基本是一致的。 下面进入正题: 一、导入Maven依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> modelVersion>4.0.0</groupId>com.foreseeartifactId>mypdfversion>0.0.1-SNAPSHOTdependencies> dependency> >com.itextpdf>itext-asian>5.2.0>itextpdf>5.4.2>org.xhtmlrenderer>core-renderer>R8>org.freemarker>freemarker>2.3.23> >net.sf.barcode4j>barcode4j-light>2.0> > project> ? 二、编写Java代码 package com.beck.util; import java.awt.image.BufferedImage; java.io.ByteArrayOutputStream; java.io.File; java.io.FileOutputStream; java.io.IOException; java.io.OutputStream; org.krysalis.barcode4j.HumanReadablePlacement; org.krysalis.barcode4j.impl.code39.Code39Bean; org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider; org.krysalis.barcode4j.tools.UnitConv; sun.misc.BASE64Encoder; public class BarcodeUtil { static final String IMG_TYPE_PNG="image/png"; final String IMG_TYPE_GIF="image/gif"final String IMG_TYPE_JPEG="image/jpeg"static String generateToBase64(String msg,String imgType) throws IOException { ByteArrayOutputStream ous = new ByteArrayOutputStream(); generateToStream(msg,imgType,ous); BASE64Encoder encoder = BASE64Encoder(); return encoder.encode(ous.toByteArray()); } static File generateToFile(String msg,String imgType,File file) IOException { FileOutputStream out = FileOutputStream(file); try { generateToStream(msg,out); } finally { if (out != null) { out.close(); } } file; } byte[] generateToByte(String msg,1)"> IOException { ByteArrayOutputStream out = ByteArrayOutputStream(); out.toByteArray(); } ) { out.close(); } } } void generateToStream(String msg,OutputStream out) IOException { if (msg == null || out == ) { ; } Code39Bean bean = Code39Bean(); // 精细度 int dpi = 150; module宽度 double moduleWidth = UnitConv.in2mm(1.0f / dpi); bean.setModuleWidth(moduleWidth); 不显示文字 bean.setMsgPosition(HumanReadablePlacement.HRP_NONE); bean.setHeight(5); bean.setWideFactor(3); bean.doQuietZone(false); 输出到流 BitmapCanvasProvider canvas = BitmapCanvasProvider(out,dpi,BufferedImage.TYPE_BYTE_BINARY,false,0); 生成条形码 bean.generateBarcode(canvas,msg); 结束绘制 canvas.finish(); } } ? java.io.OutputStreamWriter; java.io.StringWriter; java.io.Writer; java.util.HashMap; java.util.Locale; java.util.Map; freemarker.template.Configuration; freemarker.template.Template; FreemarkerTemplate { private final Configuration configuration = Configuration( Configuration.VERSION_2_3_23); private String charset; public FreemarkerTemplate(String charset) { this.charset = charset; configuration.setEncoding(Locale.CHINA,charset); configuration.setClassicCompatible(true);处理空值为空字符串 } setTemplateClassPath(Class resourceLoaderClass,String basePackagePath) { configuration.setClassForTemplateLoading(resourceLoaderClass,basePackagePath); } setTemplateDirectoryPath(String templatePath) IOException { configuration.setDirectoryForTemplateLoading( File(templatePath)); } processToStream(String templateFileName,Map<String,Object> dataMap,Writer writer) Throwable { Template template = configuration.getTemplate(templateFileName); template.process(dataMap,writer); } processToFile(String templateFileName,File outFile) Throwable { Writer writer = new OutputStreamWriter( FileOutputStream(outFile),charset); { processToStream(templateFileName,dataMap,writer); } catch (Throwable e) { e.printStackTrace(); } if (writer != ) { writer.close(); } } } String processToString(String templateFileName,Object> dataMap) new StringWriter(2048 writer.toString(); } ) { writer.close(); } } } } ? java.io.OutputStream; org.xhtmlrenderer.pdf.ITextFontResolver; org.xhtmlrenderer.pdf.ITextRenderer; com.itextpdf.text.pdf.BaseFont; PDFUtils { static String fontBasePath=PDFUtils.class.getResource("/").getPath()+"font/"; htmlFileToPDFStream(File htmlFile,OutputStream output,File imageBaseURL) Throwable { if (htmlFile == throw new RuntimeException("htmlFile is null"); } if (output == new RuntimeException("output is null"); } 生成ITextRenderer实例 ITextRenderer renderer = ITextRenderer(); 关联html页面 renderer.setDocument(htmlFile.toURI().toURL().toString()); 设置获取图片的基本路径 renderer.getSharedContext().setBaseURL( imageBaseURL.toURI().toURL().toString()); 设置字体路径,必须和html设置一致 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(fontBasePath+"msyh.ttc",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); fontResolver.addFont(fontBasePath+"msyhl.ttc" htmlFileToPDFFile(File htmlFile,File pdfFile,1)"> Throwable { OutputStream output = FileOutputStream(pdfFile); { htmlFileToPDFStream(htmlFile,output,imageBaseURL); } if (output != ) { output.close(); } } } } ? Receipt { String receiptType; double amount; String getReceiptType() { receiptType; } setReceiptType(String receiptType) { this.receiptType = getAmount() { amount; } void setAmount( amount) { this.amount = amount; } } ? 三、在src/main/resources建立HTML页面和相关的文件夹 建立font、images、templates文件夹 文件夹如图所示: ? html代码: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>报销单</title> <style type="text/css" rel="stylesheet"> * { margin: 0; padding: 0; } body { font-family: "Microsoft YaHei UI"; font-size: 12px; max-width: 555px; margin: 0 auto; padding: 20px; } h1 { text-align: center; font-size: 18px; color: #000weight: bold; } .comptitle { height: 66px; } .comptitle h2 { float: left; height: 66px; line-height: 66px; font-size: 14px; color: #000weight: bold; } .barcode { width: 162px; : right; padding: 10px 0; text-align: center; } .barcode img { width: 162px; height: 30px; display: table-cell; vertical-align: middle; margin-bottom: 5px; } .barcode h3 { font-size: 12px; color: #000; } .stafftbl,.detailstbl,.approverrd { border-collapse: collapse; border: 1px solid #f3f3f3; } .stafftbl th,.stafftbl td,.detailstbl th,.detailstbl td,.approverrd th,.approverrd td { height: 20px; line-height: 20px; border: 1px solid #f3f3f3; } .stafftbl th { font-weight: normal; background: #f8f9fd; text-align: right; color: #777; padding-right: 12px; } .stafftbl td { padding-left: 10px; } .wrap p { color: #000; margin: 12px 0 10px; } .detailstbl th,.approverrd th { font-weight: normal; color: #777; background: #f8f9fd; border: none; } .detailstbl td,.approverrd td { text-align: center; } .sum { background: #f8f9fd; color: #777; } .detailstbl td.sumdata { text-align: right; padding-right: 20px; font-weight: bold; } </style> </head> <body> <div class="wrap"> <h1>费用报销单</h1> <div class="comptitle"> <h2>*****有限公司</h2> <div class="barcode"><img src="${barcodeImg}" alt=""></img> <h3>${barcode}</h3> </div> </div> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="stafftbl"> <tbody> <tr> <th width="18%">报销人</th> <td width="32%">${userName}</td> <th width="18%">填写日期</th> <td>${submitDate}</td> </tr> <tr> <th>费用所属部门</th> <td colspan="3">${deptName}</td> </tr> <tr> <th>所属项目</th> <td colspan="3">运营平台2.0</td> </tr> <tr> <th>报销事由</th> <td colspan="3">${reimReason}</td> </tr> </tbody> </table> <p>费用明细</p> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="detailstbl"> <tbody> <tr> <th width="8%">序号</th> <th>发票类型</th> <th width="10%">发票张数</th> <th width="12%">发票金额</th> <th width="12%">报销金额</th> <th>专票税额</th> <th width="28%">用途</th> </tr> <#list receiptList as item> <tr> <td >${list_index+1}</td> <td>${item.receiptType}</td> <td>1</td> <td>¥${item.amount}</td> <td>¥${item.amount}</td> <td> </td> <td> </td> </tr> </#list> <tr> <td colspan="2" class="sum">总报销金额(小写)</td> <td colspan="5" class="sumdata" >¥259.46</td> </tr> <tr> <td colspan="2" class="sum">总报销金额(大写)</td> <td colspan="5" class="sumdata" >贰佰伍拾玖元肆角陆分</td> </tr> </tbody> </table> <p>审批记录</p> <table width="100%" border="0" cellspacing="0" cellpadding="0" class="approverrd"> <tbody> <tr> <th width="8%">序号</th> <th>节点名称</th> <th>电子签名</th> <th>签名日期</th> <th width="8%">操作</th> <th width="25%">备注</th> </tr> <tr> <td>1</td> <td>提交</td> <td>张三/平台支撑部</td> <td>2018-09-18 16:18:41</td> <td>提交</td> <td> </td> </tr> </tbody> </table> </div> </body> </html> ? ?图片要求必须符合png、jpg等格式,只要是这些格式的都行。 ? 四、编写测试类 java.util.ArrayList; java.util.List; java.util.Map; java.util.UUID; Test { void main(String[] args) Throwable { String barcode = "12345678910"; String uuid=UUID.randomUUID().toString(); String htmlBasePath="E://Demo//workspace//mypdf//src//main//resources//template";html的根目录 String tempathBasePath=Test.class.getResource("/").getPath()+"template/";模板路径 String pdfBasePath="E://Demo//workspace//mypdf//src//main//resources//template";生成的pdf目录 String barCodePath="E://Demo//workspace//mypdf//src//main//resources//images//"+uuid+".png"; String htmlPath=htmlBasePath+uuid+".html"; String pdfPath=pdfBasePath+uuid+".pdf"; 生成条形码 File barCodeFile= File(barCodePath); BarcodeUtil.generateToFile(barcode,BarcodeUtil.IMG_TYPE_PNG,barCodeFile); System.out.println("生成条形码完成!"生成html FreemarkerTemplate tp=new FreemarkerTemplate("UTF-8"); tp.setTemplateDirectoryPath(tempathBasePath); 封装数据 start ,必须是Map Map<String,Object> dataMap = new HashMap<String,Object>(); dataMap.put("barcode"); dataMap.put("submitDate","2018-09-18"); dataMap.put("deptName","研发平台"费用明细 List<Receipt> receiptList=new ArrayList<Receipt>();Receipt 必须是public类型的类 Receipt r1= Receipt(); r1.setReceiptType("普通发票"); r1.setAmount(100); Receipt r2= Receipt(); r2.setReceiptType("普通发票"); r2.setAmount(100); receiptList.add(r1); receiptList.add(r2); dataMap.put("receiptList"封装数据 end File htmlFile= File(htmlPath); tp.processToFile("expense.html"生成pdf PDFUtils.htmlFileToPDFFile(htmlFile,new File(pdfPath),1)"> File(htmlBasePath)); System.out.println("生成pdf完成!"); } } ? 运行结果如图所示(控制台打印这些就表示没有问题,如果控制台报错,常见错误就是文件找不到异常,改下路径就可以了,一般情况是没有其他错误): ? pdf显示如图: ? html显示如图: ? 条形码显示如图: ? 源码地址:https://github.com/youcong1996/study_simple_demo.git 如果实在上述代码,不能运行,大家可以将源码移植过来,运行效果是没有问题的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |