1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > freemarker转PDF 支持分页 增加页眉页脚

freemarker转PDF 支持分页 增加页眉页脚

时间:2021-06-03 03:41:01

相关推荐

freemarker转PDF 支持分页 增加页眉页脚

参考 /superad/pdf-kit.git

先看效果(不能上传PDF文档。。。)

POM.XML

<?xml version="1.0" encoding="UTF-8"?><project xmlns="/POM/4.0.0"xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.github.superad.pdf.kit</groupId><artifactId>pdf-kit</artifactId><packaging>jar</packaging><name>${project.artifactId}</name><version>1.1-RELEASE</version><properties><java.src.version>1.7</java.src.version><java.target.version>1.7</java.target.version><project.encoding>UTF-8</project.encoding></properties><parent><groupId>org.sonatype.oss</groupId><artifactId>oss-parent</artifactId><version>7</version></parent><dependencies><!--pdf生成工具类--><!--pdf生成 itext--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.4.2</version></dependency><dependency><groupId>com.itextpdf.tool</groupId><artifactId>xmlworker</artifactId><version>5.4.1</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.0.3</version></dependency><!--freemarker--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.26-incubating</version></dependency><!--jfreechart--><dependency><groupId>jfree</groupId><artifactId>jfreechart</artifactId><version>1.0.2</version></dependency><!--log--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.0.13</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.0.13</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-access</artifactId><version>1.0.13</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.5</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>log4j-over-slf4j</artifactId><version>1.7.21</version></dependency><!--util--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>20.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.14.8</version></dependency><dependency><groupId>mons</groupId><artifactId>commons-io</artifactId><version>1.3.2</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><!--servlet--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency></dependencies><!--增加的配置,过滤ttf文件的匹配--><profiles><profile><id>release</id><build><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource></resources><plugins><!--compile--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.5.1</version><configuration><source>${java.src.version}</source><target>${java.target.version}</target><encoding>${project.encoding}</encoding></configuration></plugin><!-- Source --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>2.2.1</version><executions><execution><phase>package</phase><goals><goal>jar-no-fork</goal></goals></execution></executions></plugin><!-- Javadoc --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-javadoc-plugin</artifactId><version>2.9.1</version><executions><execution><phase>package</phase><goals><goal>jar</goal></goals></execution></executions></plugin><!-- GPG --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-gpg-plugin</artifactId><version>1.5</version><executions><execution><phase>verify</phase><goals><goal>sign</goal></goals></execution></executions></plugin></plugins></build><distributionManagement><snapshotRepository><id>oss</id><url>/content/repositories/snapshots/</url></snapshotRepository><repository><id>oss</id><url>/service/local/staging/deploy/maven2</url></repository></distributionManagement></profile></profiles><licenses><license><name>The Apache Software License, Version 2.0</name><url>/licenses/LICENSE-2.0.txt</url><distribution>repo</distribution></license></licenses><scm><tag>alpha</tag><url>/superad/pdf-kit.git</url><connection>scm:git:/superad/pdf-kit.git</connection><developerConnection>scm:git:/superad/pdf-kit.git</developerConnection></scm></project>

hello.ftl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta http-equiv="Content-Style-Type" content="text/css"/><title></title><style type="text/css">body {font-family: pingfang sc light;}.center{text-align: center;width: 100%;}</style></head><body><!--第一页开始--><div class="page" ><div class="center"><p>${templateName}</p></div><div><p>iText官网:${ITEXTUrl}</p></div><div><p>FreeMarker官网:${freeMarkerUrl}</p></div><div><p>JFreeChart教程:${JFreeChartUrl}</p></div><!--外部链接--><p>静态logo图</p><div><img src="${imageUrl}" alt="美团点评" width="110" height="20.8"/></div><!--动态生成的图片--><p>气温变化对比图</p><div><img src="${picUrl}" alt="我的图片" width="500" height="270"/></div><!--jfreechart 散点图--><p>发展建议分布图</p><div><img src="${scatterUrl}" alt="散点图" width="700" height="600"/></div></div><!--第一页结束--><!---分页标记--><span style="page-break-after:always;"></span><!--第二页开始--><div class="page"><div>第二页开始了</div><div>列表值:</div><div><#list scores as item><div><p>${item}</p></div></#list></div></div><!--第二页结束--></body></html>

report_template.ftl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><meta http-equiv="Content-Style-Type" content="text/css"/><title></title><style type="text/css">body {font-family: pingfang sc light;}</style></head><body><!--第一页开始--><div class="page" ><div>report_template</div><div>姓名:${name}</div><div>年龄:${age}</div><div>成绩:</div><#list scores as item><div>${item}</div></#list></div><!--第一页结束--><!---分页标记--><span style="page-break-after:always;"></span><!--第二页开始--><div class="page"><div>第二页开始了</div><img src="${imageUrl}" alt="百度图标" width="270" height="129"/></div><!--第二页结束--></body></html>

TemplateBO

@Datapublic class TemplateBO {private String templateName;private String freeMarkerUrl;private String ITEXTUrl;private String JFreeChartUrl;private List<String> scores;private String imageUrl;private String picUrl;private String scatterUrl;}

reportKit360.java

