欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

创建Excel和PDF视图

程序员文章站 2022-06-09 12:33:47
...

用户有时可能希望将应用中的内容导出为Excel或PDF格式。Java中,有一些库可以帮助生成这些格式的文件。

然而,在web应用中直接使用这些库,你就需要在后台生成文件,并作为binary attachments返回给用户,

你需要处理HTTP响应头以及输出流。

 

Spring将Excel以及PDF文件的生成集成到了它的MVC框架中。你可以将Excel以及PDF当作是特殊类型的

视图,在controller中处理请求,将数据添加到model传给Excel和PDF视图。用这种办法,你就不需要处理

HTTP响应头以及输出流。

 

Spring MVC支持用Apache POI或JExcelAPI来生成Excel文件。相应的视图类是AbstractExcelView和

AbstractJExcelView。    导出PDF用的是iText库,相应的视图类是AbstractPdfView。

 

一、原理

假设用户需要生成一个报表,内容是某天的reservation summary。那么先在service层声明一个方法返回

某天的所有reservations。

package com.apress.springrecipes.court.service;
...
public interface ReservationService {
    ...
    public List<Reservation> findByDate(Date date);
}

实现类代码:

package com.apress.springrecipes.court.service;
...
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);
            }
        }
        return result;
    }
}

接下来是编写一个简单的controller从URL中得到date参数,此参数被格式化成一个date对象,传给

service层。controller依赖content negotiation resolver,因此,controller返回一个逻辑视图,让resolver

来决定该报表是以Excel还是PDF还是默认的HTML页面来展示。

package com.apress.springrecipes.court.web;
...
@Controller
@RequestMapping("/reservationSummary*")
public class ReservationSummaryController {
    private ReservationService reservationService;
 
    @Autowired
    public ReservationSummaryController(ReservationService reservationService) {
        this.reservationService = reservationService;
    }
 @RequestMapping(method = RequestMethod.GET)
    public String generateSummary(
           @RequestParam(required = true, value = "date") String selectedDate,
           Model model) {
        List<Reservation> reservations = java.util.Collections.emptyList();
        try {
            Date summaryDate = new SimpleDateFormat("yyyy-MM-dd").parse(selectedDate);
            reservations = reservationService.findByDate(summaryDate);
        } 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";
    }
 
}

上面的controller只包含一个默认的HTTP GET处理器方法。如果创建Date对象失败,程序抛出一个自定义

Spring异常叫ReservationWebException。如果try/catch块没有发生错误,控制器的Model对象中将放入

查询结果。最后,方法将控制交给reservationSummary视图。注意,控制器只返回一个视图,即使它

支持PDF,XLS以及HTML视图。原因是它利用了ContentNegotiatingViewResolver解析器,它会决定

用哪个视图。

 

1.1 创建Excel视图

我们可以扩展AbstractExcelView(POI)或AbstractJExcelView(JExcelAPI)来创建Excel视图。

这里,我们用AbstractExcelView举例。在buildExcelDocument()方法中,可以访问从控制器传来的

model,还有一个预先创建的Excel workbook,你的任务就是用model中的数据填充此workbook。

 

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.10-FINAL</version>
</dependency>

 

package com.apress.springrecipes.court.web.view;
...
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
import org.springframework.web.servlet.view.document.AbstractExcelView;
 
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());
        }
    }
}

 

可以用下面的URL来访问该excel视图:

http://localhost:8080/court/reservationSummary.xls?date=2009-01-14