文章目的是为了方便使用封装好的方法。如果是想了解 POI 各组件的详细介绍,百度搜一下会更详细。

Apache POI

简介

Apache POI 是 Apache 软件基金会的开放源码函式库,POI 提供 API 给 Java 程序对 Microsoft Office 格式档案读和写的功能。

结构

  • HSSF - 提供读写 Microsoft Excel 格式档案的功能。
  • XSSF - 提供读写 Microsoft Excel OOXML 格式档案的功能。
  • HWPF - 提供读写 Microsoft Word 格式档案的功能。
  • HSLF - 提供读写 Microsoft PowerPoint 格式档案的功能。
  • HDGF - 提供读写 Microsoft Visio 格式档案的功能。

下述所有的类

  • 核心类(ExcelUtil.java)
  • Excel 自定义注解(Excel.java)
  • Student 类(Student.java)
  • 反射工具类(ReflectUtils.java)
  • 类型转换器(BeanConvert.java)

实现方式

Maven 依赖

1
2
3
4
5
6
7
8
9
10
11
<!--POI 解析 Excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>

解析 Excel 使用方法

1
2
3
4
5
6
7
8
9
10
 // 传入的文件
MultipartHttpServletRequest request;

// 解析文件
Iterator<String> fileNames = request.getFileNames();
MultipartFile msrFile = request.getFile(fileNames.next());
InputStream inputStream = msrFile.getInputStream();
ExcelUtil<Student> excelUtil = new ExcelUtil<>(Student.class);
// 获取 Excel 集合
List<Student> students = excelUtil.importExcel(StringUtils.EMPTY, msrFile.getInputStream());

导出 Excel 使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 导入失败的学生列表
List<Student> failList = new ArrayList<>();

// 导出数据
LinkedHashMap<String, String> fieldMap = new LinkedHashMap<>();
fieldMap.put("name", "* 姓名 ");
fieldMap.put("idCard", "* 身份证号 ");
fieldMap.put("phone", "* 手机号 ");
fieldMap.put("nation", " 民族 ");
fieldMap.put("studentCode", " 学号 ");
fieldMap.put("remarks", " 备注 ");
fieldMap.put("failReasons", " 失败原因 ");

String fileName = " 导入学生失败数据 " + System.currentTimeMillis() + ".xlsx";
File file = new File(localFilePath + localTempFilePath + fileName);

// 导出错误的文件
if (excelUtil.listToExcel(failList, fieldMap, "sheet", file)) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("url", httpUrl + localTempFilePath + fileName);
jsonObject.put("count", failList.size());
// 休眠一段时间,确保前端访问文件时是存在的
Thread.sleep(5000L);
return R.fail(201, jsonObject.toJSONString());
}

核心类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
package com.muycode.manage.util;

