【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
1. 设计需求
订票成功后,生成一个pdf 文件,用户打印入场票,门票大致如下所示:
2. 设计思想
- 1). 使用FreeMarker 转换 ftl(就是FreeMarker 魔板文件),生成HTML
- 2). 使用jtidy库将 HTML转换成 对格式要求严格的 XHTML
- 3 ) . 使用Itext 库将XHTML转换成PDF
3. Demo 创建
简介:本项目是在Maven 的环境中搭建的,其pom.xml 主要导入的依赖如下:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.6</version>
</dependency>
<dependency>
<groupId>net.sf.jtidy</groupId>
<artifactId>jtidy</artifactId>
<version>r938</version>
</dependency>
3.1 FreeMarker 魔板转换成pdf 源码如下:
public class FreeMarkToHtml {
/**
* 通过路径 和文件名称后去魔板
*
* @param templateFilePath
* @param templateFileName
* @return
*/
public static Template getTemplate(String templateFilePath, String templateFileName) {
try {
Configuration cfg = new Configuration();
cfg.setClassicCompatible(true);
TemplateLoader templateLoader = new FileTemplateLoader(new File(
templateFilePath));
cfg.setTemplateLoader(templateLoader);
return cfg.getTemplate(templateFileName);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @param templateFilePath
* @param templateFileName 加载的模板文件名
* @param replaceData
* @param outFile 生成指定文件
* @return 成功,返回文件名;失败,返回null。
*/
public static String freemarkToHtml(String templateFilePath, String templateFileName, Map<String, Object> replaceData,
String outFile) {
String path = null;
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(outFile), "UTF-8"));
Template temp = getTemplate(templateFilePath, templateFileName);
temp.setEncoding("UTF-8");
temp.process(replaceData, out);
path = outFile;
} catch (IOException e) {
e.printStackTrace();
path = null;
} catch (TemplateException e) {
e.printStackTrace();
path = null;
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return path;
}
}
3.1 使用jtidy库将 HTML转换成 对格式要求严格的 XHTML源码
/**
* 将html 转换成为严格的XHTML
*/
public class Html2Xhtml {
/**
* 转化类
*
* @param html html文件输入路径(带文件名称)
* @param xhtml xhtml文件输入路径(带文件名称)
* @return
*/
public static String html2Xhtml(String html, String xhtml) {
String path = null;
try {
FileInputStream fin = new FileInputStream(html);
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
int data = -1;
while ((data = fin.read()) != -1) {
byteArrayOut.write(data);
}
fin.close();
byte[] htmlFileData = byteArrayOut.toByteArray();
byteArrayOut.close();
ByteArrayInputStream tidyInput = new ByteArrayInputStream(
htmlFileData);
ByteArrayOutputStream tidyOut = new ByteArrayOutputStream();
Tidy tidy = new Tidy();
tidy.setInputEncoding("UTF-8");
tidy.setOutputEncoding("UTF-8");
tidy.setShowWarnings(false);
tidy.setIndentContent(true);
tidy.setSmartIndent(true);
tidy.setIndentAttributes(false);
tidy.setMakeClean(true);
tidy.setQuiet(true);
tidy.setWord2000(true);
tidy.setXHTML(true);
tidy.setErrout(new PrintWriter(System.out));
tidy.parse(tidyInput, tidyOut);
tidyInput.close();
tidyOut.writeTo(new FileOutputStream(xhtml));
tidyOut.flush();
tidyOut.close();
path = xhtml;
} catch (FileNotFoundException e) {
e.printStackTrace();
path = null;
} catch (IOException e) {
e.printStackTrace();
path = null;
}
return path;
}
}
3.3 使用Itext 库将XHTML转换成PDF
/**
* @Description: xhtml --> pdf
* @Author: liupenghao
* @Date: 2018/4/17 ❤❤ 11:16
*/
public class XHtml2Pdf {
/**
* 转化方法
*
* @param html html文件输入路径(带文件名称)
* @param pdf pdf文件输出路径(带文件名称)
*/
public static void XHtml2Pdf(String html, String pdf)
throws FileNotFoundException, IOException, DocumentException,
CssResolverException {
int i = html.lastIndexOf(".html");
String xhtml = null;
xhtml = html.substring(0, i) + ".xhtml";
xhtml = Html2Xhtml.html2Xhtml(html, xhtml);
if (xhtml != null) {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(pdf));
document.open();
FontProvider fontProvider = new FontProvider();
fontProvider.addFontSubstitute("lowagie", "garamond");
fontProvider.setUseUnicode(true);
// 使用我们的字体提供器,并将其设置为unicode字体样式
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(
cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
CSSResolver cssResolver = XMLWorkerHelper.getInstance()
.getDefaultCssResolver(true);
Pipeline<?> pipeline = new CssResolverPipeline(cssResolver,
new HtmlPipeline(htmlContext, new PdfWriterPipeline(
document, writer)));
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser p = new XMLParser(worker);
File input = new File(xhtml);
p.parse(new InputStreamReader(new FileInputStream(input), "UTF-8"));
document.close();
}
}
}
3.4 启动类编写
/**
* 描述:
*
* @author liupenghao
* @create 2018-04-17 9:58
**/
public class ApplicationStart {
public static void main(String[] args) {
URL url = Thread.currentThread().getContextClassLoader().getResource("");
Map replaceData = initData();
FreeMarkToHtml.freemarkToHtml(url.getPath(), "template.ftl", replaceData, url.getPath() + "result.html");
try {
XHtml2Pdf.XHtml2Pdf(url.getPath() + "result.html", url.getPath() + "result.pdf");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} catch (CssResolverException e) {
e.printStackTrace();
}
}
public static HashMap<String, Object> initData() {
HashMap<String, Object> needReplaceMapData = new HashMap<String, Object>();
/******************************************单个属性************************************/
needReplaceMapData.put("name", "刘亦菲");
/******************************************list 属性添加***********************************/
List<Student> students = new ArrayList<Student>();
for (int i = 0; i < 2; i++) {
Student student = new Student();
student.setId(i);
student.setName(" 葫芦娃" + i + "号");
students.add(student);
}
needReplaceMapData.put("students", students);
/******************************************日期 ***********************************/
needReplaceMapData.put("date", new Date());
needReplaceMapData.put("showDate", true);
needReplaceMapData.put("imgUrl", "http://n.sinaimg.cn/translate/344/w700h1244/20180410/B_F_-fyzeyqa1740187.jpg");
needReplaceMapData.put("description", "描述 一只猫");
return needReplaceMapData;
}
}
3.5 中文乱码的解决
/**
* @Description: 字体提供类, 更改 默认的字体
* @Author: liupenghao
* @Date: 2018/4/17 ❤❤ 11:19
*/
public class FontProvider extends XMLWorkerFontProvider {
public FontProvider() {
super(null, null);
}
@Override
public Font getFont(final String fontname, String encoding, float size,
final int style) {
String fntname = fontname;
if (fntname == null) {
fntname = "宋体";
}
return super.getFont(fntname, encoding, size, style);
}
}
4. 项目源码:
点击下载:github
来源:oschina
链接:https://my.oschina.net/u/3801804/blog/1796958