Spring3MVC and POI

本教程我们将通过Apache的 POI进行excel的导出和写入:
即把数据库的数据导出excel格式,
读取excel表报中的数据并写入数据库.

我们将会使用mysql进行数据的操作.

POI是什么?

引用
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程式对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 POI 的功能。


也可以访问 Apache POI 官方网站

目前最新版本为3.8b2,此教程我们将采用3.7版本.

对于POI的基本用法可以观看官方的 quick-guide

下面是我们的应用程序文件夹结构:

Spring3MVC and POI_第1张图片

然后是pom.xml里添加的jar包:

Spring3MVC and POI_第2张图片

注意:poi的jar包一定要导入poi-ooxml
通过依赖顺便能导入poi.
如果直接导入poi后面的WebbookFactory将找不到jar包.

在数据库spring3db中创建一个表 computer
CREATE TABLE `computer` (
  `ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `BRAND` VARCHAR(255) DEFAULT NULL,
  `CPU` VARCHAR(255) DEFAULT NULL,
  `GPU` VARCHAR(255) DEFAULT NULL,
  `MEMORY` VARCHAR(255) DEFAULT NULL,
  `PRICE` DOUBLE DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=INNODB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8


也可以直接把附件代码中src/main/resource/data下面的spring3db.sql导入数据库中.
导入后的数据库如下所示

Spring3MVC and POI_第3张图片


首先添加Spring MVC所必须的配置.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

	<welcome-file>index.jsp</welcome-file>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		/WEB-INF/application-dataSource.xml
		/WEB-INF/applicationContext.xml
		</param-value>
	</context-param>

	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>


</web-app>



在web.xml中我们定义servlet:spring.
按照惯例,我们必须声明一个spring-servle.xml

spring-servle.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<!-- 定义一个视图解析器 -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver"
		p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

	<!-- Spring分段文件上传所必须的 ,用于检查请求中是否包含multipart
	see: http://www.html.org.cn/books/springReference/ch13s08.html
	-->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:maxUploadSize="5000000"
	 />
		
</beans>


这个XML配置声明一个视图解析器.在控制器中会根据JSP名映射到/ WEB-INF/jsp中相应的位置.
spring-servle.xml中的multipartResolver是Spring分段文件上传所必须的 ,用于检查请求中是否包含multipart.
更多的详情 对分段文件上传(multipart file upload)的支持

要进行数据库操作,一定需要一个数据库连接的配置.

jdbc.properties
# database properties
#spring3db is databaseName.
app.jdbc.driverClassName=com.mysql.jdbc.Driver
app.jdbc.url=jdbc:mysql://localhost/spring3db
app.jdbc.username=root
app.jdbc.password=root



application-dataSource.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:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	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/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<description>dataSource配置</description>

	<!-- 指定数据库配置文件地址. -->
	<context:property-placeholder location="classpath*:/jdbc.properties"/>
	
	 <!-- 启用注释管理事务注释风格. -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

	<!--声明一个数据源.c3p0-->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close"
		p:driverClass="${app.jdbc.driverClassName}"
		p:jdbcUrl="${app.jdbc.url}"
		p:user="${app.jdbc.username}"
		p:password="${app.jdbc.password}"
		p:acquireIncrement="5"
		p:idleConnectionTestPeriod="60"
		p:maxPoolSize="100"
		p:maxStatements="50"
		p:minPoolSize="10" 
		p:maxIdleTime="25000"
	/>
	
	<!--声明一个事务管理器. -->
	<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
	p:dataSource-ref="dataSource" />
	

</beans>



该文件主要配置了:
1.启用了事务管理
2.声明了一个数据源

然后创建一个applicationContext.xml.

applicationContext.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: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">

	<!-- 激活spring的注解. -->
	<context:annotation-config />

	<!-- 扫描注解组件并且自动的注入spring beans中. 
	例如,他会扫描@Controller 和@Service下的文件.所以确保此base-package设置正确. -->
	<context:component-scan base-package="org.liukai.tutorial" />

	<!-- 配置注解驱动的Spring MVC Controller 的编程模型.注:此标签只在 Servlet MVC工作! -->
	<mvc:annotation-driven />
	
</beans>



至此,基本的配置文件就完成了.

然后我们定义一个Computer对象

Computer.java
package org.liukai.tutorial.domain;

import java.io.Serializable;

public class Computer implements Serializable {

	private static final long serialVersionUID = 7955753961332480136L;

	private Long id;
	private String brand;
	private String cpu;
	private String gpu;
	private String memory;
	private Double price;

	//getter&setter

}




接下来就是POI来操作excel了.

需要注意的是POI里每个不同的模块代表了对不同格式档案的操作.如下:

 
引用
 
    HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
    XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
    HWPF - 提供读写Microsoft Word DOC格式档案的功能。
    HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
    HDGF - 提供读Microsoft Visio格式档案的功能。
    HPBF - 提供读Microsoft Publisher格式档案的功能。
    HSMF - 提供读Microsoft Outlook格式档案的功能。


在本教程中我们是实现对excel的操作.所以包含了HSSF和XLSX(开头在pom导入中强调了需要
导入ooxml的jar包,也包含了XSSF)

对导出的excel进行自定义格式:

Layouter.java
package org.liukai.tutorial.poi;


import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.liukai.tutorial.utils.DateUtils;

/**
 * 更多单元格请查看http://justdoblogger.com/blog/200911/setfillforegroundcolor.html
 * 
 * @author liukai
 * 
 */
@SuppressWarnings("deprecation")
public class Layouter {

	/**
	 * 创建报表
	 */
	public static void buildReport(HSSFSheet worksheet, int startRowIndex,
			int startColIndex) {
		// 设置列的宽度
		worksheet.setColumnWidth(0, 5000);
		worksheet.setColumnWidth(1, 5000);
		worksheet.setColumnWidth(2, 5000);
		worksheet.setColumnWidth(3, 5000);
		worksheet.setColumnWidth(4, 5000);
		worksheet.setColumnWidth(5, 5000);

		buildTitle(worksheet, startRowIndex, startColIndex);

		buildHeaders(worksheet, startRowIndex, startColIndex);

	}

	/**
	 * 创建报表标题和日期
	 */
	private static void buildTitle(HSSFSheet worksheet, int startRowIndex,
			int startColIndex) {
		// 设置报表标题字体
		Font fontTitle = worksheet.getWorkbook().createFont();
		fontTitle.setBoldweight(Font.BOLDWEIGHT_BOLD);
		fontTitle.setFontHeight((short) 280);

		// 标题单元格样式
		HSSFCellStyle cellStyleTitle = worksheet.getWorkbook()
				.createCellStyle();
		cellStyleTitle.setAlignment(CellStyle.ALIGN_CENTER);
		cellStyleTitle.setWrapText(true);
		cellStyleTitle.setFont(fontTitle);

		// 报表标题
		HSSFRow rowTitle = worksheet.createRow((short) startRowIndex);
		rowTitle.setHeight((short) 500);
		HSSFCell cellTitle = rowTitle.createCell(startColIndex);
		cellTitle.setCellValue("Computer Report!");
		cellTitle.setCellStyle(cellStyleTitle);

		// 合并区域内的报告标题
		worksheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5));

		// date header
		HSSFRow dateTitle = worksheet.createRow((short) startRowIndex + 1);
		HSSFCell cellDate = dateTitle.createCell(startColIndex);
		cellDate.setCellValue("这个报表创建于: " + DateUtils.getNowTime());
	}

	/**
	 * 创建表头
	 */
	private static void buildHeaders(HSSFSheet worksheet, int startRowIndex,
			int startColIndex) {
		// Header字体
		Font font = worksheet.getWorkbook().createFont();
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);

		// 单元格样式
		HSSFCellStyle headerCellStyle = worksheet.getWorkbook()
				.createCellStyle();
		headerCellStyle.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
		headerCellStyle.setFillPattern(CellStyle.FINE_DOTS);
		headerCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
		headerCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
		headerCellStyle.setWrapText(true);
		headerCellStyle.setFont(font);
		headerCellStyle.setBorderBottom(CellStyle.BORDER_THIN);

		// 创建字段标题
		HSSFRow rowHeader = worksheet.createRow((short) startRowIndex + 2);
		rowHeader.setHeight((short) 500);

		HSSFCell cell1 = rowHeader.createCell(startColIndex + 0);
		cell1.setCellValue("Id");
		cell1.setCellStyle(headerCellStyle);

		HSSFCell cell2 = rowHeader.createCell(startColIndex + 1);
		cell2.setCellValue("Brand");
		cell2.setCellStyle(headerCellStyle);

		HSSFCell cell3 = rowHeader.createCell(startColIndex + 2);
		cell3.setCellValue("CPU");
		cell3.setCellStyle(headerCellStyle);

		HSSFCell cell4 = rowHeader.createCell(startColIndex + 3);
		cell4.setCellValue("GPU");
		cell4.setCellStyle(headerCellStyle);

		HSSFCell cell5 = rowHeader.createCell(startColIndex + 4);
		cell5.setCellValue("Memory");
		cell5.setCellStyle(headerCellStyle);

		HSSFCell cell6 = rowHeader.createCell(startColIndex + 5);
		cell6.setCellValue("Price");
		cell6.setCellStyle(headerCellStyle);

	}

}


可以通过 POI单元格顔色设定了解更多的信息.

然后我们是填充数据的一个类:

FillComputerManager.java

package org.liukai.tutorial.poi;

import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.CellStyle;
import org.liukai.tutorial.domain.Computer;

public class FillComputerManager {

	public static void fillReport(HSSFSheet worksheet, int startRowIndex,
			int startColIndex, List<Computer> datasource) {

		// Row offset
		startRowIndex += 2;

		// Create cell style for the body
		HSSFCellStyle bodyCellStyle = worksheet.getWorkbook().createCellStyle();
		bodyCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
		bodyCellStyle.setWrapText(false); //是否自动换行.

		// Create body
		for (int i=startRowIndex; i+startRowIndex-2< datasource.size()+2; i++) {
			// Create a new row
			HSSFRow row = worksheet.createRow((short) i+1);

			// Retrieve the id value
			HSSFCell cell1 = row.createCell(startColIndex+0);
			cell1.setCellValue(datasource.get(i-2).getId());
			cell1.setCellStyle(bodyCellStyle);

			// Retrieve the brand value
			HSSFCell cell2 = row.createCell(startColIndex+1);
			cell2.setCellValue(datasource.get(i-2).getBrand());
			cell2.setCellStyle(bodyCellStyle);

			// Retrieve the model value
			HSSFCell cell3 = row.createCell(startColIndex+2);
			cell3.setCellValue(datasource.get(i-2).getCpu());
			cell3.setCellStyle(bodyCellStyle);

			// Retrieve the maximum power value
			HSSFCell cell4 = row.createCell(startColIndex+3);
			cell4.setCellValue(datasource.get(i-2).getGpu());
			cell4.setCellStyle(bodyCellStyle);

			// Retrieve the price value
			HSSFCell cell5 = row.createCell(startColIndex+4);
			cell5.setCellValue(datasource.get(i-2).getMemory());
			cell5.setCellStyle(bodyCellStyle);
		
			// Retrieve the efficiency value
			HSSFCell cell6 = row.createCell(startColIndex+5);
			cell6.setCellValue(datasource.get(i-2).getPrice());
			cell6.setCellStyle(bodyCellStyle);
		}
	}
}


报表写入类

Writer.java
package org.liukai.tutorial.poi;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFSheet;

public class Writer {
	
	private static Logger logger = Logger.getLogger("service");

	public static void write(HttpServletResponse response, HSSFSheet worksheet) {

		logger.debug("Writing report to the stream");
		try {
			// Retrieve the output stream
			ServletOutputStream outputStream = response.getOutputStream();
			// Write to the output stream
			worksheet.getWorkbook().write(outputStream);
			// 清除缓存
			outputStream.flush();

		} catch (Exception e) {
			logger.error("报表输入失败!");
		}
	}

}

这样对导出表报的格式基本设置完成.

接着我们完成一个对数据库进行操作的类.
PoiDao.java

package org.liukai.tutorial.dao;

import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.liukai.tutorial.domain.Computer;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository("poiDao")
public class PoiDao {

	private SimpleJdbcTemplate jdbcTemplate;

	@Resource(name = "dataSource")
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
	}

	public List<Computer> getComputer() {
		String sql = "SELECT * FROM computer";
		return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Computer>(
				Computer.class));

	}

	public int[] insertComputer(List<Computer> list) {
		String sql = "INSERT INTO computer (BRAND,CPU,GPU,MEMORY,PRICE)VALUES(:brand,:cpu,:gpu,:memory,:price)";
		SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(list
				.toArray());
		return jdbcTemplate.batchUpdate(sql, batch);

	}

}

该类我们实现了两个方法:查询所有的Computer对象并装入一个list的类 : getComputer
批量插入的类:insertComputer
前者用于报表的导出,后者用于报表的插入.

业务层中我们还是需要实现两个业务:导出和导入excel文件.

PoiService.java
package org.liukai.tutorial.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.liukai.tutorial.dao.PoiDao;
import org.liukai.tutorial.domain.Computer;
import org.liukai.tutorial.poi.FillComputerManager;
import org.liukai.tutorial.poi.Layouter;
import org.liukai.tutorial.poi.Writer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("poiService")
@Transactional
public class PoiService {

	@Resource(name = "poiDao")
	private PoiDao dao;
	private static Logger logger = Logger.getLogger("service");

	public void exportXLS(HttpServletResponse response) {

		// 1.创建一个 workbook
		HSSFWorkbook workbook = new HSSFWorkbook();

		// 2.创建一个 worksheet
		HSSFSheet worksheet = workbook.createSheet("Computer");

		// 3.定义起始行和列
		int startRowIndex = 0;
		int startColIndex = 0;

		// 4.创建title,data,headers
		Layouter.buildReport(worksheet, startRowIndex, startColIndex);

		// 5.填充数据
		FillComputerManager.fillReport(worksheet, startRowIndex, startColIndex,
				getDatasource());

		// 6.设置reponse参数
		String fileName = "ComputersReport.xls";
		response.setHeader("Content-Disposition", "inline; filename="
				+ fileName);
		// 确保发送的当前文本格式
		response.setContentType("application/vnd.ms-excel");

		// 7. 输出流
		Writer.write(response, worksheet);

	}

	/**
	 * 读取报表
	 */
	public List<Computer> readReport(InputStream inp) {

		List<Computer> computerList = new ArrayList<Computer>();

		try {
			String cellStr = null;

			Workbook wb = WorkbookFactory.create(inp);

			Sheet sheet = wb.getSheetAt(0);// 取得第一个sheets

			//从第四行开始读取数据
			for (int i = 3; i <= sheet.getLastRowNum(); i++) {

				Computer computer = new Computer();
				Computer addComputer = new Computer();

				Row row = sheet.getRow(i); // 获取行(row)对象

				if (row == null) {
					// row为空的话,不处理
					continue;
				}

				for (int j = 0; j < row.getLastCellNum(); j++) {

					Cell cell = row.getCell(j); // 获得单元格(cell)对象

					// 转换接收的单元格
					cellStr = ConvertCellStr(cell, cellStr);

					// 将单元格的数据添加至一个对象
					addComputer = addingComputer(j, computer, cellStr);

				}
				// 将添加数据后的对象填充至list中
				computerList.add(addComputer);
			}

		} catch (InvalidFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (inp != null) {
				try {
					inp.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			} else {
				logger.info("没有数据流!");
			}
		}
		return computerList;

	}

	/**
	 * 从数据库获得所有的Computer信息.
	 */
	private List<Computer> getDatasource() {
		return dao.getComputer();
	}

	/**
	 * 读取报表的数据后批量插入
	 */
	public int[] insertComputer(List<Computer> list) {
		return dao.insertComputer(list);

	}

	/**
	 * 获得单元格的数据添加至computer
	 * 
	 * @param j
	 *            列数
	 * @param computer
	 *            添加对象
	 * @param cellStr
	 *            单元格数据
	 * @return
	 */
	private Computer addingComputer(int j, Computer computer, String cellStr) {
		switch (j) {
		case 0:
			computer.setId(null);
			break;
		case 1:
			computer.setBrand(cellStr);
			break;
		case 2:
			computer.setCpu(cellStr);
			break;
		case 3:
			computer.setGpu(cellStr);
			break;
		case 4:
			computer.setMemory(cellStr);
			break;
		case 5:
			computer.setPrice(new Double(cellStr).doubleValue());
			break;
		}

		return computer;
	}

	/**
	 * 把单元格内的类型转换至String类型
	 */
	private String ConvertCellStr(Cell cell, String cellStr) {

		switch (cell.getCellType()) {

		case Cell.CELL_TYPE_STRING:
			// 读取String
			cellStr = cell.getStringCellValue().toString();
			break;

		case Cell.CELL_TYPE_BOOLEAN:
			// 得到Boolean对象的方法
			cellStr = String.valueOf(cell.getBooleanCellValue());
			break;

		case Cell.CELL_TYPE_NUMERIC:

			// 先看是否是日期格式
			if (DateUtil.isCellDateFormatted(cell)) {

				// 读取日期格式
				cellStr = cell.getDateCellValue().toString();

			} else {

				// 读取数字
				cellStr = String.valueOf(cell.getNumericCellValue());
			}
			break;

		case Cell.CELL_TYPE_FORMULA:
			// 读取公式
			cellStr = cell.getCellFormula().toString();
			break;
		}
		return cellStr;
	}

}


此业务层实现了两个方法:
exportXLS:用于读取数据库并导出报表.
readReport:用于读取报表并插入数据库中.

untils包里的DateUtils.java只有一个类,用于格式化日期.

DateUtils.java
package org.liukai.tutorial.utils;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {

	/**
	 * 获得yyyy-MM-dd格式的当前日期
	 */
	public static String getNowTime() {
		Date date = new Date();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		return dateFormat.format(date);
	}

}


最后就是我们的controller层了
PoiController.java

package org.liukai.tutorial.controller;

import java.io.IOException;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.liukai.tutorial.domain.Computer;
import org.liukai.tutorial.service.PoiService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
@RequestMapping("/report")
public class PoiController {

	private static Logger logger = Logger.getLogger("controller");

	@Resource(name = "poiService")
	private PoiService service;

	/**
	 * 跳转到主页.
	 */
	@RequestMapping(value = "", method = RequestMethod.GET)
	public String getIndex() {
		logger.info("index!");
		return "report";
	}

	/**
	 * 导出excel报表
	 */
	@RequestMapping(value = "/export", method = RequestMethod.GET)
	public void getXLS(HttpServletResponse response) {
		service.exportXLS(response);
	}

	/**
	 * 读取excel报表
	 */
	@RequestMapping(value = "/read", method = RequestMethod.POST)
	public String getReadReport(@RequestParam MultipartFile file)
			throws IOException {
		List<Computer> list = service.readReport(file.getInputStream());
		service.insertComputer(list);
		return "addedReport";

	}
}


到此,后台的代码基本完成了.
下面还有3个JSP页面.

index.jsp
<% response.sendRedirect("/report"); %>


report.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Report</title>
</head>
<body>
	<c:url var="exportUrl" value="/report/export" />
	<c:url var="readUrl" value="/report/read" />
	
	
	<h3><a href="${exportUrl }">Export Report</a></h3>
	<br />
	<form  id="readReportForm" action="${readUrl }" method="post" enctype="multipart/form-data"  >
			<label for="file">File</label>
			<input id="file" type="file" name="file" />
			<p><button type="submit">Read</button></p>	
		</form>
	
</body>
</html>


addedReport.jsp
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<h1>导入成功!</h1>

<a href="/spring3-poi/report">返回</a>
</body>
</html>


启动项目后输入:
http://localhost:8080/spring3-poi/report

Spring3MVC and POI_第4张图片

点击 Export Report我们会得到一个excel文件.
打开后

Spring3MVC and POI_第5张图片

如此我们通过读取数据库得到了一个excel的文件.

点击"浏览",选择需要导入的excel报表.
注:强烈建议选择我们刚导出的excel报表.因为选择其他的报表格式不同,肯定会报错.
本教程只是演示基本的POI操作.如果要用于生产环境中,请根据自己的状况进行改动和重构.


成功后会显示

Spring3MVC and POI_第6张图片

这个时候查询数据库,就会发现有2个相同的数据.说明我们导入成功.

Spring3MVC and POI_第7张图片

总结
本教程中,我们成功的通过使用POI来进行了excel操作
大家可以根据本教程自定义excel的格式,输出的字段.

需要注意的是两点:
1.导入jar包一定要包含poi-ooxml.
2.别忘记关闭InputStream


BTW:附件为本次教程源码.你可以下载后直接在tomcat或其他web服务器启动.也可以自行添加
maven插件启动.

你可能感兴趣的:(apache,spring,jdbc,Excel,ITeye)