import com.muycode.manage.annotation.Excel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* Created with IntelliJ IDEA by 2021/10/12 16:33.
* Excel 导出和解析数据
*
* @author muycode
*/
@Slf4j
public class ExcelUtil<T> {

private static final String[] parsePatterns = {
"yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss",
"yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy.MM.dd HH:mm",
"yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd", "yyyyMMdd",
"yyyy-MM", "yyyy/MM", "yyyy.MM", "yyyyMM"};

/**
* 实体对象
*/
public Class<T> clazz;

public ExcelUtil(Class<T> clazz) {
this.clazz = clazz;
}

/**
* 解析 Excel 文件
*
* @param sheetName
* @param inputStream
* @return
*/
public List<T> importExcel(String sheetName, InputStream inputStream) {
List<T> list = new ArrayList<>();
try {
// Excel 文件对象
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
XSSFSheet sheet;
if (StringUtils.isNotEmpty(sheetName)) {
// 如果指定 sheet 名, 则取指定 sheet 中的内容.
sheet = workbook.getSheet(sheetName);
} else {
// 如果传入的 sheet 名不存在则默认指向第 1 个 sheet.
sheet = workbook.getSheetAt(0);
}

if (null == sheet) {
throw new IOException(" 文件 sheet 不存在 ");
}

int rows = sheet.getPhysicalNumberOfRows();
if (rows > 0) {
// 定义一个 map 用于存放 excel 列的序号和 field.
Map<String, Integer> cellMap = new HashMap<String, Integer>();
// 获取表头
Row heard = sheet.getRow(0);
for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) {
Cell cell = heard.getCell(i);
if (null != cell) {
cellMap.put(this.getCellValue(heard, i).toString(), i);
} else {
cellMap.put(null, i);
}
}
// 有数据时才处理 得到类的所有 field.
Field[] allFields = clazz.getDeclaredFields();
// 定义一个 map 用于存放列的序号和 field.
Map<Integer, Field> fieldsMap = new HashMap<>();
for (Field field : allFields) {
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == Excel.Type.IMPORT)) {
// 设置类的私有字段属性可访问.
field.setAccessible(true);
Integer column = cellMap.get(attr.name());
fieldsMap.put(column, field);
}
}

for (int i = 1; i < rows; i++) {
// 从第 2 行开始取数据, 默认第一行是表头.
Row row = sheet.getRow(i);
T entity = null;
for (Map.Entry<Integer, Field> entry : fieldsMap.entrySet()) {
if (null == entry.getKey()) {
continue;
}
Object val = this.getCellValue(row, entry.getKey());
if (null != val && val.equals("")) {
continue;
}
entity = (entity == null ? clazz.newInstance() : entity);
// 从 map 中得到对应列的 field.
Field field = fieldsMap.get(entry.getKey());
// 取得类型, 并根据对象类型设置值.
Class<?> fieldType = field.getType();
Excel attr = field.getAnnotation(Excel.class);
String propertyName = field.getName();
if (StringUtils.isNotEmpty(attr.enumName())) {
ReflectUtils.invokeSetter(entity, attr.enumName(), val);
}
if (StringUtils.isNotEmpty(attr.targetAttr())) {
propertyName = field.getName() + "." + attr.targetAttr();
} else if (StringUtils.isNotEmpty(attr.readConverterExp())) {
val = reverseByExp(String.valueOf(val), attr.readConverterExp());
}
if (String.class == fieldType) {
String s = BeanConvert.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 = parseDateToStr(dateFormat, (Date) val);
} else {
val = BeanConvert.toStr(val);
}
}
} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
val = BeanConvert.toInt(val);
} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
val = BeanConvert.toLong(val);
} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
val = BeanConvert.toDouble(val);
} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
val = BeanConvert.toFloat(val);
} else if (BigDecimal.class == fieldType) {
val = BeanConvert.toBigDecimal(val);
} else if (Date.class == fieldType) {
if (val instanceof String) {
val = DateUtils.parseDate(val.toString(), parsePatterns);
} else if (val instanceof Double) {
val = DateUtil.getJavaDate((Double) val);
}
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
if (null != entity) {
list.add(entity);
}
}
}
} catch (Exception e) {
log.error(" 解析 Excel 文件出现异常: {}", e.getMessage(), e);
}
return list;
}

