关闭

Excel 导入工具类

标签: java poi refect 反射
120人阅读 评论(0) 收藏 举报
分类:

设计思路:平常我们导入的话,获取到表格单元格值 之后,采用new 对象出来,然后把 值赋予到 对象上,但是 此方式有个局限性就是若是 下次导入的对象与上次的不同,那么还得 再写一遍赋值代码,所以 在 重复利用率不高,因此 打算用 java 反射来实现 动态赋值,跳脱出 类型的限制;

那么 反射的使用要知道 对象名与属性名的,因此 我打算  写一个 配置文件 用来  连接(过度)Excel 与 对象 之间的 映射关系;然后通过此作为桥梁 实现反射生成对象

PS:使用 refect 的目的 是为了调高 利用性,但是 对象采用 反射机制生成 效率要低于 直接new,效率要低于一倍左右;

所以此方法 适用于 数据量不太的情况下

java 类目录结构:



Xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<root>
	<!-- 规则信息:BusinessRule  id:实体类路径 -->
	<improtExcel id="com.test.data.BusinessRule" name="ruleImport">				
		<mapping type="String" excelTitle="规则名称" property="name" required="true">	</mapping>
		<mapping type="String" excelTitle="Bps范围" property="bps_range" required="false"></mapping>
		<mapping type="String" excelTitle="Pps范围" property="pps_range" required="false">	</mapping>
		<mapping type="String" excelTitle="协议范围" property="prot" required="true"></mapping>
		<mapping type="String" excelTitle="源端口" property="src_port" required="false">	</mapping>
		<mapping type="String" excelTitle="目的端口" property="dest_port" required="false"></mapping>
		<mapping type="String" excelTitle="时间资源" property="time_res_id" required="true">	</mapping>
		<mapping type="String" excelTitle="是否启用" property="is_on" required="true"></mapping>
		<mapping type="String" excelTitle="动作是否允许" property="rosterFlag" required="true">	</mapping>
		<mapping type="String" excelTitle="源ip范围" property="srcIpRange" required="false"></mapping>
		<mapping type="String" excelTitle="目的ip范围" property="dstIpRange" required="false"></mapping>
		
	</improtExcel>
	<improtExcel id="com.test.data.BusinessModel" name="ipAreaImport">				
		
		<mapping type="String" excelTitle="区域名称" property="name" required="true">	</mapping>
		<mapping type="String" excelTitle="资产分析是否启用" property="isAnaly" required="true"></mapping>
		
		<mapping type="String" excelTitle="描述" property="description" required="false"></mapping>
		<!--地址内容 用一些字段 先临时存
		<mapping type="String" excelTitle="地址内容" property="content" required="true">	</mapping>
		 -->
		<mapping type="String" excelTitle="IP地址" property="creator" required="false"></mapping>
		<mapping type="String" excelTitle="地址范围" property="createtime" required="false">	</mapping>
		<mapping type="String" excelTitle="子网地址" property="updatetime" required="false"></mapping>
		
		
	</improtExcel>
</root>

存 xml信息的实体类:

package com.test.util.excelutil;

/**
 * 
 * @author zhangqingzhou
 * 规则导入Excel 时 , 导入 信息 的 条件 储存类(即要求)
 */
