Tip:由於產品提的需求我都開發完了,進行了項目提測;前天老大走過來講:你用spring-boot開發一個解析Excel的jar包.....詳細對話以下:前端
A:世生,你用spring-boot開發一個解析Excel的jar包。java
B:爲何不在原來的項目上進行開發呢?(很納悶,這個東西不是通常用於前端上傳數據的嘛,這是後端層,咋搞這個)git
A:由於xxxx這個需求有比較多的數據須要初始化,這個jar是做爲一個上線的數據初始化腳本github
B:嗯,好的算法
畢竟是第一次寫解析Excel代碼,問了度娘說是有兩種方式能夠作到。一是利用wso2的jxl解析,二是利用apache的poi解析;我去maven repository官網搜索了這兩個jar包,對比了下jml的最新版本是2.6.12居然是2011.05月更新的,而poi的最新版本是4.0.x是2018.08更新的;我的以爲jml最新版本都是2011.05更新的,相對於apache的poi包來講更不靠譜;不斷持續更新的開源項目或者開源jar包不論是bug仍是兼容性相對來講是愈來愈好。因此最終選定用apache大佬的poi進行開發。spring
解析Excel的關鍵點是在於從Excel表格中讀取數據到內存(解析Excel),而後多是校驗數據、經過業務邏輯分析數據、最終持久化到數據庫中;其實這其中最重要的不是解析Excel,而是將解析出的數據持久化到數據庫中以備有用之需。而解析Excel的這塊功能只能算是一個Util類,不能與業務代碼耦合一塊兒;而後我看到不少的Excel解析相關的代碼都是在解析數據中混淆業務代碼邏輯,其實這些都是不可取的,這會致使解析Excel邏輯與業務邏輯相耦合也就是冗雜、代碼重用率低、可擴展性低等問題。由於以前在作項目的時候遇到過一個問題:我負責的模塊是一箇中間模塊(通信採用Dubbo),其餘系統要依賴我這個接口進行請求的轉發可我調用其餘系統返回的結果對象卻各個都不一樣,我叫其餘系統負責人說要統一調用接口返回的對象,可是其餘系統的負責人都不是同一我的執行起來效率過低了,在歷經一個星期都無果的狀況下我只能撒下本身的殺手鐗了;在這種極端條件下最終我無論其餘數據的接口返回的對象是什麼,我直接用Object接收返回類型,經過反射獲取決定請求成功與否的屬性值(欣慰的是當時必傳屬性值卻是同樣的)。經過這種方法我能夠少些不少的代碼(當時其餘系統有15+),否則的話每調用不一樣系統的接口我都須要進行邏輯判斷或者是乾脆對於調用他們不一樣的系統我採用不一樣接口進行轉發,但選用這種方法卻便利多了。數據庫
以上問題分析及一個場景的描述很好理解,可是經過Object接收返回信息得這個場景事實上卻有所欠佳;返回對象不一樣的這個問題最好的處理方案就是統一接口,我那個方案是在需求推進但別人沒法及時配合的極端條件下使用的,是沒辦法中的辦法,但這也是一個沒有辦法中的一個最優的處理方案,兼容性比較強。如下我就用圖來分析這兩種狀況的比較:apache
1.非動態模式:將Excel數據加載到內存與業務代碼邏輯混合,數據在解析期間交叉傳遞。弊端:每新增一個須要解析的Excel,解析Excel代碼塊就須要從新開發,代碼複用率底下、可擴展性也低。後端
2.動態模式:將Excel數據加載到內存與業務代碼邏輯分開;Excel數據加載到內存以後纔將數據傳遞給業務代碼邏輯處理,解析Excel與業務代碼之間分開;優勢:將解析Excel的這部分代碼封裝爲一個ExcelUtil,代碼複用率明顯提升,並且解析與業務代碼間實行解耦,可擴展性加強。數組
要實現動態解析,實現解析與業務代碼邏輯相解耦;那麼咱們不難會想起一個Java的一個關鍵技術-Reflection(反射原理),Python、Ruby等是動態語言而理論上Java是一門靜態語言,可是Java引入了Reflection技術實現了動態性。反射原理咱們都比較熟悉,就是在運行期間動態獲取類的全部屬性及其方法,能夠對這些數據進行相關的操做。以上動態解析Excel的實現就須要用到Java這項的高級技術了,經過這項技術能夠實現動態解析、解析與業務邏輯解耦等。爲了實現動態解析的目的我應用了Java反射技術,可是在開發的過程我發現反射執行一行數據結束的時候如何保存呢?換句話說就是:解析的時候一行的Excel數據封裝後就是一個bean,一個Excel表格就是多個bean 即「beans」;若是咱們直接將反射執行後的結果保存至List中,當解析整個Excel結束後咱們會發現,整個List裏面的對象的值徹底同樣的?what?這是什麼緣由致使的呢?這就是相似於:Object obj=new Object(),咱們每次解析都只是把 obj 放在List中,List中的每個對象都是同一個 obj(引用不變,實例也不變),因此天然也就相同了;由於當一個類執行反射的時候其實它的運行時狀態只有一個,也就是相似於只有一個實例,而傳統的解析Excel是解析出一條數據就new一個對象進行封裝數據,而後將bean存放至List。然而有什麼方法可以解決這一類問題呢?那就是Object 的native clone()方法了,clone()這個大佬是比較牛逼的一我的物,在不建立對象的狀況下將屬性值複製給另外一個對象,具體實現須要實現Cloneable接口並重寫clone()。而解決這個問題的方式就是在每解析完一行Excel數據的時候,反射調用該對象的clone方法。動態解析具體實現應用了Apache POI、 LRUCache(LRU緩存)、Reflection(反射)、java的Clone等技術。若是以上技術沒有了解過的朋友能夠去自行了解,這裏不加贅述。
前提條件:由於要實現動態解析,動態設置值,那麼咱們在反射執行set操做的時候就須要知道相應的setMethod(),那麼咱們能夠在Excel規定第一行就是屬性字段,而且字段名稱跟bean的名稱同樣,讀取的時候先把第一行的數據放在一個String []數組中。具體實現請參照如下源碼。我已經把相關代碼打包成Jar,須要的朋友能夠自行下載;Jar包Git下載地址:https://github.com/GitHubSuper543/auto-resolver-excel-jar.git,源碼地址:https://github.com/GitHubSuper543/auto-resolver-excel-resource.git
使用方法:新建bean用於存儲Excel數據信息,每一個屬性須要有get、set操做,屬性與Excel首行相同,最重要的一點是要實現Clonesble接口重寫clone方法。Excel使用Office編輯,親測Wps編輯的Excel某些屬性值有問題。在new ReadExcelUtil 的時候只須要將對象類型與Excel文件路徑傳入構造函數便可,而後調用 ReadExcelUtil的getObjectList便可獲得解析後的全部對象。至於這個對象你能夠用任何的對象,你能夠換成Teacher、OrderInfo、UserInfo......可是前面提到的:Excel第一行的屬性字段須要與bean的屬性字段一致,不然沒法調用目標方法,具體可參見ReflectionInitValue的方法。具體實現請參見:文章末尾的Test類測試。
1 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
2 <dependency> 3 <groupId>org.apache.poi</groupId> 4 <artifactId>poi</artifactId> 5 <version>3.15</version> 6 </dependency> 7 <dependency> 8 <groupId>org.apache.poi</groupId> 9 <artifactId>poi-ooxml</artifactId> 10 <version>3.15</version> 11 </dependency>
1 package com.hdbs.common; 2 3 /** 4 * @author :cnblogs-WindsJune 5 * @version :1.1.0 6 * @date :2018年9月20日 下午6:33:54 7 * @comments :解析Excel公共類常量類 8 */ 9 10 public class Common { 11 12 public static final String OFFICE_EXCEL_2003_POSTFIX_xls = "xls"; 13 public static final String OFFICE_EXCEL_2010_POSTFIX_xlsx = "xlsx"; 14 public static final String DATA_TYPE_long ="long"; 15 public static final String DATA_TYPE_boolean ="boolean"; 16 public static final String DATA_TYPE_int ="int"; 17 public static final String DATA_TYPE_float ="float"; 18 public static final String DATA_TYPE_double ="double"; 19 public static final String DATA_TYPE_Long ="class java.lang.Long"; 20 public static final String DATA_TYPE_Integer ="class java.lang.Integer"; 21 22 23 }
1 package com.hdbs.exceptions; 2 3 /** 4 * Creater: cnblogs-WindsJune 5 * Date: 2018/9/21 6 * Time: 10:04 7 * Description: No Description 8 */ 9 public class LRUCacheException extends Exception{ 10 /** 11 * 錯誤碼 12 */ 13 private String errorCode; 14 15 /** 16 * 錯誤描述 17 */ 18 private String errorMessage; 19 20 public LRUCacheException(String errorCode, String errorMessage) { 21 this.errorCode = errorCode; 22 this.errorMessage = errorMessage; 23 } 24 25 public LRUCacheException(String message) { 26 super(message); 27 this.errorMessage = errorMessage; 28 } 29 30 public String getErrorCode() { 31 return errorCode; 32 } 33 34 public void setErrorCode(String errorCode) { 35 this.errorCode = errorCode; 36 } 37 38 public String getErrorMessage() { 39 return errorMessage; 40 } 41 42 public void setErrorMessage(String errorMessage) { 43 this.errorMessage = errorMessage; 44 } 45 }
1 package com.hdbs.exceptions; 2 /** 3 * Creater: cnblogs-WindsJune 4 * Date: 2018/9/20 5 * Time: 19:44 6 * Description: 解析Excel的公共異常類 7 */ 8 9 public class ResolveFileException extends RuntimeException{ 10 11 /** 12 * 錯誤碼 13 */ 14 private String errorCode; 15 16 /** 17 * 錯誤描述 18 */ 19 private String errorMessage; 20 21 public ResolveFileException(String errorCode, String errorMessage) { 22 this.errorCode = errorCode; 23 this.errorMessage = errorMessage; 24 } 25 26 public ResolveFileException(String message) { 27 super(message); 28 this.errorMessage = errorMessage; 29 } 30 31 public String getErrorCode() { 32 return errorCode; 33 } 34 35 public void setErrorCode(String errorCode) { 36 this.errorCode = errorCode; 37 } 38 39 public String getErrorMessage() { 40 return errorMessage; 41 } 42 43 public void setErrorMessage(String errorMessage) { 44 this.errorMessage = errorMessage; 45 } 46 }
1 package com.hdbs.common; 2 3 import com.hdbs.exceptions.LRUCacheException; 4 import org.slf4j.Logger; 5 import org.slf4j.LoggerFactory; 6 7 import java.lang.reflect.Method; 8 import java.util.LinkedHashMap; 9 import java.util.Map; 10 11 /** 12 * Creater: cnblogs-WindsJune 13 * Date: 2018/9/20 14 * Time: 19:44 15 * Description: LinkedHashMap實現LRU緩存不一樣線程反射獲取的Method方法 16 */ 17 public class LRUCache { 18 private static final Logger LOGGER=LoggerFactory.getLogger(LRUCache.class); 19 //緩存容量 20 private static final int cacheSize = 10; 21 22 private static final Map<Integer,Method[]> cacheMap = new LinkedHashMap<Integer, Method[]>((int) Math.ceil(cacheSize / 0.75f) + 1, 0.75f, true){ 23 @Override 24 protected boolean removeEldestEntry(Map.Entry<Integer,Method[]> eldest){ 25 26 return size()> cacheSize; 27 28 } 29 }; 30 31 /** 32 * 設置緩存 33 * @param key 34 * @param methods 35 * @return boolean 36 */ 37 public static boolean set (Integer key,Method [] methods) throws LRUCacheException { 38 try { 39 cacheMap.put(key,methods); 40 return true; 41 } 42 catch ( Exception e ){ 43 throw new LRUCacheException("Set LRU緩存異常!"); 44 } 45 } 46 47 /** 48 * 獲取緩存的Method 49 * @param key 50 * @return Method 51 */ 52 public static Method[] get(Integer key) throws LRUCacheException { 53 Method[] methods=null; 54 try { 55 methods=cacheMap.get(key); 56 }catch ( Exception e ){ 57 throw new LRUCacheException("Get LRU緩存異常!{}"); 58 } 59 return methods; 60 } 61 }
1 package com.hdbs.resolver; 2 3 import com.hdbs.common.Common; 4 import com.hdbs.exceptions.ResolveFileException; 5 import org.apache.commons.lang3.StringUtils; 6 import org.apache.poi.hssf.usermodel.HSSFCell; 7 import org.apache.poi.hssf.usermodel.HSSFRow; 8 import org.apache.poi.hssf.usermodel.HSSFSheet; 9 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 10 import org.apache.poi.xssf.usermodel.XSSFCell; 11 import org.apache.poi.xssf.usermodel.XSSFRow; 12 import org.apache.poi.xssf.usermodel.XSSFSheet; 13 import org.apache.poi.xssf.usermodel.XSSFWorkbook; 14 import org.slf4j.Logger; 15 import org.slf4j.LoggerFactory; 16 17 import java.io.File; 18 import java.io.FileInputStream; 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.lang.reflect.InvocationTargetException; 22 import java.util.ArrayList; 23 import java.util.HashMap; 24 import java.util.List; 25 import java.util.Map; 26 27 /** 28 * @author :cnblogs-WindsJune 29 * @version :1.1.0 30 * @date :2018年9月20日 下午6:13:43 31 * @comments : 32 */ 33 34 public class ReadExcelUtil { 35 36 private static final Logger LOGGER = LoggerFactory.getLogger(ReadExcelUtil.class); 37 //存放屬性集 38 private Map<Integer,String []> fieldsMap=new HashMap<>(); 39 //存放解析後的對象List 40 private List<Object> objectsList = new ArrayList<>(); 41 //反射運行時對象 42 private Object object=null; 43 //Excel文件路徑 44 private String path =null; 45 //獲取解析後的對象集 46 public List<Object> getObjectsList() { 47 return this.objectsList; 48 } 49 50 public ReadExcelUtil(Object object,String path) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException { 51 this.object=object; 52 this.path=path; 53 readExcel(); 54 } 55 56 /** 57 * 添加Object到List中 58 * @param object 59 * @return 60 */ 61 public boolean addListObject(Object object){ 62 boolean isSucceed=this.objectsList.add(object); 63 return isSucceed; 64 } 65 66 /** 67 * 讀取excel,判斷是xls結尾(2010以前);仍是xlsx結尾(2010之後)的Excel 68 * 69 * @return 70 * @throws IOException 71 */ 72 public boolean readExcel() throws IOException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { 73 if (StringUtils.isEmpty(path)) { 74 return false; 75 } else { 76 // 截取後綴名,判斷是xls仍是xlsx 77 String postfix = path.substring(path.lastIndexOf(".") + 1); 78 if (!StringUtils.isEmpty(postfix)) { 79 if (Common.OFFICE_EXCEL_2003_POSTFIX_xls.equals(postfix)) { 80 return readXls(); 81 } else if (Common.OFFICE_EXCEL_2010_POSTFIX_xlsx.equals(postfix)) { 82 return readXlsx(); 83 } 84 } else { 85 LOGGER.error("文件後綴名有誤!"); 86 throw new ResolveFileException("文件後綴名有誤!" + "[" + path + "]"); 87 } 88 } 89 return false; 90 } 91 92 /** 93 * 讀取xls(2010)以後的Excel 94 * 95 * @return 96 * @throws IOException 97 */ 98 public boolean readXlsx() throws IOException{ 99 File file = new File(path); 100 InputStream is = new FileInputStream(file); 101 XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is); 102 // 遍歷sheet頁 103 for (int numSheet = 0; numSheet < xssfWorkbook.getNumberOfSheets(); numSheet++) { 104 XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(numSheet); 105 String [] fields=null; 106 if (xssfSheet == null) { 107 continue; 108 } 109 // 循環行 110 for (int rowNum = 0; rowNum <= xssfSheet.getLastRowNum(); rowNum++) { 111 XSSFRow xssfRow = xssfSheet.getRow(rowNum); 112 int cloumns=xssfRow.getLastCellNum(); 113 int i=0; 114 //獲取第一行的全部屬性 115 if (rowNum == 0){ 116 fields=getFields(xssfRow,cloumns); 117 fieldsMap.put(numSheet,fields); 118 continue; 119 } 120 //遍歷數據,反射set值 121 while (i<cloumns){ 122 XSSFCell field=xssfRow.getCell(i); 123 String value=getValue(field); 124 try { 125 ReflectionInitValue.setValue(object,fields[i],value); 126 }catch ( Exception e ){ 127 throw new ResolveFileException(e.getMessage()); 128 } 129 i++; 130 } 131 //經過反射執行clone複製對象 132 Object result=ReflectionInitValue.invokeClone(object,"clone"); 133 this.addListObject(result); 134 // System.out.println(object.toString()); 135 } 136 } 137 return true; 138 } 139 140 /** 141 * 讀取xls(2010)以前的Excel 142 * 143 * @return 144 * @throws IOException 145 */ 146 public boolean readXls() throws IOException, ResolveFileException { 147 InputStream is = new FileInputStream(path); 148 HSSFWorkbook hssfWorkbook = new HSSFWorkbook(is); 149 // 遍歷sheet頁 150 for (int numSheet = 0; numSheet < hssfWorkbook.getNumberOfSheets(); numSheet++) { 151 HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(numSheet); 152 String[] fields = null; 153 if (hssfSheet == null) { 154 continue; 155 } 156 // 循環行Row 157 for (int rowNum = 0; rowNum <= hssfSheet.getLastRowNum(); rowNum++) { 158 HSSFRow hssfRow = hssfSheet.getRow(rowNum); 159 int cloumns=hssfRow.getLastCellNum(); 160 int i=0; 161 //獲取第一行的全部屬性 162 if (rowNum == 0){ 163 //獲取屬性字段 164 fields=getFields(hssfRow,cloumns); 165 fieldsMap.put(numSheet,fields); 166 continue; 167 } 168 //遍歷數據,反射set值 169 while (i<cloumns){ 170 HSSFCell field=hssfRow.getCell(i); 171 String value=getValue(field); 172 try { 173 ReflectionInitValue.setValue(object,fields[i],value); 174 }catch ( Exception e ){ 175 throw new ResolveFileException(e.getMessage()); 176 } 177 i++; 178 } 179 //經過反射執行clone複製對象 180 Object result=ReflectionInitValue.invokeClone(object,"clone"); 181 this.addListObject(result); 182 } 183 } 184 return true; 185 } 186 187 /** 188 * xlsx -根據數據類型,獲取單元格的值 189 * @param xssfRow 190 * @return 191 */ 192 @SuppressWarnings({ "static-access" }) 193 private static String getValue(XSSFCell xssfRow) { 194 String value=null; 195 try { 196 if (xssfRow.getCellType() == xssfRow.CELL_TYPE_BOOLEAN) { 197 // 返回布爾類型的值 198 value=String.valueOf(xssfRow.getBooleanCellValue()).replace(" ",""); 199 } else if (xssfRow.getCellType() == xssfRow.CELL_TYPE_NUMERIC) { 200 // 返回數值類型的值 201 value= String.valueOf(xssfRow.getNumericCellValue()).replace(" ",""); 202 } else { 203 // 返回字符串類型的值 204 value= String.valueOf(xssfRow.getStringCellValue()).replace(" ",""); 205 } 206 } catch (Exception e) { 207 //單元格爲空,不處理 208 value=null; 209 LOGGER.error("單元格爲空!"); 210 } 211 return value; 212 } 213 214 /** 215 * xls-根據數據類型,獲取單元格的值 216 * @param hssfCell 217 * @return 218 */ 219 @SuppressWarnings({ "static-access" }) 220 private static String getValue(HSSFCell hssfCell) { 221 String value=null; 222 try { 223 if (hssfCell.getCellType() == hssfCell.CELL_TYPE_BOOLEAN) { 224 // 返回布爾類型的值 225 value=String.valueOf(hssfCell.getBooleanCellValue()).replaceAll(" ",""); 226 } else if (hssfCell.getCellType() == hssfCell.CELL_TYPE_NUMERIC) { 227 // 返回數值類型的值 228 value=String.valueOf(hssfCell.getNumericCellValue()).replaceAll(" ",""); 229 } else { 230 // 返回字符串類型的值 231 value=String.valueOf(hssfCell.getStringCellValue()).replaceAll(" ",""); 232 } 233 } catch (Exception e) { 234 //單元格爲空,不處理 235 value=null; 236 LOGGER.error("單元格爲空!"); 237 } 238 return value; 239 } 240 241 /** 242 * xls Excel文件類型獲取屬性(2010以前) 243 * @param cloumns 244 * @return String[] 245 */ 246 private static String[] getFields (HSSFRow hssfRow,int cloumns){ 247 String [] fields=new String[cloumns]; 248 int i=0; 249 try { 250 while (i<cloumns){ 251 HSSFCell field=hssfRow.getCell(i); 252 String value=getValue(field); 253 fields[i]=value.trim(); 254 i++; 255 } 256 }catch ( Exception e){ 257 throw new ResolveFileException("獲取屬性集失敗!"); 258 } 259 return fields; 260 } 261 262 /** 263 * xlsx Excel文件類型獲取屬性(2010以後) 264 * @param cloumns 265 * @return String[] 266 */ 267 private static String[] getFields(XSSFRow xssfRow,int cloumns){ 268 String [] fields=new String[cloumns]; 269 int i=0; 270 try { 271 while (i<cloumns){ 272 XSSFCell field=xssfRow.getCell(i); 273 String value=getValue(field); 274 fields[i]=value.trim(); 275 i++; 276 } 277 }catch ( Exception e ){ 278 throw new ResolveFileException("獲取屬性集失敗!"); 279 } 280 return fields; 281 } 282 283 }
1 package com.hdbs.resolver; 2 3 import com.hdbs.common.Common; 4 import com.hdbs.common.LRUCache; 5 import com.hdbs.exceptions.LRUCacheException; 6 import com.hdbs.exceptions.ResolveFileException; 7 8 import java.lang.reflect.InvocationTargetException; 9 import java.lang.reflect.Method; 10 import java.lang.reflect.Type; 11 12 /** 13 * Creater: cnblogs-WindsJune 14 * Date: 2018/9/21 15 * Time: 9:54 16 * Description: No Description 17 */ 18 public class ReflectionInitValue { 19 20 private static int threadHashCodeKey=Thread.currentThread().toString().hashCode(); 21 22 /** 23 * 經過反射動態將Excel讀取的信息設置到對應的bean中 24 * 25 * @param object-存儲對象bean 26 * @param key-屬性參數名 27 * @param value-屬性值 28 * @throws Exception 29 */ 30 public static void setValue(Object object, String key, String value) throws LRUCacheException { 31 String methodName = null; 32 String paramType = null; 33 Method[] methods = null; 34 if (LRUCache.get(threadHashCodeKey) == null) { 35 Class<?> clazz = object.getClass(); 36 methods = clazz.getDeclaredMethods(); 37 LRUCache.set(threadHashCodeKey, methods); 38 } else { 39 methods = LRUCache.get(threadHashCodeKey); 40 } 41 for (Method method : methods) { 42 methodName = method.getName(); 43 if (methodName.startsWith("set") && methodName.toLowerCase().equals("set" + key.toLowerCase())) { 44 Type[] types = method.getGenericParameterTypes(); 45 for (Type type : types) { 46 paramType = type.toString(); 47 // 根據參數類型轉化value,並進行set操做 48 excuteInvokeSetvalue(object, method, paramType, value, 0); 49 } 50 // 該屬性已經執行setValue操做,無需循環 51 break; 52 } 53 } 54 } 55 56 /** 57 * 初始化對象bean 58 * 59 * @param object 60 * @throws Exception 61 */ 62 public static void initBeans(Object object) throws ResolveFileException, LRUCacheException { 63 // Class<?> clazz = object.getClass(); 64 String methodName = null; 65 String paramType = null; 66 Method[] methods = LRUCache.get(threadHashCodeKey); 67 try { 68 for (Method method : methods) { 69 methodName = method.getName(); 70 if (methodName.startsWith("set")) { 71 Type[] types = method.getGenericParameterTypes(); 72 for (Type type : types) { 73 paramType = type.getClass().getName(); 74 } 75 // 根據參數類型轉化value,並進行set初始化屬性值 76 excuteInvokeSetvalue(object, method, paramType, "", 1); 77 } 78 } 79 } catch (Exception e) { 80 throw new ResolveFileException("初始化bean錯誤!Method:[ " + methodName + " ]"); 81 } 82 } 83 84 /** 85 * 根據參數類型轉化value,並進行set操做 86 * 87 * @param object-存儲對象bean 88 * @param method-執行的set對應屬性的方法 89 * @param paramType-屬性參數類型 90 * @param value-屬性值 91 * @param operationType-操做類型(0-設置屬性,1-初始化bean) 92 * @throws Exception 93 */ 94 public static void excuteInvokeSetvalue(Object object, Method method, String paramType, String value, 95 int operationType){ 96 try { 97 switch (paramType) { 98 case Common.DATA_TYPE_long: {// 參數屬性long 99 if (value !=null && value.contains(".")){ 100 value=value.substring(0,value.lastIndexOf(".")); 101 } 102 Long temp = Long.valueOf(operationType == 0 && value !=null ? value : "0"); 103 method.invoke(object, temp); 104 break; 105 } 106 case Common.DATA_TYPE_boolean: {// 參數屬性boolean 107 boolean temp = (operationType == 0 ? (Boolean.valueOf(value != null ? value:"false")) : false); 108 method.invoke(object, temp); 109 break; 110 } 111 case Common.DATA_TYPE_int: {// 參數屬性int 112 if (value !=null && value.contains(".")){ 113 value=value.substring(0,value.lastIndexOf(".")); 114 } 115 int temp = Integer.valueOf(operationType == 0 && value!=null ? value : "0"); 116 method.invoke(object, temp); 117 break; 118 } 119 case Common.DATA_TYPE_float: {// 參數屬性float 120 if (value !=null && value.contains(".")){ 121 value=value.substring(0,value.lastIndexOf(".")); 122 } 123 float temp = Float.valueOf(operationType == 0 && value !=null ? value : "0"); 124 method.invoke(object, temp); 125 break; 126 } 127 case Common.DATA_TYPE_double: {// 參數屬性double 128 double temp = Double.valueOf(operationType == 0 && value !=null ? value : "0"); 129 method.invoke(object, temp); 130 break; 131 } 132 case Common.DATA_TYPE_Long: {// 參數屬性Long 133 if (value !=null && value.contains(".")){ 134 value=value.substring(0,value.lastIndexOf(".")); 135 } 136 Long temp = Long.valueOf(operationType == 0 && value!=null ? value : "0"); 137 method.invoke(object, temp); 138 break; 139 } 140 case Common.DATA_TYPE_Integer: {// 參數屬性Integer 141 if (value !=null && value.contains(".")){ 142 value=value.substring(0,value.lastIndexOf(".")); 143 } 144 int temp = Integer.valueOf(operationType == 0 && value!=null ? value : "0"); 145 method.invoke(object, temp); 146 break; 147 } 148 default: {// 參數屬性String 149 if (value !=null && value.contains(".")){ 150 value=value.substring(0,value.lastIndexOf(".")); 151 } 152 method.invoke(object, operationType == 0 ? value : null); 153 break; 154 } 155 } 156 157 } catch ( IllegalAccessException e ) { 158 throw new ResolveFileException("invoke方法錯誤![Method:" + method.getName() + " [value:" + value + " ]"); 159 } catch ( InvocationTargetException e ) { 160 throw new ResolveFileException("invoke方法錯誤![Method:" + method.getName() + " [value:" + value + " ]"); 161 } catch (Exception e) { 162 throw new ResolveFileException("字段屬性錯誤![Method:" + method.getName() + " [value:" + value + " ]"); 163 } 164 165 166 } 167 168 /** 169 * 170 * @param object 171 * @param methodName 172 * @return 173 * @throws ResolveFileException 174 */ 175 public static Object invokeClone (Object object,String methodName){ 176 Class clazz=object.getClass(); 177 try { 178 Method method=clazz.getMethod(methodName); 179 Object result=method.invoke(object); 180 return result; 181 }catch ( Exception e ){ 182 throw new ResolveFileException("解析Excel,反射執行set操做異常!"); 183 } 184 185 } 186 187 188 }
1 package com.hdbs.beans; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * @author :WindsJune/博客園:WindsJune 8 * @version :1.1.0 9 * @date :2018年9月20日 下午6:05:57 10 * @comments : 11 */ 12 13 public class Student implements Cloneable{ 14 15 /** 16 * id 17 */ 18 private Integer id; 19 /** 20 * 學號 21 */ 22 private String no; 23 /** 24 * 姓名 25 */ 26 private String name; 27 /** 28 * 學院 29 */ 30 private String age; 31 /** 32 * 成績 33 */ 34 private float score; 35 36 /** 37 * 地址 38 */ 39 private String adress; 40 41 private List<Student> studentsList=new ArrayList<>(); 42 43 public Integer getId() { 44 return id; 45 } 46 47 public void setId(Integer id) { 48 this.id = id; 49 } 50 51 public String getNo() { 52 return no; 53 } 54 55 public void setNo(String no) { 56 this.no = no; 57 } 58 59 public String getName() { 60 return name; 61 } 62 63 public void setName(String name) { 64 this.name = name; 65 } 66 67 public String getAge() { 68 return age; 69 } 70 71 public void setAge(String age) { 72 this.age = age; 73 } 74 75 public float getScore() { 76 return score; 77 } 78 79 public void setScore(float score) { 80 this.score = score; 81 } 82 83 public String getAdress() { 84 return adress; 85 } 86 87 public void setAdress(String adress) { 88 this.adress = adress; 89 } 90 91 public List<Student> getStudentsList() { 92 return studentsList; 93 } 94 95 public Object clone() throws CloneNotSupportedException{ 96 return super.clone(); 97 } 98 99 @Override 100 public String toString() { 101 return "Student{" + 102 "id=" + id + 103 ", no='" + no + '\'' + 104 ", name='" + name + '\'' + 105 ", age='" + age + '\'' + 106 ", score=" + score + 107 ", adress='" + adress + '\'' + 108 '}'; 109 } 110 }
1 package hello; 2 3 import java.util.List; 4 5 import com.hdbs.beans.Student; 6 import com.hdbs.resolver.ReadExcelUtil; 7 8 /** 9 * @version 1.0.0 10 * @author cnblogs-WindsJune 11 * @date 2018年9月23日 上午1:16:34 12 * 13 */ 14 public class Test { 15 public static void main(String[] args) { 16 Student student=new Student(); 17 String filePath="E:/test.xlsx"; 18 try { 19 ReadExcelUtil readExcelUtil=new ReadExcelUtil(student,filePath); 20 List<Object> list=readExcelUtil.getObjectsList(); 21 for (Object object:list){ 22 Student test=(Student) object; 23 System.out.println(test.toString()); 24 } 25 } catch (Exception e) { 26 e.printStackTrace(); 27 } 28 } 29 }
表格規範:
執行結果: