哈尔滨网站建设效果好,怎么下载网站的模板,淮南王刘安,饮食网站首页页面涉及较多封装的工具类#xff0c;所有依赖的工具类均提供代码#xff0c;根据名称新建对应的类#xff0c;在每个工具类中再引入相应的依赖即可
首先需要明确的是#xff0c;需要合并的每个excel的表头名称必须是相同的#xff0c; 针对表头#xff0c;建立传输的dto所有依赖的工具类均提供代码根据名称新建对应的类在每个工具类中再引入相应的依赖即可
首先需要明确的是需要合并的每个excel的表头名称必须是相同的 针对表头建立传输的dto 其中Excel为自定义注解代码如下
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.FIELD)
public interface Excel
{/*** 导出时在excel中排序*/public int sort() default Integer.MAX_VALUE;/*** 导出到Excel中的名字.*/public String name() default ;/*** 日期格式, 如: yyyy-MM-dd*/public String dateFormat() default ;/*** 读取内容转表达式 (如: 0男,1女,2未知)*/public String readConverterExp() default ;/*** 分隔符读取字符串组内容*/public String separator() default ,;/*** BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)*/public int scale() default -1;/*** BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN*/public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;/*** 导出类型0数字 1字符串*/public ColumnType cellType() default ColumnType.STRING;/*** 导出时在excel中每个列的高度 单位为字符*/public double height() default 14;/*** 导出时在excel中每个列的宽 单位为字符*/public double width() default 16;/*** 文字后缀,如% 90 变成90%*/public String suffix() default ;/*** 当值为空时,字段的默认值*/public String defaultValue() default ;/*** 提示信息*/public String prompt() default ;/*** 设置只能选择不能输入的列内容.*/public String[] combo() default {};/*** 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.*/public boolean isExport() default true;/*** 另一个类中的属性名称,支持多级获取,以小数点隔开*/public String targetAttr() default ;/*** 是否自动统计数据,在最后追加一行统计数据总和*/public boolean isStatistics() default false;/*** 导出字段对齐方式0默认1靠左2居中3靠右*/public Align align() default Align.AUTO;/*** 自定义数据处理器*/public Class? handler() default ExcelHandlerAdapter.class;/*** 自定义数据处理器参数*/public String[] args() default {};public enum Align{AUTO(0), LEFT(1), CENTER(2), RIGHT(3);private final int value;Align(int value){this.value value;}public int value(){return this.value;}}/*** 字段类型0导出导入1仅导出2仅导入*/Type type() default Type.ALL;public enum Type{ALL(0), EXPORT(1), IMPORT(2);private final int value;Type(int value){this.value value;}public int value(){return this.value;}}public enum ColumnType{NUMERIC(0), STRING(1), IMAGE(2);private final int value;ColumnType(int value){this.value value;}public int value(){return this.value;}}
}以上注解需要Excel数据格式处理适配器ExcelHandlerAdapter 代码如下
public interface ExcelHandlerAdapter
{/*** 格式化* * param value 单元格数据值* param args excel注解args参数组** return 处理后的值*/Object format(Object value, String[] args);
}接口实现如下 ApiOperation(合并草本提取物excel)PostMapping(addExcel)public void addExcel(ListMultipartFile file,HttpServletResponse response) throws Exception{ExcelUtilHerbExtractDto util2 new ExcelUtilHerbExtractDto(HerbExtractDto.class);ListHerbExtractDto herbExtractDtoList new ArrayList();int i 1;for(MultipartFile tmpFile : file){ExcelUtilHerbExtractDto util new ExcelUtilHerbExtractDto(HerbExtractDto.class);ListHerbExtractDto tmpList util.importExcel(tmpFile.getInputStream());herbExtractDtoList.addAll(tmpList);i;}util2.exportExcel(response,herbExtractDtoList,草本提取物信息);}原理是传入多个excel文件循环读取每个excel里面的数据保存到临时变量tmpList中再添加到最终需要导出的集合herbExtractDtoList中ExcelUtil代码如下
public class ExcelUtilT
{private static final Logger log LoggerFactory.getLogger(ExcelUtil.class);/*** Excel sheet最大行数默认65536*/public static final int sheetSize 6553600;/*** 工作表名称*/private String sheetName;/*** 导出类型EXPORT:导出数据IMPORT导入模板*/private Type type;/*** 工作薄对象*/private Workbook wb;/*** 工作表对象*/private Sheet sheet;/*** 样式列表*/private MapString, CellStyle styles;/*** 导入导出数据列表*/private ListT list;/*** 注解列表*/private ListObject[] fields;/*** 当前行号*/private int rownum;/*** 标题*/private String title;/*** 最大高度*/private short maxHeight;/*** 统计列表*/private MapInteger, Double statistics new HashMapInteger, Double();/*** 数字格式*/private static final DecimalFormat DOUBLE_FORMAT new DecimalFormat(######0.00);/*** 实体对象*/public ClassT clazz;public ExcelUtil(ClassT clazz){this.clazz clazz;}public void init(ListT list, String sheetName, String title, Type type){if (list null){list new ArrayListT();}this.list list;this.sheetName sheetName;this.type type;this.title title;createExcelField();createWorkbook();createTitle();}/*** 创建excel第一行标题*/public void createTitle(){if (StringUtils.isNotEmpty(title)){Row titleRow sheet.createRow(rownum 0 ? rownum : 0);titleRow.setHeightInPoints(30);Cell titleCell titleRow.createCell(0);titleCell.setCellStyle(styles.get(title));titleCell.setCellValue(title);sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(),this.fields.size() - 1));}}/*** 对excel表单默认第一个索引名转换成list* * param is 输入流* return 转换后集合*/public ListT importExcel(InputStream is) throws Exception{return importExcel(is, 0);}/*** 对excel表单默认第一个索引名转换成list* * param is 输入流* param titleNum 标题占用行数* return 转换后集合*/public ListT importExcel(InputStream is, int titleNum) throws Exception{return importExcel(StringUtils.EMPTY, is, titleNum);}/*** 对excel表单指定表格索引名转换成list* * param sheetName 表格索引名* param titleNum 标题占用行数* param is 输入流* return 转换后集合*/public ListT importExcel(String sheetName, InputStream is, int titleNum) throws Exception{this.type Type.IMPORT;this.wb WorkbookFactory.create(is);ListT list new ArrayListT();// 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheetSheet sheet StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);if (sheet null){throw new IOException(文件sheet不存在);}// 获取最后一个非空行的行下标比如总行数为n则返回的为n-1int rows sheet.getLastRowNum();if (rows 0){// 定义一个map用于存放excel列的序号和field.MapString, Integer cellMap new HashMapString, Integer();// 获取表头Row heard sheet.getRow(titleNum);for (int i 0; i heard.getPhysicalNumberOfCells(); i){Cell cell heard.getCell(i);if (StringUtils.isNotNull(cell)){String value this.getCellValue(heard, i).toString();cellMap.put(value, i);}else{cellMap.put(null, i);}}// 有数据时才处理 得到类的所有field.ListObject[] fields this.getFields();MapInteger, Object[] fieldsMap new HashMapInteger, Object[]();for (Object[] objects : fields){Excel attr (Excel) objects[1];Integer column cellMap.get(attr.name());if (column ! null){fieldsMap.put(column, objects);}}for (int i titleNum 1; i rows; i){// 从第2行开始取数据,默认第一行是表头.Row row sheet.getRow(i);// 判断当前行是否是空行if (isRowEmpty(row)){continue;}T entity null;for (Map.EntryInteger, Object[] entry : fieldsMap.entrySet()){Object val this.getCellValue(row, entry.getKey());// 如果不存在实例则新建.entity (entity null ? clazz.newInstance() : entity);// 从map中得到对应列的field.Field field (Field) entry.getValue()[0];Excel attr (Excel) entry.getValue()[1];// 取得类型,并根据对象类型设置值.Class? fieldType field.getType();if (String.class fieldType){String s Convert.toStr(val);if (StringUtils.endsWith(s, .0)){val StringUtils.substringBefore(s, .0);}else{String dateFormat field.getAnnotation(Excel.class).dateFormat();if (StringUtils.isNotEmpty(dateFormat)){val DateUtils.parseDateToStr(dateFormat, (Date) val);}else{val Convert.toStr(val);}}}else if ((Integer.TYPE fieldType || Integer.class fieldType) StringUtils.isNumeric(Convert.toStr(val))){val Convert.toInt(val);}else if (Long.TYPE fieldType || Long.class fieldType){val Convert.toLong(val);}else if (Double.TYPE fieldType || Double.class fieldType){val Convert.toDouble(val);}else if (Float.TYPE fieldType || Float.class fieldType){val Convert.toFloat(val);}else if (BigDecimal.class fieldType){val Convert.toBigDecimal(val);}else if (Date.class fieldType){if (val instanceof String){val DateUtils.parseDate(val);}else if (val instanceof Double){val DateUtil.getJavaDate((Double) val);}}else if (Boolean.TYPE fieldType || Boolean.class fieldType){val Convert.toBool(val, false);}if (StringUtils.isNotNull(fieldType)){String propertyName field.getName();if (StringUtils.isNotEmpty(attr.targetAttr())){propertyName field.getName() . attr.targetAttr();}else if (StringUtils.isNotEmpty(attr.readConverterExp())){val reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());}else if (!attr.handler().equals(ExcelHandlerAdapter.class)){val dataFormatHandlerAdapter(val, attr);}ReflectUtils.invokeSetter(entity, propertyName, val);}}list.add(entity);}}return list;}/*** 对list数据源将其里面的数据导入到excel表单* * param response 返回数据* param list 导出数据集合* param sheetName 工作表的名称* return 结果* throws IOException*/public void exportExcel(HttpServletResponse response, ListT list, String sheetName){exportExcel(response, list, sheetName, StringUtils.EMPTY);}/*** 对list数据源将其里面的数据导入到excel表单** param stream 输出流* param list 导出数据集合* param sheetName 工作表的名称* return 结果* throws IOException*/public void exportExcel(OutputStream stream, ListT list, String sheetName) throws IOException {exportExcel(stream, list, sheetName, StringUtils.EMPTY);}/*** 对list数据源将其里面的数据导入到excel表单* * param response 返回数据* param list 导出数据集合* param sheetName 工作表的名称* param title 标题* return 结果* throws IOException*/public void exportExcel(HttpServletResponse response, ListT list, String sheetName, String title){response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet);response.setCharacterEncoding(utf-8);this.init(list, sheetName, title, Type.EXPORT);exportExcel(response);}/*** 对list数据源将其里面的数据导入到excel表单** param stream 输出流* param list 导出数据集合* param sheetName 工作表的名称* param title 标题* return 结果* throws IOException*/public void exportExcel(OutputStream stream, ListT list, String sheetName, String title) throws IOException {this.init(list, sheetName, title, Type.EXPORT);exportExcel(stream);}/*** 对list数据源将其里面的数据导入到excel表单* * param sheetName 工作表的名称* return 结果*//*** 对list数据源将其里面的数据导入到excel表单* * param sheetName 工作表的名称* return 结果*/public void importTemplateExcel(HttpServletResponse response, String sheetName){importTemplateExcel(response, sheetName, StringUtils.EMPTY);}/*** 对list数据源将其里面的数据导入到excel表单* * param sheetName 工作表的名称* param title 标题* return 结果*/public void importTemplateExcel(HttpServletResponse response, String sheetName, String title){response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet);response.setCharacterEncoding(utf-8);this.init(null, sheetName, title, Type.IMPORT);exportExcel(response);}/*** 对list数据源将其里面的数据导入到excel表单** return 结果*/public void exportExcel(HttpServletResponse response){try{writeSheet();wb.write(response.getOutputStream());}catch (Exception e){log.error(导出Excel异常{}, e.getMessage());}finally{IOUtils.closeQuietly(wb);}}/*** 对list数据源将其里面的数据导入到excel表单** return 结果*/public void exportExcel(OutputStream stream) throws IOException {try{writeSheet();wb.write(stream);}catch (Exception e){log.error(导出Excel异常{}, e.getMessage());}finally{stream.close();}}/*** 创建写入数据到Sheet*/public void writeSheet(){// 取出一共有多少个sheet.int sheetNo Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));for (int index 0; index sheetNo; index){createSheet(sheetNo, index);// 产生一行Row row sheet.createRow(rownum);int column 0;// 写入各个字段的列头名称for (Object[] os : fields){Excel excel (Excel) os[1];this.createCell(excel, row, column);}if (Type.EXPORT.equals(type)){fillExcelData(index, row);addStatisticsRow();}}}/*** 填充excel数据* * param index 序号* param row 单元格行*/public void fillExcelData(int index, Row row){int startNo index * sheetSize;int endNo Math.min(startNo sheetSize, list.size());for (int i startNo; i endNo; i){row sheet.createRow(i 1 rownum - startNo);// 得到导出对象.T vo (T) list.get(i);int column 0;for (Object[] os : fields){Field field (Field) os[0];Excel excel (Excel) os[1];this.addCell(excel, row, vo, field, column);}}}/*** 创建表格样式* * param wb 工作薄对象* return 样式列表*/private MapString, CellStyle createStyles(Workbook wb){// 写入各条记录,每条记录对应excel表中的一行MapString, CellStyle styles new HashMapString, CellStyle();CellStyle style wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);Font titleFont wb.createFont();titleFont.setFontName(Arial);titleFont.setFontHeightInPoints((short) 16);titleFont.setBold(true);style.setFont(titleFont);styles.put(title, style);style wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setBorderRight(BorderStyle.THIN);style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderLeft(BorderStyle.THIN);style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderTop(BorderStyle.THIN);style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setBorderBottom(BorderStyle.THIN);style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());Font dataFont wb.createFont();dataFont.setFontName(Arial);dataFont.setFontHeightInPoints((short) 10);style.setFont(dataFont);styles.put(data, style);style wb.createCellStyle();style.cloneStyleFrom(styles.get(data));style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());style.setFillPattern(FillPatternType.SOLID_FOREGROUND);Font headerFont wb.createFont();headerFont.setFontName(Arial);headerFont.setFontHeightInPoints((short) 10);headerFont.setBold(true);headerFont.setColor(IndexedColors.WHITE.getIndex());style.setFont(headerFont);styles.put(header, style);style wb.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);Font totalFont wb.createFont();totalFont.setFontName(Arial);totalFont.setFontHeightInPoints((short) 10);style.setFont(totalFont);styles.put(total, style);style wb.createCellStyle();style.cloneStyleFrom(styles.get(data));style.setAlignment(HorizontalAlignment.LEFT);styles.put(data1, style);style wb.createCellStyle();style.cloneStyleFrom(styles.get(data));style.setAlignment(HorizontalAlignment.CENTER);styles.put(data2, style);style wb.createCellStyle();style.cloneStyleFrom(styles.get(data));style.setAlignment(HorizontalAlignment.RIGHT);styles.put(data3, style);return styles;}/*** 创建单元格*/public Cell createCell(Excel attr, Row row, int column){// 创建列Cell cell row.createCell(column);// 写入列信息cell.setCellValue(attr.name());setDataValidation(attr, row, column);cell.setCellStyle(styles.get(header));return cell;}/*** 设置单元格信息* * param value 单元格值* param attr 注解相关* param cell 单元格信息*/public void setCellVo(Object value, Excel attr, Cell cell){if (ColumnType.STRING attr.cellType()){cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value attr.suffix());}else if (ColumnType.NUMERIC attr.cellType()){if (StringUtils.isNotNull(value)){cell.setCellValue(StringUtils.contains(Convert.toStr(value), .) ? Convert.toDouble(value) : Convert.toInt(value));}}else if (ColumnType.IMAGE attr.cellType()){ClientAnchor anchor new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() 1), cell.getRow().getRowNum() 1);String imagePath Convert.toStr(value);if (StringUtils.isNotEmpty(imagePath)){byte[] data ImageUtils.getImage(imagePath);getDrawingPatriarch(cell.getSheet()).createPicture(anchor,cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));}}}/*** 获取画布*/public static Drawing? getDrawingPatriarch(Sheet sheet){if (sheet.getDrawingPatriarch() null){sheet.createDrawingPatriarch();}return sheet.getDrawingPatriarch();}/*** 获取图片类型,设置图片插入类型*/public int getImageType(byte[] value){String type FileTypeUtils.getFileExtendName(value);if (JPG.equalsIgnoreCase(type)){return Workbook.PICTURE_TYPE_JPEG;}else if (PNG.equalsIgnoreCase(type)){return Workbook.PICTURE_TYPE_PNG;}return Workbook.PICTURE_TYPE_JPEG;}/*** 创建表格样式*/public void setDataValidation(Excel attr, Row row, int column){if (attr.name().indexOf(注) 0){sheet.setColumnWidth(column, 6000);}else{// 设置列宽sheet.setColumnWidth(column, (int) ((attr.width() 0.72) * 256));}// 如果设置了提示信息则鼠标放上去提示.if (StringUtils.isNotEmpty(attr.prompt())){// 这里默认设了2-101列提示.setXSSFPrompt(sheet, , attr.prompt(), 1, 100, column, column);}// 如果设置了combo属性则本列只能选择不能输入if (attr.combo().length 0){// 这里默认设了2-101列只能选择不能输入.setXSSFValidation(sheet, attr.combo(), 1, 100, column, column);}}/*** 添加单元格*/public Cell addCell(Excel attr, Row row, T vo, Field field, int column){Cell cell null;try{// 设置行高row.setHeight(maxHeight);// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.if (attr.isExport()){// 创建cellcell row.createCell(column);int align attr.align().value();cell.setCellStyle(styles.get(data (align 1 align 3 ? align : )));// 用于读取对象中的属性Object value getTargetValue(vo, field, attr);String dateFormat attr.dateFormat();String readConverterExp attr.readConverterExp();String separator attr.separator();if (StringUtils.isNotEmpty(dateFormat) StringUtils.isNotNull(value)){cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));}else if (StringUtils.isNotEmpty(readConverterExp) StringUtils.isNotNull(value)){cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));}else if (value instanceof BigDecimal -1 ! attr.scale()){cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString());}else if (!attr.handler().equals(ExcelHandlerAdapter.class)){cell.setCellValue(dataFormatHandlerAdapter(value, attr));}else{// 设置列类型setCellVo(value, attr, cell);}addStatisticsData(column, Convert.toStr(value), attr);}}catch (Exception e){log.error(导出Excel失败{}, e);}return cell;}/*** 设置 POI XSSFSheet 单元格提示* * param sheet 表单* param promptTitle 提示标题* param promptContent 提示内容* param firstRow 开始行* param endRow 结束行* param firstCol 开始列* param endCol 结束列*/public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,int firstCol, int endCol){DataValidationHelper helper sheet.getDataValidationHelper();DataValidationConstraint constraint helper.createCustomConstraint(DD1);CellRangeAddressList regions new CellRangeAddressList(firstRow, endRow, firstCol, endCol);DataValidation dataValidation helper.createValidation(constraint, regions);dataValidation.createPromptBox(promptTitle, promptContent);dataValidation.setShowPromptBox(true);sheet.addValidationData(dataValidation);}/*** 设置某些列的值只能输入预制的数据,显示下拉框.* * param sheet 要设置的sheet.* param textlist 下拉框显示的内容* param firstRow 开始行* param endRow 结束行* param firstCol 开始列* param endCol 结束列* return 设置好的sheet.*/public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol){DataValidationHelper helper sheet.getDataValidationHelper();// 加载下拉列表内容DataValidationConstraint constraint helper.createExplicitListConstraint(textlist);// 设置数据有效性加载在哪个单元格上,四个参数分别是起始行、终止行、起始列、终止列CellRangeAddressList regions new CellRangeAddressList(firstRow, endRow, firstCol, endCol);// 数据有效性对象DataValidation dataValidation helper.createValidation(constraint, regions);// 处理Excel兼容性问题if (dataValidation instanceof XSSFDataValidation){dataValidation.setSuppressDropDownArrow(true);dataValidation.setShowErrorBox(true);}else{dataValidation.setSuppressDropDownArrow(false);}sheet.addValidationData(dataValidation);}/*** 解析导出值 0男,1女,2未知* * param propertyValue 参数值* param converterExp 翻译注解* param separator 分隔符* return 解析后值*/public static String convertByExp(String propertyValue, String converterExp, String separator){StringBuilder propertyString new StringBuilder();String[] convertSource converterExp.split(,);for (String item : convertSource){String[] itemArray item.split();if (StringUtils.containsAny(separator, propertyValue)){for (String value : propertyValue.split(separator)){if (itemArray[0].equals(value)){propertyString.append(itemArray[1] separator);break;}}}else{if (itemArray[0].equals(propertyValue)){return itemArray[1];}}}return StringUtils.stripEnd(propertyString.toString(), separator);}/*** 反向解析值 男0,女1,未知2* * param propertyValue 参数值* param converterExp 翻译注解* param separator 分隔符* return 解析后值*/public static String reverseByExp(String propertyValue, String converterExp, String separator){StringBuilder propertyString new StringBuilder();String[] convertSource converterExp.split(,);for (String item : convertSource){String[] itemArray item.split();if (StringUtils.containsAny(separator, propertyValue)){for (String value : propertyValue.split(separator)){if (itemArray[1].equals(value)){propertyString.append(itemArray[0] separator);break;}}}else{if (itemArray[1].equals(propertyValue)){return itemArray[0];}}}return StringUtils.stripEnd(propertyString.toString(), separator);}/*** 数据处理器* * param value 数据值* param excel 数据注解* return*/public String dataFormatHandlerAdapter(Object value, Excel excel){try{Object instance excel.handler().newInstance();Method formatMethod excel.handler().getMethod(format, new Class[] { Object.class, String[].class });value formatMethod.invoke(instance, value, excel.args());}catch (Exception e){log.error(不能格式化数据 excel.handler(), e.getMessage());}return Convert.toStr(value);}/*** 合计统计信息*/private void addStatisticsData(Integer index, String text, Excel entity){if (entity ! null entity.isStatistics()){Double temp 0D;if (!statistics.containsKey(index)){statistics.put(index, temp);}try{temp Double.valueOf(text);}catch (NumberFormatException e){}statistics.put(index, statistics.get(index) temp);}}/*** 创建统计行*/public void addStatisticsRow(){if (statistics.size() 0){Row row sheet.createRow(sheet.getLastRowNum() 1);SetInteger keys statistics.keySet();Cell cell row.createCell(0);cell.setCellStyle(styles.get(total));cell.setCellValue(合计);for (Integer key : keys){cell row.createCell(key);cell.setCellStyle(styles.get(total));cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));}statistics.clear();}}/*** 获取bean中的属性值* * param vo 实体对象* param field 字段* param excel 注解* return 最终的属性值* throws Exception*/private Object getTargetValue(T vo, Field field, Excel excel) throws Exception{Object o field.get(vo);if (StringUtils.isNotEmpty(excel.targetAttr())){String target excel.targetAttr();if (target.indexOf(.) -1){String[] targets target.split([.]);for (String name : targets){o getValue(o, name);}}else{o getValue(o, target);}}return o;}/*** 以类的属性的get方法方法形式获取值* * param o* param name* return value* throws Exception*/private Object getValue(Object o, String name) throws Exception{if (StringUtils.isNotNull(o) StringUtils.isNotEmpty(name)){Class? clazz o.getClass();Field field clazz.getDeclaredField(name);field.setAccessible(true);o field.get(o);}return o;}/*** 得到所有定义字段*/private void createExcelField(){this.fields getFields();this.fields this.fields.stream().sorted(Comparator.comparing(objects - ((Excel) objects[1]).sort())).collect(Collectors.toList());this.maxHeight getRowHeight();}/*** 获取字段注解信息*/public ListObject[] getFields(){ListObject[] fields new ArrayListObject[]();ListField tempFields new ArrayList();tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));for (Field field : tempFields){// 单注解if (field.isAnnotationPresent(Excel.class)){Excel attr field.getAnnotation(Excel.class);if (attr ! null (attr.type() Type.ALL || attr.type() type)){field.setAccessible(true);fields.add(new Object[] { field, attr });}}// 多注解if (field.isAnnotationPresent(Excels.class)){Excels attrs field.getAnnotation(Excels.class);Excel[] excels attrs.value();for (Excel attr : excels){if (attr ! null (attr.type() Type.ALL || attr.type() type)){field.setAccessible(true);fields.add(new Object[] { field, attr });}}}}return fields;}/*** 根据注解获取最大行高*/public short getRowHeight(){double maxHeight 0;for (Object[] os : this.fields){Excel excel (Excel) os[1];maxHeight maxHeight excel.height() ? maxHeight : excel.height();}return (short) (maxHeight * 20);}/*** 创建一个工作簿*/public void createWorkbook(){this.wb new SXSSFWorkbook(500);this.sheet wb.createSheet();wb.setSheetName(0, sheetName);this.styles createStyles(wb);}/*** 创建工作表* * param sheetNo sheet数量* param index 序号*/public void createSheet(int sheetNo, int index){// 设置工作表的名称.if (sheetNo 1 index 0){this.sheet wb.createSheet();this.createTitle();wb.setSheetName(index, sheetName index);}}/*** 获取单元格值* * param row 获取的行* param column 获取单元格列号* return 单元格值*/public Object getCellValue(Row row, int column){if (row null){return row;}Object val ;try{Cell cell row.getCell(column);if (StringUtils.isNotNull(cell)){if (cell.getCellType() CellType.NUMERIC || cell.getCellType() CellType.FORMULA){val cell.getNumericCellValue();if (DateUtil.isCellDateFormatted(cell)){val DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换}else{if ((Double) val % 1 ! 0){val new BigDecimal(val.toString());}else{val new DecimalFormat(0).format(val);}}}else if (cell.getCellType() CellType.STRING){val cell.getStringCellValue();}else if (cell.getCellType() CellType.BOOLEAN){val cell.getBooleanCellValue();}else if (cell.getCellType() CellType.ERROR){val cell.getErrorCellValue();}}}catch (Exception e){return val;}return val;}/*** 判断是否是空行* * param row 判断的行* return*/private boolean isRowEmpty(Row row){if (row null){return true;}for (int i row.getFirstCellNum(); i row.getLastCellNum(); i){Cell cell row.getCell(i);if (cell ! null cell.getCellType() ! CellType.BLANK){return false;}}return true;}
}其中需要依赖的各种工具类也写在下面 多注解Excels
Target(ElementType.FIELD)
Retention(RetentionPolicy.RUNTIME)
public interface Excels
{Excel[] value();
}类型转换器Convert
public class Convert
{/*** 转换为字符串br* 如果给定的值为null或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static String toStr(Object value, String defaultValue){if (null value){return defaultValue;}if (value instanceof String){return (String) value;}return value.toString();}/*** 转换为字符串br* 如果给定的值为codenull/code或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static String toStr(Object value){return toStr(value, null);}/*** 转换为字符br* 如果给定的值为null或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Character toChar(Object value, Character defaultValue){if (null value){return defaultValue;}if (value instanceof Character){return (Character) value;}final String valueStr toStr(value, null);return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);}/*** 转换为字符br* 如果给定的值为codenull/code或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Character toChar(Object value){return toChar(value, null);}/*** 转换为bytebr* 如果给定的值为codenull/code或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Byte toByte(Object value, Byte defaultValue){if (value null){return defaultValue;}if (value instanceof Byte){return (Byte) value;}if (value instanceof Number){return ((Number) value).byteValue();}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return Byte.parseByte(valueStr);}catch (Exception e){return defaultValue;}}/*** 转换为bytebr* 如果给定的值为codenull/code或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Byte toByte(Object value){return toByte(value, null);}/*** 转换为Shortbr* 如果给定的值为codenull/code或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Short toShort(Object value, Short defaultValue){if (value null){return defaultValue;}if (value instanceof Short){return (Short) value;}if (value instanceof Number){return ((Number) value).shortValue();}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return Short.parseShort(valueStr.trim());}catch (Exception e){return defaultValue;}}/*** 转换为Shortbr* 如果给定的值为codenull/code或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Short toShort(Object value){return toShort(value, null);}/*** 转换为Numberbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Number toNumber(Object value, Number defaultValue){if (value null){return defaultValue;}if (value instanceof Number){return (Number) value;}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return NumberFormat.getInstance().parse(valueStr);}catch (Exception e){return defaultValue;}}/*** 转换为Numberbr* 如果给定的值为空或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Number toNumber(Object value){return toNumber(value, null);}/*** 转换为intbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Integer toInt(Object value, Integer defaultValue){if (value null){return defaultValue;}if (value instanceof Integer){return (Integer) value;}if (value instanceof Number){return ((Number) value).intValue();}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return Integer.parseInt(valueStr.trim());}catch (Exception e){return defaultValue;}}/*** 转换为intbr* 如果给定的值为codenull/code或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Integer toInt(Object value){return toInt(value, null);}/*** 转换为Integer数组br* * param str 被转换的值* return 结果*/public static Integer[] toIntArray(String str){return toIntArray(,, str);}/*** 转换为Long数组br* * param str 被转换的值* return 结果*/public static Long[] toLongArray(String str){return toLongArray(,, str);}/*** 转换为Integer数组br* * param split 分隔符* param split 被转换的值* return 结果*/public static Integer[] toIntArray(String split, String str){if (StringUtils.isEmpty(str)){return new Integer[] {};}String[] arr str.split(split);final Integer[] ints new Integer[arr.length];for (int i 0; i arr.length; i){final Integer v toInt(arr[i], 0);ints[i] v;}return ints;}/*** 转换为Long数组br* * param split 分隔符* param str 被转换的值* return 结果*/public static Long[] toLongArray(String split, String str){if (StringUtils.isEmpty(str)){return new Long[] {};}String[] arr str.split(split);final Long[] longs new Long[arr.length];for (int i 0; i arr.length; i){final Long v toLong(arr[i], null);longs[i] v;}return longs;}/*** 转换为String数组br* * param str 被转换的值* return 结果*/public static String[] toStrArray(String str){return toStrArray(,, str);}/*** 转换为String数组br* * param split 分隔符* param split 被转换的值* return 结果*/public static String[] toStrArray(String split, String str){return str.split(split);}/*** 转换为longbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Long toLong(Object value, Long defaultValue){if (value null){return defaultValue;}if (value instanceof Long){return (Long) value;}if (value instanceof Number){return ((Number) value).longValue();}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{// 支持科学计数法return new BigDecimal(valueStr.trim()).longValue();}catch (Exception e){return defaultValue;}}/*** 转换为longbr* 如果给定的值为codenull/code或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Long toLong(Object value){return toLong(value, null);}/*** 转换为doublebr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Double toDouble(Object value, Double defaultValue){if (value null){return defaultValue;}if (value instanceof Double){return (Double) value;}if (value instanceof Number){return ((Number) value).doubleValue();}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{// 支持科学计数法return new BigDecimal(valueStr.trim()).doubleValue();}catch (Exception e){return defaultValue;}}/*** 转换为doublebr* 如果给定的值为空或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Double toDouble(Object value){return toDouble(value, null);}/*** 转换为Floatbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Float toFloat(Object value, Float defaultValue){if (value null){return defaultValue;}if (value instanceof Float){return (Float) value;}if (value instanceof Number){return ((Number) value).floatValue();}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return Float.parseFloat(valueStr.trim());}catch (Exception e){return defaultValue;}}/*** 转换为Floatbr* 如果给定的值为空或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Float toFloat(Object value){return toFloat(value, null);}/*** 转换为booleanbr* String支持的值为true、false、yes、ok、no1,0 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static Boolean toBool(Object value, Boolean defaultValue){if (value null){return defaultValue;}if (value instanceof Boolean){return (Boolean) value;}String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}valueStr valueStr.trim().toLowerCase();switch (valueStr){case true:return true;case false:return false;case yes:return true;case ok:return true;case no:return false;case 1:return true;case 0:return false;default:return defaultValue;}}/*** 转换为booleanbr* 如果给定的值为空或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static Boolean toBool(Object value){return toBool(value, null);}/*** 转换为Enum对象br* 如果给定的值为空或者转换失败返回默认值br* * param clazz Enum的Class* param value 值* param defaultValue 默认值* return Enum*/public static E extends EnumE E toEnum(ClassE clazz, Object value, E defaultValue){if (value null){return defaultValue;}if (clazz.isAssignableFrom(value.getClass())){SuppressWarnings(unchecked)E myE (E) value;return myE;}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return Enum.valueOf(clazz, valueStr);}catch (Exception e){return defaultValue;}}/*** 转换为Enum对象br* 如果给定的值为空或者转换失败返回默认值codenull/codebr* * param clazz Enum的Class* param value 值* return Enum*/public static E extends EnumE E toEnum(ClassE clazz, Object value){return toEnum(clazz, value, null);}/*** 转换为BigIntegerbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static BigInteger toBigInteger(Object value, BigInteger defaultValue){if (value null){return defaultValue;}if (value instanceof BigInteger){return (BigInteger) value;}if (value instanceof Long){return BigInteger.valueOf((Long) value);}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return new BigInteger(valueStr);}catch (Exception e){return defaultValue;}}/*** 转换为BigIntegerbr* 如果给定的值为空或者转换失败返回默认值codenull/codebr* 转换失败不会报错* * param value 被转换的值* return 结果*/public static BigInteger toBigInteger(Object value){return toBigInteger(value, null);}/*** 转换为BigDecimalbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* param defaultValue 转换错误时的默认值* return 结果*/public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue){if (value null){return defaultValue;}if (value instanceof BigDecimal){return (BigDecimal) value;}if (value instanceof Long){return new BigDecimal((Long) value);}if (value instanceof Double){return new BigDecimal((Double) value);}if (value instanceof Integer){return new BigDecimal((Integer) value);}final String valueStr toStr(value, null);if (StringUtils.isEmpty(valueStr)){return defaultValue;}try{return new BigDecimal(valueStr);}catch (Exception e){return defaultValue;}}/*** 转换为BigDecimalbr* 如果给定的值为空或者转换失败返回默认值br* 转换失败不会报错* * param value 被转换的值* return 结果*/public static BigDecimal toBigDecimal(Object value){return toBigDecimal(value, null);}/*** 将对象转为字符串br* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法* * param obj 对象* return 字符串*/public static String utf8Str(Object obj){return str(obj, CharsetKit.CHARSET_UTF_8);}/*** 将对象转为字符串br* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法* * param obj 对象* param charsetName 字符集* return 字符串*/public static String str(Object obj, String charsetName){return str(obj, Charset.forName(charsetName));}/*** 将对象转为字符串br* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法* * param obj 对象* param charset 字符集* return 字符串*/public static String str(Object obj, Charset charset){if (null obj){return null;}if (obj instanceof String){return (String) obj;}else if (obj instanceof byte[] || obj instanceof Byte[]){if (obj instanceof byte[]){return str((byte[]) obj, charset);}else{Byte[] bytes (Byte[]) obj;int length bytes.length;byte[] dest new byte[length];for (int i 0; i length; i){dest[i] bytes[i];}return str(dest, charset);}}else if (obj instanceof ByteBuffer){return str((ByteBuffer) obj, charset);}return obj.toString();}/*** 将byte数组转为字符串* * param bytes byte数组* param charset 字符集* return 字符串*/public static String str(byte[] bytes, String charset){return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));}/*** 解码字节码* * param data 字符串* param charset 字符集如果此字段为空则解码的结果取决于平台* return 解码后的字符串*/public static String str(byte[] data, Charset charset){if (data null){return null;}if (null charset){return new String(data);}return new String(data, charset);}/*** 将编码的byteBuffer数据转换为字符串* * param data 数据* param charset 字符集如果为空使用当前系统字符集* return 字符串*/public static String str(ByteBuffer data, String charset){if (data null){return null;}return str(data, Charset.forName(charset));}/*** 将编码的byteBuffer数据转换为字符串* * param data 数据* param charset 字符集如果为空使用当前系统字符集* return 字符串*/public static String str(ByteBuffer data, Charset charset){if (null charset){charset Charset.defaultCharset();}return charset.decode(data).toString();}// ----------------------------------------------------------------------- 全角半角转换/*** 半角转全角* * param input String.* return 全角字符串.*/public static String toSBC(String input){return toSBC(input, null);}/*** 半角转全角* * param input String* param notConvertSet 不替换的字符集合* return 全角字符串.*/public static String toSBC(String input, SetCharacter notConvertSet){char c[] input.toCharArray();for (int i 0; i c.length; i){if (null ! notConvertSet notConvertSet.contains(c[i])){// 跳过不替换的字符continue;}if (c[i] ){c[i] \u3000;}else if (c[i] \177){c[i] (char) (c[i] 65248);}}return new String(c);}/*** 全角转半角* * param input String.* return 半角字符串*/public static String toDBC(String input){return toDBC(input, null);}/*** 替换全角为半角* * param text 文本* param notConvertSet 不替换的字符集合* return 替换后的字符*/public static String toDBC(String text, SetCharacter notConvertSet){char c[] text.toCharArray();for (int i 0; i c.length; i){if (null ! notConvertSet notConvertSet.contains(c[i])){// 跳过不替换的字符continue;}if (c[i] \u3000){c[i] ;}else if (c[i] \uFF00 c[i] \uFF5F){c[i] (char) (c[i] - 65248);}}String returnString new String(c);return returnString;}/*** 数字金额大写转换 先写个完整的然后将如零拾替换成零* * param n 数字* return 中文大写数字*/public static String digitUppercase(double n){String[] fraction { 角, 分 };String[] digit { 零, 壹, 贰, 叁, 肆, 伍, 陆, 柒, 捌, 玖 };String[][] unit { { 元, 万, 亿 }, { , 拾, 佰, 仟 } };String head n 0 ? 负 : ;n Math.abs(n);String s ;for (int i 0; i fraction.length; i){s (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] fraction[i]).replaceAll((零.), );}if (s.length() 1){s 整;}int integerPart (int) Math.floor(n);for (int i 0; i unit[0].length integerPart 0; i){String p ;for (int j 0; j unit[1].length n 0; j){p digit[integerPart % 10] unit[1][j] p;integerPart integerPart / 10;}s p.replaceAll((零.)*零$, ).replaceAll(^$, 零) unit[0][i] s;}return head s.replaceAll((零.)*零元, 元).replaceFirst((零.), ).replaceAll((零.), 零).replaceAll(^整$, 零元整);}
}
时间工具类DateUtils
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{public static String YYYY yyyy;public static String YYYY_MM yyyy-MM;public static String YYYY_MM_DD yyyy-MM-dd;public static String YYYYMMDDHHMMSS yyyyMMddHHmmss;public static String YYYY_MM_DD_HH_MM_SS yyyy-MM-dd HH:mm:ss;private static String[] parsePatterns {yyyy-MM-dd, yyyy-MM-dd HH:mm:ss, yyyy-MM-dd HH:mm, yyyy-MM, yyyy/MM/dd, yyyy/MM/dd HH:mm:ss, yyyy/MM/dd HH:mm, yyyy/MM,yyyy.MM.dd, yyyy.MM.dd HH:mm:ss, yyyy.MM.dd HH:mm, yyyy.MM};/*** 获取当前Date型日期* * return Date() 当前日期*/public static Date getNowDate(){return new Date();}/*** 获取当前日期, 默认格式为yyyy-MM-dd* * return String*/public static String getDate(){return dateTimeNow(YYYY_MM_DD);}public static final String getTime(){return dateTimeNow(YYYY_MM_DD_HH_MM_SS);}public static final String dateTimeNow(){return dateTimeNow(YYYYMMDDHHMMSS);}public static final String dateTimeNow(final String format){return parseDateToStr(format, new Date());}public static final String dateTime(final Date date){return parseDateToStr(YYYY_MM_DD, date);}public static final String parseDateToStr(final String format, final Date date){return new SimpleDateFormat(format).format(date);}public static final Date dateTime(final String format, final String ts){try{return new SimpleDateFormat(format).parse(ts);}catch (ParseException e){throw new RuntimeException(e);}}/*** 日期路径 即年/月/日 如2018/08/08*/public static final String datePath(){Date now new Date();return DateFormatUtils.format(now, yyyy/MM/dd);}/*** 日期路径 即年/月/日 如20180808*/public static final String dateTime(){Date now new Date();return DateFormatUtils.format(now, yyyyMMdd);}/*** 日期型字符串转化为日期 格式*/public static Date parseDate(Object str){if (str null){return null;}try{return parseDate(str.toString(), parsePatterns);}catch (ParseException e){return null;}}/*** 获取服务器启动时间*/public static Date getServerStartDate(){long time ManagementFactory.getRuntimeMXBean().getStartTime();return new Date(time);}/*** 计算两个时间差*/public static String getDatePoor(Date endDate, Date nowDate){long nd 1000 * 24 * 60 * 60;long nh 1000 * 60 * 60;long nm 1000 * 60;// long ns 1000;// 获得两个时间的毫秒时间差异long diff endDate.getTime() - nowDate.getTime();// 计算差多少天long day diff / nd;// 计算差多少小时long hour diff % nd / nh;// 计算差多少分钟long min diff % nd % nh / nm;// 计算差多少秒//输出结果// long sec diff % nd % nh % nm / ns;return day 天 hour 小时 min 分钟;}
}字符串工具类StringUtils
public class StringUtils extends org.apache.commons.lang3.StringUtils
{/** 空字符串 */private static final String NULLSTR ;/** 下划线 */private static final char SEPARATOR _;/*** 获取参数不为空值* * param value defaultValue 要判断的value* return value 返回值*/public static T T nvl(T value, T defaultValue){return value ! null ? value : defaultValue;}/*** * 判断一个Collection是否为空 包含ListSetQueue* * param coll 要判断的Collection* return true为空 false非空*/public static boolean isEmpty(Collection? coll){return isNull(coll) || coll.isEmpty();}/*** * 判断一个Collection是否非空包含ListSetQueue* * param coll 要判断的Collection* return true非空 false空*/public static boolean isNotEmpty(Collection? coll){return !isEmpty(coll);}/*** * 判断一个对象数组是否为空* * param objects 要判断的对象数组** return true为空 false非空*/public static boolean isEmpty(Object[] objects){return isNull(objects) || (objects.length 0);}/*** * 判断一个对象数组是否非空* * param objects 要判断的对象数组* return true非空 false空*/public static boolean isNotEmpty(Object[] objects){return !isEmpty(objects);}/*** * 判断一个Map是否为空* * param map 要判断的Map* return true为空 false非空*/public static boolean isEmpty(Map?, ? map){return isNull(map) || map.isEmpty();}/*** * 判断一个Map是否为空* * param map 要判断的Map* return true非空 false空*/public static boolean isNotEmpty(Map?, ? map){return !isEmpty(map);}/*** * 判断一个字符串是否为空串* * param str String* return true为空 false非空*/public static boolean isEmpty(String str){return isNull(str) || NULLSTR.equals(str.trim());}/*** * 判断一个字符串是否为非空串* * param str String* return true非空串 false空串*/public static boolean isNotEmpty(String str){return !isEmpty(str);}/*** * 判断一个对象是否为空* * param object Object* return true为空 false非空*/public static boolean isNull(Object object){return object null;}/*** * 判断一个对象是否非空* * param object Object* return true非空 false空*/public static boolean isNotNull(Object object){return !isNull(object);}/*** * 判断一个对象是否是数组类型Java基本型别的数组* * param object 对象* return true是数组 false不是数组*/public static boolean isArray(Object object){return isNotNull(object) object.getClass().isArray();}/*** 去空格*/public static String trim(String str){return (str null ? : str.trim());}/*** 截取字符串* * param str 字符串* param start 开始* return 结果*/public static String substring(final String str, int start){if (str null){return NULLSTR;}if (start 0){start str.length() start;}if (start 0){start 0;}if (start str.length()){return NULLSTR;}return str.substring(start);}/*** 截取字符串* * param str 字符串* param start 开始* param end 结束* return 结果*/public static String substring(final String str, int start, int end){if (str null){return NULLSTR;}if (end 0){end str.length() end;}if (start 0){start str.length() start;}if (end str.length()){end str.length();}if (start end){return NULLSTR;}if (start 0){start 0;}if (end 0){end 0;}return str.substring(start, end);}/*** 判断是否为空并且不是空白字符* * param str 要判断的value* return 结果*/public static boolean hasText(String str){return (str ! null !str.isEmpty() containsText(str));}private static boolean containsText(CharSequence str){int strLen str.length();for (int i 0; i strLen; i){if (!Character.isWhitespace(str.charAt(i))){return true;}}return false;}/*** 格式化文本, {} 表示占位符br* 此方法只是简单将占位符 {} 按照顺序替换为参数br* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可br* 例br* 通常使用format(this is {} for {}, a, b) - this is a for bbr* 转义{} format(this is \\{} for {}, a, b) - this is \{} for abr* 转义\ format(this is \\\\{} for {}, a, b) - this is \a for bbr* * param template 文本模板被替换的部分用 {} 表示* param params 参数值* return 格式化后的文本*/public static String format(String template, Object... params){if (isEmpty(params) || isEmpty(template)){return template;}return StrFormatter.format(template, params);}/*** 是否为http(s)://开头* * param link 链接* return 结果*/public static boolean ishttp(String link){return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);}/*** 驼峰转下划线命名*/public static String toUnderScoreCase(String str){if (str null){return null;}StringBuilder sb new StringBuilder();// 前置字符是否大写boolean preCharIsUpperCase true;// 当前字符是否大写boolean curreCharIsUpperCase true;// 下一字符是否大写boolean nexteCharIsUpperCase true;for (int i 0; i str.length(); i){char c str.charAt(i);if (i 0){preCharIsUpperCase Character.isUpperCase(str.charAt(i - 1));}else{preCharIsUpperCase false;}curreCharIsUpperCase Character.isUpperCase(c);if (i (str.length() - 1)){nexteCharIsUpperCase Character.isUpperCase(str.charAt(i 1));}if (preCharIsUpperCase curreCharIsUpperCase !nexteCharIsUpperCase){sb.append(SEPARATOR);}else if ((i ! 0 !preCharIsUpperCase) curreCharIsUpperCase){sb.append(SEPARATOR);}sb.append(Character.toLowerCase(c));}return sb.toString();}/*** 是否包含字符串* * param str 验证字符串* param strs 字符串组* return 包含返回true*/public static boolean inStringIgnoreCase(String str, String... strs){if (str ! null strs ! null){for (String s : strs){if (str.equalsIgnoreCase(trim(s))){return true;}}}return false;}/*** 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空则返回空字符串。 例如HELLO_WORLD-HelloWorld* * param name 转换前的下划线大写方式命名的字符串* return 转换后的驼峰式命名的字符串*/public static String convertToCamelCase(String name){StringBuilder result new StringBuilder();// 快速检查if (name null || name.isEmpty()){// 没必要转换return ;}else if (!name.contains(_)){// 不含下划线仅将首字母大写return name.substring(0, 1).toUpperCase() name.substring(1);}// 用下划线将原始字符串分割String[] camels name.split(_);for (String camel : camels){// 跳过原始字符串中开头、结尾的下换线或双重下划线if (camel.isEmpty()){continue;}// 首字母大写result.append(camel.substring(0, 1).toUpperCase());result.append(camel.substring(1).toLowerCase());}return result.toString();}/*** 驼峰式命名法 例如user_name-userName*/public static String toCamelCase(String s){if (s null){return null;}s s.toLowerCase();StringBuilder sb new StringBuilder(s.length());boolean upperCase false;for (int i 0; i s.length(); i){char c s.charAt(i);if (c SEPARATOR){upperCase true;}else if (upperCase){sb.append(Character.toUpperCase(c));upperCase false;}else{sb.append(c);}}return sb.toString();}/*** 查找指定字符串是否匹配指定字符串列表中的任意一个字符串* * param str 指定字符串* param strs 需要检查的字符串数组* return 是否匹配*/public static boolean matches(String str, ListString strs){if (isEmpty(str) || isEmpty(strs)){return false;}for (String pattern : strs){if (isMatch(pattern, str)){return true;}}return false;}/*** 判断url是否与规则配置: * ? 表示单个字符; * * 表示一层路径内的任意字符串不可跨层级; * ** 表示任意层路径;* * param pattern 匹配规则* param url 需要匹配的url* return*/public static boolean isMatch(String pattern, String url){AntPathMatcher matcher new AntPathMatcher();return matcher.match(pattern, url);}SuppressWarnings(unchecked)public static T T cast(Object obj){return (T) obj;}/*** 将二进制的byte转换为指定的个数* return*/public static String toBinary(int num, int digits) {int value 1 digits | num;String bs Integer.toBinaryString(value);return bs.substring(1);}
}文件类型工具类FileTypeUtils
public class FileTypeUtils
{/*** 获取文件类型* p* 例如: herb.txt, 返回: txt* * param file 文件名* return 后缀不含.)*/public static String getFileType(File file){if (null file){return StringUtils.EMPTY;}return getFileType(file.getName());}/*** 获取文件类型* p* 例如: herb.txt, 返回: txt** param fileName 文件名* return 后缀不含.)*/public static String getFileType(String fileName){int separatorIndex fileName.lastIndexOf(.);if (separatorIndex 0){return ;}return fileName.substring(separatorIndex 1).toLowerCase();}/*** 获取文件类型* * param photoByte 文件字节码* return 后缀不含.)*/public static String getFileExtendName(byte[] photoByte){String strFileExtendName JPG;if ((photoByte[0] 71) (photoByte[1] 73) (photoByte[2] 70) (photoByte[3] 56) ((photoByte[4] 55) || (photoByte[4] 57)) (photoByte[5] 97)){strFileExtendName GIF;}else if ((photoByte[6] 74) (photoByte[7] 70) (photoByte[8] 73) (photoByte[9] 70)){strFileExtendName JPG;}else if ((photoByte[0] 66) (photoByte[1] 77)){strFileExtendName BMP;}else if ((photoByte[1] 80) (photoByte[2] 78) (photoByte[3] 71)){strFileExtendName PNG;}return strFileExtendName;}
}图片处理工具类ImageUtils
public class ImageUtils
{private static final Logger log LoggerFactory.getLogger(ImageUtils.class);public static byte[] getImage(String imagePath){InputStream is getFile(imagePath);try{return IOUtils.toByteArray(is);}catch (Exception e){log.error(图片加载异常 {}, e);return null;}finally{IOUtils.closeQuietly(is);}}public static InputStream getFile(String imagePath){try{byte[] result readFile(imagePath);result Arrays.copyOf(result, result.length);return new ByteArrayInputStream(result);}catch (Exception e){log.error(获取图片异常 {}, e);}return null;}/*** 读取文件为字节数据* * param key 地址* return 字节数据*/public static byte[] readFile(String url){InputStream in null;ByteArrayOutputStream baos null;try{// 网络地址URL urlObj new URL(url);URLConnection urlConnection urlObj.openConnection();urlConnection.setConnectTimeout(30 * 1000);urlConnection.setReadTimeout(60 * 1000);urlConnection.setDoInput(true);in urlConnection.getInputStream();return IOUtils.toByteArray(in);}catch (Exception e){log.error(访问文件异常 {}, e);return null;}finally{IOUtils.closeQuietly(in);IOUtils.closeQuietly(baos);}}
}
反射工具类ReflectUtils. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
public class ReflectUtils
{private static final String SETTER_PREFIX set;private static final String GETTER_PREFIX get;private static final String CGLIB_CLASS_SEPARATOR $$;private static Logger logger LoggerFactory.getLogger(ReflectUtils.class);/*** 调用Getter方法.* 支持多级如对象名.对象名.方法*/SuppressWarnings(unchecked)public static E E invokeGetter(Object obj, String propertyName){Object object obj;for (String name : StringUtils.split(propertyName, .)){String getterMethodName GETTER_PREFIX StringUtils.capitalize(name);object invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});}return (E) object;}/*** 调用Setter方法, 仅匹配方法名。* 支持多级如对象名.对象名.方法*/public static E void invokeSetter(Object obj, String propertyName, E value){Object object obj;String[] names StringUtils.split(propertyName, .);for (int i 0; i names.length; i){if (i names.length - 1){String getterMethodName GETTER_PREFIX StringUtils.capitalize(names[i]);object invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});}else{String setterMethodName SETTER_PREFIX StringUtils.capitalize(names[i]);invokeMethodByName(object, setterMethodName, new Object[] { value });}}}/*** 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.*/SuppressWarnings(unchecked)public static E E getFieldValue(final Object obj, final String fieldName){Field field getAccessibleField(obj, fieldName);if (field null){logger.debug(在 [ obj.getClass() ] 中没有找到 [ fieldName ] 字段 );return null;}E result null;try{result (E) field.get(obj);}catch (IllegalAccessException e){logger.error(不可能抛出的异常{}, e.getMessage());}return result;}/*** 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.*/public static E void setFieldValue(final Object obj, final String fieldName, final E value){Field field getAccessibleField(obj, fieldName);if (field null){// throw new IllegalArgumentException(在 [ obj.getClass() ] 中没有找到 [ fieldName ] 字段 );logger.debug(在 [ obj.getClass() ] 中没有找到 [ fieldName ] 字段 );return;}try{field.set(obj, value);}catch (IllegalAccessException e){logger.error(不可能抛出的异常: {}, e.getMessage());}}/*** 直接调用对象方法, 无视private/protected修饰符.* 用于一次性调用的情况否则应使用getAccessibleMethod()函数获得Method后反复调用.* 同时匹配方法名参数类型*/SuppressWarnings(unchecked)public static E E invokeMethod(final Object obj, final String methodName, final Class?[] parameterTypes,final Object[] args){if (obj null || methodName null){return null;}Method method getAccessibleMethod(obj, methodName, parameterTypes);if (method null){logger.debug(在 [ obj.getClass() ] 中没有找到 [ methodName ] 方法 );return null;}try{return (E) method.invoke(obj, args);}catch (Exception e){String msg method: method , obj: obj , args: args ;throw convertReflectionExceptionToUnchecked(msg, e);}}/*** 直接调用对象方法, 无视private/protected修饰符* 用于一次性调用的情况否则应使用getAccessibleMethodByName()函数获得Method后反复调用.* 只匹配函数名如果有多个同名函数调用第一个。*/SuppressWarnings(unchecked)public static E E invokeMethodByName(final Object obj, final String methodName, final Object[] args){Method method getAccessibleMethodByName(obj, methodName, args.length);if (method null){// 如果为空不报错直接返回空。logger.debug(在 [ obj.getClass() ] 中没有找到 [ methodName ] 方法 );return null;}try{// 类型转换将参数数据类型转换为目标方法参数类型Class?[] cs method.getParameterTypes();for (int i 0; i cs.length; i){if (args[i] ! null !args[i].getClass().equals(cs[i])){if (cs[i] String.class){args[i] Convert.toStr(args[i]);if (StringUtils.endsWith((String) args[i], .0)){args[i] StringUtils.substringBefore((String) args[i], .0);}}else if (cs[i] Integer.class){args[i] Convert.toInt(args[i]);}else if (cs[i] Long.class){args[i] Convert.toLong(args[i]);}else if (cs[i] Double.class){args[i] Convert.toDouble(args[i]);}else if (cs[i] Float.class){args[i] Convert.toFloat(args[i]);}else if (cs[i] Date.class){if (args[i] instanceof String){args[i] DateUtils.parseDate(args[i]);}else{args[i] DateUtil.getJavaDate((Double) args[i]);}}else if (cs[i] boolean.class || cs[i] Boolean.class){args[i] Convert.toBool(args[i]);}}}return (E) method.invoke(obj, args);}catch (Exception e){String msg method: method , obj: obj , args: args ;throw convertReflectionExceptionToUnchecked(msg, e);}}/*** 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.* 如向上转型到Object仍无法找到, 返回null.*/public static Field getAccessibleField(final Object obj, final String fieldName){// 为空不报错。直接返回 nullif (obj null){return null;}Validate.notBlank(fieldName, fieldName cant be blank);for (Class? superClass obj.getClass(); superClass ! Object.class; superClass superClass.getSuperclass()){try{Field field superClass.getDeclaredField(fieldName);makeAccessible(field);return field;}catch (NoSuchFieldException e){continue;}}return null;}/*** 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.* 如向上转型到Object仍无法找到, 返回null.* 匹配函数名参数类型。* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)*/public static Method getAccessibleMethod(final Object obj, final String methodName,final Class?... parameterTypes){// 为空不报错。直接返回 nullif (obj null){return null;}Validate.notBlank(methodName, methodName cant be blank);for (Class? searchType obj.getClass(); searchType ! Object.class; searchType searchType.getSuperclass()){try{Method method searchType.getDeclaredMethod(methodName, parameterTypes);makeAccessible(method);return method;}catch (NoSuchMethodException e){continue;}}return null;}/*** 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.* 如向上转型到Object仍无法找到, 返回null.* 只匹配函数名。* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)*/public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum){// 为空不报错。直接返回 nullif (obj null){return null;}Validate.notBlank(methodName, methodName cant be blank);for (Class? searchType obj.getClass(); searchType ! Object.class; searchType searchType.getSuperclass()){Method[] methods searchType.getDeclaredMethods();for (Method method : methods){if (method.getName().equals(methodName) method.getParameterTypes().length argsNum){makeAccessible(method);return method;}}}return null;}/*** 改变private/protected的方法为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。*/public static void makeAccessible(Method method){if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) !method.isAccessible()){method.setAccessible(true);}}/*** 改变private/protected的成员变量为public尽量不调用实际改动的语句避免JDK的SecurityManager抱怨。*/public static void makeAccessible(Field field){if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())|| Modifier.isFinal(field.getModifiers())) !field.isAccessible()){field.setAccessible(true);}}/*** 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处* 如无法找到, 返回Object.class.*/SuppressWarnings(unchecked)public static T ClassT getClassGenricType(final Class clazz){return getClassGenricType(clazz, 0);}/*** 通过反射, 获得Class定义中声明的父类的泛型参数的类型.* 如无法找到, 返回Object.class.*/public static Class getClassGenricType(final Class clazz, final int index){Type genType clazz.getGenericSuperclass();if (!(genType instanceof ParameterizedType)){logger.debug(clazz.getSimpleName() s superclass not ParameterizedType);return Object.class;}Type[] params ((ParameterizedType) genType).getActualTypeArguments();if (index params.length || index 0){logger.debug(Index: index , Size of clazz.getSimpleName() s Parameterized Type: params.length);return Object.class;}if (!(params[index] instanceof Class)){logger.debug(clazz.getSimpleName() not set the actual class on superclass generic parameter);return Object.class;}return (Class) params[index];}public static Class? getUserClass(Object instance){if (instance null){throw new RuntimeException(Instance must not be null);}Class clazz instance.getClass();if (clazz ! null clazz.getName().contains(CGLIB_CLASS_SEPARATOR)){Class? superClass clazz.getSuperclass();if (superClass ! null !Object.class.equals(superClass)){return superClass;}}return clazz;}/*** 将反射时的checked exception转换为unchecked exception.*/public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e){if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException|| e instanceof NoSuchMethodException){return new IllegalArgumentException(msg, e);}else if (e instanceof InvocationTargetException){return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());}return new RuntimeException(msg, e);}
}通用常量信息Constants
public class Constants
{/*** UTF-8 字符集*/public static final String UTF8 UTF-8;/*** GBK 字符集*/public static final String GBK GBK;/*** RMI 远程方法调用*/public static final String LOOKUP_RMI rmi://;/*** LDAP 远程方法调用*/public static final String LOOKUP_LDAP ldap://;/*** http请求*/public static final String HTTP http://;/*** https请求*/public static final String HTTPS https://;/*** 成功标记*/public static final Integer SUCCESS 200;/*** 失败标记*/public static final Integer FAIL 500;/*** 登录成功*/public static final String LOGIN_SUCCESS Success;/*** 注销*/public static final String LOGOUT Logout;/*** 注册*/public static final String REGISTER Register;/*** 登录失败*/public static final String LOGIN_FAIL Error;/*** 当前记录起始索引*/public static final String PAGE_NUM pageNum;/*** 每页显示记录数*/public static final String PAGE_SIZE pageSize;/*** 排序列*/public static final String ORDER_BY_COLUMN orderByColumn;/*** 排序的方向 desc 或者 asc.*/public static final String IS_ASC isAsc;/*** 验证码 redis key*/public static final String CAPTCHA_CODE_KEY captcha_codes:;/*** 验证码有效期分钟*/public static final long CAPTCHA_EXPIRATION 2;/*** 参数管理 cache key*/public static final String SYS_CONFIG_KEY sys_config:;/*** 字典管理 cache key*/public static final String SYS_DICT_KEY sys_dict:;/*** 资源映射路径 前缀*/public static final String RESOURCE_PREFIX /profile;/*** 定时任务违规的字符*/public static final String[] JOB_ERROR_STR { java.net.URL, javax.naming.InitialContext, org.yaml.snakeyaml,org.springframework.jndi };/*** DISEASETYPE_SCOPE*/public static final Integer DISEASETYPE_SCOPE 10000;/*** KEGGTYPE_SCOPE*/public static final Integer KEGGTYPE_SCOPE 10000;
}字符串格式化StrFormatter
public class StrFormatter
{public static final String EMPTY_JSON {};public static final char C_BACKSLASH \\;public static final char C_DELIM_START {;public static final char C_DELIM_END };/*** 格式化字符串br* 此方法只是简单将占位符 {} 按照顺序替换为参数br* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可br* 例br* 通常使用format(this is {} for {}, a, b) - this is a for bbr* 转义{} format(this is \\{} for {}, a, b) - this is \{} for abr* 转义\ format(this is \\\\{} for {}, a, b) - this is \a for bbr* * param strPattern 字符串模板* param argArray 参数列表* return 结果*/public static String format(final String strPattern, final Object... argArray){if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)){return strPattern;}final int strPatternLength strPattern.length();// 初始化定义好的长度以获得更好的性能StringBuilder sbuf new StringBuilder(strPatternLength 50);int handledPosition 0;int delimIndex;// 占位符所在位置for (int argIndex 0; argIndex argArray.length; argIndex){delimIndex strPattern.indexOf(EMPTY_JSON, handledPosition);if (delimIndex -1){if (handledPosition 0){return strPattern;}else{ // 字符串模板剩余部分不再包含占位符加入剩余部分后返回结果sbuf.append(strPattern, handledPosition, strPatternLength);return sbuf.toString();}}else{if (delimIndex 0 strPattern.charAt(delimIndex - 1) C_BACKSLASH){if (delimIndex 1 strPattern.charAt(delimIndex - 2) C_BACKSLASH){// 转义符之前还有一个转义符占位符依旧有效sbuf.append(strPattern, handledPosition, delimIndex - 1);sbuf.append(Convert.utf8Str(argArray[argIndex]));handledPosition delimIndex 2;}else{// 占位符被转义argIndex--;sbuf.append(strPattern, handledPosition, delimIndex - 1);sbuf.append(C_DELIM_START);handledPosition delimIndex 1;}}else{// 正常占位符sbuf.append(strPattern, handledPosition, delimIndex);sbuf.append(Convert.utf8Str(argArray[argIndex]));handledPosition delimIndex 2;}}}// 加入最后一个占位符后所有的字符sbuf.append(strPattern, handledPosition, strPattern.length());return sbuf.toString();}
}在启动服务后postman中调用接口勾选需要合并的excel然后将输出保存为文件即可