public class MappingBean {
	/**
	 * excel 表 列名
	 */
	private String excelTitle;
	/**
	 * 对应到 实体类 上的 属性值
	 */
	private String property;
	/**
	 * 字段值类型
	 */
	private String type;
	/**
	 * 是否 为 必须字段
	 */
	private boolean required;
	/**
	 * 最小长度
	 */
	private int minLength;
	/**
	 * 最大长度
	 */
	private int maxLength;
	private String mapName;
	private String mapDefaultValue;
	/**
	 * 注解名
	 */
	private String annoName;
	/**
	 * 反射到的 类
	 */
	private String className;
	/**
	 * 方法名
	 */
	private String methodName;
	public String getExcelTitle() {
		return excelTitle;
	}
	public void setExcelTitle(String excelTitle) {
		this.excelTitle = excelTitle;
	}
	public String getProperty() {
		return property;
	}
	public void setProperty(String property) {
		this.property = property;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public boolean isRequired() {
		return required;
	}
	public void setRequired(boolean required) {
		this.required = required;
	}
	public int getMinLength() {
		return minLength;
	}
	public void setMinLength(int minLength) {
		this.minLength = minLength;
	}
	public int getMaxLength() {
		return maxLength;
	}
	public void setMaxLength(int maxLength) {
		this.maxLength = maxLength;
	}
	public String getMapName() {
		return mapName;
	}
	public void setMapName(String mapName) {
		this.mapName = mapName;
	}
	public String getMapDefaultValue() {
		return mapDefaultValue;
	}
	public void setMapDefaultValue(String mapDefaultValue) {
		this.mapDefaultValue = mapDefaultValue;
	}
	public String getAnnoName() {
		return annoName;
	}
	public void setAnnoName(String annoName) {
		this.annoName = annoName;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public String getMethodName() {
		return methodName;
	}
	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}
	
	
}

读取xml 信息放入 容器中:

package com.test.util.excelutil;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.test.excelImportUtil.ExcelMappingBean;
import com.test.util.excelImportUtil.StringUtil;


/**
 * 初始化映射 工具类
 * @author Administrator
 *
 */
public class RuleImportMappingUtil {

	private static RuleImportMappingUtil singleton = null;
	private Map<String, MappingBean> mappingBeanMap = new HashMap<String, MappingBean>();
	private Map<String, List<String>> titlesMap = new HashMap<String, List<String>>();
	
	public static RuleImportMappingUtil getInstance(){
		if(singleton == null){
			singleton = getSyncInstance();
		}
		return singleton;
	}
	/**
	 * 线程安全 获取实例
	 * @return
	 */
	private static synchronized RuleImportMappingUtil getSyncInstance(){
		return new RuleImportMappingUtil();
	}
	