/**
* list 集合导出 Excel 文件
*
* @param list:需要导出的数据
* @param fieldMap:导出的字段
* @param sheetName:sheet 名称
* @param file:输出文件
* @param <T>
* @return
*/
public <T> Boolean listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, File file) {
// Excel 文件对象
XSSFWorkbook workbook = null;
FileOutputStream fileOutputStream = null;
if (list.size() > 0) {
try {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
fileOutputStream = new FileOutputStream(file);
workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(sheetName);

String[] enFields = new String[fieldMap.size()];
String[] cnFields = new String[fieldMap.size()];

int count = 0;
for (Iterator<Map.Entry<String, String>> var9 = fieldMap.entrySet().iterator(); var9.hasNext(); ++count) {
Map.Entry<String, String> entry = var9.next();
enFields[count] = entry.getKey();
cnFields[count] = entry.getValue();
}

// 设置标题
XSSFRow row = sheet.createRow(0);
for (int i = 0; i < cnFields.length; i++) {
XSSFCell cell = row.createCell(i);
cell.setCellValue(cnFields[i]);
}

int rowNo = 1;
for (T item : list) {
XSSFRow rowValue = sheet.createRow(rowNo);
for (int i1 = 0; i1 < enFields.length; i1++) {
Object objValue = getFieldValueByNameSequence(enFields[i1], item);
String fieldValue = objValue == null ? "" : objValue.toString();
XSSFCell cell = rowValue.createCell(i1);
cell.setCellValue(fieldValue);
}
rowNo++;
}
workbook.write(fileOutputStream);
return true;
} catch (Exception var12) {
var12.printStackTrace();
return false;
} finally {
try {
if (null != workbook) {
workbook.close();
}
if (null != fileOutputStream) {
fileOutputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
return false;
}
}

/**
* 获取 cell 的值
*
* @param row
* @param column
* @return
*/
private Object getCellValue(Row row, int column) {
if (null == row) {
return null;
}
Object val = "";
try {
Cell cell = row.getCell(column);
if (cell != null) {
if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) {
val = cell.getNumericCellValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
// POI Excel 日期格式转换
val = DateUtil.getJavaDate((Double) val);
} else {
if ((Double) val % 1 > 0) {
val = new DecimalFormat("0.00").format(val);
} 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;
}

private String parseDateToStr(String format, final Date date) {
return new SimpleDateFormat(format).format(date);
}

/**
* 反向解析值 0= 男,1= 女,2= 未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @return 解析后值
* @throws Exception
*/
private String reverseByExp(String propertyValue, String converterExp) {
String[] convertSource = converterExp.split(",");
for (String item : convertSource) {
String[] itemArray = item.split("=");
if (itemArray[1].equals(propertyValue)) {
return itemArray[0];
}
}
return propertyValue;
}

// 解析 类属性

private static Object getFieldValueByNameSequence(String fieldNameSequence, Object o) throws Exception {
Object value;
String[] attributes = fieldNameSequence.split("\\.");
if (attributes.length == 1) {
value = getFieldValueByName(fieldNameSequence, o);
} else {
Object fieldObj = getFieldValueByName(attributes[0], o);
String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);
value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);
}

return value;
}

private static Object getFieldValueByName(String fieldName, Object o) throws Exception {
Object value;
Field field = getFieldByName(fieldName, o.getClass());
if (field != null) {
field.setAccessible(true);
value = field.get(o);
return value;
} else {
throw new NullPointerException(o.getClass().getSimpleName() + " 类不存在字段名 " + fieldName);
}
}

private static Field getFieldByName(String fieldName, Class<?> clazz) {
Field[] selfFields = clazz.getDeclaredFields();
for (Field field : selfFields) {
if (field.getName().equals(fieldName)) {
return field;
}
}
Class<?> superClazz = clazz.getSuperclass();
return superClazz != null && superClazz != Object.class ? getFieldByName(fieldName, superClazz) : null;
}
}

其他辅助类

Excel 自定义注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.muycode.manage.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Created with IntelliJ IDEA by 2021/10/12 17:07.
* 自定义 Excel 数据注解
*
* @author muycode
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

/**
* 导出到 Excel 中的名字
*/
String name() default "";

/**
* 枚举值对应的名称
*/
String enumName() default "";

/**
* 日期格式, 如: yyyy-MM-dd
*/
String dateFormat() default "";

/**
* 读取内容转表达式 (如: 0= 男,1= 女,2= 未知)
*/
String readConverterExp() default "";

/**
* 导出类型(0 数字 1 字符串)
*/
ColumnType cellType() default ColumnType.STRING;

/**
* 导出时在 excel 中每个列的高度 单位为字符
*/
double height() default 14;

/**
* 导出时在 excel 中每个列的宽 单位为字符
*/
double width() default 16;

/**
* 文字后缀, 如 % 90 变成 90%
*/
String suffix() default "";

/**
* 当值为空时, 字段的默认值
*/
String defaultValue() default "";

/**
* 提示信息
*/
String prompt() default "";

/**
* 设置只能选择不能输入的列内容.
*/
String[] combo() default {};

/**
* 是否导出数据
*/
boolean isExport() default true;

/**
* 另一个类中的属性名称, 支持多级获取, 以小数点隔开
*/
String targetAttr() default "";

/**
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
Type type() default Type.ALL;

enum Type {
ALL(0), EXPORT(1), IMPORT(2);
private final int value;

Type(int value) {
this.value = value;
}

public int value() {
return this.value;
}
}

enum ColumnType {
NUMERIC(0), STRING(1);
private final int value;

ColumnType(int value) {
this.value = value;
}

public int value() {
return this.value;
}
}
}

Student 类使用 Excel 注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@Data
@Table(name = "student")
public class Student {
@Id
@Column(name = "rid")
@GeneratedValue(generator = "JDBC")
private Long rid;

/**
* 姓名
*/
@Column(name = "`name`")
@Excel(name = "* 姓名 ")
private String name;

/**
* 身份号码
*/
@Column(name = "id_card")
@Excel(name = "* 身份证号 ")
private String idCard;

/**
* 性别: 1- 男生 0- 女生 2- 未知
*/
@Column(name = "gender")
// @Excel(name = " 性别 ", enumName = "genderName", readConverterExp = "1- 男生,0- 女生,2- 未知 ")
private Integer gender;
@Transient
private String genderName;

/**
* 手机号
*/
@Column(name = "phone")
@Excel(name = "* 手机号 ")
private String phone;

/**
* 民族
*/
@Column(name = "nation")
@Excel(name = " 民族 ")
private String nation;

/**
* 学号
*/
@Column(name = "student_code")
@Excel(name = " 学号 ")
private String studentCode;

/**
* 备注
*/
@Column(name = "remarks")
@Excel(name = " 备注 ")
private String remarks;

/**
* 创建用户
*/
@Column(name = "create_user")
private String createUser;

/**
* 创建时间
*/
@Column(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;

/**
* 导入学生信息时 失败原因
*/
@Transient
private String failReasons;

/**
* 导入 小学
*/
@Transient
@Excel(name = " 小学 ")
private String smallSchoolName;

/**
* 导入 小学地址
*/
@Transient
@Excel(name = " 小学地址 ")
private String smallSchoolAddress;
}

反射工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
package com.muycode.manage.util;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.time.DateUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.*;
import java.util.Date;

/**
* Created with IntelliJ IDEA by 2021/10/12 17:23.
* 反射工具类. 提供调用 getter/setter 方法, 访问私有变量, 调用私有方法, 获取泛型类型 Class, 被 AOP 过的真实类等工具函数.
*
* @author muycode
*/
public class ReflectUtils {

private static final String[] parsePatterns = {
"yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss",
"yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm", "yyyy.MM.dd HH:mm",
"yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd", "yyyyMMdd",
"yyyy-MM", "yyyy/MM", "yyyy.MM", "yyyyMM"};

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] = BeanConvert.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] = BeanConvert.toInt(args[i]);
} else if (cs[i] == Long.class) {
args[i] = BeanConvert.toLong(args[i]);
} else if (cs[i] == Double.class) {
args[i] = BeanConvert.toDouble(args[i]);
} else if (cs[i] == Float.class) {
args[i] = BeanConvert.toFloat(args[i]);
} else if (cs[i] == Date.class) {
if (args[i] instanceof String) {
args[i] = DateUtils.parseDate(args[i].toString(), parsePatterns);
} else {
args[i] = DateUtil.getJavaDate((Double) 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) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notEmpty(fieldName, "fieldName can't 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) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notEmpty(methodName, "methodName can't 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) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notEmpty(methodName, "methodName can't 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> Class<T> 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);
}
}

