Apache POI组件操作Excel,制作报表(四)

     上一篇 我们介绍了如何制作复杂报表的分析和设计,本篇结合Spring MVC框架来说一下如何在Web层使用POI组件来动态生成报表供用户查看或下载。为什么选择Spring MVC框架,理由很简单,因为Spring的MVC框架对Excel视图的扩展使用的正是POI组件,那么使用Spring来整合就非常方便了,当然其它的框架都有自己的处理办法,这个可以具体咨询其对视图扩展支持的配置方法。 
    使用Spring对Excel的支持,需要扩展MVC的视图组件,就是要创建一个自定义的View,这个在后面会详细介绍,通过这个view,就可以将Excel报表展现出来了,非常方便。 
    基于Spring MVC的程序,那么首先要构建起来Spring MVC的环境,这个很简单,下面我们来看看如何搭建Spring MVC环境。我们使用Spring 3.0.5的库,但是配置方式不用注解,用传统的配置方式来说明。 
    使用Maven管理项目,引入必要的依赖,如下: 
 
    并建立如下的项目结构: 
 
    在web.xml描述符中,首先配置Spring配置文件的路径: 
Xml代码   收藏代码
  1. <context-param>  
  2.     <param-name>contextConfigLocation</param-name>  
  3. <param-value>classpath:org/ourpioneer/spring/*.xml,classpath:org/ourpioneer/spring/*/*.xml</param-value>  
  4. </context-param>  
  5. <listener>  
  6. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  7. </listener>  

    其次配置一个字符过滤器,使用Spring提供的就好,这样就不用过多考虑字符编码的问题了: 