	private RuleImportMappingUtil(){
		
		initExcelInfo();
	};
	public static void main(String[] args) {
		new RuleImportMappingUtil().initExcelInfo();
	}
	/**
	 * 初始化 参数 读取 xml 文件,初始化 信息
	 */
	private void initExcelInfo(){
		// xml 文件路径
		//E:/gyy/cupid_tomcat_7.0.53/webapps/nta/WEB-INF/_conf/nta/util
		String webinfo = "E:/gyy/cupid_tomcat_7.0.53/webapps/nta/WEB-INF/_conf";
		
		String fileName = webinfo + "/nta/util/importExcelMappingRule.xml";
		SAXReader reader = new SAXReader();
		Document document;
		try {
			document = reader.read(new File(fileName));
			Element root = document.getRootElement();
			List<Element> excelEles = root.elements();
			for(Element excelEle : excelEles){
				String id = excelEle.attributeValue("id");
				String alias = excelEle.attributeValue("name");
				
				List<Element> mappingEles = excelEle.elements();
				List<String> titles = new ArrayList<String>();
				for(Element mappingEle : mappingEles){
					
					MappingBean excelMapping = new MappingBean();
					excelMapping.setExcelTitle(mappingEle.attributeValue("excelTitle"));
					excelMapping.setProperty(mappingEle.attributeValue("property"));
					excelMapping.setRequired(Boolean.valueOf(mappingEle.attributeValue("required")));
					
					titles.add(excelMapping.getExcelTitle());
					
					excelMapping.setType(mappingEle.attributeValue("type"));
					
					
					
					if(StringUtil.strIsNull(alias)){
						mappingBeanMap.put(id + "_" + excelMapping.getExcelTitle(), excelMapping);
					}else{
						mappingBeanMap.put(id + "$" + alias + "_" + excelMapping.getExcelTitle(), excelMapping);
					}
				}
				
				if(!titles.isEmpty()){
					if(StringUtil.strIsNull(alias)){
						titlesMap.put(id, titles);
					}else{
						titlesMap.put(id + "$" + alias + "_", titles);
					}
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		} 
		
	
	}
	
	/**
	 * 
	 * @param packagePath  包路径
	 * @param name    总文件名  约定
	 * @param excelTitle  列的标题
	 * @return
	 */
	public MappingBean  getMappingBean(String packagePath , String name , String excelTitle){
		if(name == null || name.equals("")){
			
			return mappingBeanMap.get(packagePath + "_" + excelTitle);
		}else{
			return mappingBeanMap.get(packagePath  + "$" + name + "_" + excelTitle);
		}
	}
	/**
	 * 获取 所有的 字段值-中文含义
	 * @param packagePath
	 * @param name
	 * @return
	 */
	public List<String>  getAllTitles(String packagePath , String name ){
		if(name == null || name.equals("")){
					
					return titlesMap.get(packagePath);
				}else{
					return titlesMap.get(packagePath + "$" + name +"_");
				}
				
		}
	/**
	 * 检验 Excel 格式是否正确
	 * @param packagePath
	 * @param name
	 * @param titles
	 * @return  
	 * true:列名合法  
	 * false:列名不合法
	 */
	public boolean checkTitleIsright(String packagePath , String name ,String[] titles){
		boolean flag = true;
		List<String> allTitles = getAllTitles(packagePath, name);
		if(allTitles != null){
			
			for (String string : titles) {
				boolean flag2 = false;
				for (String str : allTitles) {
					if(string.equals(str)){
						flag2 = true;
						break;
						
					}	
				}	
				// 遍历之后 还是没有发现
				if(flag2 == false){
					
					return false;
				}
			}
		}
		
		return flag;
	}
	
}
反射工具类:

package com.tst.util.excelutil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

/*
 * zhangqingzhou
 * 动态 导入过程,表值与对象 的映射
 */
public class ReflectUtil {

	public static Object reflectBean(Class<?> fclass , Map<String , Object> map){
		// 得到 此类的所有属性
		Field[] fileds = fclass.getDeclaredFields();
		
		Object bean = null;
		try {
			bean = fclass.newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// 遍历类的属性 进行赋值
		for (Field field : fileds) {
			String filedName = null;
			
			// 获取方法名
			filedName = field.getName();
			if(filedName != null){
				// 过滤 序列化 字段
				if(filedName.equals("serialVersionUID")){
					continue;
				}
				// 进行 赋值操作
				
				try {
					if(map.containsKey(filedName)){
						 // 1.1 先 获取 此字段的 类型
						Class<?> type = field.getType();
						Method setMethod = fclass.getMethod(getSetMethod(filedName), type);
						setMethod.invoke(bean, map.get(filedName));
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return bean;
	}
	
	/**
	 * 获取 set方法名
	 * @param fieldName
	 * @return
	 */
	public static String getSetMethod(String fieldName){
		String method = null;
		if(fieldName != null && fieldName.length() > 0){
			byte[] bytes = fieldName.getBytes();
			// + 32 变大写
			bytes[0] = (byte)( bytes[0] - 'a' + 'A');
			method = "set" + new String(bytes);
			}
		return method;
	}
	
	/**
	 * 获取 Get方法名
	 * @param fieldName
	 * @return
	 */
	public static String getGetMethod(String fieldName){
		String method = null;
		if(fieldName != null && fieldName.length() > 0){
			byte[] bytes = fieldName.getBytes();
			// + 32 变大写
			bytes[0] = (byte)( bytes[0] - 'a' + 'A');
			method = "get" + new String(bytes);
		}
		return method;
	}
}



读取excel的 controller:

@SuppressWarnings({ "unchecked" })
	@Log(isEnabled=false)
	@At("/import")
	@AdaptBy(type = UploadAdaptor.class, args = {})
	@Ok("jsp:jsp.nta.rule.business_rule")
	@Fail("jsp:jsp.nta.rule.lead_bug")
	public void importResourse(Ioc ioc,HttpServletRequest request,HttpServletResponse response,@Param("filename") TempFile tempFile,@Param("groupIdTemp") String groupId) throws Exception{		
		boolean bug=false;
		// 存储消息
		Map<Integer, String> returnMap = new HashMap<Integer, String>();
		FieldMeta meta=tempFile.getMeta();
		String fileName = meta.getFileLocalName();
		//判断文件类型是否合法,支持excel2003、2007
		if(!(fileName.endsWith(".xlsx") || fileName.endsWith(".xls"))){
			request.setAttribute("fileError", "导入失败,文件格式不正确,只支持.xls和.xlsx后缀文件!");
			request.setAttribute("returnMapErr",returnMap);
			throw ExceptionWrapper.wrapError(new EC("导入失败,文件格式不正确,只支持.xls和.xlsx后缀文件!", false));
		}
		System.out.println("groupId:"+groupId);
		FileInputStream inputStream = null;
		Workbook workbook = null;
		Sheet sheet = null;
		try {
			inputStream = new FileInputStream(tempFile.getFile());
			//创建workbook
			workbook = WorkbookFactory.create(inputStream);
			sheet = workbook.getSheet("Rule");
			if(sheet != null){
				List<BusinessRule> dataList = (List<BusinessRule>)ExcelUtil.parseExcelData(BusinessRule.class, sheet, "ruleImport", returnMap);
				for (Map.Entry<Integer, String> entry : returnMap.entrySet()) {
					if(entry.getValue().indexOf("<BR/>")==-1){
						request.setAttribute("returnMapErr",returnMap);
						bug=true;
						throw ExceptionWrapper.wrapError(new EC("第"+entry.getKey()+"行未成功导入,原因是:" + entry.getValue(), false));
					}
				}
				if(!bug){
					System.out.println("dataSize:"+dataList.size());
					if(dataList != null){
						// 对数据 进行判断 过滤  正确性验证
						List<BusinessRule> beanList = ExcelUtil.wrapDataRule(dataList, returnMap, getConnectInfo(), unitMap);
						for (Map.Entry<Integer, String> entry : returnMap.entrySet()) {
							if(entry.getValue().contains("重新导入")){
								request.setAttribute("returnMapErr",returnMap);
								
								throw ExceptionWrapper.wrapError(new EC("第"+entry.getKey()+"行未成功导入,原因是:" + entry.getValue(), false));
							}
						}
						
						// 添加数据
						for (BusinessRule obj : beanList) {
							obj.setAlert_level(5);
							obj.setStandby1(groupId);//规则组ip
							obj.setTotal_doctets_end_unit("");
							obj.setPkg_len_range("");
							obj = filterPortByprotocol(obj);
							businessRuleService.insert(obj, "");
						}
						
					}
				}
			}else {
				
				throw ExceptionWrapper.wrapError(new EC("导入失败,请使用正确的模板文件填写数据!", false));
			}
		}catch (Exception e) {
			
			throw ExceptionWrapper.wrapError(new EC("导入失败,请使用正确的模板文件填写数据!", false));
		}
		
	}

读取Excel 的工具类:

package com.venustech.tsoc.cupid.apm.rule.util.excelutil;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.cxf.binding.corba.wsdl.Array;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;



/**
 * Excel 工具箱
 * @author zqz
 *
 */
public class ExcelUtil {

	// 组合方式 获取 映射工具
	private static RuleImportMappingUtil  mappingUtil = RuleImportMappingUtil.getInstance();
	private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * 
	 * @param fclass  被反射的实体类
	 * @param sheet  Excel 表单
	 * @param name  名字
	 * @param returnMap  异常Map
	 * @return List<?>
	 * @throws Exception
	 */
	public static List<?>  parseExcelData(Class<?>  fclass , Sheet  sheet ,String name ,Map<Integer,String>  returnMap)throws Exception{
	
		// 泛型的使用
		List<Object> dataList =	new ArrayList<Object>();
		int rowIndex = 0;
		try {
			// 开始 行数
			int startRow = sheet.getFirstRowNum();
			// 结尾行数
			int lastRow = sheet.getLastRowNum();
			// 验证是否为 空内容
			if(startRow >= lastRow){
				// 添加 提示消息
				returnMap("0","文件为空!");
				return null;
			}
			
			
			// 获取 第一行 的列标题
			String[] titles = getExcelContext(sheet.getRow(startRow));
			if(titles == null || titles.length == 0){
				return dataList;
			}
			// 验证 标题是否存在
			if(!mappingUtil.checkTitleIsright(fclass.getName(), name, titles)){
				returnMap.put(0, "表格格式不对(表格列名不合法),请使用模板重新导入!");
				return dataList;
			}
			// 开始遍历取值
			Row row = null;
			Cell cell = null;
			String cellValue = null;
			
			// 设置 容器 存值
			MappingBean  mappingBean = null;// 映射类
			Map<String ,Object> rowMap = new HashMap<String, Object>();//每一行的数据
			//1.1 遍历所有数据 行
			for(int rowNum = startRow+1;rowNum <= lastRow; rowNum++ ){
				  row =	sheet.getRow(rowNum);
				  if(row == null){
					  continue;
				  }
				  // 1.2 遍历列
				  short lastCellNum = row.getLastCellNum();
				  for(short cellNum = 0; cellNum <=lastCellNum; cellNum++ ){
					  // 1.3 取单元格的值
					 cell = row.getCell(cellNum);
					 
					 if(cell != null){
						 // 统一值的 类型,方便存储
						 cell.setCellType(Cell.CELL_TYPE_STRING);
						 cellValue = cell.getStringCellValue();
						 if(cellValue != null){
							 // 去除两边空格
							 cellValue = cellValue.trim();
						 }else{
							 cellValue = "";
						 }
						 
						 // 与xml 文件进行匹配,找到 此字段的信息
						 String title = titles[cellNum];
						 mappingBean = mappingUtil.getMappingBean(fclass.getName(), name, title);
						 if(mappingBean != null){
							 if(title.equals("是否启用") || title.equals("动作是否允许") || title.equals("资产分析是否启用")){
								 cellValue = (cellValue.equals("是")?"1":(title.contains("是否启用")?"0":"2"));
								 rowMap.put(mappingBean.getProperty(), Integer.parseInt(cellValue));
							 }else{
								 
								 rowMap.put(mappingBean.getProperty(), cellValue);
							 }
						 }
						 
					 }
					 
					 // 清空 数据
					 cell = null;
					 cellValue = null;
					 mappingBean = null;
					
				  }
				  // 把一行的数据 反射生成队形
				
					  dataList.add(ReflectUtil.reflectBean(fclass, rowMap));
				 
				  //清空行数据
				  rowMap.clear();
				  
				  rowIndex++;
				  row = null;
				  
			}
		} catch (Exception e) {
			returnMap.put("0","文件导入失败");
		}
		return dataList;
	}
	
	
	/**
	 * 获取 此行所有列的内容
	 * @param row
	 * @return
	 */
	private static String[]  getExcelContext(Row row){
		short firstCellNum = row.getFirstCellNum();//1
		short lastCellNum = row.getLastCellNum();//10
		
		String[] contexts = new String[lastCellNum];
		// 遍历取值
		for(short index = firstCellNum; index < lastCellNum ;index++){
			// 为了 方便对应,1-1  ,2--2
			Cell cell = row.getCell(index);
			if(cell != null){
				
				contexts[index] = cell.getStringCellValue();
			}
		}
		return contexts;
	}
	
}

这样就避免 每导入一次,死板new 对象的问题了!

2
0

猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6976次
    • 积分:710
    • 等级:
    • 排名:千里之外
    • 原创:62篇
    • 转载:18篇
    • 译文:0篇
    • 评论:4条