MVC中网页spring mvc 导出文件为PDF怎么实现

SpringMVC:生成Excel和PDF - 咫尺天涯 - ITeye技术网站
博客分类:
参考资料
1 用spring MVC 生成Excel和PDF
2 Spring MVC export data to Excel file via AbstractExcelView
3 用Java的iText实现PDF报表
使用JXL请关注:JXL2.6:解决JXL的IndexOutOfBoundsException getSheet问题,使用了修复版本的jxl包
一 工程代码结构图片
二 具体代码如下
1 index.jsp
&%@ page language="java" pageEncoding="UTF-8" contentType="text/ charset=UTF-8"%&
&!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&
&%@ taglib uri="/WEB-INF/c.tld" prefix="c"%&
&script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery/jquery-1.4.4.min.js"&&/script&
&%@ include file="/common/meta.jsp"%&
&script type="text/javascript"&
$(document).ready(function(){
$("#exec").click(function(){
//获取下拉框的值
var titlesValue = "";//$("#columns").find("option:selected").text();
$("#columns").find("option:selected").each(function(){ //由于复选框一般选中的是多个,所以可以循环输出
titlesValue += ($(this).text())+",";
var names =
$("#columns").val();
$("#colums").val(names);
$("#titles").val(titlesValue);
&body&&& &
&div style="border: 1px solid # width: 50%;height:200align:margin-top:200margin-left:300padding:50"&
&form action="${pageContext.request.contextPath}/view/excel.do" method="post"&
&input type="submit" value="使用POI导出Excel"&&br&
&form method="post" action="${pageContext.request.contextPath}/view/jxlExcel.do"&
&select id="columns" multiple="multiple" style="width:100height:120"&
&option value="id"&ID&/option&
&option value="name"&姓名&/option&
&option value="sex"&性别&/option&
&option value="age"&年龄&/option&
&option value="password"&密码&/option&
&option value="address"&地址&/option&
&input type="hidden" id="titles" name="titles"&
&input type="hidden" id="colums" name="colums"&
&input type="submit" id="exec" value="使用JXL导出Excel"&&br&
&form action="${pageContext.request.contextPath}/view/pdf.do" method="post"&
&input type="submit" value="导出PDF"&&br&
&img src="${pageContext.request.contextPath}/img/car.do" width="100px" height="50px"/&
2 ViewController.java
package com.liuzd.sj.
import java.util.ArrayL
import java.util.HashM
import java.util.L
import java.util.M
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import org.springframework.stereotype.C
import org.springframework.web.bind.annotation.RequestM
import org.springframework.web.bind.annotation.RequestP
import org.springframework.web.servlet.ModelAndV
import com.liuzd.sj.entity.S
import com.liuzd.sj.entity.U
* 生成excel或PDF类型试图 根据参数进行数据组装,并跳转到相应的视图页面 View Controller Bean&br&
@Controller
@RequestMapping("/view")
public class ViewController {
@RequestMapping("/excel")
public ModelAndView viewExcel(HttpServletRequest request,
HttpServletResponse response) {
Map model = new HashMap();
model.put("list", getStudents());
return new ModelAndView(new ViewExcel(), model);
private List getStudents(){
List stuList = new ArrayList();
// 构造数据
Student stu1 = new Student("gaoxiang1", "male1", "", 1);
Student stu2 = new Student("gaoxiang2", "male2", "", 2);
Student stu3 = new Student("gaoxiang3", "male3", "", 3);
Student stu4 = new Student("gaoxiang4", "male4", "", 4);
Student stu5 = new Student("gaoxiang5", "male5", "", 5);
stuList.add(stu1);
stuList.add(stu2);
stuList.add(stu3);
stuList.add(stu4);
stuList.add(stu5);
return stuL
@RequestMapping("/jxlExcel")
public ModelAndView viewJxlExcel(@RequestParam("titles") String titles,@RequestParam("colums") String colums,HttpServletRequest request,
HttpServletResponse response) {
String [] array1 =
if(null != colums && colums.indexOf(",") != -1){
array1 = colums.split(",");
String [] array2 =
if(null != titles && titles.indexOf(",") != -1){
array2 = titles.split(",");
Map model = new HashMap();
// 构造数据
List&User& users = new ArrayList&User&();
users.add(new User("123456", "李逵", "123", "成都市", "1", 23));
users.add(new User("123457", "李四", "124", "北京市", "2", 53));
users.add(new User("123458", "李三", "125", "河南市", "0", 73));
users.add(new User("123459", "李五", "126", "大路市", "3", 93));
model.put("list", users);
model.put("columns", array1);
model.put("titles", array2);
return new ModelAndView(new JXLExcelView(), model);
@RequestMapping("/pdf")
public ModelAndView viewPDF(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map model = new HashMap();
model.put("list", getStudents());
return new ModelAndView(new ViewPDF(), model);
3 JXLExcelView.java
package com.liuzd.sj.
import java.io.IOE
import java.io.OutputS
import java.net.URLE
import java.util.L
import java.util.M
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import jxl.W
import jxl.WorkbookS
import jxl.format.A
import jxl.format.VerticalA
import jxl.write.WritableCellF
import jxl.write.WritableF
import jxl.write.WritableS
import jxl.write.WritableW
import jxl.write.WriteE
import jxl.write.biff.RowsExceededE
import mons.beanutils.PropertyU
import org.springframework.web.servlet.view.document.AbstractJExcelV
import com.liuzd.sj.entity.U
public class JXLExcelView extends AbstractJExcelView {
private String[] columnNames = new String[] { "编号", "姓名", "年龄", "性别", "密码",
private String[] dbColumnNames = new String[] { "id", "name", "age", "sex",
"password", "address" };
private Integer[] columnWidths = new Integer[] { 20, 20, 20, 20, 20, 20 };
public void buildExcelDocument(Map&String, Object& map,
WritableWorkbook work, HttpServletRequest req,
HttpServletResponse response) {
String [] titles = (String[])map.get("titles");
if(null != titles && titles.length & 0){
columnNames =
String [] columns = (String[])map.get("columns");
if(null != columns &&
columns.length & 0){
dbColumnNames =
OutputStream os =
String excelName = "用户信息.xls";
// 设置response方式,使执行此controller时候自动出现下载页面,而非直接使用excel打开
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", " filename="
+ URLEncoder.encode(excelName, "UTF-8"));
os = response.getOutputStream();
// sheet名称
String sheetName = "用户信息";
// 全局设置
WorkbookSettings setting = new WorkbookSettings();
java.util.Locale locale = new java.util.Locale("zh", "CN");
setting.setLocale(locale);
setting.setEncoding("ISO-8859-1");
// 创建工作薄
work = Workbook.createWorkbook(os); // 建立excel文件
// 创建第一个工作表
jxl.write.WritableSheet ws = work.createSheet(sheetName, 1); // sheet名称
// 添加标题
addColumNameToWsheet(ws);
List&User& list = (List&User&) map.get("list");
writeContext(ws, list);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 写入文件
work.write();
work.close();
os.flush();
os.close();
} catch (WriteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
private &T& void writeContext(WritableSheet wsheet, List&T& list) {
int rows = list.size();
jxl.write.Label wlabel =
jxl.write.WritableCellFormat wcf = getFormat();
int cols = dbColumnNames.
String columnName =
Object value =
for (int i = 0; i & i++) {
T t = (T) list.get(i);
for (int j = 0; j & j++) {
columnName = dbColumnNames[j].toLowerCase();
value = PropertyUtils.getProperty(t, columnName);
wlabel = new jxl.write.Label(j, (i + 1), value + "", wcf);
wlabel = new jxl.write.Label(j, (i + 1), value + "");
wsheet.addCell(wlabel);
} catch (Exception e) {
e.printStackTrace();
// 添加标题样式
private void addColumNameToWsheet(jxl.write.WritableSheet wsheet)
throws RowsExceededException, WriteException {
// 设置excel标题
jxl.write.WritableFont wfont = getFont();
if (null == wfont) {
wfont = new WritableFont(WritableFont.ARIAL,
WritableFont.DEFAULT_POINT_SIZE, WritableFont.BOLD);
jxl.write.WritableCellFormat wcfFC = getFormat();
if (null == wcfFC) {
wcfFC = new jxl.write.WritableCellFormat(wfont);
wcfFC.setWrap(true);// 自动换行
wcfFC.setAlignment(Alignment.CENTRE);
wcfFC.setVerticalAlignment(VerticalAlignment.CENTRE);// 设置对齐方式
} catch (WriteException e) {
e.printStackTrace();
jxl.write.Label wlabel1 =
String[] columNames = columnN
if (null == columNames)
int colSize = columNames.
Integer[] colsWidth = columnW
if (null == colsWidth) {
colsWidth = new Integer[colSize];
for (int i = 0; i & colS i++) {
colsWidth[i] = 20;
int temp = 0;
String colName =
for (int i = 0; i & colS i++) {
colName = columNames[i];
if (null == colName || "".equals(colName))
colName = "";
wlabel1 = new jxl.write.Label(i, 0, colName, wcfFC);
wsheet.addCell(wlabel1);
temp = colsWidth[i].intValue();
// 默认设置列宽
temp = temp == 0 ? 20 :
wsheet.setColumnView(i, temp);
// 设置格式
private WritableCellFormat getFormat() {
jxl.write.WritableFont wfont = getFont();
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(
wcfFC.setWrap(true);
wcfFC.setAlignment(Alignment.CENTRE);
wcfFC.setVerticalAlignment(VerticalAlignment.CENTRE);
} catch (WriteException e) {
e.printStackTrace();
return wcfFC;
// 设置字体
private WritableFont getFont() {
return new WritableFont(WritableFont.ARIAL,
WritableFont.DEFAULT_POINT_SIZE, WritableFont.BOLD);
4 ViewExcel.java
package com.liuzd.sj.
import java.net.URLE
import java.util.I
import java.util.L
import java.util.M
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import org.apache.poi.hssf.usermodel.HSSFCellS
import org.apache.poi.hssf.usermodel.HSSFDataF
import org.apache.poi.hssf.usermodel.HSSFR
import org.apache.poi.hssf.usermodel.HSSFS
import org.apache.poi.hssf.usermodel.HSSFW
import org.springframework.web.servlet.view.document.AbstractExcelV
import com.liuzd.sj.entity.S
* 生成excel视图,可用excel工具打开或者保存
* 由ViewController的return new ModelAndView(viewExcel, model)生成
public class ViewExcel extends AbstractExcelView {
public void buildExcelDocument(Map model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String excelName = "用户信息.xls";
// 设置response方式,使执行此controller时候自动出现下载页面,而非直接使用excel打开
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", " filename="+ URLEncoder.encode(excelName, "UTF-8"));
List stuList = (List) model.get("list");
// 产生Excel表头
HSSFSheet sheet = workbook.createSheet("studentList");
HSSFRow header = sheet.createRow(0); // 第0行
// 产生标题列
header.createCell((short) 0).setCellValue("name");
header.createCell((short) 1).setCellValue("sex");
header.createCell((short) 2).setCellValue("date");
header.createCell((short) 3).setCellValue("count");
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("mm/dd/yyyy"));
// 填充数据
int rowNum = 1;
for (Iterator iter = stuList.iterator(); iter.hasNext();) {
Student element = (Student) iter.next();
HSSFRow row = sheet.createRow(rowNum++);
row.createCell((short) 0)
.setCellValue(element.getName().toString());
row.createCell((short) 1).setCellValue(element.getSex().toString());
row.createCell((short) 2)
.setCellValue(element.getDate().toString());
row.getCell((short) 2).setCellStyle(cellStyle);
row.createCell((short) 3).setCellValue(element.getCount());
// 列总和计算
HSSFRow row = sheet.createRow(rowNum);
row.createCell((short) 0).setCellValue("TOTAL:");
String formual = "SUM(D2:D" + rowNum + ")"; // D2到D[rowNum]单元格起(count数据)
row.createCell((short) 3).setCellFormula(formual);
5 ViewPDF.java
package com.liuzd.sj.
import java.net.URLE
import java.util.L
import java.util.M
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import org.springframework.web.servlet.view.document.AbstractPdfV
import com.liuzd.sj.entity.S
import com.lowagie.text.D
import com.lowagie.text.P
import com.lowagie.text.pdf.BaseF
import com.lowagie.text.pdf.PdfW
* 生成PDF视图,可用PDF浏览器打开或者保存
* 由ViewController的return new ModelAndView(viewPDF, model)生成
* @version Version 1.0
public class ViewPDF extends AbstractPdfView {
public void buildPdfDocument(Map model, Document document,
PdfWriter writer, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String excelName = "用户信息.pdf";
// 设置response方式,使执行此controller时候自动出现下载页面,而非直接使用excel打开
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", " filename="+ URLEncoder.encode(excelName, "UTF-8"));
List stuList = (List) model.get("list");
//显示中文
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
com.lowagie.text.Font FontChinese = new com.lowagie.text.Font(bfChinese, 12, com.lowagie.text.Font.NORMAL );
String value =
for (int i = 0; i & stuList.size(); i++) {
Student s = (Student)stuList.get(i);
value = "姓名: "+ s.getName()+",性别: "+s.getSex() + ",日期: " + s.getDate() + ",总数: " + s.getCount();
document.add(new Paragraph(value,FontChinese));
6 springmvc.xml
&?xml version="1.0" encoding="UTF-8" ?&
&beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"&
自动搜索@Controller标注的类
用于指明系统从哪个路径下寻找controller,然后提前初始化这些对象。
&context:component-scan base-package="com.liuzd.sj.web" /&
&mvc:annotation-driven/&
③:对模型视图名称的解析,即在模型视图名称添加前后缀 --&
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" /&
三 附件为工程源代码
四 相关jar包下载
jackson-all-1.8.1.jar请参见:SpringMVC:整合JQUERY与JSON
jexcelapi_2_6_12_1.jar
iText-POI.zip中包含jar包有:iText-2.1.2.jar,iTextAsian.jar,poi-3.7-.jar
下载次数: 892
下载次数: 675
浏览 13018
浏览: 1035976 次
来自: 成都
zyg 写道总结的很好,推荐一个框架整合:h ...
spring mvc demo教程源代码下载,地址:http: ...
pager.jar的page中好像没executePage,调 ...
//向任务2传递数据,这里不知怎么回事,传递参数在任务2取值为 ...1、通过iText生成pdf文件(包含中文)参照:
&&&&1)下载jar包:
&&&&&&&& & &&CORE 包:
&&&&&&&&&&&&XML &包:
&&&&2)前端页面
&input&type="button"&style="position:top:55right:20background:url(resources/images/48221_easyicon_net_48.png)&no-width:48height:48cursor:border:0"&onclick="download('&+&id&+&')"/&
function&download(id)&{
&&&&window.open("service.do?method=download&id="&+&id);
&&&&3)后台代码
@RequestMapping(params&=&"method=download")
public&void&download(@RequestParam("id")&Integer&id,&HttpServletRequest&req,&HttpServletResponse&response)&{
ServiceInfoEntity&serviceItem&=&configCategoryService.getServiceItem(id);
String&newsContent&=&"&div&id='pano_camera'&class='servie_info1'&&h3&"&+&
serviceItem.getNewsTitle()&+&
"&/h3&"&+&
serviceItem.getNewsContent()&+&"&/div&";
newsContent&=&"&!DOCTYPE&html&PUBLIC&\"-//W3C//DTD&XHTML&1.0&Transitional//EN\"&\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"&"&+&newsC
newsContent&=&newsContent.replaceAll("\240$",&"");
newsContent&=&"&html&&body&123&/body&&/html&";
String&path&=&req.getRealPath("/")&+&"resources"+&File.separator&+&"pdf";
String&filename&=&serviceItem.getNewsTitle();
FileOutputStream&
fos&=&new&FileOutputStream(path&+&File.separator&+&filename&+&".html");
OutputStreamWriter&osw&=&new&OutputStreamWriter(fos,&"UTF-8");&
&&&&&&&&osw.write(newsContent);
&&&&&&&&osw.flush();
&&&&&&&&fos.close();
&&&&&&&&osw.close();
&&&&&&&&ParseHtmlAsian.createPdf(path,&filename);
}&catch&(FileNotFoundException&e1)&{
//&TODO&Auto-generated&catch&block
e1.printStackTrace();
}&catch&(UnsupportedEncodingException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
}&catch&(IOException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
}&catch&(DocumentException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
File&file&=&new&File(path&+&File.separator&+&filename&+&".pdf");
PDFReport.exportPdfFile(newsContent,&req.getRealPath("/"),&serviceItem.getNewsTitle());
}&catch&(IOException&e1)&{
//&TODO&Auto-generated&catch&block
e1.printStackTrace();
byte[]&buf&=&new&byte[1024&*&1024&*&10];&&
&&&&int&len&=&0;&
ServletOutputStream&ut&=&
BufferedInputStream&br&=&&&
response.reset();&&
&&&&response.setHeader("Pragma",&"No-cache");&&
&&&&response.setHeader("Cache-Control",&"must-revalidate,&no-transform");&&
&&&&response.setDateHeader("Expires",&0L);&&
&&&&String&userAgent&=&req.getHeader("User-Agent");&&
&&&&boolean&isIE&=&(userAgent&!=&null)&&&&(userAgent.toLowerCase().indexOf("msie")&!=&-1);&
&&&&String&displayFilename&=&file.getName();
&&&&response.setContentType("application/x-download");&
&&&&if&(isIE)&{&&
&&&& try&{
displayFilename&=&URLEncoder.encode(displayFilename,&"UTF-8");
}&catch&(UnsupportedEncodingException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
&&&&&&&&response.setHeader("Content-Disposition",&"filename=\""&+&displayFilename&+&"\"");&&
&&&&}&else&{&&
&&&&&&&&try&{
displayFilename&=&new&String(displayFilename.getBytes("UTF-8"),&"ISO8859-1");
}&catch&(UnsupportedEncodingException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
&&&&&&&&response.setHeader("Content-Disposition",&"filename="&+&displayFilename);&&
br&=&new&BufferedInputStream(new&FileInputStream(file));
ut&=&response.getOutputStream();&&
&&&&while&((len&=&br.read(buf))&!=&-1)&&
&&&&&&&&ut.write(buf,&0,&len);
}&catch&(FileNotFoundException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
}&catch&(IOException&e)&{
//&TODO&Auto-generated&catch&block
e.printStackTrace();
package&com.superscene.vhscene.
import&java.io.F
import&java.io.FileInputS
import&java.io.FileOutputS
import&java.io.IOE
import&java.nio.charset.C
import&com.itextpdf.text.D
import&com.itextpdf.text.DocumentE
import&com.itextpdf.text.pdf.PdfW
import&com.itextpdf.tool.xml.XMLWorkerH
public&class&ParseHtmlAsian&{
&&&&&*&Creates&a&PDF&with&the&words&"Hello&World"
&&&&&*&@param&file
&&&&&*&@throws&IOException
&&&&&*&@throws&DocumentException
&&&&public&static&void&createPdf(String&path,&String&fileName)&throws&IOException,&DocumentException&{
&&&&&&&&//&step&1
&&&&&&&&Document&document&=&new&Document();
&&&&&&&&//&step&2
&&&&&&&&PdfWriter&writer&=&PdfWriter.getInstance(document,&new&FileOutputStream(new&File(path&+&File.separator&+&fileName&+&".pdf")));
&&&&&&&&//&step&3
&&&&&&&&document.open();
&&&&&&&&//&step&4
&&&&&&&&XMLWorkerHelper.getInstance().parseXHtml(writer,&document,
&&&&&&&&&&&&&&&&new&FileInputStream(path&+&File.separator&+&fileName&+&".html"),&Charset.forName("UTF-8"));
&&&&&&&&//&step&5
&&&&&&&&document.close();Spring3.X @MVC - (八)Spring MVC创建并导出Excel和PDF视图 - 脚本百事通Spring3.X @MVC - (八)Spring MVC创建并导出Excel和PDF视图
在Spring3.X @MVC - (七)Spring中强大的内容协商视图解析器的基础上,
来学习怎样在Spring中创建和导出Excel和PDF的视图。
尽管HTML是显示Web内容最常见的方法,但是有时候你的用户希望从Web应用中导出Excel或者PDF格式的内容。在java中,有许多的的程序库有助于生成Excel和PDF文件。但是,为了在Web应用中直接使用这些程序库,你必须在后台生成这些文件,然后将它们作为二进制返回给用户。为此你必须处理HTTP的响应头标和输出流。
2.解决方案:
Spring将Excel和PDF文件的生成集成到MVC框架中。你可以将Excel和PDF文件看作特殊类型的视图,因此你就可以在控制器中一致性地处理web请求,并将数据添加到一个传递给Excel和PDF视图的模式中。这样,你就没有必要再去考虑处理复杂的HTTP响应头标和输出流了。
Spring MVC支持使用Apache POI程序库(http://poi.apache.org)或者JExcel API程序库(http://jexcelapi.sourceforge.net)生成Excel文件。对应的视图类分别是AbstractExceView和AbstractJExcelView。PDF文件由IText程序库(/iText/)生成,对应的视图类是AbstractPdfView类。
3. 工作原理:
假定你的用户希望生成特定日期的预定摘要报告。他们希望这个报告可以以Excel、PDF或者基本的HTML格式生成。为了这个报告的生成功能,你可以在service层定义一个方法,返回具体日期的所有预定:
public interface ReservationService {
public List&Reservation& findByDate(Date date);
然后为这个方法提供一个简单的实现,枚举所有的预定:
public class ReservationServiceImpl implements ReservationService {
public List&Reservation& findByDate(Date date) {
List&Reservation& result = new ArrayList&Reservation&();
for (Reservation reservation : reservations) {
if (reservation.getDate().equals(date)) {
result.add(reservation);
接下来我们可以编写一个简单的控制器,该控制器会从URL请求中获取date,然后将date格式化为一个日期对象并且传递给服务层查询预订。控制器依赖上一节中所讲的内容协商视图解析器,因此控制器会返回一个逻辑视图,然后由解析器决定生成Excel, PDF,还是默认的HTML网页。
package com.wsheng.spring.
@Controller
@RequestMapping("/reservationSummary*")
public class ReservationSummaryController {
private ReservationService reservationS
@Autowired
public ReservationSummaryController(ReservationService reservationService) {
this.reservationService = reservationS
@RequestMapping(method = RequestMethod.GET)
public String generateSummary(
@RequestParam(required = true, value = "date") String selectedDate, Model model) {
List&Reservation& reservations = java.util.Collections.emptyList();
// Format date
Date summaryDate = new SimpleDateFormat("yyyy-MM-dd").parse(selectedDate);
reservations = reservationService.findByDate(summaryDate);
// Catch error if request parameter date is not in format
} catch (java.text.ParseException ex) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
throw new ReservationWebException("Invalid date format for reservation summary",new Date(),sw.toString());
model.addAttribute("reservations",reservations);
return "reservationSummary";
你可能注意到了,尽管我们设计该控制器的初衷是需要支持PDF,XLS和HTML视图,但是代码中只返回单一的视图(return "reservationSummary"),这是由ContentNegotiatingViewResolver解析器根据这个视图的名称确定使用哪一个视图。更多关于这个解析器的信息,你可以参照我的上一节博客:
创建Excel视图
Excel视图可以通过扩展AbstractExcelView(对于Apache POI)或者AbstractJExcelView(对于JExcel API)来创建。这里以POI及AbstractExcelView为例,在buildExcelDocument()方法中,你可以访问到Sping MVC控制器传递过来的模式Model和一个预先创建好的Excel工作薄,然后你所需要写的代码就是用模式中的数据来填充这个工作薄。在Maven中引入poi的dependency:
&dependency&
&groupId&org.apache.poi&/groupId&
&artifactId&poi&/artifactId&
&version&3.0.2-FINAL&/version&
&/dependency&
package com.wsheng.spring.web.
public class ExcelReservationSummary extends AbstractExcelView {
protected void buildExcelDocument(Map model, HSSFWorkbook workbook,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
List&Reservation& reservations = (List) model.get("reservations");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
HSSFSheet sheet = workbook.createSheet();
HSSFRow header = sheet.createRow(0);
header.createCell((short) 0).setCellValue("Court Name");
header.createCell((short) 1).setCellValue("Date");
header.createCell((short) 2).setCellValue("Hour");
header.createCell((short) 3).setCellValue("Player Name");
header.createCell((short) 4).setCellValue("Player Phone");
int rowNum = 1;
for (Reservation reservation : reservations) {
HSSFRow row = sheet.createRow(rowNum++);
row.createCell((short) 0).setCellValue(reservation.getCourtName());
row.createCell((short) 1).setCellValue(
dateFormat.format(reservation.getDate()));
row.createCell((short) 2).setCellValue(reservation.getHour());
row.createCell((short) 3).setCellValue(
reservation.getPlayer().getName());
row.createCell((short) 4).setCellValue(
reservation.getPlayer().getPhone());
因为我们前面在控制器中配置了@RequestMapping("/reservationSummary*"),URL请求中需要一个required的参数,date,所以可以这样访问Excel视图:
http://localhost:8088/wsheng-spring-mvc/reservationSummary.xlsdate= 可以下载或直接打开相关的excel,里面应该有2条值。
http://localhost:8088/wsheng-spring-mvc/reservationSummary.xlsdate= 可以看到页面上显示相应的异常信息。
http://localhost:8088/wsheng-spring-mvc/reservationSummary.xlsdate=可以下载或直接打开相关的excel,里面没有header信息,没有值。
创建PDF视图
PDF视图通过扩展AbstractPdfView类来创建。在buildPdfDocument()方法中,你可以访问控制器传递过来的模式Model和一个预先创建的PDF文档。然后将模式中的数据填充到该PDF文档中。添加itext的dependency
&dependency&
&groupId&com.lowagie&/groupId&
&artifactId&itext&/artifactId&
&version&2.0.8&/version&
&/dependency&
package com.wsheng.spring.web.
public class PdfReservationSummary extends AbstractPdfView {
protected void buildPdfDocument(Map model, Document document,
PdfWriter writer, HttpServletRequest request,
HttpServletResponse response) throws Exception {
List&Reservation& reservations =
(List&Reservation&) model.get("reservations");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Table table = new Table(5);
table.addCell("Court Name");
table.addCell("Date");
table.addCell("Hour");
table.addCell("Player Name");
table.addCell("Player Phone");
if (!reservations.isEmpty()) {
for (Reservation reservation : reservations) {
table.addCell(reservation.getCourtName());
table.addCell(dateFormat.format(reservation.getDate()));
table.addCell(Integer.toString(reservation.getHour()));
table.addCell(reservation.getPlayer().getName());
table.addCell(reservation.getPlayer().getPhone());
document.add(table);
因为我们前面在控制器中配置了@RequestMapping("/reservationSummary*"),URL请求中需要一个required的参数,date,所以可以这样访问PDF视图:
http://localhost:8088/wsheng-spring-mvc/reservationSummary.pdfdate=
为Excel和PDF视图创建视图解析器
在前面几篇博客中,我们知道了"根据名称解析视图”,知道了怎样将MVC控制器中返回的逻辑视图名称解析为具体视图的不同的策略。这里我们选择用资源集(properties)文件的方式,即将对PDF和XLS类别的视图的映射的配置放在properties中。
1. 在Web应用上下文中(court-servlet.xml)中配置ResourceBundleViewResolver bean作为视图解析器。
2. 确保在Web应用的classpath根目录下有views.properties和secondaryviews.properties.
在views.properties中包含:
reservationSummary.(class)=com.wsheng.spring.web.view.ExcelReservationSummary
在secondaryviews.properties中包含:
reservationSummary.(class)=com.wsheng.spring.web.view.PdfReservationSummary
在控制器中返回的逻辑视图名称是reservationSummary。ContentNegotiatingViewResolver解析器的任务是根据用户的请求确定使用哪一个各类。一旦确定了这一点,执行对应的类生成PDF或者XLS文件。
此时你可能已经发现无论是你使用http://localhost:8088/wsheng-spring-mvc/reservationSummary.xlsdate=
或者使用http://localhost:8088/wsheng-spring-mvc/reservationSummary.pdfdate=
此时浏览器提示的都是保存或者打开reservationSummary.pdf或者reservationSummary.xls这种命名习惯是基于用户请求资源的URL的。但是,我们还在URL中提供了日期的信息,如果能自动保存为reservationSummary_.xls或者reservationSummary_.pdf,就是一个很好的功能。为了实现这个功能,我们可以通过一个拦截器来重写返回的URL。
public class ExtensionInterceptor extends HandlerInterceptorAdapter {
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
//Model model) throws Exception {
ModelAndView modelAndView) throws Exception {
// Report date is present in request
String reportName =
String reportDate = request.getQueryString().replace("date=","").replace("-","_");
if (request.getServletPath().endsWith(".pdf")) {
reportName= "ReservationSummary_" + reportDate + ".pdf";
if (request.getServletPath().endsWith(".xls")) {
reportName= "ReservationSummary_" + reportDate + ".xls";
// ONLY if its a PDF or XLS extension rewrite response URL
// If reportName name was modified, its PDF or XLS
if (reportName != null) {
// Set "Content-Disposition" HTTP Header so a user gets a pretty 'Save as' address
response.setHeader("Content-Disposition"," filename="+reportName);
1. request.getQueryString()返回的是请求url中”?“后面的内容。
2. request.getServletPath()返回的是请求url中""前面的内容。
3. 为了确保用户接收到下载提示,用相应的文件名的名称的格式(pdf/xls)来设置Content-Disposition HTTP头标。
在web上下文中,配置该Interceptor,order为0即优先级最高,当url请求中有reservationSummary的时候,由该interceptor处理。
&bean id="publicMapper" class="org.springplugins.web.SelectedAnnotationHandlerMapping"&
&property name="order" value="0" /&
&property name="urls"&
&value&/reservationSummary*&/value&
&/property&
&property name="interceptors"&
&ref bean="summaryReportInterceptor" /&
&/property&
总结: 尽管这个应用中使用了ContentNegotiatingViewResolver解析器选择合适的视图,但是修改返回URL的过程超出了视图解析器的范围。因此,有必要使用拦截器人工检查请求扩展名,并且设置必要的HTTP头标,修改输出的URL。
更多文章:

我要回帖

更多关于 mvc 导出pdf 的文章

 

随机推荐