SpringMVC Excel导入导出2.0升级版



该博客依赖1.0版本编写,只体现升级内容。1.0请参照

SpringMVC操作Excel上传下载.


升级内容介绍:
MyBatis在批量插入的时候,入参的形式多种多样,1.0版本使用List<Map<String, String>>的形式作为入参。不排除有些情况下需要使用POJO传递数据。基于此需求,研发的2.0版本,读取Excel之后返回List类型,自定义POJO的类型。

设计思想:

1、要求Excel中标题的名字和POJO中的属性名一致
(我们需要制定一些规矩,好让我们的代码能顺利的跑起来,当然这一点可能会降低用户的体验度,项目真正上线,Excel的文件模板肯定也是定好的,所以,体验上不会很差。)
2、从Excel中把标题取出
3、利用反射,获取到POJO的set方法,并执行赋值。
----------------------------------------
set方法的完整方法名如何获取?
4、利用反射获取到POJO的所有属性,并与【2、】去到的Excel中的标题比较(忽略大小写比较);
	比较条件成立
		将POJO的属性名首字母变大写,再拼接“set”即可的到完整的方法名。同时也可以通过方法名获取到指定的方法,然后执行传参。

话不多说,上代码
ExcelUtil.java

import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.Cell;
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.xssf.usermodel.XSSFWorkbook;

@SuppressWarnings("hiding")
public class ExcelUtil<T> {

	// 2007以前版本
	public static final String XLS = ".XLS"; 
	// 2007以后版本
	public static final String XLSX = ".XLSX"; 
	
	/**
	 * -读取excel,返回List<T>类型
	 * -要求Excel的标题名字要和传入的实体类的属性名保持一致
	 * @param suffix 文件的后缀名
	 * @param is 输入流
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "null" })
	public List<T> readExcel(String suffix, InputStream is, Class<T> clazz) throws Exception {
		// 入参判断,任意一个为空则返回null
		if(suffix == null || "".equals(suffix) || is == null || clazz == null) {
			return null;
		}
		
		// 创建List用于封装数据
		List<T> list = null;
		String[] title = null;
		Object obj = null;
		// 获取类对象中所有的属性
		Field[] fields = clazz.getDeclaredFields();
		
		// 根据不同版本创建不同的EXCEL对象
		Workbook wb = null;
		if(XLS.equalsIgnoreCase(suffix)) {
			wb = new HSSFWorkbook(is);
		} else {
			wb = new XSSFWorkbook(is);
		}
		
		// 获取第一个sheet
		Sheet sheet = wb.getSheetAt(0);
		// 获取最后一行(总行数)
		int rowNum = sheet.getLastRowNum();
				
		// 循环行
		for(int r = 0; r <= rowNum; r++) {
			// 行对象
			Row row = sheet.getRow(r);
			// 创建单条数据对象
			if(r > 0) {
				obj = clazz.newInstance();
				
				if(list == null) {
					list = new ArrayList<T>();
				}
				// 封装数据到list
				list.add((T)obj);
			}
			
			// 每行最大的单元格数
			int cellNum = row.getLastCellNum();
			
			for(int c = 0; c < cellNum; c++) {
				// 单元格对象
				Cell cell = row.getCell(c);
				String value = cell.getStringCellValue();
				
				// excel第一行是标题行,将标题单独拿出放到数组中
				if(r == 0) {
					if(title == null) {
						title = new String[cellNum];
					}
					title[c] = value;
				// 第二行开始时数据行,将数据封装到对象中
				} else {
					// 属性名
					String fieldName = "";
					StringBuffer sb = null;
					
					// 遍历属性,循环比较excel中读取的属性是否和类对象中的属性
					for(Field field : fields) {
						// 获取属性名
						fieldName = field.getName();
						
						// 忽略大小写比较excel中读取的属性是否和类对象中的相等
						if(fieldName.equalsIgnoreCase(title[c])) {
							sb = new StringBuffer();
							// 属性名首字母大写
							String firstChar = fieldName.substring(0, 1).toUpperCase();
							// 属性名除首字母以外的字符
							String otherChar = fieldName.substring(1);
							
							// 拼接属性名,最后结果是属性名大写
							sb.append(firstChar);
							sb.append(otherChar);
							break;
						}
					}
					
					// 属性名构造失败时跳过当前循环
					if(sb != null || !"".equals(sb.toString().trim())) {
						// 构造set方法的方法名
						String methodName = "set" + sb.toString();
						
						// 根据方法名获取方法对象
						Method method = clazz.getDeclaredMethod(methodName, String.class);
						// 执行方法,传入参数
						method.invoke(obj, value);
					}			
				}
			}
		}
		// 关闭资源
		close(wb, is);
		
		return list;
	}
	
	/**
	 * -关闭资源
	 * @param wb
	 * @param is
	 */
	public static void close(Workbook wb, InputStream is) {
		try {
			if(wb != null) {
				wb.close();
			}
			if(is != null) {
				is.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

测试类

@RequestMapping(value="/excelImport", method= {RequestMethod.POST})
public void excelImport(@RequestParam("userExcel") MultipartFile file) {
	try {
		// 文件的输入流(文件已经得到)
		InputStream is = file.getInputStream();
		// 文件名
		String fileName = file.getOriginalFilename();
		int index = fileName.lastIndexOf(".");
		// 后缀名
		String suffix = fileName.substring(index);
		
		ExcelUtil<Users> excelUtil = new ExcelUtil<Users>();
		List<Users> list = excelUtil.readExcel(suffix, is, Users.class);
		for(Users user : list) {
			System.out.println(user);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

POJO

public class Users {
	String id;
	String name;
	String dept;
	String account;
	String password;
	String headimg;
	String gender;
	String email;
	String mobile;
	String birthday;
	String state;
	String memo;
	
	// 省略set/get
}

Exel数据

springboot hive 导入csv_List


导入之后

Users [id=2, name=admin, dept=部门A, account=admin, password=admin, headimg=, gender=1, email=, mobile=, birthday=, state=1, memo=, sakujyo=1]
Users [id=402881e8578453390157845bd2730000, name=超级管理员, dept=部门A, account=superadmin, password=000000, headimg=user/402881e8578453390157845bd2730000.jpg, gender=1, email=790018823@qq.com, mobile=15238652508, birthday=2016-10-01, state=1, memo=我是superadmin, sakujyo=1]
Users [id=402881e9575c8fa101575c90a6150000, name=Peter, dept=部门B, account=admin, password=111, headimg=user/9027b570841341bfbb3617f924d26335.JPG, gender=0, email=790018823@qq.com, mobile=15238652508, birthday=2011-09-07, state=1, memo=测试数据, sakujyo=1]
Users [id=4028eedd57c0e09b0157c0e55f4f0000, name=jim, dept=部门B, account=jim, password=111, headimg=user/4028eedd57c0e09b0157c0e55f4f0000.jpg, gender=0, email=790018823@qq.com, mobile=15238652508, birthday=2016-10-05, state=1, memo=, sakujyo=1]
Users [id=4028eedd5870048a0158700e474f0003, name=aaa, dept=部门A, account=aaa, password=aaa, headimg=, gender=0, email=, mobile=, birthday=2016-11-15, state=1, memo=, sakujyo=1]
Users [id=4028eedd58715cd00158715db2ea0000, name=哦哦哦, dept=部门A, account=11, password=111, headimg=user/4028eedd58715cd00158715db2ea0000.jpg, gender=0, email=11@qq.com, mobile=, birthday=, state=1, memo=, sakujyo=1]
Users [id=ff8080815a409218015a418ca8fd0000, name=lisa, dept=部门A, account=admin1111, password=123456, headimg=, gender=0, email=790018823@qq.com, mobile=15238652508, birthday=1992-09-07, state=1, memo=, sakujyo=0]