出处:http://www.cnblogs.com/crazy-fox/archive/2012/02/18/2357705.html
Spring mvc 中对于输出格式为pdf和xsl的view,提供了两个abstract的view类供继承分别为AbstractPdfView和AbstractExcelView。 Pdf格式输出 对于pdf格式的输出,spring 缺省提供的模板类为AbstractPdfView,并利用iText来实现pdf的输出。但此类只支持iText 2.x的版本,而目前iText最新的版本是5.x,为支持最新版本的iText类库,需要根据AbstractPdfView的内容依样画葫芦自己实现一个PdfView模板类。
AbstractIText5PdfView AbstractView { AbstractIText5PdfView() { setContentType("application/pdf"); } @Override generatesDownloadContent() { ; } @Override renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) 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); } Document newDocument() { Document(PageSize.A4); } PdfWriter newWriter(Document document, OutputStream os) DocumentException { PdfWriter.getInstance(document, os); } prepareWriter(Map<String, Object> model, PdfWriter writer, HttpServletRequest request) DocumentException { writer.setViewerPreferences(getViewerPreferences()); } getViewerPreferences() { PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage; } buildPdfMetadata(Map<String, Object> model, Document document, HttpServletRequest request) { } buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) Exception; }
修改pom.xml,增加对iText 5 的类库引用。
com.itextpdf itext-asian 5.1.0 com.itextpdf itextpdf 5.1.0
继承AbstractIText5PdfView ,实现自己的pdf输出实现类
Pdfview AbstractIText5PdfView { @Override buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) Exception { Paragraph header = Paragraph( Chunk("PDF 输出测试", getChineseFont(24))); document.add(header); document.add( Paragraph("测试",getChineseFont(12))); } Font getChineseFont( size) { Font FontChinese = ; { BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); FontChinese = Font(bfChinese, size, Font.NORMAL); } (DocumentException de) { System.err.println(de.getMessage()); } (IOException ioe) { System.err.println(ioe.getMessage()); } FontChinese; } }
修改MultiAction controll类,增加对pdf输出的handler method测试代码
@RequestMapping("/pdf") String helloPDF(){ "helloPDF"; }
这里我们将使用ResourceBundleViewResolver来作为pdf view的ViewResolver,修改servlet context xml配置文件如下
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver"
p:basename="views" p:order="2" />
表示spring mvc将在classpath根目录下查找名为views.properties的配置文件来根据view name匹配对应的view实现类。 views.properties中的配置如下 helloPDF.(class)=net.zhepu.web.view.Pdfview 其中helloPDF与之前handler method返回的viewName相匹配,(class)表示此行配置是要将viewName和view实现类关联。 最后访问url http://localhost:8080/springmvc/pdf 以查看输出的pdf文件
Excel格式输出 Spring mvc利用POI或jExcel来实现对excel输出的支持,如果使用POI需要继承AbstractExcelView类,如果使用jExcel则需要继承AbstractJExcelView类。这里以POI为例。 首先修改pom.xml,增加对POI的引用。
org.apache.poi poi 3.7
再增加一个继承自AbstractExcelView的实现类,来实际输出excel
buildExcelDocument(Map<String, Object> model, HSSFWorkbook workbook, HttpServletRequest request, HttpServletResponse response) Exception { HSSFSheet sheet; HSSFCell cell; sheet = workbook.createSheet("Spring"); sheet.setDefaultColumnWidth(() 12); cell = getCell(sheet, 0, 0); setText(cell, "Spring-Excel 测试"); }
修改MultiAction controll类,增加对excel输出的handler method测试代码
@RequestMapping("/excel") String helloExcel(){ "excel"; }
同样可以使用ResourceBundleViewResolver来实现view name和view class的关联,但这里我们使用XmlViewResolver来实现。 修改servlet context xml配置文件,增加如下配置
<!-- excel output setting using XmlViewResolver -->
<bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="order" value="3" />
<property name="location" value="classpath:views.xml" />
</bean>
以上配置表示XmlViewResolver将在views.xml中查找viewname和view class的对应关系。Views.xml配置文件实际上就是一个标准的spring bean的配置文件。内容如下
<bean name="excel" class="net.zhepu.web.view.ExcelView" />
这样将bean name “excel”与view实现类相关联。 最后访问url http://localhost:8080/springmvc/excel 查看excel输出内容。
使用XmlViewResolver 和ResourceBundleViewResolver可能存在的问题 使用XmlViewReslover和ResourceBundleViewResolver后,访问sample工程的首页面helloWorld会发现页面出现报错信息 Bean named 'helloworld' must be of type [org.springframework.web.servlet.View], but was actually of type [net.zhepu.web.Helloworld] ,原因是这两个viewResolver本质上都是在配置文件中定义一个spring bean,并将bean name 和view name相关联来实现view mapping。因此实际上只要context中存在对应名字的bean name,spring 就可以根据相应的viewName找到匹配的view bean来生成视图。而这也导致类似如下的配置出现问题。
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver"
p:basename="views" p:order="1" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
对应的controller代码如下
@Controller("controllerHelloWorld") @RequestMapping("/helloworld") Helloworld { @RequestMapping(method=RequestMethod.GET) ModelAndView hello() { ModelAndView mv = ModelAndView(); mv.setViewName("helloworld"); mv; } }
此时访问/helloworld原意是要返回对应/WEB-INF/helloworld.jsp, 但spring mvc在解析viewname时,根据配置文件中的order顺序,先找到ResourceBundleViewResolver来解析viewname,且发现此时context中存在bean name 为 helloWorld的bean,就试图使用helloWorld这个bean来解析view,因此出现了上述的报错。 因此在使用ResourceBundleViewResolver或XmlViewResolver时需要注意返回的viewname不要和当前工程中已经定义的beanName存在冲突。