package pdf.kit;import mon.collect.Lists;import lombok.extern.slf4j.Slf4j;import mons.lang.exception.ExceptionUtils;import ponent.PDFHeaderFooter;import ponent.PDFKit;import ponent.chart.ScatterPlotChart;import ponent.chart.model.XYLine;import ponent.chart.impl.DefaultLineChart;import java.util.ArrayList;import java.util.List;/*** Created by fgm on /4/17.* 360报告**/@Slf4jpublic class ReportKit360 {public static List<XYLine> getTemperatureLineList() {List<XYLine> list= Lists.newArrayList();for(int i=1;i<=7;i++){XYLine line=new XYLine();float random=Math.round(Math.random()*10);line.setXValue("星期"+i);line.setYValue(20+random);line.setGroupName("下周");list.add(line);}for(int i=1;i<=7;i++){XYLine line=new XYLine();float random=Math.round(Math.random()*10);line.setXValue("星期"+i);line.setYValue(20+random);line.setGroupName("这周");list.add(line);}return list;}public String createPDF(String templatePath,Object data, String fileName){//pdf保存路径try {//设置自定义PDF页眉页脚工具类PDFHeaderFooter headerFooter=new PDFHeaderFooter();PDFKit kit=new PDFKit();kit.setHeaderFooterBuilder(headerFooter);//设置输出路径kit.setSaveFilePath("D:\\gitee\\pdf-kit\\hello.pdf");String saveFilePath=kit.exportToFile(fileName,data);return saveFilePath;} catch (Exception e) {log.error("PDF生成失败{}", ExceptionUtils.getFullStackTrace(e));return null;}}public static void main(String[] args) {ReportKit360 kit=new ReportKit360();TemplateBO templateBO=new TemplateBO();templateBO.setTemplateName("Hello iText! Hello freemarker! Hello jFreeChart!");templateBO.setFreeMarkerUrl("http://www.zheng-/chm/freemarker2_3_24/ref_directive_if.html");templateBO.setITEXTUrl("/examples-itext5");templateBO.setJFreeChartUrl("/jfreechart/jfreechart_referenced_apis.html");templateBO.setImageUrl("http://mss./v1/mss_74e5b6ab17f44f799a524fa86b6faebf/360report/logo_1.png");List<String> scores=new ArrayList<String>();scores.add("90");scores.add("95");scores.add("98");templateBO.setScores(scores);//折线图List<XYLine> lineList=getTemperatureLineList();DefaultLineChart lineChart=new DefaultLineChart();lineChart.setHeight(500);lineChart.setWidth(300);String picUrl=lineChart.draw(lineList,0);templateBO.setPicUrl(picUrl);//散点图String scatterUrl=ScatterPlotChart.draw(ScatterPlotChartTest.getData(),1,"他评得分(%)","自评得分(%)");templateBO.setScatterUrl(scatterUrl);String templatePath="D:\\gitee\\pdf-kit\\src\\test\\resources\\templates";String path = kit.createPDF(templatePath, templateBO, "hello.pdf");System.out.println(path);}}

ScatterPlotChartTest.java

package pdf.kit;import mon.collect.Lists;import ponent.chart.ScatterPlotChart;import ponent.chart.model.XYScatter;import java.util.List;/*** Created by fgm on /7/9.*/public class ScatterPlotChartTest {public static void main(String[] args) {List<XYScatter> list=getData();String path= ScatterPlotChart.draw(list,-1,"他评得分(%)","自评得分(%)");System.out.println(path);}public static List<XYScatter> getData() {List<XYScatter> list= Lists.newArrayList();XYScatter xy=new XYScatter();xy.setX(45);xy.setY(55);xy.setLabel("主见");list.add(xy);XYScatter xy1=new XYScatter();xy1.setX(75);xy1.setY(80);xy1.setLabel("定战略");list.add(xy1);XYScatter xy2=new XYScatter();xy2.setX(80);xy2.setY(80);xy2.setLabel("拿结果");list.add(xy2);XYScatter xy3=new XYScatter();xy3.setX(90);xy3.setY(25);xy3.setLabel("带团队");list.add(xy3);return list;}}

interface HeaderFooterBuilder

package ponent.builder;import com.itextpdf.text.Document;import com.itextpdf.text.Font;import com.itextpdf.text.pdf.PdfTemplate;import com.itextpdf.text.pdf.PdfWriter;/*** Created by fgm on /4/15.*/public interface HeaderFooterBuilder {/*** @description 写页眉*/void writeHeader(PdfWriter writer, Document document, Object data, Font font, PdfTemplate template);/*** @description 写页脚*/void writeFooter(PdfWriter writer, Document document, Object data, Font font, PdfTemplate template);/*** @description 关闭文档前,获取替换页眉页脚处设置模板的文本*/String getReplaceOfTemplate(PdfWriter writer, Document document, Object data);}

class PDFBuilder

package ponent.builder;import com.itextpdf.text.Document;import com.itextpdf.text.DocumentException;import com.itextpdf.text.Font;import com.itextpdf.text.pdf.BaseFont;import com.itextpdf.text.pdf.PdfPageEventHelper;import com.itextpdf.text.pdf.PdfTemplate;import com.itextpdf.text.pdf.PdfWriter;import mons.lang.StringUtils;import mons.lang.exception.ExceptionUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import pdf.kit.exception.PDFException;import java.io.IOException;/*** 设置页面附加属性**/public class PDFBuilder extends PdfPageEventHelper {private static Logger log= LoggerFactory.getLogger(PDFBuilder.class);//字体文件名private String fontFileName;// 基础字体对象private BaseFont bf;// 利用基础字体生成的字体对象,一般用于生成中文文字private Font fontDetail;//文档字体大小private int fontSize=12;//模板private PdfTemplate template;//数据实体private Object data;//页眉页脚定制接口private HeaderFooterBuilder headerFooterBuilder;//不允许空的构造方法private PDFBuilder() {}public PDFBuilder(HeaderFooterBuilder headerFooterBuilder) {this(headerFooterBuilder,null);}public PDFBuilder(HeaderFooterBuilder headerFooterBuilder, Object data) {this(headerFooterBuilder, data, "ping_fang_light.ttf");}public PDFBuilder(HeaderFooterBuilder headerFooterBuilder, Object data, String fontFileName) {this(headerFooterBuilder, data, fontFileName, 12);}public PDFBuilder(HeaderFooterBuilder headerFooterBuilder, Object data, String fontFileName, int fontSize) {this.headerFooterBuilder = headerFooterBuilder;this.data=data;this.fontFileName=fontFileName;this.fontSize=fontSize;}public void onOpenDocument(PdfWriter writer, Document document) {template = writer.getDirectContent().createTemplate(50, 50);}/**** 关闭每页的时候,写入页眉,页脚等**/public void onEndPage(PdfWriter writer, Document document) {this.addPage(writer, document);}//加分页private void addPage(PdfWriter writer, Document document){if(headerFooterBuilder !=null){//1.初始化字体initFront();//2.写入页眉headerFooterBuilder.writeHeader(writer,document,data,fontDetail,template);//3.写入前半部分页脚headerFooterBuilder.writeFooter(writer,document,data,fontDetail,template);}}/**** 关闭文档时,替换模板,完成整个页眉页脚组件**/public void onCloseDocument(PdfWriter writer, Document document) {if(headerFooterBuilder !=null){template.beginText();template.setFontAndSize(bf,fontSize);String replace= headerFooterBuilder.getReplaceOfTemplate(writer,document,data);template.showText(replace);template.endText();template.closePath();}}/*** @description 初始化字体*/private void initFront(){if(StringUtils.isEmpty(fontFileName)){throw new PDFException("PDF文档字体未设置!");}try {if (bf == null) {//添加字体,以支持中文String classpath=PDFBuilder.class.getClassLoader().getResource("").getPath();String fontPath =classpath+"fonts/"+fontFileName;//创建基础字体bf = BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);}if (fontDetail == null) {fontDetail = new Font(bf, fontSize, Font.NORMAL);// 数据体字体log.info("PDF文档字体初始化完成!");}} catch (DocumentException e) {log.error("字体初始化失败{}", ExceptionUtils.getFullStackTrace(e));throw new PDFException("字体初始化失败",e);} catch (IOException e) {log.error("字体初始化失败{}", ExceptionUtils.getFullStackTrace(e));throw new PDFException("字体初始化失败",e);}}public int getPresentFontSize() {return fontSize;}public void setPresentFontSize(int fontSize) {this.fontSize = fontSize;}public String getFontFileName() {return fontFileName;}public void setFontFileName(String fontFileName) {this.fontFileName = fontFileName;}}

class DefaultLineChart

package ponent.chart.impl;import lombok.extern.slf4j.Slf4j;import org.jfree.chart.JFreeChart;import org.jfree.chart.labels.ItemLabelAnchor;import org.jfree.chart.labels.ItemLabelPosition;import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;import org.jfree.chart.plot.CategoryPlot;import org.jfree.chart.renderer.category.LineAndShapeRenderer;import org.jfree.data.category.DefaultCategoryDataset;import org.jfree.ui.TextAnchor;import ponent.chart.LineChart;/*** Created by fgm on /5/15.* 设置默认的画图工具**/@Slf4jpublic class DefaultLineChart extends LineChart {private int width;private int height;protected void initPlot(JFreeChart chart, DefaultCategoryDataset dataSet) {CategoryPlot plot = chart.getCategoryPlot();super.initDefaultXYPlot(plot);//设置节点的值显示LineAndShapeRenderer lineRender = new LineAndShapeRenderer();lineRender.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());lineRender.setBaseItemLabelsVisible(true);lineRender.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER));plot.setRenderer(lineRender);}@Overridepublic int getWidth() {if(width==0){return super.getWidth();}return width;}@Overridepublic void setWidth(int width) {this.width = width;}@Overridepublic int getHeight() {if(height==0){return super.getHeight();}return height;}@Overridepublic void setHeight(int height) {this.height = height;}}

class XYLine

package ponent.chart.model;import lombok.Data;/*** Created by fgm on /4/7.*/@Datapublic class XYLine {private double yValue;private String xValue;private String groupName;public XYLine(){}public XYLine(double yValue, String xValue, String groupName){this.yValue=yValue;this.xValue=xValue;this.groupName=groupName;}}

class XYScatter

package ponent.chart.model;import lombok.Data;/*** Created by fgm on /7/9.*/@Datapublic class XYScatter {private double x;private double y;private String label;}

abstract class LineChart

package ponent.chart;import lombok.extern.slf4j.Slf4j;import org.jfree.chart.ChartFactory;import org.jfree.chart.ChartUtilities;import org.jfree.chart.JFreeChart;import org.jfree.chart.axis.CategoryAxis;import org.jfree.chart.axis.CategoryLabelPositions;import org.jfree.chart.axis.NumberAxis;import org.jfree.chart.axis.NumberTickUnit;import org.jfree.chart.plot.CategoryPlot;import org.jfree.chart.plot.PlotOrientation;import org.jfree.data.category.DefaultCategoryDataset;import ponent.chart.model.XYLine;import pdf.kit.util.FontUtil;import java.awt.*;import java.io.File;import java.io.IOException;import java.util.List;/*** Created by fgm on /4/7.*/@Slf4jpublic abstract class LineChart {private int width;private int height;private static int defaultWidth=500;private static int defaultHeight=220;private String fileName;public String draw(List<XYLine> lineList, int picId){return draw("","","",lineList,picId);}public String draw(String title, String xLabel, String yLabel,List<XYLine> lineList, int picId){if(lineList==null || lineList.size()==0){return "";}DefaultCategoryDataset dataSet=new DefaultCategoryDataset();for(XYLine line:lineList){dataSet.addValue(line.getYValue(),line.getGroupName(),line.getXValue());}try {return drawLineChar(title,xLabel,yLabel,dataSet,picId);}catch (Exception ex){log.error("画图异常{}",ex);return "";}}/*** @description 设置自定义的线条和背景色*/protected abstract void initPlot(JFreeChart chart,DefaultCategoryDataset dataSet);protected void initDefaultXYPlot(CategoryPlot plot){// 设置X轴CategoryAxis domainAxis = plot.getDomainAxis();domainAxis.setLabelFont(FontUtil.getFont(Font.PLAIN,13)); // 设置横轴字体domainAxis.setTickLabelFont(FontUtil.getFont(Font.PLAIN,13));// 设置坐标轴标尺值字体domainAxis.setLowerMargin(0.01);// 左边距 边框距离domainAxis.setUpperMargin(0.06);// 右边距 边框距离,防止最后边的一个数据靠近了坐标轴。domainAxis.setMaximumCategoryLabelLines(10);domainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);// 横轴 lable 的位置 横轴上的 Lable 45度倾斜 DOWN_45// 设置Y轴NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();rangeAxis.setLabelFont(FontUtil.getFont(Font.PLAIN, 13));rangeAxis.setAutoRangeMinimumSize(1); //最小跨度rangeAxis.setUpperMargin(0.18);//上边距,防止最大的一个数据靠近了坐标轴。rangeAxis.setLowerBound(18); //最小值显示18rangeAxis.setUpperBound(33); //最大值显示33rangeAxis.setAutoRange(false); //不自动分配Y轴数据rangeAxis.setTickMarkStroke(new BasicStroke(1.6f)); // 设置坐标标记大小rangeAxis.setTickMarkPaint(Color.BLACK);// 设置坐标标记颜色rangeAxis.setTickUnit(new NumberTickUnit(1));//每1个刻度显示一个刻度值}/*** @description 画出折线图* @return 图片地址*/private String drawLineChar(String title, String xLabel, String yLabel, DefaultCategoryDataset dataSet, int picId)throws IOException {JFreeChart lineChartObject= ChartFactory.createLineChart(title,xLabel, // 横轴yLabel, // 纵轴dataSet, // 获得数据集PlotOrientation.VERTICAL,// 图标方向垂直true, // 显示图例false, // 不用生成工具false // 不用生成URL地址);String path=this.getClass().getClassLoader().getResource("").getPath();String filePath=path+"/images/"+picId+"/"+getFileName();File lineChart = new File(filePath);if(!lineChart.getParentFile().exists()){lineChart.getParentFile().mkdirs();}//初始化表格样式initDefaultPlot(lineChartObject,dataSet);ChartUtilities.saveChartAsJPEG(lineChart ,lineChartObject, getWidth() ,getHeight());return lineChart.getAbsolutePath();}private void initDefaultPlot(JFreeChart chart,DefaultCategoryDataset dataSet){//设置公共颜色chart.getTitle().setFont(FontUtil.getFont(Font.PLAIN, 15)); // 设置标题字体chart.getLegend().setItemFont(FontUtil.getFont(Font.PLAIN, 13));// 设置图例类别字体chart.setBackgroundPaint(Color.white);// 设置背景色CategoryPlot plot = chart.getCategoryPlot();plot.setNoDataMessage("无对应的数据。");plot.setNoDataMessageFont(FontUtil.getFont(Font.PLAIN, 13));//字体的大小plot.setNoDataMessagePaint(Color.RED);//字体颜色//设置自定义颜色initPlot(chart,dataSet);}public int getWidth() {if(width==0){return defaultWidth;}return width;}public void setWidth(int width) {this.width = width;}public int getHeight() {if(height==0){return defaultHeight;}return height;}public void setHeight(int height) {this.height = height;}public String getFileName() {return fileName;}public void setFileName(String fileName) {this.fileName = fileName;}}

class ScatterPlotChart extends ChartFactory

package ponent.chart;import mon.collect.Lists;import freemarker.template.utility.CollectionUtils;import lombok.extern.slf4j.Slf4j;import mons.lang.exception.ExceptionUtils;import org.jfree.chart.ChartFactory;import org.jfree.chart.ChartUtilities;import org.jfree.chart.JFreeChart;import org.jfree.chart.annotations.XYBoxAnnotation;import org.jfree.chart.annotations.XYTextAnnotation;import org.jfree.chart.axis.NumberAxis;import org.jfree.chart.axis.NumberTickUnit;import org.jfree.chart.axis.ValueAxis;import org.jfree.chart.labels.StandardXYToolTipGenerator;import org.jfree.chart.plot.PlotOrientation;import org.jfree.chart.plot.XYPlot;import org.jfree.chart.renderer.xy.StandardXYItemRenderer;import org.jfree.chart.renderer.xy.XYItemRenderer;import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;import org.jfree.chart.urls.StandardXYURLGenerator;import org.jfree.data.xy.DefaultXYDataset;import org.jfree.data.xy.XYDataset;import ponent.chart.model.XYScatter;import pdf.kit.util.FontUtil;import javax.imageio.ImageIO;import java.awt.*;import java.awt.geom.Ellipse2D;import java.awt.image.BufferedImage;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.List;/*** Created by fgm on /7/4.* 散点图生成*/@Slf4jpublic class ScatterPlotChart extends ChartFactory {private static BufferedImage backgroundImage;private static String fileName="scatterChart.png";private static int width=700;private static int height=600;//上方垂直private static double turnTop=4.712389;public static String draw(List<XYScatter> list,int picId,String xLabel,String yLabel){return draw(list,picId,"",xLabel,yLabel);}public static String draw(List<XYScatter> list,int picId,String title,String xLabel,String yLabel){XYDataset xyDataset= ScatterPlotChart.createXYDataSet(list,"");String path=LineChart.class.getClassLoader().getResource("").getPath();String filePath=path+"/images/"+picId+"/"+fileName;File scatterChartFile = new File(filePath);if(!scatterChartFile.getParentFile().exists()){scatterChartFile.getParentFile().mkdirs();}try {JFreeChart jFreeChart = createChart(xyDataset,list,title,xLabel,yLabel);ChartUtilities.saveChartAsJPEG(scatterChartFile ,jFreeChart, width ,height);} catch (IOException ex) {log.error("散点图生成异常:{}", ExceptionUtils.getFullStackTrace(ex));return "";}return scatterChartFile.getAbsolutePath();}public static JFreeChart createScatterPlot(String title, String xAxisLabel, String yAxisLabel, XYDataset dataset, PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls) {if(orientation == null) {throw new IllegalArgumentException("Null \'orientation\' argument.");} else {NumberAxis xAxis = new NumberAxis(xAxisLabel);xAxis.setAutoRangeIncludesZero(false);NumberAxis yAxis = new NumberAxis(yAxisLabel);yAxis.setAutoRangeIncludesZero(false);XYItemRenderer render=new StandardXYItemRenderer();render.setBaseItemLabelsVisible(false);XYPlot plot = new XYPlot(dataset, xAxis, yAxis, render);StandardXYToolTipGenerator toolTipGenerator = null;if(tooltips) {toolTipGenerator = new StandardXYToolTipGenerator();}StandardXYURLGenerator urlGenerator = null;if(urls) {urlGenerator = new StandardXYURLGenerator();}XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(false, true);renderer.setSeriesItemLabelFont(0,FontUtil.getFont(Font.PLAIN,14));renderer.setBaseItemLabelsVisible(false);renderer.setBaseToolTipGenerator(toolTipGenerator);renderer.setURLGenerator(urlGenerator);plot.setRenderer(renderer);plot.setOrientation(orientation);JFreeChart chart = new JFreeChart(title, FontUtil.getFont(Font.PLAIN,18), plot, legend);return chart;}}public static XYDataset createXYDataSet(List<XYScatter> dataList,String dataName) {DefaultXYDataset dataSet = new DefaultXYDataset();if(dataList==null ||dataList.size()==0){return dataSet;}int size = dataList.size();double[][] data = new double[2][size];for (int i = 0; i < size; i++) {XYScatter behaviorBO = dataList.get(i);double x = behaviorBO.getX();double y = behaviorBO.getY();data[0][i] = x;data[1][i] = y;}dataSet.addSeries(dataName,data);return dataSet;}public static JFreeChart createChart(XYDataset xydataset, List<XYScatter> dataList,String title,String xLabel,String yLabel) throws IOException {JFreeChart jfreechart = createScatterPlot(title,xLabel,yLabel,xydataset, PlotOrientation.VERTICAL, true, true, false);jfreechart.getLegend().setItemFont(FontUtil.getFont(Font.PLAIN,14));//去掉图例jfreechart.getLegend().setBorder(0,0,0,0);//画每个坐标点Shape shape = new Ellipse2D.Double(-4,-4,8,8);XYPlot xyPlot = (XYPlot) jfreechart.getPlot();XYItemRenderer renderer = xyPlot.getRenderer();renderer.setItemLabelFont(FontUtil.getFont(Font.PLAIN, 14));for(int i=0;i<xydataset.getSeriesCount();i++){renderer.setSeriesShape(i, shape);renderer.setSeriesPaint(i, Color.WHITE);}//初始化背景色和坐标轴initBackGroundAndAxis(jfreechart);//区间划分initRegionPartition(jfreechart);//数据标签initDataLabels(jfreechart,dataList);return jfreechart;}/*** @description 初始化数据标签*/private static void initDataLabels(JFreeChart jfreechart, List<XYScatter> dataList) {//数据录入if(dataList==null ||dataList.size()==0){return;}XYPlot xyplot = (XYPlot) jfreechart.getPlot();for(XYScatter xyScatter:dataList){XYPointerFrameAnnotation pointerAnnotation=new XYPointerFrameAnnotation(xyScatter.getLabel(),xyScatter.getX(),xyScatter.getY(),turnTop);pointerAnnotation.setFont(FontUtil.getFont(Font.PLAIN, 13));xyplot.addAnnotation(pointerAnnotation);}}/*** @description 初始化背景色*/private static void initBackGroundAndAxis(JFreeChart jfreechart) throws IOException {jfreechart.setBackgroundPaint(Color.white);jfreechart.setBorderPaint(Color.black);jfreechart.setBorderStroke(new BasicStroke(1.5f));XYPlot xyplot = (XYPlot) jfreechart.getPlot();//无数据显示xyplot.setNoDataMessage("没有数据");xyplot.setNoDataMessageFont(FontUtil.getFont(Font.PLAIN, 18));//背景色if(backgroundImage==null){String classpath= ScatterPlotChart.class.getClassLoader().getResource("").getPath();String backgroundImg=classpath+"/background/back.png";backgroundImage = ImageIO.read(new FileInputStream(backgroundImg));}xyplot.setBackgroundImage(backgroundImage);xyplot.setBackgroundImageAlpha(1.0F);xyplot.setOutlineStroke(new BasicStroke(1.5f)); // 边框粗细ValueAxis vaaxis = xyplot.getDomainAxis();vaaxis.setAxisLineStroke(new BasicStroke(1.5f));vaaxis.setLabelFont(FontUtil.getFont(Font.PLAIN,14));//坐标轴和背景色ValueAxis va = xyplot.getDomainAxis(0);va.setAxisLineStroke(new BasicStroke(1.5f));va.setAxisLineStroke(new BasicStroke(1.5f)); // 坐标轴粗细va.setAxisLinePaint(Color.black); // 坐标轴颜色va.setLabelPaint(Color.black); // 坐标轴标题颜色va.setTickLabelPaint(Color.black); // 坐标轴标尺值颜色va.setAxisLineVisible(false);va.setLabelFont(FontUtil.getFont(Font.PLAIN, 14));ValueAxis axis = xyplot.getRangeAxis();axis.setAxisLineStroke(new BasicStroke(1.5f));XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyplot.getRenderer();xylineandshaperenderer.setSeriesOutlinePaint(0, Color.WHITE);xylineandshaperenderer.setUseOutlinePaint(false);//x 轴NumberAxis xAxis = (NumberAxis) xyplot.getDomainAxis();xAxis.setAutoRangeIncludesZero(false);xAxis.setAutoRangeStickyZero(false);xAxis.setTickMarkInsideLength(2.0F);xAxis.setTickMarkOutsideLength(0.0F);xAxis.setAxisLineStroke(new BasicStroke(1.5f));xAxis.setTickUnit(new NumberTickUnit(25));xAxis.setLabelFont(FontUtil.getFont(Font.PLAIN, 14));xAxis.setUpperBound(101);//最大值xAxis.setLowerBound(0);//最小值//y 轴NumberAxis yAxis = (NumberAxis) xyplot.getRangeAxis();yAxis.setAutoRangeIncludesZero(false);yAxis.setAutoRangeStickyZero(false);yAxis.setTickMarkInsideLength(2.0F);yAxis.setTickMarkOutsideLength(0.0F);yAxis.setTickUnit(new NumberTickUnit(25));yAxis.setAxisLineStroke(new BasicStroke(1.5f));yAxis.setLabelFont(FontUtil.getFont(Font.PLAIN, 14));yAxis.setUpperBound(101);//最大值yAxis.setLowerBound(0);//最小值}/*** @description 初始化区域划分* | 00 | 10 | 20 |* | 01 | 11 | 21 |* | 02 | 21 | 22 |***/private static void initRegionPartition(JFreeChart jfreechart) {Stroke stroke=new BasicStroke(0.5F);Paint outlinePaint=Color.WHITE;//划分区间XYBoxAnnotation box00 = new XYBoxAnnotation(0, 0, 50, 50,stroke,outlinePaint);XYBoxAnnotation box01 = new XYBoxAnnotation(0, 50, 50, 75,stroke,outlinePaint);XYBoxAnnotation box02 = new XYBoxAnnotation(0, 75, 50, 101,stroke,outlinePaint);XYBoxAnnotation box10 = new XYBoxAnnotation(50, 0, 75, 50,stroke,outlinePaint);XYBoxAnnotation box11 = new XYBoxAnnotation(50, 50, 75, 75,stroke,outlinePaint);XYBoxAnnotation box12 = new XYBoxAnnotation(50, 75, 75, 101,stroke,outlinePaint);XYBoxAnnotation box20 = new XYBoxAnnotation(75, 0, 101, 50,stroke,outlinePaint);XYBoxAnnotation box21 = new XYBoxAnnotation(75, 50, 101, 75,stroke,outlinePaint);XYBoxAnnotation box22 = new XYBoxAnnotation(75, 75, 101, 101,stroke,outlinePaint);XYPlot xyplot = (XYPlot) jfreechart.getPlot();xyplot.addAnnotation(box00);xyplot.addAnnotation(box01);xyplot.addAnnotation(box02);xyplot.addAnnotation(box10);xyplot.addAnnotation(box11);xyplot.addAnnotation(box12);xyplot.addAnnotation(box20);xyplot.addAnnotation(box21);xyplot.addAnnotation(box22);//添加区间标识XYTextAnnotation text1 = new XYTextAnnotation("盲区", 4, 98);text1.setFont(FontUtil.getFont(Font.PLAIN, 18));text1.setPaint(new Color(255,165,0));XYTextAnnotation text2 = new XYTextAnnotation("待发展共识区", 10, 3);text2.setFont(FontUtil.getFont(Font.PLAIN, 18));text2.setPaint(new Color(253, 88, 72));XYTextAnnotation text3 = new XYTextAnnotation("潜能区", 96, 3);text3.setFont(FontUtil.getFont(Font.PLAIN, 18));text3.setPaint(new Color(45, 139, 251));XYTextAnnotation text4 = new XYTextAnnotation("优势共识区", 93, 98);text4.setFont(FontUtil.getFont(Font.PLAIN, 18));text4.setPaint(new Color(20, 149, 134));xyplot.addAnnotation(text1);xyplot.addAnnotation(text2);xyplot.addAnnotation(text3);xyplot.addAnnotation(text4);}}

class XYPointerFrameAnnotation extends XYTextAnnotation implements Cloneable, PublicCloneable, Serializable

package ponent.chart;import org.jfree.chart.annotations.XYTextAnnotation;import org.jfree.chart.axis.ValueAxis;import org.jfree.chart.plot.Plot;import org.jfree.chart.plot.PlotOrientation;import org.jfree.chart.plot.PlotRenderingInfo;import org.jfree.chart.plot.XYPlot;import org.jfree.io.SerialUtilities;import org.jfree.text.TextUtilities;import org.jfree.ui.RectangleEdge;import org.jfree.ui.TextAnchor;import org.jfree.util.ObjectUtilities;import org.jfree.util.PublicCloneable;import java.awt.*;import java.awt.geom.Line2D;import java.awt.geom.Rectangle2D;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;/*** Created by fgm on /7/4.*/public class XYPointerFrameAnnotation extends XYTextAnnotation implements Cloneable, PublicCloneable, Serializable{private static final long serialVersionUID = -4031161445009858499L;public static final double DEFAULT_TIP_RADIUS = 10.0D;public static final double DEFAULT_BASE_RADIUS = 40.0D;public static final double DEFAULT_LABEL_OFFSET = 8.0D;public static final double DEFAULT_ARROW_LENGTH = 10.0D;public static final double DEFAULT_ARROW_WIDTH = 3.0D;private double angle;private double tipRadius;private double baseRadius;private double arrowLength;private double arrowWidth;private transient Stroke arrowStroke;private transient Paint arrowPaint;private double labelOffset;private transient Paint linePaint;public XYPointerFrameAnnotation(String label, double x, double y, double angle) {super(label, x, y);this.angle = angle;this.tipRadius = 1;//连接线到点的距离this.baseRadius =50;//连接线的半径this.arrowLength =0;//箭头长度 不需要this.arrowWidth = 0;//箭头宽度 不需要this.labelOffset = 10;//label字体和竖线的距离this.arrowStroke = new BasicStroke(1.0F);this.arrowPaint = Color.WHITE;this.linePaint=Color.WHITE;}public double getAngle() {return this.angle;}public void setAngle(double angle) {this.angle = angle;}public double getTipRadius() {return this.tipRadius;}public void setTipRadius(double radius) {this.tipRadius = radius;}public double getBaseRadius() {return this.baseRadius;}public void setBaseRadius(double radius) {this.baseRadius = radius;}public double getLabelOffset() {return this.labelOffset;}public void setLabelOffset(double offset) {this.labelOffset = offset;}public double getArrowLength() {return this.arrowLength;}public void setArrowLength(double length) {this.arrowLength = length;}public double getArrowWidth() {return this.arrowWidth;}public void setArrowWidth(double width) {this.arrowWidth = width;}public Stroke getArrowStroke() {return this.arrowStroke;}public Paint getLinePaint() {return linePaint;}public void setLinePaint(Paint linePaint) {this.linePaint = linePaint;}public void setArrowStroke(Stroke stroke) {if(stroke == null) {throw new IllegalArgumentException("Null \'stroke\' not permitted.");} else {this.arrowStroke = stroke;}}public Paint getArrowPaint() {return this.arrowPaint;}public void setArrowPaint(Paint paint) {this.arrowPaint = paint;}public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) {PlotOrientation orientation = plot.getOrientation();RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(plot.getDomainAxisLocation(), orientation);RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(plot.getRangeAxisLocation(), orientation);double j2DX = domainAxis.valueToJava2D(this.getX(), dataArea, domainEdge);double j2DY = rangeAxis.valueToJava2D(this.getY(), dataArea, rangeEdge);double startX;if(orientation == PlotOrientation.HORIZONTAL) {startX = j2DX;j2DX = j2DY;j2DY = startX;}startX = j2DX + Math.cos(this.angle) * this.baseRadius;double startY = j2DY + Math.sin(this.angle) * this.baseRadius;double endX = j2DX + Math.cos(this.angle) * this.tipRadius;double endY = j2DY + Math.sin(this.angle) * this.tipRadius;g2.setStroke(this.arrowStroke);g2.setPaint(this.arrowPaint);Line2D.Double line = new Line2D.Double(startX, startY, endX, endY);g2.draw(line);g2.setFont(this.getFont());g2.setPaint(this.getPaint());double labelX = j2DX + Math.cos(this.angle) * (this.baseRadius + this.labelOffset);double labelY = j2DY + Math.sin(this.angle) * (this.baseRadius + this.labelOffset);Rectangle2D rectangle2D=TextUtilities.drawAlignedString(this.getText(), g2,(float)labelX, (float)labelY, TextAnchor.BASELINE_CENTER);//添加边框g2.setColor(Color.WHITE);g2.setStroke(new BasicStroke(1.0F));rectangle2D.setFrame(rectangle2D.getX()-3,rectangle2D.getY()-2,rectangle2D.getWidth()+5,rectangle2D.getHeight()+2);g2.draw(rectangle2D);}public boolean equals(Object obj) {if(obj == null) {return false;} else if(obj == this) {return true;} else if(!(obj instanceof XYPointerFrameAnnotation)) {return false;} else if(!super.equals(obj)) {return false;} else {XYPointerFrameAnnotation that = (XYPointerFrameAnnotation)obj;return this.angle != that.angle?false:(this.tipRadius != that.tipRadius?false:(this.baseRadius != that.baseRadius?false:(this.arrowLength != that.arrowLength?false:(this.arrowWidth != that.arrowWidth?false:(!this.arrowPaint.equals(that.arrowPaint)?false:(!ObjectUtilities.equal(this.arrowStroke, that.arrowStroke)?false:this.labelOffset == that.labelOffset))))));}}public Object clone() throws CloneNotSupportedException {return super.clone();}private void writeObject(ObjectOutputStream stream) throws IOException {stream.defaultWriteObject();SerialUtilities.writePaint(this.arrowPaint, stream);SerialUtilities.writeStroke(this.arrowStroke, stream);}private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {stream.defaultReadObject();this.arrowPaint = SerialUtilities.readPaint(stream);this.arrowStroke = SerialUtilities.readStroke(stream);}}

class PDFHeaderFooter implements HeaderFooterBuilder

package ponent;import com.itextpdf.text.Document;import com.itextpdf.text.Element;import com.itextpdf.text.Font;import com.itextpdf.text.Phrase;import com.itextpdf.text.pdf.ColumnText;import com.itextpdf.text.pdf.PdfContentByte;import com.itextpdf.text.pdf.PdfTemplate;import com.itextpdf.text.pdf.PdfWriter;import ponent.builder.HeaderFooterBuilder;/*** Created by fgm on /4/22.* 页眉页脚定制工具*/public class PDFHeaderFooter implements HeaderFooterBuilder {/*** @param writer PDF编写类* @param document PDF文档对象* @param data业务数据* @param font字体设置* @param template PDF模板* @description PDF页脚设置类*/public void writeFooter(PdfWriter writer,Document document,Object data,Font font,PdfTemplate template) {if (data == null) {return;}int pageS = writer.getPageNumber();int currentPage = pageS - 1;if (currentPage <= 0) {return;}Phrase footer1 = new Phrase("页脚一", font);Phrase footer2 = new Phrase("页脚二" + " " + currentPage + "/", font);PdfContentByte cb = writer.getDirectContent();ColumnText.showTextAligned(cb,Element.ALIGN_LEFT,footer1,(document.left() + 10),document.bottom() - 20,0);ColumnText.showTextAligned(cb,Element.ALIGN_RIGHT,footer2,(document.right() - 30),document.bottom() - 20, 0);//设置模板位置cb.addTemplate(template, document.right() - 30, document.bottom() - 20);}/*** @param writer PDF编写类* @param document PDF文档对象* @param data业务数据* @param font字体设置* @param template PDF模板* @description PDF页头设置类*/public void writeHeader(PdfWriter writer,Document document,Object data,Font font,PdfTemplate template) {ColumnText.showTextAligned(writer.getDirectContent(),Element.ALIGN_LEFT,new Phrase("我是页眉", font),document.left(),document.top() + 20, 0);}/*** @param writer PDF编写类* @param document PDF文档对象* @param data业务数据* @description 页头、页眉设置的模板替换类*/public String getReplaceOfTemplate(PdfWriter writer, Document document, Object data) {int total = writer.getPageNumber() - 2;return total + "";}}

PDFKit

package ponent;import com.itextpdf.text.Document;import com.itextpdf.text.PageSize;import com.itextpdf.text.pdf.PdfWriter;import com.itextpdf.tool.xml.XMLWorkerFontProvider;import com.itextpdf.tool.xml.XMLWorkerHelper;import lombok.extern.slf4j.Slf4j;import mons.io.IOUtils;import mons.lang.StringUtils;import org.xhtmlrenderer.pdf.ITextRenderer;import ponent.builder.HeaderFooterBuilder;import ponent.builder.PDFBuilder;import pdf.kit.exception.PDFException;import pdf.kit.util.FreeMarkerUtil;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.nio.charset.Charset;@Slf4jpublic class PDFKit {//PDF页眉、页脚定制工具private HeaderFooterBuilder headerFooterBuilder;private String saveFilePath;/*** @description导出pdf到文件* @param fileName 输出PDF文件名* @param data模板所需要的数据**/public String exportToFile(String fileName,Object data){String htmlData= FreeMarkerUtil.getContent(fileName, data);if(StringUtils.isEmpty(saveFilePath)){saveFilePath=getDefaultSavePath(fileName);}File file=new File(saveFilePath);if(!file.getParentFile().exists()){file.getParentFile().mkdirs();}FileOutputStream outputStream=null;try{//设置输出路径outputStream=new FileOutputStream(saveFilePath);//设置文档大小Document document = new Document(PageSize.A4);PdfWriter writer = PdfWriter.getInstance(document, outputStream);//设置页眉页脚PDFBuilder builder = new PDFBuilder(headerFooterBuilder,data);builder.setPresentFontSize(10);writer.setPageEvent(builder);//输出为PDF文件convertToPDF(writer,document,htmlData);}catch(Exception ex){throw new PDFException("PDF export to File fail",ex);}finally{IOUtils.closeQuietly(outputStream);}return saveFilePath;}/*** 生成PDF到输出流中(ServletOutputStream用于下载PDF)* @param ftlPath ftl模板文件的路径(不含文件名)* @param data 输入到FTL中的数据* @param response HttpServletResponse* @return*/public OutputStream exportToResponse(String ftlPath,Object data,HttpServletResponse response){String html= FreeMarkerUtil.getContent(ftlPath,data);try{OutputStream out = null;ITextRenderer render = null;out = response.getOutputStream();//设置文档大小Document document = new Document(PageSize.A4);PdfWriter writer = PdfWriter.getInstance(document, out);//设置页眉页脚PDFBuilder builder = new PDFBuilder(headerFooterBuilder,data);writer.setPageEvent(builder);//输出为PDF文件convertToPDF(writer,document,html);return out;}catch (Exception ex){throw new PDFException("PDF export to response fail",ex);}}/*** @description PDF文件生成*/private void convertToPDF(PdfWriter writer,Document document,String htmlString){//获取字体路径String fontPath=getFontPath();document.open();try {XMLWorkerHelper.getInstance().parseXHtml(writer,document,new ByteArrayInputStream(htmlString.getBytes()),XMLWorkerHelper.class.getResourceAsStream("/default.css"),Charset.forName("UTF-8"),new XMLWorkerFontProvider(fontPath));} catch (IOException e) {e.printStackTrace();throw new PDFException("PDF文件生成异常",e);}finally {document.close();}}/*** @description 创建默认保存路径*/private String getDefaultSavePath(String fileName){String classpath=PDFKit.class.getClassLoader().getResource("").getPath();String saveFilePath=classpath+"pdf/"+fileName;File f=new File(saveFilePath);if(!f.getParentFile().exists()){f.mkdirs();}return saveFilePath;}/*** @description 获取字体设置路径*/public static String getFontPath() {String classpath=PDFKit.class.getClassLoader().getResource("").getPath();String fontpath=classpath+"fonts";return fontpath;}public HeaderFooterBuilder getHeaderFooterBuilder() {return headerFooterBuilder;}public void setHeaderFooterBuilder(HeaderFooterBuilder headerFooterBuilder) {this.headerFooterBuilder = headerFooterBuilder;}public String getSaveFilePath() {return saveFilePath;}public void setSaveFilePath(String saveFilePath) {this.saveFilePath = saveFilePath;}}

BaseException

package pdf.kit.exception;/*** Created by fgm on /4/22.*/public class BaseException extends RuntimeException {public int errorCode;public String errorMsg;public BaseException(){super("运行时异常");}public BaseException(int errorCode, String errorMsg){super(errorMsg);this.errorCode=errorCode;this.errorMsg=errorMsg;}public BaseException(String errorMsg){super(errorMsg);this.errorCode=500;this.errorMsg=errorMsg;}public BaseException(String errorMsg, Exception e){super(errorMsg,e);this.errorCode=500;this.errorMsg=errorMsg;}}

FreeMarkerException

package pdf.kit.exception;/*** Created by fgm on /4/22.*/public class FreeMarkerException extends BaseException {public FreeMarkerException(){super("FreeMarker异常");}public FreeMarkerException(int errorCode, String errorMsg){super(errorMsg);this.errorCode=errorCode;this.errorMsg=errorMsg;}public FreeMarkerException(String errorMsg){super(errorMsg);this.errorCode=500;this.errorMsg=errorMsg;}public FreeMarkerException(String errorMsg, Exception e){super(errorMsg,e);this.errorCode=500;this.errorMsg=errorMsg;}}

PDFException

package pdf.kit.exception;/*** Created by fgm on /4/22.*/public class PDFException extends BaseException {public PDFException(){super("PDF异常");}public PDFException(int errorCode, String errorMsg){super(errorMsg);this.errorCode=errorCode;this.errorMsg=errorMsg;}public PDFException(String errorMsg){super(errorMsg);this.errorCode=500;this.errorMsg=errorMsg;}public PDFException(String errorMsg, Exception e){super(errorMsg,e);this.errorCode=500;this.errorMsg=errorMsg;}}

FontUtil

package pdf.kit.util;import mon.collect.Maps;import lombok.extern.slf4j.Slf4j;import mons.lang.exception.ExceptionUtils;import java.awt.*;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.Map;/*** Created by fgm on /4/22.*/@Slf4jpublic class FontUtil {private static final Map<String,Font> fontCache= Maps.newConcurrentMap();public static String getFontPath(String fontName){String classPath=FontUtil.class.getClassLoader().getResource("").getPath();return classPath+"/fonts/"+fontName;}/*** @description 加载自定义字体*/public static Font loadFont(String fontFileName, int style, float fontSize) throws IOException {FileInputStream fis=null;String key=fontFileName+"|"+style;Font dynamicFont=fontCache.get(key);if(dynamicFont==null){try{File file = new File(fontFileName);fis= new FileInputStream(file);dynamicFont = Font.createFont(style, fis);fontCache.put(key,dynamicFont);}catch(Exception e){return new Font("宋体", Font.PLAIN, 14);}finally{fis.close();}}Font dynamicFontPt = dynamicFont.deriveFont(fontSize);return dynamicFontPt;}public static Font getFont(int style,float fontSize){try {String fontPath = FontUtil.getFontPath("SIMLI.TTF");Font font = loadFont(fontPath,style,fontSize);return font;} catch (IOException e) {log.error("字体加载异常{}", ExceptionUtils.getFullStackTrace(e));}return null;}}

FreeMarkerUtil

package pdf.kit.util;import mon.collect.Maps;import freemarker.cache.FileTemplateLoader;import freemarker.template.Configuration;import freemarker.template.Template;import freemarker.template.TemplateExceptionHandler;import mons.lang.StringUtils;import ponent.PDFKit;import pdf.kit.exception.FreeMarkerException;import pdf.kit.exception.PDFException;import java.io.File;import java.io.IOException;import java.io.StringWriter;import java.util.Map;/*** Created by fgm on /4/22.* FREEMARKER 模板工具类*/public class FreeMarkerUtil {private static final String WINDOWS_SPLIT = "\\";private static final String UTF_8="UTF-8";private static Map<String,FileTemplateLoader> fileTemplateLoaderCache=Maps.newConcurrentMap();private static Map<String,Configuration> configurationCache= Maps.newConcurrentMap();public static Configuration getConfiguration(String templateFilePath){if(null!=configurationCache.get(templateFilePath)){return configurationCache.get(templateFilePath);}Configuration config = new Configuration(Configuration.VERSION_2_3_25);config.setDefaultEncoding(UTF_8);config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);config.setLogTemplateExceptions(false);FileTemplateLoader fileTemplateLoader=null;if(null!=fileTemplateLoaderCache.get(templateFilePath)){fileTemplateLoader=fileTemplateLoaderCache.get(templateFilePath);}try {fileTemplateLoader=new FileTemplateLoader(new File(templateFilePath));fileTemplateLoaderCache.put(templateFilePath,fileTemplateLoader);} catch (IOException e) {throw new FreeMarkerException("fileTemplateLoader init error!",e);}config.setTemplateLoader(fileTemplateLoader);configurationCache.put(templateFilePath,config);return config;}/*** @description 获取模板*/public static String getContent(String fileName, Object data) {String templatePath = getPDFTemplatePath(fileName);String templateFileName = getTemplateName(templatePath);String templateFilePath = getTemplatePath(templatePath);if (StringUtils.isEmpty(templatePath)) {throw new FreeMarkerException("templatePath can not be empty!");}try {Template template=getConfiguration(templateFilePath).getTemplate(templateFileName);StringWriter writer = new StringWriter();template.process(data, writer);writer.flush();return writer.toString();} catch (Exception ex) {throw new FreeMarkerException("FreeMarkerUtil process fail", ex);}}private static String getTemplatePath(String templatePath) {if (StringUtils.isEmpty(templatePath)) {return "";}if (templatePath.contains(WINDOWS_SPLIT)) {return templatePath.substring(0, templatePath.lastIndexOf(WINDOWS_SPLIT));}return templatePath.substring(0, templatePath.lastIndexOf("/"));}private static String getTemplateName(String templatePath) {if (StringUtils.isEmpty(templatePath)) {return "";}if (templatePath.contains(WINDOWS_SPLIT)) {return templatePath.substring(templatePath.lastIndexOf(WINDOWS_SPLIT) + 1);}return templatePath.substring(templatePath.lastIndexOf("/") + 1);}/*** @param fileName PDF文件名 (hello.pdf)* @return 匹配到的模板名* @description 获取PDF的模板路径,* 默认按照PDF文件名匹对应模板*/public static String getPDFTemplatePath(String fileName) {String classpath = PDFKit.class.getClassLoader().getResource("").getPath();String templatePath = classpath + "/templates";File file = new File(templatePath);if (!file.isDirectory()) {throw new PDFException("PDF模板文件不存在,请检查templates文件夹!");}String pdfFileName = fileName.substring(0, fileName.lastIndexOf("."));File defaultTemplate = null;File matchTemplate = null;for (File f : file.listFiles()) {if (!f.isFile()) {continue;}String templateName = f.getName();if (templateName.lastIndexOf(".ftl") == -1) {continue;}if (defaultTemplate == null) {defaultTemplate = f;}if (StringUtils.isEmpty(fileName) && defaultTemplate != null) {break;}templateName = templateName.substring(0, templateName.lastIndexOf("."));if (templateName.toLowerCase().equals(pdfFileName.toLowerCase())) {matchTemplate = f;break;}}if (matchTemplate != null) {return matchTemplate.getAbsolutePath();}if (defaultTemplate != null) {return defaultTemplate.getAbsolutePath();}return null;}}

default.css

pre, tt, code, kbd, samp {font-family: Courier;font-size: 9pt;line-height: 12pt;}dt {margin: 0;}/* styles below are taken from Mozilla Defaults */body {margin: 10%;font-size: 12pt;}p, dl, multicol {margin: 1em 0;}dd {margin-left: 40px;margin-bottom: 0;margin-right: 0;margin-top: 0;}blockquote, figure {margin: 1em 40px;}center {display: block;text-align: center;}blockquote[type="cite"] {border: 3px solid;padding-left: 1em;border-color: blue;border-width: thin;margin: 1em 0;}h1 {font-size: 2em;font-weight: bold;margin: 0.67em 0;}h2 {font-size: 1.5em;font-weight: bold;margin: 0.83em 0;}h3 {font-size: 1.17em;font-weight: bold;margin: 1em 0;}h4{font-size: 1em;font-weight: bold;margin: 1.33em 0;}h5 {font-size: 0.83em;font-weight: bold;margin: 1.67em 0;}h6 {font-size: 0.67em;font-weight: bold;margin: 2.33em 0;}listing {font-size: medium;margin: 1em 0;white-space: pre;}xmp, pre, plaintext {margin: 1em 0;white-space: pre;}table {margin-bottom: 0;margin-top: 0;margin-left: 0;margin-right: 0;text-indent: 0;}caption {text-align: center;}tr {vertical-align: inherit;}tbody {vertical-align: middle;}thead {vertical-align: middle;}tfoot {vertical-align: middle;}table > tr {vertical-align: middle;}td {padding: 1px;text-align: inherit;vertical-align: inherit;}th {display: table-cell;font-weight: bold;padding: 1px;vertical-align: inherit;}sub {font-size: smaller;vertical-align: sub;}sup {font-size: smaller;vertical-align: super;}nobr {white-space: nowrap;}mark {background: none repeat scroll 0 0 yellow;color: black;}abbr[title], acronym[title] {border-bottom: 1px dotted;}ul, menu, dir {list-style-type: disc;}ul li ul {list-style-type: circle;}ol {list-style-type: decimal;}hr {color: gray;height: 2px;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。