Xml代码   收藏代码
  1. <filter>  
  2.     <filter-name>EncodingFilter</filter-name>  
  3.     <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
  4.     <init-param>  
  5.         <param-name>encoding</param-name>  
  6.         <param-value>UTF-8</param-value>  
  7.     </init-param>  
  8.     <init-param>  
  9.         <param-name>forceEncoding</param-name>  
  10.         <param-value>true</param-value>  
  11.     </init-param>  
  12. </filter>  
  13. <filter-mapping>  
  14.     <filter-name>EncodingFilter</filter-name>  
  15.     <url-pattern>/*</url-pattern>  
  16. </filter-mapping>  

    最后是Spring MVC的ServletDispatcher配置了: 
Xml代码   收藏代码
  1. <servlet>  
  2.     <servlet-name>board</servlet-name>  
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  4.     <init-param>  
  5.         <param-name>contextConfigLocation</param-name>  
  6.         <param-value>/WEB-INF/Dispatcher-Servlet.xml</param-value>  
  7.     </init-param>  
  8. </servlet>  
  9. <servlet-mapping>  
  10.     <servlet-name>board</servlet-name>  
  11.     <url-pattern>*.do</url-pattern>  
  12. </servlet-mapping>  

    我们配置了一个初始化文件,在Servlet加载时会加载这个配置文件,并使用*.do风格的映射地址。在这个初始配置文件中,主要配置了映射和拦截器等信息。内容如下: 
Xml代码   收藏代码
  1.     <!-- 扩展命名拦截器 -->  
  2. <bean id="extensionInterceptor"  
  3. class="org.ourpioneer.excel.web.interceptor.ExtensionInterceptor"></bean>  
  4. <!-- 控制器映射 -->  
  5. <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  6.     <property name="interceptors">  
  7.         <list>  
  8.             <ref bean="extensionInterceptor" />  
  9.         </list>  
  10.     </property>  
  11.     <property name="mappings">  
  12.         <props>  
  13.             <prop key="/excel.do">ExcelController</prop>  
  14.         </props>  
  15.     </property>  
  16. </bean>  

    其中扩展名拦截器是对生成Excel文件后的扩展名进行处理的,这个后面会说,下面就是配置映射,这里我们只有一个测试,那么就写一个映射即可,最后使用这个地址来测试,配置好映射信息后,那么就要配置其中的每个映射,那么来看看ExcelController的配置: 
Xml代码   收藏代码
  1. <bean id="ExcelController" class="org.ourpioneer.excel.web.controller.ExcelController">  
  2. <property name="reportService" ref="reportService" />  
  3. <property name="reportView" ref="reportView" />  
  4. lt;/bean>  

    这个也很简单,注入两个属性,一个service和一个view。为什么要用view,因为Spring MVC已经和POI进行了整合,这两个bean分别配置一下即可,这里不再说明了。详见附件中的完整源码。下面来看看控制器: 
Java代码   收藏代码
  1. package org.ourpioneer.excel.web.controller;  
  2. import java.util.HashMap;  
  3. import java.util.List;  
  4. import javax.servlet.http.HttpServletRequest;  
  5. import javax.servlet.http.HttpServletResponse;  
  6. import org.ourpioneer.excel.bean.CruiseServiceLocation;  
  7. import org.ourpioneer.excel.service.ReportService;  
  8. import org.ourpioneer.excel.web.views.ReportView;  
  9. import org.springframework.web.servlet.ModelAndView;  
  10. import org.springframework.web.servlet.mvc.AbstractController;  
  11.   
  12. /** 
  13.  * Excel处理控制器 
  14.  *  
  15.  * @author Nanlei 
  16.  *  
  17.  */  
  18. public class ExcelController extends AbstractController {  
  19.     private ReportView reportView;  
  20.     private ReportService reportService;  
  21.     public void setReportView(ReportView reportView) {  
  22.         this.reportView = reportView;  
  23.     }  
  24.     public void setReportService(ReportService reportService) {  
  25.         this.reportService = reportService;  
  26.     }  
  27.     @Override  
  28.     protected ModelAndView handleRequestInternal(HttpServletRequest request,  
  29.             HttpServletResponse response) throws Exception {  
  30.         HashMap model = new HashMap();  
  31.         List<CruiseServiceLocation> cslList = reportService  
  32.                 .getCruiseLocationList();  
  33.         model.put("cruiseServiceLocationList", cslList);  
  34.         return new ModelAndView(reportView, model);   
  35.     }  
  36. }  

    控制器扩展了AbstractController,覆盖了handleRequestInternal方法,这样就可以编写我们自定义的处理代码了。类开始是对service和view的注入,业务代码中从Service中获取了数据,然后放入model中,这个model是一个HashMap,也是Spring MVC中传递数据的纽带,使用方便。就像Struts2中的值栈一样,不过这个是显式使用,而值栈更像是隐式存在的数据桥梁。那么来看看Service: 
