一、先在pom.xml中引入poi依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
关于办公文档插件使用的基本思想:把办公文档的所有元素封装成普通的Java类,程序员通过操作这些类达到操作办公文档的目的。
文件——HSSFWorkbook
页——HSSFSheet
行——HSSFRow
列——HSSFCell
样式——HSSFCellStyle
二、JSP页面
给导出按钮设置id="exportActivityAllBtn",添加单击事件发送请求
$("#exportActivityAllBtn").click(function () {
window.location.href="exportAllActivitys.do" ;
});
三、Controller层,使用返回的activityList导出到excel
@RequestMapping("/exportAllActivitys.do")
public void exportAllActivitys(HttpServletResponse response) throws Exception{
//调用service返回activityList
List<Activity> activityList = activityService.queryAllActivitys();
//用apache的poi创建excel文件,并把activityList写入excel文件中
//创建HSSFWorkbook对象,对应一个excel文件
HSSFWorkbook wb = new HSSFWorkbook();
//使用wb创建HSSFSheet对象,对应wb文件中的一页
HSSFSheet sheet = wb.createSheet("市场活动列表");//设置页名
//使用sheet创建HSSFRow对象,对应sheet中的一行
HSSFRow row = sheet.createRow(0);//索引为0就是第一行
//使用row创建HSSFCell对象,对应row中的列
HSSFCell cell = row.createCell(0);//索引为0就是第一列
//往列里设置值
cell.setCellValue("ID");
cell = row.createCell(1);
cell.setCellValue("所有者");
cell = row.createCell(2);
cell.setCellValue("活动名称");
cell = row.createCell(3);
cell.setCellValue("开始日期");
cell = row.createCell(4);
cell.setCellValue("结束日期");
cell = row.createCell(5);
cell.setCellValue("成本");
cell = row.createCell(6);
cell.setCellValue("描述");
cell = row.createCell(7);
cell.setCellValue("创建时间");
cell = row.createCell(8);
cell.setCellValue("创建者");
cell = row.createCell(9);
cell.setCellValue("修改时间");
cell = row.createCell(10);
cell.setCellValue("修改者");
//遍历ActivityList,创建Row
//先判断list有没有数据
if(activityList!=null&&activityList.size()>0){
Activity activity=null;//activity拿到外面定义就不用每次循环都创建,效率更高
for(int i=0;i<activityList.size();i++){
activity = activityList.get(i);
//每遍历出一个activity,生成一行
row=sheet.createRow(i+1);
cell = row.createCell(0);
cell.setCellValue(activity.getId());
cell = row.createCell(1);
cell.setCellValue(activity.getOwner());
cell = row.createCell(2);
cell.setCellValue(activity.getName());
cell = row.createCell(3);
cell.setCellValue(activity.getStartDate());
cell = row.createCell(4);
cell.setCellValue(activity.getEndDate());
cell = row.createCell(5);
cell.setCellValue(activity.getCost());
cell = row.createCell(6);
cell.setCellValue(activity.getDescription());
cell = row.createCell(7);
cell.setCellValue(activity.getCreateTime());
cell = row.createCell(8);
cell.setCellValue(activity.getCreateBy());
cell = row.createCell(9);
cell.setCellValue(activity.getEditTime());
cell = row.createCell(10);
cell.setCellValue(activity.getEditBy());
}
}
//改进后!!!!!!!!!!!!!!!!!!!!!
//设置响应类型 application/octet-stream表示excel文件
response.setContentType("application/octet-stream;charset=UTF-8");
//设置响应头 Content-Disposition打开方式 attachment以附件的形式
response.addHeader("Content-Disposition","attachment;filename=AllactivityList.xls");
OutputStream out = response.getOutputStream();
wb.write(out);
wb.close();
out.flush();//out由response生成的,tomcat会自己关闭,不能自己关闭,不flush可能会数据丢失
}
记得配置扫描Controller
四、Service和实现类
public interface ActivityService {
List<Activity> queryAllActivitys();
}
@Service("activityService")
public class ActivityServiceImpl implements ActivityService{
@Autowired
ActivityMapper activityMapper;
@Override
public List<Activity> queryAllActivitys() {
return activityMapper.selectAllActivitys();
}
}
记得配置扫描Service
五、Dao和mapper
public interface ActivityMapper {
//查询所有市场活动
List<Activity> selectAllActivitys();
}
<select id="selectAllActivitys" resultMap="BaseResultMap">
select a.id , u1.name as owner, a.name, a.start_date, a.end_date, a.cost, a.description, a.create_time,
u2.name as create_by, a.edit_time, u3.name as edit_by
from tbl_activity a
join tbl_user u1 on a.owner = u1.id
join tbl_user u2 on a.create_by = u2.id
left join tbl_user u3 on a.edit_by =u3.id
order by a.create_time desc
</select>
记得配置mapper注解扫描器
六、改进
先写到磁盘再读取磁盘效率太低了,正好workbook对象里有个方法wb.write(out) ,把workbook对象里的数据输出到outputStream对象out里,直接让它输出到浏览器。下面是未改前,上面已经改了。
OutputStream os = new FileOutputStream("E:\\serverDir\\activityList.xls");
wb.write(os);//wb.write(os)表示你要吧它生成到哪个文件。从内存写到磁盘。内存访问磁盘效率是很低的,要建立链接,占内存,占cpu,不亚于访问一次数据库
os.close();
wb.close();
//把生成的excel文件下载到客户端
//设置响应类型 application/octet-stream表示excel文件
response.setContentType("application/octet-stream;charset=UTF-8");
//设置响应头 Content-Disposition打开方式 attachment以附件的形式
response.addHeader("Content-Disposition","attachment;filename=AllactivityList.xls");
OutputStream out = response.getOutputStream();
InputStream is = new FileInputStream("E:\\serverDir\\activityList.xls");//从磁盘读到内存,要建立链接,占内存,占cpu,不亚于访问一次数据库
//缓存区,以一个字节数组为单位读更快
byte[] buff = new byte[256];
int len=0; //实际读取个数,等于-1时说明读完了
while((len=is.read(buff))!=-1){
out.write(buff,0,len);
}
is.close();
out.flush();//out由response生成的,tomcat会自己关闭,不能自己关闭,不flush可能会数据丢失,因为可能还在缓冲区里
七、总结
导出功能不能使用异步请求,这样下载框弹不出来,只能使用同步请求(三种:地址栏、超链接、表单)