类型转换器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
package com.muycode.manage.util;

import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* Created with IntelliJ IDEA by 2021/10/12 17:24.
* 类型转换器
*
* @author muycode
*/
public class BeanConvert {
/**
* 转换为字符串 <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>
* 如果给定的值为 <code>null</code>,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @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>
* 如果给定的值为 <code>null</code>,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Character toChar(Object value) {
return toChar(value, null);
}

/**
* 转换为 byte<br>
* 如果给定的值为 <code>null</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;
}
}

/**
* 转换为 byte<br>
* 如果给定的值为 <code>null</code>,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Byte toByte(Object value) {
return toByte(value, null);
}

/**
* 转换为 Short<br>
* 如果给定的值为 <code>null</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;
}
}

/**
* 转换为 Short<br>
* 如果给定的值为 <code>null</code>,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Short toShort(Object value) {
return toShort(value, null);
}

/**
* 转换为 Number<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 Number<br>
* 如果给定的值为空,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Number toNumber(Object value) {
return toNumber(value, null);
}

/**
* 转换为 int<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 int<br>
* 如果给定的值为 <code>null</code>,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @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);
}

/**
* 转换为 long<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 long<br>
* 如果给定的值为 <code>null</code>,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Long toLong(Object value) {
return toLong(value, null);
}

/**
* 转换为 double<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 double<br>
* 如果给定的值为空,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Double toDouble(Object value) {
return toDouble(value, null);
}

/**
* 转换为 Float<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 Float<br>
* 如果给定的值为空,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Float toFloat(Object value) {
return toFloat(value, null);
}

/**
* 转换为 boolean<br>
* String 支持的值为:true、false、yes、ok、no,1,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;
}
}

/**
* 转换为 boolean<br>
* 如果给定的值为空,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @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 Enum<E>> E toEnum(Class<E> 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>
* 如果给定的值为空,或者转换失败,返回默认值 <code>null</code><br>
*
* @param clazz Enum 的 Class
* @param value 值
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value) {
return toEnum(clazz, value, null);
}

/**
* 转换为 BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值 <code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigInteger toBigInteger(Object value) {
return toBigInteger(value, null);
}

/**
* 转换为 BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值 <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;
}
}

/**
* 转换为 BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值 <br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value) {
return toBigDecimal(value, null);
}

/**
* 将对象转为字符串 <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[]) {
return str((byte[]) obj, 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, Set<Character> 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, Set<Character> 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("^ 整 $", " 零元整 ");
}

/**
* 如果 Map 结果集为 null 替换为无
*
* @param jtmap
* @return
*/
public static Map<String, Object> isResultNull(Map<String, Object> jtmap) {
if (jtmap != null && jtmap.size() > 0) {
for (Map.Entry<String, Object> m : jtmap.entrySet()) {
if (m.getValue() == "" || m.getValue().equals("")) {
m.setValue(" 无 ");
}
}
}
return jtmap;
}

/**
* 如果 MapList 结果集为 null 替换为无
*
* @param ryjbqkmaps
* @return
*/
public static List<Map<String, Object>> isListResultNull(List<Map<String, Object>> ryjbqkmaps) {
if (ryjbqkmaps != null && ryjbqkmaps.size() > 0) {
for (Map<String, Object> smap : ryjbqkmaps) {
for (Map.Entry<String, Object> m : smap.entrySet()) {
if (m.getValue() == "" || m.getValue().equals("")) {
m.setValue(" 无 ");
}
}

}
}
return ryjbqkmaps;
}
}