Java代码   收藏代码
  1. package org.ourpioneer.excel.service;  
  2.   
  3. import java.util.Arrays;  
  4. import java.util.List;  
  5.   
  6. import org.ourpioneer.excel.bean.CruiseServiceLocation;  
  7.   
  8. /** 
  9.  * 报表数据业务类 
  10.  *  
  11.  * @author Nanlei 
  12.  *  
  13.  */  
  14. public class ReportService {  
  15.     /** 
  16.      * 获取数据 
  17.      *  
  18.      * @return 
  19.      */  
  20.     public List<CruiseServiceLocation> getCruiseLocationList() {  
  21.         CruiseServiceLocation csl[] = new CruiseServiceLocation[21];  
  22.         csl[0] = new CruiseServiceLocation("T001""北京市""北京总部""bj""清华大学",  
  23.                 20);  
  24. ...  
  25.         csl[20] = new CruiseServiceLocation(""""""""""0);// 合并算法捕捉最后一行有问题,增补一行无效数据,计算时去除  
  26.   
  27.         return Arrays.asList(csl);  
  28.     }  
  29. }  

    这是很简单的类了,数据是我们准备好的,实际应用中就可以操作数据库了,这都没是由什么难度。下面来看一下展示Excel的View: 
Java代码   收藏代码
  1. package org.ourpioneer.excel.web.views;  
  2. /** 
  3.  * 报表的Excel视图 
  4.  *  
  5.  * @author Nanlei 
  6.  *  
  7.  */  
  8. public class ReportView extends AbstractExcelView {  
  9.   
  10.     @Override  
  11.     protected void buildExcelDocument(Map<String, Object> model,  
  12.             HSSFWorkbook workbook, HttpServletRequest request,  
  13.             HttpServletResponse response) throws Exception {  
  14.         // 从model中获取数据对象  
  15.         List<CruiseServiceLocation> cruiseServiceLocationList = (List<CruiseServiceLocation>) model  
  16.                 .get("cruiseServiceLocationList");  
  17. …  
  18.     }  
  19. }  

    中间的处理代码不贴出了,这和以前的都是一样的。主要来看这个视图的写法,因为要生成Excel,那么就扩展AbstractExcelView,覆盖其中的buildExcelDocument方法,它为我们提供了存储数据的model,创建Excel的POI API,还有请求和响应对象,这都是很熟悉的内容了。首先是从model对象中取出我们放置的数据列表,下面是用POI来制作报表,之前已经写过,都是一模一样的代码,就不贴出了。 
    至此,配置结束,就剩下一个问题了,触发该请求后,数据填充完毕要展示给用户看,可此时还没有配置文件类型的信息,要给用户合理的反馈,那么就需要对处理后的结果进行最后的处理,这就是前面提到的拦截器。 
Java代码   收藏代码
  1. package org.ourpioneer.excel.web.interceptor;  
  2. import java.net.URLEncoder;  
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Date;  
  5. import java.util.Map;  
  6. import javax.servlet.http.HttpServletRequest;  
  7. import javax.servlet.http.HttpServletResponse;  
  8. import org.apache.commons.lang.StringUtils;  
  9. import org.springframework.web.servlet.ModelAndView;  
  10. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  
  11.   
  12. /** 
  13.  * 扩展名命名处理拦截器 
  14.  *  
  15.  * @author Nanlei 
  16.  *  
  17.  */  
  18. public class ExtensionInterceptor extends HandlerInterceptorAdapter {  
  19.     /** 
  20.      * 用在流程处理之后 
  21.      */  
  22.     @Override  
  23.     public void postHandle(HttpServletRequest request,  
  24.             HttpServletResponse response, Object handler,  
  25.             ModelAndView modelAndView) throws Exception {  
  26.         // 获取Controller过来的Model对象  
  27.         Map model = modelAndView.getModel();  
  28.         // 获取请求URI  
  29.         String uri = request.getRequestURI();  
  30.         // 生成文件的名称  
  31.         String exportFileName = null;  
  32.         if (uri.endsWith("excel.do")) {  
  33.             String time = new SimpleDateFormat("yyyyMMddHHmmss")  
  34.                     .format(new Date());  
  35.             exportFileName = "报表" + time + ".xls";  
  36.         }  
  37.         if (StringUtils.isNotEmpty(exportFileName)) {  
  38.             response.setHeader("Content-Disposition""attachment; filename="  
  39.                     + URLEncoder.encode(exportFileName, "UTF-8"));  
  40.         }  
  41.         super.postHandle(request, response, handler, modelAndView);  
  42.     }  
  43. }  

    Spring的拦截器也相当简练,看看这个方法名就知道这是在流程处理结束之后的拦截器,而流程处理之前可以不配置,也就是拦截器可以配置成前后不同的处理方法,同时允许链接拦截器。它不像Struts2的拦截器,处理前通过1,2,3,处理后再通过3,2,1要走两次相同内容。更为高效。 
    在这里,我们可以拿到model对象从其中取出一些控制器传递过来的参数,当然这是根据需要使用的,之后获取到请求uri,来处理这个uri,是excel.do结尾的请求,我们要作为附件下载来体现,那么就要重新命名,然后设置响应对象,这也就是一般下载流程的最后一个步骤,很简单。 
    写完代码,在Maven中配置项目 
 
    这部分的介绍就全部结束了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值