最近临时做个PDF 生成预览 下载的一些东西,了解了下,发现itext 这个插件包 和spring 是已经集成在一起的,其实itext 已经很强大了,普通的servlet 也够了,这里先大概介绍一下吧!
spring mvc 里面的视图结构很多,这里我转载一下:
可以看到其中有AbstractPdf 的类,这里简单介绍它,如果你要用其他的视图,可以参考该图,是否已经实现。
// 可以看出 是继承的抽象视图,可以参考上面图例,具体内容我们这里不探讨,直接看方法 public abstract class AbstractPdfView extends AbstractView {
// 这里是设置了我们返回类型 public AbstractPdfView() { setContentType("application/pdf"); } // 这里默认是下载 @Override protected boolean generatesDownloadContent() { return true; }
@Override // 这个方法和名字描述一样,就是创建输出模型的,总的来说是创建Document protected final void renderMergedOutputModel( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // IE workaround: write into byte array first. ByteArrayOutputStream baos = createTemporaryOutputStream(); // 这里创建 itext 是识别的Document // Apply preferences and build metadata. Document document = newDocument(); PdfWriter writer = newWriter(document, baos); prepareWriter(model, writer, request); buildPdfMetadata(model, document, request); // Build PDF document. document.open(); // 具体PDF内容让子类自己处理,后面我们会看到。 buildPdfDocument(model, document, writer, request, response); document.close(); // Flush to HTTP response.返回客户端 writeToResponse(response, baos); }
// 默认A4 大小 protected Document newDocument() { return new Document(PageSize.A4); } // 创建流对象 protected PdfWriter newWriter(Document document, OutputStream os) throws DocumentException { return PdfWriter.getInstance(document, os); }
从上面看,整个过程很简单,抽象了一些行为,但是大部分都要子类进行实现,一些简单的功能 也是调用itext 里面的东西进行实现,大部分情况我们只需要itext 就行了,这里仅仅作为spring 视图特性的一种介绍。
因为spring 3.0 支持itext 2的版本,而 我是itest 5 版本,导入引入路径变了,这里我仿照上面的类,从新写一个。
/** * 这里就全部复制spring 的,然后引入的东西改成第5版的就行了 * 代码 几乎不变,唯一变的是引用路径~。~ 没贴出来了,自己导入就能看见 * @author Ran * */ public abstract class AbstractIText5PdfView extends AbstractView { public AbstractIText5PdfView() { setContentType("application/pdf"); } @Override protected boolean generatesDownloadContent() { return true; } @Override protected final void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获得流 ByteArrayOutputStream baos = createTemporaryOutputStream(); Document document = newDocument(); PdfWriter writer = newWriter(document, baos); prepareWriter(model, writer, request); buildPdfMetadata(model, document, request); document.open(); buildPdfDocument(model, document, writer, request, response); document.close(); writeToResponse(response, baos); } protected Document newDocument() { return new Document(PageSize.A4); } protected PdfWriter newWriter(Document document, OutputStream os) throws DocumentException { return PdfWriter.getInstance(document, os); } protected void prepareWriter(Map<String, Object> model, PdfWriter writer, HttpServletRequest request) throws DocumentException { writer.setViewerPreferences(getViewerPreferences()); } protected int getViewerPreferences() { return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage; } protected void buildPdfMetadata(Map<String, Object> model, Document document, HttpServletRequest request) { } protected abstract void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception; }
下面看看我的子类,如何构建我们需要的对象
/** * * @author 生成我需要的PDF * */ public class BusinessPdfView extends AbstractIText5PdfView{ // 标题 public static final String title_content = "测试数据"; // 敬语 public static final String honorific_content ="亲爱的程序员:"; // 这是主体内容 public static String context = "我的名字叫:{name} 编号:{no}{#}" +"这是另一行内容:{xxx}"; // 表格标题 public static String[] cellTitles = {"标题1","标题2","标题3"}; // 银行信息 public static String bank_content = "请贵司将货款汇入我公司如下银行帐户:{account}"; public static void test(Map<String,Object> map){ } // 从写方法 // 这里我要实现一个 大概这样的PDF // 标题 //抬头: // 正文(...) // 表格(...) @Override protected void buildPdfDocument(Map<String, Object> map, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception { try{ document.open(); // 标题居中 Paragraph title = PDFUtil.getParagraph( new Chunk(title_content,new Font(PDFUtil.bfChinese,16,Font.BOLD))); title.setAlignment(Paragraph.ALIGN_CENTER); // 中文 黑体 document.add(title); Paragraph head = PDFUtil.getParagraph(honorific_content); head.setSpacingBefore(20); head.setSpacingAfter(10); document.add(head); // 正文 List<Paragraph> paragraphs = PDFUtil.createParagraphs(context, map); for(Paragraph p : paragraphs){ document.add(p); } // 表格标题 PdfPTable table = new PdfPTable(cellTitles.length); table.setSpacingBefore(20); table.setSpacingAfter(30); for(String str : cellTitles){ table.addCell(PDFUtil.getParagraph(str)); } // 表格数据 List<String> cells = (List<String>) map.get("poTableList"); if(cells != null){ for(String cell : cells){ table.addCell(cell); } } document.add(table); // 关闭 document.close(); }catch (Exception e) { e.printStackTrace(); } } }
上面代码很简单,我仅仅是向Document 里面设置各种值,段落等信息就行,其他的spring 就帮我们搞定。其中我用到一个工具类,这里也贴出来。
工具类仅仅是封装了itext 的API,然后对我需要的参数替换 规则,以及换行等内容进行了处理。
还有关键的编码处理,一会介绍。
/** * 这仅仅作为itext5 提供一些方法,更多的需要自己去看相关API * @author Ran * */ public class PDFUtil { // 对参数的封装形式比如{name} public static final String BEGIN = "{"; public static final String END = "}"; // 换行形式{#} public static final String NEW_LINE = "#"; // 默认的行间距、首行距离等,自己添加 public static final float DEFAULT_LEADING = 20; public static final float DEFAULT_LINE_INDENT = 30; // 基本字体和样式 public static BaseFont bfChinese; public static Font fontChinese; public static Font UNDER_LINE = null; static{ try { // SIMKAI.TTF 默认系统语言,这里没使用第三方语言包 //bfChinese = BaseFont.createFont(PDFTest.class.getResource("/content/")+"SIMKAI.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); fontChinese = new Font(bfChinese, 14, Font.NORMAL); UNDER_LINE = new Font(bfChinese, 14,Font.UNDERLINE); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } // 默认样式 public static Paragraph getParagraph(String context){ return getParagraph(context,fontChinese); } public static Paragraph getParagraph(Chunk chunk){ return new Paragraph(chunk); } // 指定字体样式 public static Paragraph getParagraph(String context,Font font){ return new Paragraph(context,font); } // 获得新行,首行缩进,和行间距 public static Paragraph getNewParagraph(String context,float fixedLeading,float firstLineIndent){ Paragraph p = getParagraph(context); p.setLeading(fixedLeading); p.setFirstLineIndent(firstLineIndent); return p; } public static Paragraph getParagraph(String content , Font font , float fixedLeading , int alignment){ Paragraph p = getParagraph(content); p.setFont(font); p.setLeading(fixedLeading); p.setAlignment(alignment); return p; } // 默认段落样式 public static Paragraph getDefaultParagraph(String context){ Paragraph p = getParagraph(context); // 默认行间距 p.setLeading(DEFAULT_LEADING); // 默认首行空隙 p.setFirstLineIndent(DEFAULT_LINE_INDENT); return p; } // 将参数和字符串内容组合成集合 public static List<Paragraph> createParagraphs(String context ,Map<String,Object> map){ int index = 0; List<Paragraph> list = new ArrayList<Paragraph>(); Paragraph p = getDefaultParagraph(null); while((index = context.indexOf(BEGIN)) > -1){ String text = context.substring(0,index); context = context.substring(index, context.length()); index = context.indexOf(END); String param = null; if(index > 0){ param = context.substring(BEGIN.length(),index); } p.add(text); if(!NEW_LINE.equals(param)){ Object value = map.get(param); if(value != null){ p.add(new Chunk(value.toString(),UNDER_LINE)); }else{ p.add(new Chunk("")); } }else{ list.add(p); p = getDefaultParagraph(null); p.setSpacingBefore(0); } context = context.substring(index+END.length(),context.length()); } list.add(p); list.add(getParagraph(context)); return list; } }
当子类完成了之后,回到我们的控制层,看看如何调用。
@RequestMapping("/business/applyFor.pdf") public ModelAndView text(HttpServletRequest req, HttpServletResponse res){ Map<String,Object> map = new HashMap<String,Object>(); // 参数 设置,这里略,根据自己的东西进行匹配吧。 BusinessPdfView view = new BusinessPdfView(); view.setAttributesMap(map); // 这里使用了spring mvc 的人,应该不陌生,其他配置就略了。 return new ModelAndView(view); }
上面就完成了,整个过程,重点还是itext API 那些调用,下面我们用itext 单独生成PDF,这里类可以导入的jar,可以直接使用:语言包请下载我从新打包的
public class PDFTest { // 基本字体和样式 static BaseFont bfChinese = null; static Font fontChinese = null; static String CHANGE_LINE = "\n "; static Font UNDER_LINE = null; /** * 这里 * @param args * @throws IOException */ public static void main(String[] args) throws IOException { Document document = new Document(PageSize.A4, 33, 33, 33, 33); PdfWriter writer = null; try { // 语言 .tif 结尾的,都是Windows下的,我是拷贝进行项目了 //bfChinese = BaseFont.createFont( PDFTest.class.getResource("/content/")+"SIMKAI.TTF",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED); // 这里我用的第三方语言包,具体的操作,后面说,有一定更改,这里可以测试 bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED); fontChinese = new Font(bfChinese, 14, Font.NORMAL); UNDER_LINE = new Font(bfChinese, 14,Font.UNDERLINE); writer = PdfWriter.getInstance(document, new FileOutputStream("hellword.pdf")); // 打开 document.open(); Paragraph title = new Paragraph(); // 设置页面格式 title.setSpacingBefore(8); title.setSpacingAfter(2); title.setAlignment(1); // 设置PDF标题 title.add(new Chunk("付款申请书",new Font(bfChinese, 16,Font.BOLD))); document.add(title); // 抬头 Paragraph head = getParagraph("致:程序员们"); head.setSpacingBefore(30); document.add(head); // 文字参数 Map<String,String> map = new HashMap<String, String>(); map.put("name", "ranqiqiang"); map.put("sex", "男"); map.put("height", "178"); map.put("time", new Date().toString()); // 文字数据 String str = getString(); List<Paragraph> l = getPars(str, map); for(Paragraph p : l){ document.add(p); } //表格数据 //创建一个有4列的表格 PdfPTable table = new PdfPTable(4); // 可以对表格进行控制 // 默认会生成普通cell,特殊cell 要通过PdfPCell 进行设置 table.addCell(getParagraph("发票税率")); table.addCell(getParagraph("发票编号")); table.addCell(getParagraph("发票类型")); table.addCell(getParagraph("金额")); // 剩余的表格数据 List<String> cells = getTableParams(); for(String cell:cells){ table.addCell(getParagraph(cell)); } document.add(table); document.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } } // 给Dcouemnt 添加内容 public Document setDocumentContext(Document document,List<Paragraph> paragraphs){ if(paragraphs != null){ for(Paragraph paragraph : paragraphs){ try { document.add(paragraph); } catch (DocumentException e) { e.printStackTrace(); } } } return document; } public static String setParams(String context,List<String> params,String str_replace){ if(context == null || params == null || str_replace == null){ return context; } for(String param : params){ Chunk chunk = new Chunk(param, UNDER_LINE); context = context.replaceFirst(str_replace, chunk.toString()); } return context; } public static void setParams(String param,Paragraph pa){ pa.add( new Chunk(param, UNDER_LINE)); } public static String setParams(String context,List<String> params){ return setParams(context, params,"\\?"); } public static List<Chunk> getListChunks(List<String> params){ List<Chunk> chunks = new ArrayList<Chunk>(); for(String param : params){ Chunk e = new Chunk(param, UNDER_LINE); chunks.add(e); } return chunks; } public static List<String> getList(){ List<String> params = new ArrayList<String>(); params.add("计划-08-采购-购置-传输08-202-002-006"); params.add("2008503180"); params.add("993290.00"); params.add("到货款"); params.add("20%"); params.add("198658.00"); params.add("壹拾玖万捌仟陆佰伍拾捌圆整"); params.add("1"); params.add("198658.00"); return params; } public static final String BEGIN = "{"; public static final String END = "}"; public static final String NEW_LINE = "#"; public static final float DEFAULT_LEADING = 20; public static final float DEFAULT_LINE_INDENT = 30; public static String getString2(){ String str = "贵司与我司签订的采购合同,合同编号:" +"{conNo},采购订单号:{poNo} ,该合同金额为:{conMoney} 。" +"{#} 发票明细:{pp} {#} 魔法:{xx} {#} OVER!"; return str; } public static String getString(){ String str = "{#}工程师们,大家晚上好,我叫:{name},性别:{sex},身高:{height}cm." + "当前时间是:{time}{#}" + "这是文字行的测试数据,下面我们尝试表格型的测试数据。" + "{#}这里展示我们的订单信息:{#}"; return str; } public static List<String> getTableParams(){ // 为了方便就按顺序存放 List<String> l = new ArrayList<String>(); l.add("%12"); l.add("T9090990"); l.add("食品类发票"); l.add("1000.0"); l.add("%15"); l.add("Q12023"); l.add("服务类发票"); l.add("9999.0"); return l; } public static List<Paragraph> getPars(String context ,Map<String,String> map){ int index = 0; List<Paragraph> list = new ArrayList<Paragraph>(); Paragraph p = getDefaultParagraph(null); while((index = context.indexOf(BEGIN)) > -1){ String text = context.substring(0,index); context = context.substring(index, context.length()); index = context.indexOf(END); String param = null; if(index > 0){ param = context.substring(BEGIN.length(),index); } p.add(text); if(!NEW_LINE.equals(param)){ Object value = map.get(param); if(value != null){ p.add(new Chunk(value.toString(),UNDER_LINE)); }else{ p.add(new Chunk(param)); } }else{ list.add(p); p = getDefaultParagraph(null); p.setSpacingBefore(0); } context = context.substring(index+END.length(),context.length()); } list.add(p); list.add(getParagraph(context)); return list; } // 默认样式 public static Paragraph getParagraph(String context){ return getParagraph(context,fontChinese); } // 指定字体样式 public static Paragraph getParagraph(String context,Font font){ return new Paragraph(context,font); } // 获得新行,首行缩进,和行间距 public static Paragraph getNewParagraph(String context,float fixedLeading,float firstLineIndent){ Paragraph p = getParagraph(context); p.setLeading(fixedLeading); p.setFirstLineIndent(firstLineIndent); return p; } // 默认段落样式 public static Paragraph getDefaultParagraph(String context){ Paragraph p = getParagraph(context); // 默认行间距 p.setLeading(DEFAULT_LEADING); // 默认首行空隙 p.setFirstLineIndent(DEFAULT_LINE_INDENT); return p; } }
上面的类,可能有点乱,也是测试用用。在语言包的选择上,itext 5 的和我下到的iTextAsian.jar 不同,因为引用路径变了,也就是说解压iTextAsian.jar,然后将lowagie 改为itextpdf 就行了,然后从新压缩。
命令:jar cvf iTextAsian.jar com/itextpdf/text/pdf/fonts/*
这里我都做好了,下面两个jar,可以直接使用。
小结:
1.最近比较忙,上面的例子很粗糙,但是能给大家一个思路,基本上照着上面的写都可以完成。
2.对于itext 的使用,我也是第一次,很多地方不完善,API 以及语言 还不深入,暂时能用就行,需要深入的,大家自己研究。
3.spring mvc 提供了很多视图,大家平时操作的时候,可以先了解下,如果提供了,可以减少你的部分代码。
4.如果有误的地方,请指出,非常感谢~。~
相关推荐
对于PDF和Excel格式的输出,Spring MVC可以通过Apache POI库来处理Excel,使用Flying Saucer或iText库来生成PDF。这些库能够将HTML内容转换为所需的格式,方便导出和下载。 总的来说,Spring MVC是Spring框架的重要...
这个例子展示了如何使用 Spring MVC 和相关的库(Apache POI 和 iText)来动态生成 Excel 和 PDF 文件,提供给用户下载。整个流程涉及到 Spring MVC 的配置、控制器的编写以及与第三方库的集成,实现了从数据到视图...
iTextPDF能够很好地与Servlets、Spring MVC等Web框架集成,通过HTTP响应直接将PDF发送到客户端浏览器。 iTextPDF有多个版本,每个版本可能包含性能优化、新特性或对旧API的改进。例如,早期版本可能不支持PDF/A标准...
Java是一种广泛使用的编程语言,尤其在企业级应用开发中占据主导...综上所述,这个压缩包提供了Java项目中用于生成PDF和Word文档所需的库,同时考虑了Spring框架的集成,适合需要进行文档导出功能的Java开发者使用。
将两者整合,可以方便地在Spring MVC应用中动态生成复杂的报表。以下是对整合过程的详细讲解: 1. **iReport介绍** iReport是一款开源的报表设计工具,基于JasperReports库,支持多种数据源和多种报表样式,包括...
在 Spring MVC 中,我们通常会借助第三方库如 Apache PDFBox、iText 或 Flying Saucer 来生成或处理 PDF 文件。 首先,要使用 PDF 功能,我们需要在项目中引入相应的依赖。例如,如果选择 iText 作为 PDF 处理库,...
easypoi教程总结为我们提供了关于easypoi的详细使用教程,涵盖了Excel、Word、HTML、PDF等多种文档的导出和导入操作,以及与Spring MVC框架的集成。通过学习本教程,我们可以快速掌握easypoi的使用,并应用于实际...
10. **iText-2.1.3.jar**: iText是一个用于生成PDF文档的Java库。在Spring Web应用中,可能会用于生成PDF格式的发票、合同等文档。 综合以上分析,这个压缩包包含的库展示了Spring 2.5 Web应用的典型组件和依赖,...
生成PDF和Excel文件的功能常用于报表或者数据导出。PDF生成可以借助iText、Apache PDFBox等库,而Excel生成则可以使用Apache POI库。在SSM框架中,可以通过Controller接收请求,调用后台服务生成文件,然后以流的...
1. **Web应用集成**:将转换服务集成到Java Web应用程序中,如Spring MVC或Servlet,用户可以通过HTTP请求上传文件,服务器端进行转换,然后返回转换后的PDF。 2. **文件存储和访问**:转换后的PDF文件需要存储在...
首先,我们需要确保在项目中引入了必要的库,这可能包括Struts2的核心库、JasperReport库以及相关的依赖,例如iText(用于PDF生成)和Apache POI(用于Excel生成)。 1. **Struts2配置**: - 在`struts.xml`配置...
在服务器端,可以使用如Spring MVC的Controller来处理请求,返回一个包含Base64编码PDF内容的HTML页面。浏览器接收到这个页面后,解析HTML并显示Base64解码后的PDF。 5. **安全性考虑**:尽管通过Java服务器端处理...
在Java中,可以使用Apache POI库来操作Excel文件,iText库来生成PDF文件。 导出Excel功能通常涉及到读取数据源,如数据库或文件,然后将数据填充到Excel工作表中。而导出PDF则需要将HTML、文本或图像转换成PDF格式...
8. itext-2.1.0.jar:iText是一个用于生成和处理PDF文档的Java库,可以在服务器端生成PDF报告。 9. axis2-kernel-1.6.2.jar:Apache Axis2是Web服务引擎,用于处理SOAP消息,实现Web服务的发布和调用。 这些库的...
10. itext-2.1.7.jar:基础版本的iText库,用于生成PDF。 这些库在构建复杂的Web应用程序时经常被用到,例如,FreeMarker和JSTL可以作为Spring MVC的视图技术,BeanUtils帮助处理对象属性,而日志库则用于记录应用...
4. **iText或Apache PDFBox**:这两个库主要用于生成PDF报表。iText提供了API来创建、修改和解析PDF文档,而Apache PDFBox是Apache软件基金会的一个项目,用于处理PDF文档。 5. **JavaFX**:JavaFX是一个用于构建...
在Java中,通常使用iText或Apache PDFBox库来生成PDF文件。这两个库都提供了API来创建、修改PDF文档,包括添加文本、图片、表格等元素,从而实现从应用中导出PDF报告。 以上技术的整合可以创建一个完整的Java企业级...
只有当你的Web应用需要生成PDF输出时,才需要包含这个JAR文件。 14. **J2EE** - **JAR文件**:activation.jar, connector-api.jar, ejb.jar, jaxrpc.jar, jdb... - **说明**:对于J2EE相关的各种不同JAR文件,...
4. **itext**:iText是一个用于处理PDF文档的Java库,可以用于生成或修改PDF文件。在Spring应用中,这可能用于生成报表或文档,尤其是在需要服务器端处理PDF生成的场景下。 5. **serp**:SERP(Software ...