POI是一個(gè)開源項(xiàng)目,專用于java平臺(tái)上操作MS OFFICE,企業(yè)應(yīng)用開發(fā)中可用它方便導(dǎo)出Excel. 下面是使用示例: 1、maven中先添加依賴項(xiàng) 1 <dependency> 2 <groupId>org.apache.poi</groupId> 3 <artifactId>poi</artifactId> 4 <version>3.11</version> 5 </dependency> 2、最基本的導(dǎo)出示例 a) 先定義一個(gè)基本的類AwbData ![]() 1 package com.cnblogs.yjmyzz.test.domain; 2 3 public class AwbDto { 4 5 public AwbDto() { 6 super(); 7 8 } 9 10 public AwbDto(String awbNumber, String agent) { 11 super(); 12 this.awbNumber = awbNumber; 13 this.agent = agent; 14 } 15 16 /** 17 * 運(yùn)單號 18 */ 19 private String awbNumber; 20 21 /** 22 * 代理人 23 */ 24 private String agent; 25 26 public String getAwbNumber() { 27 return awbNumber; 28 } 29 30 public void setAwbNumber(String awbNumber) { 31 this.awbNumber = awbNumber; 32 } 33 34 public String getAgent() { 35 return agent; 36 } 37 38 public void setAgent(String agent) { 39 this.agent = agent; 40 } 41 } b) 偽造點(diǎn)數(shù)據(jù) ![]() 1 private List<AwbDto> getData1() { 2 List<AwbDto> data = new ArrayList<AwbDto>(); 3 for (int i = 0; i < 1000; i++) { 4 data.add(new AwbDto("112-" + FileUtil.leftPad(i + "", 8, '0'), "張三")); 5 } 6 return data; 7 } 8 9 private List<AwbDto> getData2() { 10 List<AwbDto> data = new ArrayList<AwbDto>(); 11 for (int i = 0; i < 1000; i++) { 12 data.add(new AwbDto("999-" + FileUtil.leftPad(i + "", 8, '0'), "李四")); 13 } 14 return data; 15 } 上面都是準(zhǔn)備工作,下面才是重點(diǎn): ![]() 1 @Test 2 public void testExcelExport() throws Exception { 3 4 // 創(chuàng)建excel 5 HSSFWorkbook wb = new HSSFWorkbook(); 6 7 // 創(chuàng)建sheet 8 HSSFSheet sheet = wb.createSheet("運(yùn)單數(shù)據(jù)"); 9 10 // 創(chuàng)建一行 11 HSSFRow rowTitle = sheet.createRow(0); 12 13 // 創(chuàng)建標(biāo)題欄樣式 14 HSSFCellStyle styleTitle = wb.createCellStyle(); 15 styleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 居中 16 HSSFFont fontTitle = wb.createFont(); 17 // 宋體加粗 18 fontTitle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 19 fontTitle.setFontName("宋體"); 20 fontTitle.setFontHeight((short) 200); 21 styleTitle.setFont(fontTitle); 22 23 // 在行上創(chuàng)建1列 24 HSSFCell cellTitle = rowTitle.createCell(0); 25 26 // 列標(biāo)題及樣式 27 cellTitle.setCellValue("運(yùn)單號"); 28 cellTitle.setCellStyle(styleTitle); 29 30 // 在行上創(chuàng)建2列 31 cellTitle = rowTitle.createCell(1); 32 cellTitle.setCellValue("代理人"); 33 cellTitle.setCellStyle(styleTitle); 34 35 HSSFCellStyle styleCenter = wb.createCellStyle(); 36 styleCenter.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 居中 37 38 // 取數(shù)據(jù) 39 List<AwbDto> data = getData1(); 40 41 for (int i = 0; i < data.size(); i++) { 42 43 AwbDto item = data.get(i); 44 HSSFRow row = sheet.createRow(i + 1); 45 46 HSSFCell cell = row.createCell(0); 47 cell.setCellValue(item.getAwbNumber()); 48 cell.setCellStyle(styleCenter); 49 50 cell = row.createCell(1); 51 cell.setCellValue(item.getAgent()); 52 cell.setCellStyle(styleCenter); 53 } 54 55 FileOutputStream fout = new FileOutputStream("r:/awb.xls"); 56 wb.write(fout); 57 fout.close(); 58 wb.close(); 59 60 System.out.println("導(dǎo)出完成!"); 61 } 導(dǎo)出后,大致是這個(gè)樣子: 3、通用的Excel導(dǎo)出類 對于格式不太復(fù)雜的常規(guī)excel,如果每次都要寫上面這一堆代碼,當(dāng)然有點(diǎn)2,已經(jīng)有無私的高逼格程序猿在開源中國上奉獻(xiàn)了自己的勞動(dòng)成果,借來用一下(再次向作者表示感謝),不過這份代碼年頭略久,有些方法已經(jīng)被現(xiàn)在的版本標(biāo)識(shí)為過時(shí),略微改進(jìn)了一下下,貼在這里: ![]() 1 package com.cnblogs.yjmyzz.utils; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.text.SimpleDateFormat; 6 import java.util.Date; 7 import java.util.LinkedHashMap; 8 import java.util.List; 9 import java.util.Set; 10 import java.util.Map.Entry; 11 import org.apache.poi.hssf.usermodel.HSSFCell; 12 import org.apache.poi.hssf.usermodel.HSSFRow; 13 import org.apache.poi.hssf.usermodel.HSSFSheet; 14 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 15 import org.apache.poi.ss.usermodel.CellStyle; 16 import org.apache.poi.ss.usermodel.Font; 17 import org.apache.poi.ss.usermodel.IndexedColors; 18 import org.apache.poi.ss.util.CellRangeAddress; 19 20 public class ExcelUtil { 21 private static HSSFWorkbook wb; 22 23 private static CellStyle titleStyle; // 標(biāo)題行樣式 24 private static Font titleFont; // 標(biāo)題行字體 25 private static CellStyle dateStyle; // 日期行樣式 26 private static Font dateFont; // 日期行字體 27 private static CellStyle headStyle; // 表頭行樣式 28 private static Font headFont; // 表頭行字體 29 private static CellStyle contentStyle; // 內(nèi)容行樣式 30 private static Font contentFont; // 內(nèi)容行字體 31 32 /** 33 * 導(dǎo)出文件 34 * 35 * @param setInfo 36 * @param outputExcelFileName 37 * @return 38 * @throws IOException 39 */ 40 public static boolean export2File(ExcelExportData setInfo, 41 String outputExcelFileName) throws Exception { 42 return FileUtil.write(outputExcelFileName, export2ByteArray(setInfo), 43 true, true); 44 } 45 46 /** 47 * 導(dǎo)出到byte數(shù)組 48 * 49 * @param setInfo 50 * @return 51 * @throws Exception 52 */ 53 public static byte[] export2ByteArray(ExcelExportData setInfo) 54 throws Exception { 55 return export2Stream(setInfo).toByteArray(); 56 } 57 58 /** 59 * 導(dǎo)出到流 60 * 61 * @param setInfo 62 * @return 63 * @throws Exception 64 */ 65 public static ByteArrayOutputStream export2Stream(ExcelExportData setInfo) 66 throws Exception { 67 init(); 68 69 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 70 71 Set<Entry<String, List<?>>> set = setInfo.getDataMap().entrySet(); 72 String[] sheetNames = new String[setInfo.getDataMap().size()]; 73 int sheetNameNum = 0; 74 for (Entry<String, List<?>> entry : set) { 75 sheetNames[sheetNameNum] = entry.getKey(); 76 sheetNameNum++; 77 } 78 HSSFSheet[] sheets = getSheets(setInfo.getDataMap().size(), sheetNames); 79 int sheetNum = 0; 80 for (Entry<String, List<?>> entry : set) { 81 // Sheet 82 List<?> objs = entry.getValue(); 83 84 // 標(biāo)題行 85 createTableTitleRow(setInfo, sheets, sheetNum); 86 87 // 日期行 88 createTableDateRow(setInfo, sheets, sheetNum); 89 90 // 表頭 91 creatTableHeadRow(setInfo, sheets, sheetNum); 92 93 // 表體 94 String[] fieldNames = setInfo.getFieldNames().get(sheetNum); 95 96 int rowNum = 3; 97 for (Object obj : objs) { 98 HSSFRow contentRow = sheets[sheetNum].createRow(rowNum); 99 contentRow.setHeight((short) 300); 100 HSSFCell[] cells = getCells(contentRow, setInfo.getFieldNames() 101 .get(sheetNum).length); 102 int cellNum = 1; // 去掉一列序號,因此從1開始 103 if (fieldNames != null) { 104 for (int num = 0; num < fieldNames.length; num++) { 105 106 Object value = ReflectionUtil.invokeGetterMethod(obj, 107 fieldNames[num]); 108 cells[cellNum].setCellValue(value == null ? "" : value 109 .toString()); 110 cellNum++; 111 } 112 } 113 rowNum++; 114 } 115 adjustColumnSize(sheets, sheetNum, fieldNames); // 自動(dòng)調(diào)整列寬 116 sheetNum++; 117 } 118 wb.write(outputStream); 119 return outputStream; 120 } 121 122 /** 123 * @Description: 初始化 124 */ 125 private static void init() { 126 wb = new HSSFWorkbook(); 127 128 titleFont = wb.createFont(); 129 titleStyle = wb.createCellStyle(); 130 dateStyle = wb.createCellStyle(); 131 dateFont = wb.createFont(); 132 headStyle = wb.createCellStyle(); 133 headFont = wb.createFont(); 134 contentStyle = wb.createCellStyle(); 135 contentFont = wb.createFont(); 136 137 initTitleCellStyle(); 138 initTitleFont(); 139 initDateCellStyle(); 140 initDateFont(); 141 initHeadCellStyle(); 142 initHeadFont(); 143 initContentCellStyle(); 144 initContentFont(); 145 } 146 147 /** 148 * @Description: 自動(dòng)調(diào)整列寬 149 */ 150 private static void adjustColumnSize(HSSFSheet[] sheets, int sheetNum, 151 String[] fieldNames) { 152 for (int i = 0; i < fieldNames.length + 1; i++) { 153 sheets[sheetNum].autoSizeColumn(i, true); 154 } 155 } 156 157 /** 158 * @Description: 創(chuàng)建標(biāo)題行(需合并單元格) 159 */ 160 private static void createTableTitleRow(ExcelExportData setInfo, 161 HSSFSheet[] sheets, int sheetNum) { 162 CellRangeAddress titleRange = new CellRangeAddress(0, 0, 0, setInfo 163 .getFieldNames().get(sheetNum).length); 164 sheets[sheetNum].addMergedRegion(titleRange); 165 HSSFRow titleRow = sheets[sheetNum].createRow(0); 166 titleRow.setHeight((short) 800); 167 HSSFCell titleCell = titleRow.createCell(0); 168 titleCell.setCellStyle(titleStyle); 169 titleCell.setCellValue(setInfo.getTitles()[sheetNum]); 170 } 171 172 /** 173 * @Description: 創(chuàng)建日期行(需合并單元格) 174 */ 175 private static void createTableDateRow(ExcelExportData setInfo, 176 HSSFSheet[] sheets, int sheetNum) { 177 CellRangeAddress dateRange = new CellRangeAddress(1, 1, 0, setInfo 178 .getFieldNames().get(sheetNum).length); 179 sheets[sheetNum].addMergedRegion(dateRange); 180 HSSFRow dateRow = sheets[sheetNum].createRow(1); 181 dateRow.setHeight((short) 350); 182 HSSFCell dateCell = dateRow.createCell(0); 183 dateCell.setCellStyle(dateStyle); 184 // dateCell.setCellValue("導(dǎo)出時(shí)間:" + new 185 // SimpleDateFormat("yyyy-MM-dd HH:mm:ss") 186 // .format(new Date())); 187 dateCell.setCellValue(new SimpleDateFormat("yyyy-MM-dd") 188 .format(new Date())); 189 } 190 191 /** 192 * @Description: 創(chuàng)建表頭行(需合并單元格) 193 */ 194 private static void creatTableHeadRow(ExcelExportData setInfo, 195 HSSFSheet[] sheets, int sheetNum) { 196 // 表頭 197 HSSFRow headRow = sheets[sheetNum].createRow(2); 198 headRow.setHeight((short) 350); 199 // 序號列 200 HSSFCell snCell = headRow.createCell(0); 201 snCell.setCellStyle(headStyle); 202 snCell.setCellValue("序號"); 203 // 列頭名稱 204 for (int num = 1, len = setInfo.getColumnNames().get(sheetNum).length; num <= len; num++) { 205 HSSFCell headCell = headRow.createCell(num); 206 headCell.setCellStyle(headStyle); 207 headCell.setCellValue(setInfo.getColumnNames().get(sheetNum)[num - 1]); 208 } 209 } 210 211 /** 212 * @Description: 創(chuàng)建所有的Sheet 213 */ 214 private static HSSFSheet[] getSheets(int num, String[] names) { 215 HSSFSheet[] sheets = new HSSFSheet[num]; 216 for (int i = 0; i < num; i++) { 217 sheets[i] = wb.createSheet(names[i]); 218 } 219 return sheets; 220 } 221 222 /** 223 * @Description: 創(chuàng)建內(nèi)容行的每一列(附加一列序號) 224 */ 225 private static HSSFCell[] getCells(HSSFRow contentRow, int num) { 226 HSSFCell[] cells = new HSSFCell[num + 1]; 227 228 for (int i = 0, len = cells.length; i < len; i++) { 229 cells[i] = contentRow.createCell(i); 230 cells[i].setCellStyle(contentStyle); 231 } 232 233 // 設(shè)置序號列值,因?yàn)槌鋈?biāo)題行和日期行,所有-2 234 cells[0].setCellValue(contentRow.getRowNum() - 2); 235 236 return cells; 237 } 238 239 /** 240 * @Description: 初始化標(biāo)題行樣式 241 */ 242 private static void initTitleCellStyle() { 243 titleStyle.setAlignment(CellStyle.ALIGN_CENTER); 244 titleStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); 245 titleStyle.setFont(titleFont); 246 titleStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.index); 247 } 248 249 /** 250 * @Description: 初始化日期行樣式 251 */ 252 private static void initDateCellStyle() { 253 dateStyle.setAlignment(CellStyle.ALIGN_CENTER_SELECTION); 254 dateStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); 255 dateStyle.setFont(dateFont); 256 dateStyle.setFillBackgroundColor(IndexedColors.SKY_BLUE.index); 257 } 258 259 /** 260 * @Description: 初始化表頭行樣式 261 */ 262 private static void initHeadCellStyle() { 263 headStyle.setAlignment(CellStyle.ALIGN_CENTER); 264 headStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); 265 headStyle.setFont(headFont); 266 headStyle.setFillBackgroundColor(IndexedColors.YELLOW.index); 267 headStyle.setBorderTop(CellStyle.BORDER_MEDIUM); 268 headStyle.setBorderBottom(CellStyle.BORDER_THIN); 269 headStyle.setBorderLeft(CellStyle.BORDER_THIN); 270 headStyle.setBorderRight(CellStyle.BORDER_THIN); 271 headStyle.setTopBorderColor(IndexedColors.BLUE.index); 272 headStyle.setBottomBorderColor(IndexedColors.BLUE.index); 273 headStyle.setLeftBorderColor(IndexedColors.BLUE.index); 274 headStyle.setRightBorderColor(IndexedColors.BLUE.index); 275 } 276 277 /** 278 * @Description: 初始化內(nèi)容行樣式 279 */ 280 private static void initContentCellStyle() { 281 contentStyle.setAlignment(CellStyle.ALIGN_CENTER); 282 contentStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); 283 contentStyle.setFont(contentFont); 284 contentStyle.setBorderTop(CellStyle.BORDER_THIN); 285 contentStyle.setBorderBottom(CellStyle.BORDER_THIN); 286 contentStyle.setBorderLeft(CellStyle.BORDER_THIN); 287 contentStyle.setBorderRight(CellStyle.BORDER_THIN); 288 contentStyle.setTopBorderColor(IndexedColors.BLUE.index); 289 contentStyle.setBottomBorderColor(IndexedColors.BLUE.index); 290 contentStyle.setLeftBorderColor(IndexedColors.BLUE.index); 291 contentStyle.setRightBorderColor(IndexedColors.BLUE.index); 292 contentStyle.setWrapText(true); // 字段換行 293 } 294 295 /** 296 * @Description: 初始化標(biāo)題行字體 297 */ 298 private static void initTitleFont() { 299 titleFont.setFontName("華文楷體"); 300 titleFont.setFontHeightInPoints((short) 20); 301 titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD); 302 titleFont.setCharSet(Font.DEFAULT_CHARSET); 303 titleFont.setColor(IndexedColors.BLUE_GREY.index); 304 } 305 306 /** 307 * @Description: 初始化日期行字體 308 */ 309 private static void initDateFont() { 310 dateFont.setFontName("隸書"); 311 dateFont.setFontHeightInPoints((short) 10); 312 dateFont.setBoldweight(Font.BOLDWEIGHT_BOLD); 313 dateFont.setCharSet(Font.DEFAULT_CHARSET); 314 dateFont.setColor(IndexedColors.BLUE_GREY.index); 315 } 316 317 /** 318 * @Description: 初始化表頭行字體 319 */ 320 private static void initHeadFont() { 321 headFont.setFontName("宋體"); 322 headFont.setFontHeightInPoints((short) 10); 323 headFont.setBoldweight(Font.BOLDWEIGHT_BOLD); 324 headFont.setCharSet(Font.DEFAULT_CHARSET); 325 headFont.setColor(IndexedColors.BLUE_GREY.index); 326 } 327 328 /** 329 * @Description: 初始化內(nèi)容行字體 330 */ 331 private static void initContentFont() { 332 contentFont.setFontName("宋體"); 333 contentFont.setFontHeightInPoints((short) 10); 334 contentFont.setBoldweight(Font.BOLDWEIGHT_NORMAL); 335 contentFont.setCharSet(Font.DEFAULT_CHARSET); 336 contentFont.setColor(IndexedColors.BLUE_GREY.index); 337 } 338 339 /** 340 * Excel導(dǎo)出數(shù)據(jù)類 341 * 342 * @author jimmy 343 * 344 */ 345 public static class ExcelExportData { 346 347 /** 348 * 導(dǎo)出數(shù)據(jù) key:String 表示每個(gè)Sheet的名稱 value:List<?> 表示每個(gè)Sheet里的所有數(shù)據(jù)行 349 */ 350 private LinkedHashMap<String, List<?>> dataMap; 351 352 /** 353 * 每個(gè)Sheet里的頂部大標(biāo)題 354 */ 355 private String[] titles; 356 357 /** 358 * 單個(gè)sheet里的數(shù)據(jù)列標(biāo)題 359 */ 360 private List<String[]> columnNames; 361 362 /** 363 * 單個(gè)sheet里每行數(shù)據(jù)的列對應(yīng)的對象屬性名稱 364 */ 365 private List<String[]> fieldNames; 366 367 public List<String[]> getFieldNames() { 368 return fieldNames; 369 } 370 371 public void setFieldNames(List<String[]> fieldNames) { 372 this.fieldNames = fieldNames; 373 } 374 375 public String[] getTitles() { 376 return titles; 377 } 378 379 public void setTitles(String[] titles) { 380 this.titles = titles; 381 } 382 383 public List<String[]> getColumnNames() { 384 return columnNames; 385 } 386 387 public void setColumnNames(List<String[]> columnNames) { 388 this.columnNames = columnNames; 389 } 390 391 public LinkedHashMap<String, List<?>> getDataMap() { 392 return dataMap; 393 } 394 395 public void setDataMap(LinkedHashMap<String, List<?>> dataMap) { 396 this.dataMap = dataMap; 397 } 398 399 } 400 } 里面提供了3個(gè)方法,可用于導(dǎo)出到文件、byte數(shù)組、以及流,其中有一個(gè)反射工具類: ![]() 1 package com.cnblogs.yjmyzz.utils; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Modifier; 7 import java.lang.reflect.ParameterizedType; 8 import java.lang.reflect.Type; 9 import java.util.ArrayList; 10 import java.util.Collection; 11 import java.util.Date; 12 import java.util.List; 13 14 import org.apache.commons.beanutils.BeanUtils; 15 import org.apache.commons.beanutils.ConvertUtils; 16 import org.apache.commons.beanutils.PropertyUtils; 17 import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; 18 import org.apache.commons.lang.StringUtils; 19 import org.apache.commons.logging.Log; 20 import org.apache.commons.logging.LogFactory; 21 import org.springframework.util.Assert; 22 23 /** 24 * 反射工具類. 25 * 26 * 提供訪問私有變量,獲取泛型類型Class, 提取集合中元素的屬性, 轉(zhuǎn)換字符串到對象等Util函數(shù). 27 * 28 */ 29 30 public class ReflectionUtil { 31 32 private static Log logger = LogFactory.getLog(ReflectionUtil.class); 33 34 static { 35 DateLocaleConverter dc = new DateLocaleConverter(); 36 // dc.setPatterns(new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" }); 37 ConvertUtils.register(dc, Date.class); 38 } 39 40 /** 41 * 調(diào)用Getter方法. 42 */ 43 public static Object invokeGetterMethod(Object target, String propertyName) { 44 String getterMethodName = "get" + StringUtils.capitalize(propertyName); 45 return invokeMethod(target, getterMethodName, new Class[] {}, 46 new Object[] {}); 47 } 48 49 /** 50 * 調(diào)用Setter方法.使用value的Class來查找Setter方法. 51 */ 52 public static void invokeSetterMethod(Object target, String propertyName, 53 Object value) { 54 invokeSetterMethod(target, propertyName, value, null); 55 } 56 57 /** 58 * 調(diào)用Setter方法. 59 * 60 * @param propertyType 61 * 用于查找Setter方法,為空時(shí)使用value的Class替代. 62 */ 63 public static void invokeSetterMethod(Object target, String propertyName, 64 Object value, Class<?> propertyType) { 65 Class<?> type = propertyType != null ? propertyType : value.getClass(); 66 String setterMethodName = "set" + StringUtils.capitalize(propertyName); 67 invokeMethod(target, setterMethodName, new Class[] { type }, 68 new Object[] { value }); 69 } 70 71 /** 72 * 直接讀取對象屬性值, 無視private/protected修飾符, 不經(jīng)過getter函數(shù). 73 */ 74 public static Object getFieldValue(final Object object, 75 final String fieldName) { 76 Field field = getDeclaredField(object, fieldName); 77 78 if (field == null) { 79 throw new IllegalArgumentException("Could not find field [" 80 + fieldName + "] on target [" + object + "]"); 81 } 82 83 makeAccessible(field); 84 85 Object result = null; 86 try { 87 result = field.get(object); 88 } catch (IllegalAccessException e) { 89 logger.error("不可能拋出的異常{}" + e.getMessage()); 90 } 91 return result; 92 } 93 94 /** 95 * 直接設(shè)置對象屬性值, 無視private/protected修飾符, 不經(jīng)過setter函數(shù). 96 */ 97 public static void setFieldValue(final Object object, 98 final String fieldName, final Object value) { 99 Field field = getDeclaredField(object, fieldName); 100 101 if (field == null) { 102 throw new IllegalArgumentException("Could not find field [" 103 + fieldName + "] on target [" + object + "]"); 104 } 105 106 makeAccessible(field); 107 108 try { 109 field.set(object, value); 110 } catch (IllegalAccessException e) { 111 logger.error("不可能拋出的異常:{}" + e.getMessage()); 112 } 113 } 114 115 /** 116 * 直接調(diào)用對象方法, 無視private/protected修飾符. 117 */ 118 public static Object invokeMethod(final Object object, 119 final String methodName, final Class<?>[] parameterTypes, 120 final Object[] parameters) { 121 Method method = getDeclaredMethod(object, methodName, parameterTypes); 122 if (method == null) { 123 throw new IllegalArgumentException("Could not find method [" 124 + methodName + "] parameterType " + parameterTypes 125 + " on target [" + object + "]"); 126 } 127 128 method.setAccessible(true); 129 130 try { 131 return method.invoke(object, parameters); 132 } catch (Exception e) { 133 throw convertReflectionExceptionToUnchecked(e); 134 } 135 } 136 137 /** 138 * 循環(huán)向上轉(zhuǎn)型, 獲取對象的DeclaredField. 139 * 140 * 如向上轉(zhuǎn)型到Object仍無法找到, 返回null. 141 */ 142 protected static Field getDeclaredField(final Object object, 143 final String fieldName) { 144 Assert.notNull(object, "object不能為空"); 145 Assert.hasText(fieldName, "fieldName"); 146 for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass 147 .getSuperclass()) { 148 try { 149 return superClass.getDeclaredField(fieldName); 150 } catch (NoSuchFieldException e) {// NOSONAR 151 // Field不在當(dāng)前類定義,繼續(xù)向上轉(zhuǎn)型 152 } 153 } 154 return null; 155 } 156 157 /** 158 * 強(qiáng)行設(shè)置Field可訪問. 159 */ 160 protected static void makeAccessible(final Field field) { 161 if (!Modifier.isPublic(field.getModifiers()) 162 || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { 163 field.setAccessible(true); 164 } 165 } 166 167 /** 168 * 循環(huán)向上轉(zhuǎn)型, 獲取對象的DeclaredMethod. 169 * 170 * 如向上轉(zhuǎn)型到Object仍無法找到, 返回null. 171 */ 172 protected static Method getDeclaredMethod(Object object, String methodName, 173 Class<?>[] parameterTypes) { 174 Assert.notNull(object, "object不能為空"); 175 176 for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass 177 .getSuperclass()) { 178 try { 179 return superClass.getDeclaredMethod(methodName, parameterTypes); 180 } catch (NoSuchMethodException e) {// NOSONAR 181 // Method不在當(dāng)前類定義,繼續(xù)向上轉(zhuǎn)型 182 } 183 } 184 return null; 185 } 186 187 /** 188 * 通過反射, 獲得Class定義中聲明的父類的泛型參數(shù)的類型. 如無法找到, 返回Object.class. eg. public UserDao 189 * extends HibernateDao<User> 190 * 191 * @param clazz 192 * The class to introspect 193 * @return the first generic declaration, or Object.class if cannot be 194 * determined 195 */ 196 @SuppressWarnings("unchecked") 197 public static <T> Class<T> getSuperClassGenricType(final Class<?> clazz) { 198 return getSuperClassGenricType(clazz, 0); 199 } 200 201 /** 202 * 通過反射, 獲得定義Class時(shí)聲明的父類的泛型參數(shù)的類型. 如無法找到, 返回Object.class. 203 * 204 * 如public UserDao extends HibernateDao<User,Long> 205 * 206 * @param clazz 207 * clazz The class to introspect 208 * @param index 209 * the Index of the generic ddeclaration,start from 0. 210 * @return the index generic declaration, or Object.class if cannot be 211 * determined 212 */ 213 @SuppressWarnings("unchecked") 214 public static Class getSuperClassGenricType(final Class<?> clazz, 215 final int index) { 216 Type genType = clazz.getGenericSuperclass(); 217 218 if (!(genType instanceof ParameterizedType)) { 219 logger.warn(clazz.getSimpleName() 220 + "'s superclass not ParameterizedType"); 221 return Object.class; 222 } 223 224 Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); 225 226 if (index >= params.length || index < 0) { 227 logger.warn("Index: " + index + ", Size of " 228 + clazz.getSimpleName() + "'s Parameterized Type: " 229 + params.length); 230 return Object.class; 231 } 232 if (!(params[index] instanceof Class)) { 233 logger.warn(clazz.getSimpleName() 234 + " not set the actual class on superclass generic parameter"); 235 return Object.class; 236 } 237 238 return (Class) params[index]; 239 } 240 241 /** 242 * 提取集合中的對象的屬性(通過getter函數(shù)), 組合成List. 243 * 244 * @param collection 245 * 來源集合. 246 * @param propertyName 247 * 要提取的屬性名. 248 */ 249 250 public static List convertElementPropertyToList( 251 final Collection collection, final String propertyName) { 252 List list = new ArrayList(); 253 254 try { 255 for (Object obj : collection) { 256 list.add(PropertyUtils.getProperty(obj, propertyName)); 257 } 258 } catch (Exception e) { 259 throw convertReflectionExceptionToUnchecked(e); 260 } 261 262 return list; 263 } 264 265 /** 266 * 提取集合中的對象的屬性(通過getter函數(shù)), 組合成由分割符分隔的字符串. 267 * 268 * @param collection 269 * 來源集合. 270 * @param propertyName 271 * 要提取的屬性名. 272 * @param separator 273 * 分隔符. 274 */ 275 @SuppressWarnings("unchecked") 276 public static String convertElementPropertyToString( 277 final Collection collection, final String propertyName, 278 final String separator) { 279 List list = convertElementPropertyToList(collection, propertyName); 280 return StringUtils.join(list, separator); 281 } 282 283 /** 284 * 轉(zhuǎn)換字符串到相應(yīng)類型. 285 * 286 * @param value 287 * 待轉(zhuǎn)換的字符串 288 * @param toType 289 * 轉(zhuǎn)換目標(biāo)類型 290 */ 291 @SuppressWarnings("unchecked") 292 public static <T> T convertStringToObject(String value, Class<T> toType) { 293 try { 294 return (T) ConvertUtils.convert(value, toType); 295 } catch (Exception e) { 296 throw convertReflectionExceptionToUnchecked(e); 297 } 298 } 299 300 /** 301 * 將反射時(shí)的checked exception轉(zhuǎn)換為unchecked exception. 302 */ 303 public static RuntimeException convertReflectionExceptionToUnchecked( 304 Exception e) { 305 return convertReflectionExceptionToUnchecked(null, e); 306 } 307 308 public static RuntimeException convertReflectionExceptionToUnchecked( 309 String desc, Exception e) { 310 desc = (desc == null) ? "Unexpected Checked Exception." : desc; 311 if (e instanceof IllegalAccessException 312 || e instanceof IllegalArgumentException 313 || e instanceof NoSuchMethodException) { 314 return new IllegalArgumentException(desc, e); 315 } else if (e instanceof InvocationTargetException) { 316 return new RuntimeException(desc, 317 ((InvocationTargetException) e).getTargetException()); 318 } else if (e instanceof RuntimeException) { 319 return (RuntimeException) e; 320 } 321 return new RuntimeException(desc, e); 322 } 323 324 public static final <T> T getNewInstance(Class<T> cls) { 325 try { 326 return cls.newInstance(); 327 } catch (InstantiationException e) { 328 e.printStackTrace(); 329 } catch (IllegalAccessException e) { 330 e.printStackTrace(); 331 } 332 return null; 333 } 334 335 /** 336 * 拷貝 source 指定的porperties 屬性 到 dest中 337 * 338 * @return void 339 * @throws InvocationTargetException 340 * @throws IllegalAccessException 341 */ 342 public static void copyPorperties(Object dest, Object source, 343 String[] porperties) throws InvocationTargetException, 344 IllegalAccessException { 345 for (String por : porperties) { 346 Object srcObj = invokeGetterMethod(source, por); 347 logger.debug("屬性名:" + por + "------------- 屬性值:" + srcObj); 348 if (srcObj != null) { 349 try { 350 BeanUtils.setProperty(dest, por, srcObj); 351 } catch (IllegalArgumentException e) { 352 e.printStackTrace(); 353 } catch (IllegalAccessException e) { 354 throw e; 355 } catch (InvocationTargetException e) { 356 throw e; 357 } 358 } 359 } 360 } 361 362 /** 363 * 兩者屬性名一致時(shí),拷貝source里的屬性到dest里 364 * 365 * @return void 366 * @throws IllegalAccessException 367 * @throws InvocationTargetException 368 */ 369 370 public static void copyPorperties(Object dest, Object source) 371 throws IllegalAccessException, InvocationTargetException { 372 Class<? extends Object> srcCla = source.getClass(); 373 Field[] fsF = srcCla.getDeclaredFields(); 374 375 for (Field s : fsF) { 376 String name = s.getName(); 377 Object srcObj = invokeGetterMethod(source, name); 378 try { 379 BeanUtils.setProperty(dest, name, srcObj); 380 } catch (IllegalArgumentException e) { 381 e.printStackTrace(); 382 } catch (IllegalAccessException e) { 383 throw e; 384 } catch (InvocationTargetException e) { 385 throw e; 386 } 387 } 388 // BeanUtils.copyProperties(dest, orig); 389 } 390 391 public static void main(String[] args) throws InvocationTargetException, 392 IllegalAccessException { 393 /* 394 * Document document = new Document(); document.setId(2); 395 * document.setCreateDate(new Date()); DocumentVo dcoVo = new 396 * DocumentVo(); ReflectionUtils.copyPorperties(dcoVo, document,new 397 * String[]{"id","businessName","createDate","applyName","docTitle", 398 * "transactStatus"}); System.out.println(dcoVo.getId()); 399 */ 400 } 401 } 此外,導(dǎo)出到文件時(shí),還用到了一個(gè)讀寫文件的工具類: ![]() 最后是調(diào)用示例: ![]() 導(dǎo)出后的樣子如下: |
|