jdk1.8
包:jxl-2.6.12.jar、commons-beanutils-1.9.3.jar
1、定义属性模型AttributeModel.java
public class AttributeModel {
/**
* @param attribute 属性 eg:age
* @param name 名称 eg:年龄
* @param hasWarn 标红提醒 eg:true
* */
public AttributeModel(String attribute, String name, Boolean hasWarn){
this.attribute = attribute;
this.name = name;
if(hasWarn){
this.hasWarn = hasWarn;
}
}
// excel表头
private String name;
// 实体类属性名
private String attribute;
// 是否提醒必填
private Boolean hasWarn = false;
public String getName() {
return name;
}
public String getAttribute() {
return attribute;
}
public Boolean isHasWarn() {
return hasWarn;
}
}
2、定义attributeList,也就是需要导入的字段和中文名,为提供导入的模板做准备
/**
* @doc会员导入
* 数据第三个字符串是为了设置导出excel是单元格样式,true就标红提醒必填,没这需求可以不加
**/
public static List getMemberImportConstant() {
List attributeList = new ArrayList<>();
attributeList.add(new AttributeModel("memberName","会员名", true));
attributeList.add(new AttributeModel("idCar", "身份证号", true));
attributeList.add(new AttributeModel("birthday", "生日", false));
attributeList.add(new AttributeModel("sex", "性别", true));
attributeList.add(new AttributeModel("phone", "手机号", true));
return attributeList;
}
3、定义一个示例数据,方便用户参考,这一步非必须
/**
* @doc 会员信息导入 案例
**/
public static List getMemberImportExample() {
Memberexample = new Member();
List exampleList = new ArrayList();
example.setMemberName("张三");
example.setIdCar("410*****0012");
example.setSex("男");
example.setPhone("1388888888");
example.setBirthday("1999-8-8");
exampleList.add(example);
return exampleList;
}
4、导出模板只需传入第二部准备好的示例数据(List
/**
* 用于表头导出用
* @param response
* @parm list 数据集合
* @parm attributeList 属性模型集合
*/
public void writeHeadToFile(List list, List attributeList, HttpServletResponse response) {
if (CollectionUtils.isEmpty(attributeList)) {
return;
}
try {
WritableWorkbook book = Workbook.createWorkbook(response.getOutputStream());
// 创建一个工作区。
WritableSheet sheet = book.createSheet("第一页", 0);
// 在工作区上面添加内容
try {
// 处理第一行,标题
Label newLabel = null;// new Label(j, i, String.valueOf(j));
for (int i = 0; i < attributeList.size(); i++) {
Boolean hasRed = attributeList.get(i).getHasWarn();
newLabel = new Label(i, FIRST_ROW, attributeList.get(i).getName(),getHeaderCellStyle(hasRed));
sheet.addCell(newLabel);
}
if (!CollectionUtils.isEmpty(list)) {
Object param = null;
for (int i = FIRST_ROW + 1; i <= list.size(); i++) {
T t = list.get(i - 1);
Map properties = conversionToMapByTool(t);
for (int j = 0; j < attributeList.size(); j++) {
param = properties.get(attributeList.get(j).getAttribute());
newLabel = new Label(j, i, objToString(param));
sheet.addCell(newLabel);
}
}
}
} catch (RowsExceededException e) {
logger.error("行或列参数错误!{}", e);
} catch (WriteException e) {
logger.error("写入失败!{}", e);
} catch (Exception e) {
logger.error("写入失败!{}", e);
} finally {
if (book != null) {
book.write();
try {
book.close();
} catch (WriteException e) {
logger.error("文件关闭失败!{}", e);
}
}
}
} catch (IOException e) {
logger.error("创建文件失败!{}", e);
}
}
private Map conversionToMapByTool(T bean) throws Exception {
Map map = new HashMap();
PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(bean);
for (PropertyDescriptor d : descriptors) {
String fieldName = d.getName();
Object value = propertyUtilsBean.getNestedProperty(bean, fieldName);
if (!"class".equals(fieldName))
map.put(fieldName, value);
}
return map;
}
/**
* 表头单元格样式的设定
*/
public WritableCellFormat getHeaderCellStyle(Boolean hasRed){
/*
* WritableFont.createFont("宋体"):设置字体为宋体
* 10:设置字体大小
* WritableFont.BOLD:设置字体加粗(BOLD:加粗 NO_BOLD:不加粗)
* false:设置非斜体
* UnderlineStyle.NO_UNDERLINE:没有下划线
*/
WritableFont font = null;
if(hasRed){
font = new WritableFont(WritableFont.ARIAL,10,WritableFont.BOLD,false, UnderlineStyle.NO_UNDERLINE,Colour.RED);
}else{
font = new WritableFont(WritableFont.ARIAL,10,WritableFont.NO_BOLD,false,UnderlineStyle.NO_UNDERLINE,Colour.BLACK);
}
WritableCellFormat headerFormat = new WritableCellFormat();
try {
//添加字体设置
headerFormat.setFont(font);
//设置单元格背景色:表头为黄色
//headerFormat.setBackground(Colour.YELLOW);
//设置表头表格边框样式
//整个表格线为粗线、黑色
//headerFormat.setBorder(Border.ALL, BorderLineStyle.THICK, Colour.BLACK);
//表头内容水平居中显示
headerFormat.setAlignment(Alignment.LEFT);
} catch (WriteException e) {
System.out.println("表头单元格样式设置失败!");
}
return headerFormat;
}
5、用户填好导出的excel后,上传文件处理方法
/**
*@param file,request,response
*@doc 会员导入
**/
@ResponseBody
@RequestMapping(value = "importExcel", method = {RequestMethod.GET, RequestMethod.POST})
public Result
自己封装的导入导出工具类:JxlImportExcelUtil
// JxlImportExcelUtil
/**
* @throws BiffException
* @throws IOException
* @Title: readLines
* @Description: TODO 读取excel
* @return List
* @throws
*/
public List readLines(MultipartFile mfile) throws IOException, BiffException {
if (mfile == null) {
return new ArrayList<>(0);
}
return readLinesFromstream(mfile.getInputStream());
}
// JxlImportExcelUtil
/**
* 读取数据
**/
private List readLinesFromstream(InputStream ins) throws BiffException, IOException {
List list = new ArrayList();
Workbook rwb = null;
try {
rwb = Workbook.getWorkbook(new BufferedInputStream(ins, 20 * 1024 * 1024));
Sheet sheet = rwb.getSheet(0);
// 设置导入条数限制5W
if (sheet.getRows() > Integer.parseInt(import_Limit) + 1) {
return null;
}
for (int i = 0; i < sheet.getRows(); i++) {
String[] str = new String[sheet.getColumns()];
Cell cell = null;
for (int j = 0; j < sheet.getColumns(); j++) {
cell = sheet.getCell(j, i);
if (cell instanceof DateCell) {
// DateUtil.formatDateYMDHMS 时间转换工具类,把日期转换为字符串格式
str[j] = DateUtil.formatDateYMDHMS(((DateCell) cell).getDate(), "GMT");
} else {
str[j] = cell.getContents();
if(!StringUtils.isEmpty(str[j])) {
str[j].trim();
}
}
}
list.add(str);
}
} catch (Exception e) {
throw e;
} finally {
if (rwb != null) {
rwb.close();
}
ins.close();
}
return list;
}
/**
* @param valueList excel 读取的数据
* @param className T的classname
* @param strList param与中文描述的对应
* @Title: generatorTargets
* @Description: TODO
* @return List 将读取的excel转换成目标对象列表。
* @throws
*/
public List generatorTargets(List valueList, String className, List strList)
throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException {
List paramCnName = Arrays.asList(valueList.get(0));// excel 表头
List pname = new ArrayList();// 表头对应的属性名称
Map namesMap = strList.stream().collect(Collectors.toMap(str -> str[1], str -> str[0]));
paramCnName.forEach(o -> {
pname.add(namesMap.get(o));
});
// 因为第一行为示例数据,所以删除第一行,没有示例数据可以不删
valueList.remove(0);
List tList = new ArrayList();
if (CollectionUtils.isEmpty(valueList)) {
return tList;
}
final int scalar = 2500;
int size = valueList.size();
long jobNums = 0;
if (size % scalar == 0) {
jobNums = size / scalar;
} else {
jobNums = size / scalar + 1;
}
List>> jobs = new ArrayList>>();
List subList = null;
for (int i = 0; i < jobNums; i++) {
if (i == jobNums - 1) {
subList = valueList.subList(i * scalar, size);
} else {
subList = valueList.subList(i * scalar, (i + 1) * scalar);
}
// JxlImportCallable 继承了Callable,下面会粘出代码
Callable> c = new JxlImportCallable(subList, className, pname);
jobs.add(c);
}
// MutiThreadJobUtil 多线程处理工具类,下面粘出代码
tList = MultiThreadJobsUtil.doJob(jobs);
return tList;
}
JxlImportCallable 类
import com.david.domain.common.DateUtil;
import com.david.web.util.myConverter.MyBooleanConverter;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.collections.CollectionUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
public class JxlImportCallable implements Callable> {
private List dataList;
private String clazzName;
List pname;
public JxlImportCallable(List dtList, String claName, List pnameList) {
this.dataList = dtList;
this.clazzName = claName;
this.pname = pnameList;
}
@Override
public List call() throws Exception {
List dataList = null;
try {
dataList = generatorData();
} catch (Exception e) {
dataList = new ArrayList();
}
return dataList;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private List generatorData()
throws IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
if (CollectionUtils.isEmpty(dataList)) {
return null;
}
/**
* 实现java.util.Date的cover
*/
ConvertUtils.register(new Converter() {
public Object convert(Class type, Object value) {
return DateUtil.parseDate(value.toString());
}
}, java.util.Date.class);
// 注册自定义boolean值转换工具类
ConvertUtils.register(new MyBooleanConverter(), java.lang.Boolean.class);
List tList = new ArrayList();
T t = null;
for (int i = 0; i < dataList.size(); i++) {
t = (T) Class.forName(clazzName).newInstance();
for (int j = 0; j < pname.size(); j++) {
BeanUtils.setProperty(t, pname.get(j), dataList.get(i)[j]);
}
tList.add(t);
}
return tList;
}
}
MultiThreadJobsUtil 多线程任务通用工具
package com.david.web.util;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 多线程任务通用工具
*
*/
public class MultiThreadJobsUtil {
private static final Logger log = LoggerFactory.getLogger(MultiThreadJobsUtil.class);
private static ExecutorService executor = new ThreadPoolExecutor(10, 10, 30L, TimeUnit.MINUTES,
new LinkedBlockingQueue(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("CRM-线程-" + t.getId());
return t;
}
});
public static List doJob(final List>> jobs) {
List result = new ArrayList();
try {
if (!executor.isShutdown()) {
List>> results = executor.invokeAll(jobs);
for (Future> future : results)
result.addAll(future.get());
}
} catch (InterruptedException e) {
log.error("线程中断异常", e);
} catch (ExecutionException e) {
log.error("线程执行异常", e);
} catch (Exception e) {
log.error("其它错误异常", e);
}
return result;
}
public static void doJob(final Runnable r) {
try {
if (!executor.isShutdown()) {
executor.submit(r);
}
} catch (Exception e) {
log.error("其它错误异常", e);
}
}
public static void shutdown() throws InterruptedException {
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
executor.shutdownNow();
}
@Override
protected void finalize() throws Throwable {
shutdown();
}
}