常用工具类
1、DateUtil
import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * 日期工具类 * * @author yangyongjie * @date 2019/9/24 * @desc */ public class DateUtil { private DateUtil() { } private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class); public static final String YYYYMMDD_HHMMSS = "yyyy-MM-dd HH:mm:ss"; public static final String YYYYMMDD = "yyyy-MM-dd"; public static final String YYYYMMHHMMSSS = "yyyyMMddHHmmssS"; public static String getMonth(Timestamp time) { return new SimpleDateFormat("yyyyMM").format(time); } /** * 将Date格式化为字符串,默认yyyy-MM-dd HH:mm:ss格式 * * @param date * @return */ public static String formatDate(Date date) { return formatDate(date, YYYYMMDD_HHMMSS); } /** * 将Date格式化为字符串根据传入的格式 * * @param date * @param pattern * @return */ public static String formatDate(Date date, String pattern) { if (date == null) { return null; } if (StringUtils.isEmpty(pattern)) { return formatDate(date); } SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.format(date); } /** * 将指定格式的日期字符串解析为Date * * @param dateStr * @param pattern * @return */ public static Date parseDate(String dateStr, String pattern) { if (StringUtils.isEmpty(dateStr) || StringUtils.isEmpty(pattern)) { return null; } SimpleDateFormat sdf = new SimpleDateFormat(pattern); Date date = null; try { date = sdf.parse(dateStr); } catch (ParseException e) { LOGGER.error("解析日期字符串异常" + e.getMessage(), e); } return date; } /** * 讲默认格式的日期字符串解析为Date * * @param dateStr * @return */ public static Date parseDate(String dateStr) { return parseDate(dateStr, YYYYMMDD_HHMMSS); } /** * 获取当前时间的时间戳 * * @return */ public static String getTimeInMillis() { long timeInMillis = Calendar.getInstance().getTimeInMillis(); return timeInMillis + ""; } /** * 获取当前时间的字符串 * * @return */ public static String getCurrentDate() { return formatDate(new Date(), YYYYMMDD_HHMMSS); } /** * 获取当前时间的秒数 * * @return */ public static int currentTimeSec() { return (int) (System.currentTimeMillis() / 1000); } /** * 获取当前时间往后的第几天的时间,为负表示前几天的时间 * * @param i * @return */ public static Date getBeforeOrNextDay(int i) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_MONTH, i); return calendar.getTime(); } /** * 获得当前时间的n秒前或后 * * @param origin * @param seconds * @return */ public static Date getIntervalSeconds(Date origin, long seconds) { return new Date(origin.getTime() + seconds * 1000L); } }
2、LogUtil:用于发送错误日志邮件
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.PrintWriter; import java.io.StringWriter; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 日志工具类,用来发送错误邮件 * * @author yangyongjie * @date 2019/11/1 * @desc */ public class LogUtil { private LogUtil() { } private static final Logger LOGGER = LoggerFactory.getLogger(LogUtil.class); /** * 创建一个用于发送邮件的线程池,核心线程数为1,最大线程数为5,线程空闲时间为60s,拒绝策略为打印日志 */ private static ThreadPoolExecutor executor = new ThreadPoolExecutor( 1, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100), new CustomThreadFactory("sendErrorMail"), (r, executor) -> { // 只打印日志,什么都不做 LOGGER.error("Task{},rejected from{}", r.toString(), executor.toString()); }); /** * 打印日志并发送错误邮件 * * @param msg * @param t */ public static void LogAndMail(String msg, Throwable t) { // 获取调用此工具类的该方法 的调用方信息 // 查询当前线程的堆栈信息 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); // 按照规则,此方法的上一级调用类为 StackTraceElement ste = stackTrace[2]; String className = ste.getClassName(); String methodName = ste.getMethodName(); LOGGER.error("{}#{},{}," + t.getMessage(), className, methodName, msg, t); // 异步发送邮件 String ms = "[" + ThreadContext.currentThreadContext().getThreadId() + "]" + msg; executor.execute(() -> ErrorMailUtil.sendErrorMail(ms, t, 3)); } /** * 只发送错误邮件不打印日志 * * @param msg */ public static void sendErrorLogMail(String msg, Throwable t) { // 异步发送邮件 String ms = "[" + ThreadContext.currentThreadContext().getThreadId() + "]" + msg + assembleStackTrace(t); executor.execute(() -> ErrorMailUtil.sendErrorMail(ms, t, 3)); } /** * 组装异常堆栈 * * @param t * @return */ public static String assembleStackTrace(Throwable t) { StringWriter sw = new StringWriter(); PrintWriter ps = new PrintWriter(sw); t.printStackTrace(ps); return sw.toString(); } }
3、HttpParamUtil:
import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * Http 参数处理相关工具类 * * @author yangyongjie * @date 2019/10/28 * @desc */ public class HttpParamUtil { private HttpParamUtil() { } private static final Logger LOGGER = LoggerFactory.getLogger(HttpParamUtil.class); /** * 获取request中的body信息 JSON格式 * * @param request * @return */ public static String getRequestBody(HttpServletRequest request) { StringBuilder bodyDataBuilder = new StringBuilder(); BufferedReader br = null; try { br = request.getReader(); String str; while ((str = br.readLine()) != null) { bodyDataBuilder.append(str); } br.close(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); } finally { if (null != br) { try { br.close(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); } } } /* InputStream is = null; try { is = request.getInputStream(); byte[] b = new byte[4096]; for (int n; (n = is.read(b)) != -1; ) { bodyDataBuilder.append(new String(b, 0, n)); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } }*/ String bodyString = bodyDataBuilder.toString(); LOGGER.info("bodyString={}", bodyString); return bodyString; } /** * 获取request中的body信息,并组装好按“参数=参数值”的格式 * * @param request * @return */ public static String getAssembleRequestBody(HttpServletRequest request) { String bodyString = getRequestBody(request); Map<String, Object> originMap = JacksonUtil.toObject(bodyString, Map.class); Map<String, Object> sortedParams = getSortedMap(originMap); String assembleBody = getSignContent(sortedParams); return assembleBody; } /** * 根据requestBody中的原始map获取解析后并组装的参数字符串,根据&符拼接 * * @param originMap * @return */ public static String getAssembleParam(Map<String, Object> originMap) { return getSignContent(getSortedMap(originMap)); } /** * 将body转成按key首字母排好序 * * @return */ public static Map<String, Object> getSortedMap(Map<String, Object> originMap) { Map<String, Object> sortedParams = new TreeMap<String, Object>(); if (originMap != null && originMap.size() > 0) { sortedParams.putAll(originMap); } return sortedParams; } /** * 将排序好的map的key和value拼接成字符串 * * @param sortedParams * @return */ public static String getSignContent(Map<String, Object> sortedParams) { StringBuffer content = new StringBuffer(); List<String> keys = new ArrayList<String>(sortedParams.keySet()); Collections.sort(keys); int index = 0; for (int i = 0; i < keys.size(); i++) { String key = keys.get(i); Object value = sortedParams.get(key); if (StringUtils.isNotEmpty(key) && value != null) { content.append((index == 0 ? "" : "&") + key + "=" + value); index++; } } return content.toString(); } /** * Json转实体对象 * * @param jsonStr * @param clazz 目标生成实体对象 * @return */ public static <T> T fromJsonToObject(String jsonStr, Class clazz) { T results = null; try { results = (T) JacksonUtil.toObject(jsonStr, clazz); } catch (Exception e) { } return results; } /** * 对请求参数进行校验,目前只进行非空校验 * * @param tarObj 目标实体类 * @return 校验成功返回true */ public static <T> boolean paramCheck(T tarObj) { try { Class<T> tarClass = (Class<T>) tarObj.getClass(); List<Field> fields = new ArrayList<>(); fields.addAll(Arrays.asList(tarClass.getDeclaredFields())); Class supClass = tarClass.getSuperclass(); while (supClass != null) { fields.addAll(Arrays.asList(supClass.getDeclaredFields())); supClass = supClass.getSuperclass(); } for (Field field : fields) { field.setAccessible(true); ParamVerify verify = field.getAnnotation(ParamVerify.class); if (verify != null) { //非空校验,后续若需增加校验类型,应抽离 if (verify.nullable() == CheckEnum.NOTNULL) { Object val = field.get(tarObj); if (val == null || "".equals(val.toString())) { return false; } } } } } catch (Exception ex) { LOGGER.info("Param verify error"); return false; } return true; } } /** * 字段校验注解,目前只进行非空校验,可扩展,用在字段上 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ParamVerify { /** * 是否允许为空 */ CheckEnum nullable() default CheckEnum.NULL; } public enum CheckEnum { NOTNULL, NULL
优化版:
查看代码
import com.xiaomi.mitv.uvcas.common.annotation.DateCheck;
import com.xiaomi.mitv.uvcas.common.annotation.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
* Http请求参数处理工具类
*/
public class ParamUtil {
private ParamUtil() {
}
private static final Logger LOGGER = LoggerFactory.getLogger(ParamUtil.class);
/**
* 获取request中的body信息 JSON格式
*
* @param request
* @return
*/
public static String getRequestBody(HttpServletRequest request) {
StringBuilder bodyDataBuilder = new StringBuilder();
BufferedReader br = null;
try {
br = request.getReader();
String str;
while ((str = br.readLine()) != null) {
bodyDataBuilder.append(str);
}
br.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
} finally {
if (null != br) {
try {
br.close();
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
String bodyString = bodyDataBuilder.toString();
LOGGER.info("bodyString={}", bodyString);
return bodyString;
}
/**
* 获取request中的body信息,并组装好按“参数=参数值”的格式
*
* @param request
* @return
*/
public static String getAssembleRequestBody(HttpServletRequest request) {
String bodyString = getRequestBody(request);
Map<String, Object> originMap = JacksonUtil.toObject(bodyString, Map.class);
Map<String, Object> sortedParams = getSortedMap(originMap);
String assembleBody = getSignContent(sortedParams);
return assembleBody;
}
/**
* 根据requestBody中的原始map获取解析后并组装的参数字符串,根据&符拼接
*
* @param originMap
* @return
*/
public static String getAssembleParam(Map<String, Object> originMap) {
return getSignContent(getSortedMap(originMap));
}
/**
* 将body转成按key首字母排好序
*
* @return
*/
public static Map<String, Object> getSortedMap(Map<String, Object> originMap) {
Map<String, Object> sortedParams = new TreeMap<String, Object>();
if (originMap != null && originMap.size() > 0) {
sortedParams.putAll(originMap);
}
return sortedParams;
}
/**
* 将排序好的map的key和value拼接成字符串
*
* @param sortedParams
* @return
*/
public static String getSignContent(Map<String, Object> sortedParams) {
StringBuffer content = new StringBuffer();
List<String> keys = new ArrayList<String>(sortedParams.keySet());
Collections.sort(keys);
int index = 0;
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
Object value = sortedParams.get(key);
if (StringUtils.isNotEmpty(key) && value != null) {
content.append((index == 0 ? "" : "&") + key + "=" + value);
index++;
}
}
return content.toString();
}
/**
* 对请求参数进行校验
*
* @param tarObj 目标实体类
* @return 校验成功返回true
*/
public static <T> boolean paramCheck(T tarObj) {
if (tarObj == null) {
return false;
}
try {
Class<T> tarClass = (Class<T>) tarObj.getClass();
List<Field> fields = getFields(tarClass);
return fieldCheck(fields, tarObj);
} catch (Exception ex) {
LOGGER.info("Param check error" + ex.getMessage(), ex);
return false;
}
}
/**
* 请求集合参数校验
*
* @param tarObjs
* @param tarClass
* @param <T>
* @return
*/
public static <T> boolean paramCheck(List<T> tarObjs, Class<T> tarClass) {
if (tarObjs == null) {
return false;
}
try {
List<Field> fields = new ArrayList<>();
fields.addAll(Arrays.asList(tarClass.getDeclaredFields()));
Class supClass = tarClass.getSuperclass();
while (supClass != null) {
fields.addAll(Arrays.asList(supClass.getDeclaredFields()));
supClass = supClass.getSuperclass();
}
for (T tarObj : tarObjs) {
boolean pass = fieldCheck(fields, tarObj);
if (!pass) {
return false;
}
}
} catch (Exception ex) {
LOGGER.info("Param check error" + ex.getMessage(), ex);
return false;
}
return true;
}
/**
* 获取指定字节码文件对应的属性集合
*
* @param tarClass
* @param <T>
* @return
*/
private static <T> List<Field> getFields(Class<T> tarClass) {
List<Field> fields = new ArrayList<>();
fields.addAll(Arrays.asList(tarClass.getDeclaredFields()));
Class supClass = tarClass.getSuperclass();
while (supClass != null) {
fields.addAll(Arrays.asList(supClass.getDeclaredFields()));
supClass = supClass.getSuperclass();
}
return fields;
}
/**
* 属性校验
*
* @param fields
* @param tarObj
* @param <T>
* @return
* @throws IllegalAccessException
*/
private static <T> boolean fieldCheck(List<Field> fields, T tarObj) throws IllegalAccessException {
for (Field field : fields) {
field.setAccessible(true);
// 非空字段校验
NonNull nonNull = field.getAnnotation(NonNull.class);
if (nonNull != null) {
Object val = field.get(tarObj);
if (val == null || "".equals(val.toString())) {
LOGGER.info("field:{}为空", field.getName());
return false;
}
}
// 日期字符串格式校验
DateCheck dateCheck = field.getAnnotation(DateCheck.class);
if (dateCheck != null) {
Object val = field.get(tarObj);
String format = dateCheck.format();
try {
LocalDate.parse((CharSequence) val, DateTimeFormatter.ofPattern(format));
} catch (DateTimeParseException e) {
LOGGER.info("field:{}日期不合法,值为{}", field.getName(), val);
return false;
}
}
}
return true;
}
}
4、DigestUtil:(MD5,SHA1)
查看代码
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
/**
* 摘要工具类
*
* @author yangyongjie
* @date 2022/6/22
*/
public class DigestUtil {
private DigestUtil() {
}
public static String getMd5(String message) {
return message != null && message.length() != 0 ? getDigest(message.getBytes(), "MD5") : "";
}
public static String getSha1(String message) {
return message != null && message.length() != 0 ? getDigest(message.getBytes(), "SHA1") : "";
}
public static String getDigest(byte[] bytes, String digestType) {
if (bytes == null) {
return "";
} else {
String digest = "";
try {
MessageDigest algorithm = MessageDigest.getInstance(digestType);
algorithm.reset();
algorithm.update(bytes);
digest = toHexString(algorithm.digest());
} catch (Exception e) {
e.printStackTrace();
}
return digest;
}
}
private static String toHexString(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
int length = bytes.length;
for (int i = 0; i < length; ++i) {
byte b = bytes[i];
String str;
for (str = Integer.toHexString(255 & b); str.length() < 2; str = "0" + str) {
}
hexString.append(str);
}
return hexString.toString();
}
/**
* 获取文件字节流的MD5
*
* @param data
* @return
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static String md5Hex(InputStream data) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
for (int read = data.read(buffer, 0, 1024); read > -1; read = data.read(buffer, 0, 1024)) {
digest.update(buffer, 0, read);
}
byte[] digestByte = digest.digest();
// 摘要字节数组转成16进制字符串
return toHexString(digestByte);
} catch (Exception e) {
return UUID.randomUUID().toString().replace("-", "");
}
}
}
5、IpUtil
import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.UnknownHostException; /** * 获取用户ip工具类 */ public class IpUtil { public static String getIpAddress(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); if (ip.equals("127.0.0.1")) { // 根据网卡取本机配置的IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ip = inet.getHostAddress(); } } // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 // "***.***.***.***".length() if (ip != null && ip.length() > 15) { // = 15 if (ip.indexOf(",") > 0) { ip = ip.substring(0, ip.indexOf(",")); } } return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; } /** * 将 ip 字符串转换为 int 类型的数字 * <p> * 思路就是将 ip 的每一段数字转为 8 位二进制数,并将它们放在结果的适当位置上 * * @param ipString ip字符串,如 127.0.0.1 * @return ip字符串对应的 int 值 */ public static int ip2Int(String ipString) { // 取 ip 的各段 String[] ipSlices = ipString.split("\\."); int len = ipSlices.length; int rs = 0; for (int i = 0; i < len; i++) { // 将 ip 的每一段解析为 int,并根据位置左移 8 位 int intSlice = Integer.parseInt(ipSlices[i]) << 8 * (len - i - 1); // 求或 rs = rs | intSlice; } return rs; } /** * 将 int 转换为 ip 字符串 * * @param ipInt 用 int 表示的 ip 值 * @return ip字符串,如 127.0.0.1 */ public static String int2Ip(int ipInt) { int len = 4; String[] ipString = new String[len]; for (int i = 0; i < len; i++) { // 每 8 位为一段,这里取当前要处理的最高位的位置 int pos = (len - i - 1) * 8; // 取当前处理的 ip 段的值 int and = ipInt & (255 << pos); // 将当前 ip 段转换为 0 ~ 255 的数字,注意这里必须使用无符号右移 ipString[i] = String.valueOf(and >>> pos); } return String.join(".", ipString); } public static void main(String[] args) { String ip1 = "1.10.0.0"; int intIp = ip2Int(ip1); String ip2 = int2Ip(intIp); System.out.println(ip2.equals(ip1)); } }
6、ByteUtil
public class ByteUtil { private ByteUtil() { } public static byte[] toByteArray(int value) { byte[] bytes = new byte[4]; bytes[3] = (byte) (value & 0xff); bytes[2] = (byte) (value >> 8 & 0xff); bytes[1] = (byte) (value >> 16 & 0xff); bytes[0] = (byte) (value >> 24 & 0xff); return bytes; } public static byte[] toByteArray(long value) { byte[] bytes = new byte[8]; bytes[7] = (byte) (value & 0xff); bytes[6] = (byte) (value >> 8 & 0xff); bytes[5] = (byte) (value >> 16 & 0xff); bytes[4] = (byte) (value >> 24 & 0xff); bytes[3] = (byte) (value >> 32 & 0xff); bytes[2] = (byte) (value >> 40 & 0xff); bytes[1] = (byte) (value >> 48 & 0xff); bytes[0] = (byte) (value >> 56 & 0xff); return bytes; } }
7、StringUtil
查看代码
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 自定义字符串工具类
*/
public class StringUtil {
private StringUtil() {
}
private static final AtomicInteger AI = new AtomicInteger(1);
/**
* 返回UUID
*
* @return
*/
public static String getUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* 返回唯一ID,对ID唯一性要求不高时可用此方式
*
* @return
*/
public static String getOnlyId() {
// 当前毫秒数
long currentMills = System.currentTimeMillis();
// 拼接一个自增数
int value = AI.getAndIncrement();
if (value == 999) {
AI.set(1);
}
// 不满三位前面补0
String num = String.format("%3d", value).replace(" ", "0");
return currentMills + num;
}
/**
* 检查指定的字符串列表是否不为空。
*/
public static boolean areNotEmpty(String... values) {
boolean result = true;
if (values == null || values.length == 0) {
result = false;
} else {
for (String value : values) {
result &= !isEmpty(value);
}
}
return result;
}
/**
* 有一个为空,则为true
*
* @param values
* @return
*/
public static boolean haveEmpty(String... values) {
if (values == null || values.length == 0) {
return true;
} else {
for (String value : values) {
if (isEmpty(value)) {
return true;
}
}
}
return false;
}
/**
* 检查指定的字符串是否为空。
* <ul>
* <li>SysUtils.isEmpty(null) = true</li>
* <li>SysUtils.isEmpty("") = true</li>
* <li>SysUtils.isEmpty(" ") = true</li>
* <li>SysUtils.isEmpty("abc") = false</li>
* </ul>
*
* @param cs 待检查的字符串
* @return true/false
*/
public static boolean isEmpty(final CharSequence cs) {
// return cs == null || cs.length() == 0;
if (cs == null || cs.length() == 0) {
return true;
}
for (int i = 0; i < cs.length(); i++) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
}
public static boolean isNotEmpty(final CharSequence cs) {
return !isEmpty(cs);
}
/**
* 两个字符串是否相等
*
* @param cs1
* @param cs2
* @return
*/
public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
if (cs1 == cs2) {
return true;
}
if (cs1 == null || cs2 == null) {
return false;
}
if (cs1.length() != cs2.length()) {
return false;
}
if (cs1 instanceof String && cs2 instanceof String) {
return cs1.equals(cs2);
}
// Step-wise comparison
final int length = cs1.length();
for (int i = 0; i < length; i++) {
if (cs1.charAt(i) != cs2.charAt(i)) {
return false;
}
}
return true;
}
}
8、result
①:HandleResult(属性带默认值)
查看代码
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
public class HandleResult {
private Integer code = 0;
private String message = "success";
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Object data;
public HandleResult() {
}
public HandleResult(ResponseEnum response) {
this.code = response.getCode();
this.message = response.getMessage();
}
public HandleResult(Object data) {
this.data = data;
}
public HandleResult fail(ResponseEnum response) {
this.code = response.getCode();
this.message = response.getMessage();
return this;
}
@JsonIgnore
public boolean isSuccess() {
return ResponseEnum.SUCCESS.getCode().equals(code);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
②:CommonResult
import com.fasterxml.jackson.annotation.JsonInclude; import com.xiaomi.mitv.uvcas.common.enums.ResponseEnum; /** * 公共返回结果类 * * @author yangyongjie */ public class CommonResult { private String code; private String msg; /** * 返回结果,如果为null则不序列化此字段 */ @JsonInclude(JsonInclude.Include.NON_NULL) private Object data; public CommonResult() { this.code = ResponseEnum.SUCCESS.getCode(); this.msg = ResponseEnum.SUCCESS.getMsg(); } /** * 默认成功 */ public CommonResult(Object obj) { this.code = ResponseEnum.SUCCESS.getCode(); this.msg = ResponseEnum.SUCCESS.getMsg(); this.data = obj; } /** * 成功返回 */ public static CommonResult success() { return new CommonResult(); } /** * 失败返回 */ public static CommonResult fail(ResponseEnum responseEnum) { CommonResult result = new CommonResult(); result.code = responseEnum.getCode(); result.msg = responseEnum.getMsg(); return result; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } }
9、ZlibUtil
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayOutputStream; import java.util.zip.Deflater; import java.util.zip.Inflater; public class ZlibUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ZlibUtil.class); private ZlibUtil() { } public static byte[] compress(byte[] data) { byte[] output; Deflater deflater = new Deflater(); deflater.reset(); deflater.setInput(data); deflater.finish(); try(ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length)) { byte[] buf = new byte[1024]; while (!deflater.finished()) { int i = deflater.deflate(buf); bos.write(buf, 0, i); } output = bos.toByteArray(); } catch (Exception e) { output = data; LOGGER.info(e.getMessage(), e); } deflater.end(); return output; } public static byte[] decompress(byte[] data) { byte[] output; Inflater inflater = new Inflater(); inflater.reset(); inflater.setInput(data); try(ByteArrayOutputStream o = new ByteArrayOutputStream(data.length)) { byte[] buf = new byte[1024]; while (!inflater.finished()) { int i = inflater.inflate(buf); o.write(buf, 0, i); } output = o.toByteArray(); } catch (Exception e) { output = data; LOGGER.info(e.getMessage(), e); } inflater.end(); return output; } }
10、BeanUtil map和Object互相转换
import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; public class BeanUtil { private BeanUtil() { } /** * object转换成map */ public static Map<String, Object> Obj2Map(Object obj) { Map<String, Object> map = new HashMap<>(8); Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); try { map.put(field.getName(), field.get(obj)); } catch (IllegalAccessException e) { e.printStackTrace(); } } return map; } /** * map转换为object * * @param map * @param clz * @return * @throws Exception */ public static <T> T map2Obj(Map<String, Object> map, Class<T> clz) { try { T obj = clz.newInstance(); Field[] declaredFields = obj.getClass().getDeclaredFields(); for (Field field : declaredFields) { int mod = field.getModifiers(); if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) { continue; } field.setAccessible(true); field.set(obj, map.get(field.getName())); } return obj; } catch (Exception e) { // 打印日志省略 return null; } } }
11、ClassUtils
import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.jeesite.common.codec.EncodeUtils; /** * Class工具类,借鉴ibatis的io包的ResolverUtil类。 * @author ThinkGem * @version 2016-4-28 */ public class ClassUtils { /* * An instance of Log to use for logging in this class. */ private static final Log log = LogFactory.getLog(ClassUtils.class); /** * A simple interface that specifies how to test classes to determine if they * are to be included in the results produced by the ResolverUtil. */ public static interface Test { /** * Will be called repeatedly with candidate classes. Must return True if a class * is to be included in the results, false otherwise. */ boolean matches(Class<?> type); } /** * 查询实现类,继承与parentType,并不是当前类,不是抽象类。 * * A Test that checks to see if each class is assignable to the provided class. Note * that this test will match the parent type itself if it is presented for matching. */ public static class IsA implements Test { private Class<?> parent; /** Constructs an IsA test using the supplied Class as the parent class/interface. */ public IsA(Class<?> parentType) { this.parent = parentType; } /** Returns true if type is assignable to the parent type supplied in the constructor. */ @Override public boolean matches(Class<?> type) { return type != null && parent.isAssignableFrom(type) // 是继承与该类 && !type.getName().equals(parent.getName()) // 不包含当前类 && !Modifier.isAbstract(type.getModifiers()); // 不包含抽象类 } @Override public String toString() { return "is assignable to " + parent.getSimpleName(); } } /** * 查询设置此注解的类。 * * A Test that checks to see if each class is annotated with a specific annotation. If it * is, then the test returns true, otherwise false. */ public static class AnnotatedWith implements Test { private Class<? extends Annotation> annotation; /** Constructs an AnnotatedWith test for the specified annotation type. */ public AnnotatedWith(Class<? extends Annotation> annotation) { this.annotation = annotation; } /** Returns true if the type is annotated with the class provided to the constructor. */ @Override public boolean matches(Class<?> type) { return type != null && type.isAnnotationPresent(annotation); } @Override public String toString() { return "annotated with @" + annotation.getSimpleName(); } } /** The set of matches being accumulated. */ private Set<Class<?>> matches = new HashSet<Class<?>>(); /** * The ClassLoader to use when looking for classes. If null then the ClassLoader returned * by Thread.currentThread().getContextClassLoader() will be used. */ private ClassLoader classloader; /** * Provides access to the classes discovered so far. If no calls have been made to * any of the {@code find()} methods, this set will be empty. * * @return the set of classes that have been discovered. */ public Set<Class<?>> getClasses() { return matches; } /** * Returns the classloader that will be used for scanning for classes. If no explicit * ClassLoader has been set by the calling, the context class loader will be used. * * @return the ClassLoader that will be used to scan for classes */ public ClassLoader getClassLoader() { return classloader == null ? Thread.currentThread().getContextClassLoader() : classloader; } /** * Sets an explicit ClassLoader that should be used when scanning for classes. If none * is set then the context classloader will be used. * * @param classloader a ClassLoader to use when scanning for classes */ public void setClassLoader(ClassLoader classloader) { this.classloader = classloader; } /** * 查询实现类,继承与parentType,并不是当前类,不是抽象类。 * * Attempts to discover classes that are assignable to the type provided. In the case * that an interface is provided this method will collect implementations. In the case * of a non-interface class, subclasses will be collected. Accumulated classes can be * accessed by calling {@link #getClasses()}. * * @param parent the class of interface to find subclasses or implementations of * @param packageNames one or more package names to scan (including subpackages) for classes */ public static <T> Set<Class<?>> findImplementations(Class<?> parent, String... packageNames) { if (packageNames == null) { return new HashSet<Class<?>>(); } ClassUtils cu = new ClassUtils(); Test test = new IsA(parent); for (String pkg : packageNames) { cu.find(test, pkg); } return cu.getClasses(); } /** * 查询设置此注解的类。 * * Attempts to discover classes that are annotated with the annotation. Accumulated * classes can be accessed by calling {@link #getClasses()}. * * @param annotation the annotation that should be present on matching classes * @param packageNames one or more package names to scan (including subpackages) for classes */ public static Set<Class<?>> findAnnotated(Class<? extends Annotation> annotation, String... packageNames) { if (packageNames == null) { return new HashSet<Class<?>>(); } ClassUtils cu = new ClassUtils(); Test test = new AnnotatedWith(annotation); for (String pkg : packageNames) { cu.find(test, pkg); } return cu.getClasses(); } /** * Scans for classes starting at the package provided and descending into subpackages. * Each class is offered up to the Test as it is discovered, and if the Test returns * true the class is retained. Accumulated classes can be fetched by calling * {@link #getClasses()}. * * @param test an instance of {@link Test} that will be used to filter classes * @param packageName the name of the package from which to start scanning for * classes, e.g. {@code net.sourceforge.stripes} */ public ClassUtils find(Test test, String packageName) { String path = getPackagePath(packageName); try { List<String> children = VFS.getInstance().list(path); for (String child : children) { if (child.endsWith(".class")) { addIfMatching(test, child); } } } catch (IOException ioe) { log.error("Could not read package: " + packageName, ioe); } return this; } /** * Converts a Java package name to a path that can be looked up with a call to * {@link ClassLoader#getResources(String)}. * * @param packageName The Java package name to convert to a path */ protected String getPackagePath(String packageName) { return packageName == null ? null : packageName.replace('.', '/'); } /** * Add the class designated by the fully qualified class name provided to the set of * resolved classes if and only if it is approved by the Test supplied. * * @param test the test used to determine if the class matches * @param fqn the fully qualified name of a class */ protected void addIfMatching(Test test, String fqn) { try { String externalName = fqn.substring(0, fqn.indexOf('.')).replace('/', '.'); ClassLoader loader = getClassLoader(); log.debug("Checking to see if class " + externalName + " matches criteria [" + test + "]"); Class<?> type = loader.loadClass(externalName); if (test.matches(type)) { matches.add((Class<?>) type); } } catch (Exception t) { log.warn("Could not examine class '" + fqn + "'" + " due to a " + t.getClass().getName() + " with message: " + t.getMessage()); } } } /** * Provides a very simple API for accessing resources within an application server. * * @author Ben Gunter */ abstract class VFS { private static final Log log = LogFactory.getLog(ClassUtils.class); /** The built-in implementations. */ public static final Class<?>[] IMPLEMENTATIONS = { JBoss6VFS.class, DefaultVFS.class }; /** The list to which implementations are added by {@link #addImplClass(Class)}. */ public static final List<Class<? extends VFS>> USER_IMPLEMENTATIONS = new ArrayList<Class<? extends VFS>>(); /** Singleton instance. */ private static VFS instance; /** * Get the singleton {@link VFS} instance. If no {@link VFS} implementation can be found for the * current environment, then this method returns null. */ @SuppressWarnings("unchecked") public static VFS getInstance() { if (instance != null) { return instance; } // Try the user implementations first, then the built-ins List<Class<? extends VFS>> impls = new ArrayList<Class<? extends VFS>>(); impls.addAll(USER_IMPLEMENTATIONS); impls.addAll(Arrays.asList((Class<? extends VFS>[]) IMPLEMENTATIONS)); // Try each implementation class until a valid one is found VFS vfs = null; for (int i = 0; vfs == null || !vfs.isValid(); i++) { Class<? extends VFS> impl = impls.get(i); try { vfs = impl.getDeclaredConstructor().newInstance(); if (vfs == null || !vfs.isValid()) { log.debug("VFS implementation " + impl.getName() + " is not valid in this environment."); } } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { log.error("Failed to instantiate " + impl, e); return null; } } log.debug("Using VFS adapter " + vfs.getClass().getName()); return VFS.instance = vfs; } /** * Adds the specified class to the list of {@link VFS} implementations. Classes added in this * manner are tried in the order they are added and before any of the built-in implementations. * * @param clazz The {@link VFS} implementation class to add. */ public static void addImplClass(Class<? extends VFS> clazz) { if (clazz != null) { USER_IMPLEMENTATIONS.add(clazz); } } /** Get a class by name. If the class is not found then return null. */ protected static Class<?> getClass(String className) { try { return Thread.currentThread().getContextClassLoader().loadClass(className); // return ReflectUtil.findClass(className); } catch (ClassNotFoundException e) { log.debug("Class not found: " + className); return null; } } /** * Get a method by name and parameter types. If the method is not found then return null. * * @param clazz The class to which the method belongs. * @param methodName The name of the method. * @param parameterTypes The types of the parameters accepted by the method. */ protected static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) { try { if (clazz == null) { return null; } else { return clazz.getMethod(methodName, parameterTypes); } } catch (SecurityException e) { log.error("Security exception looking for method " + clazz.getName() + "." + methodName + ". Cause: " + e); return null; } catch (NoSuchMethodException e) { log.error("Method not found " + clazz.getName() + "." + methodName + "." + methodName + ". Cause: " + e); return null; } } /** * Invoke a method on an object and return whatever it returns. * * @param method The method to invoke. * @param object The instance or class (for static methods) on which to invoke the method. * @param parameters The parameters to pass to the method. * @return Whatever the method returns. * @throws IOException If I/O errors occur * @throws StripesRuntimeException If anything else goes wrong */ @SuppressWarnings("unchecked") protected static <T> T invoke(Method method, Object object, Object... parameters) throws IOException, RuntimeException { try { return (T) method.invoke(object, parameters); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { if (e.getTargetException() instanceof IOException) { throw (IOException) e.getTargetException(); } else { throw new RuntimeException(e); } } } /** * Get a list of {@link URL}s from the context classloader for all the resources found at the * specified path. * * @param path The resource path. * @return A list of {@link URL}s, as returned by {@link ClassLoader#getResources(String)}. * @throws IOException If I/O errors occur */ protected static List<URL> getResources(String path) throws IOException { return Collections.list(Thread.currentThread().getContextClassLoader().getResources(path)); } /** Return true if the {@link VFS} implementation is valid for the current environment. */ public abstract boolean isValid(); /** * Recursively list the full resource path of all the resources that are children of the * resource identified by a URL. * * @param url The URL that identifies the resource to list. * @param forPath The path to the resource that is identified by the URL. Generally, this is the * value passed to {@link #getResources(String)} to get the resource URL. * @return A list containing the names of the child resources. * @throws IOException If I/O errors occur */ protected abstract List<String> list(URL url, String forPath) throws IOException; /** * Recursively list the full resource path of all the resources that are children of all the * resources found at the specified path. * * @param path The path of the resource(s) to list. * @return A list containing the names of the child resources. * @throws IOException If I/O errors occur */ public List<String> list(String path) throws IOException { List<String> names = new ArrayList<String>(); for (URL url : getResources(path)) { names.addAll(list(url, path)); } return names; } } /** * A default implementation of {@link VFS} that works for most application servers. * * @author Ben Gunter */ class DefaultVFS extends VFS { private static final Log log = LogFactory.getLog(ClassUtils.class); /** The magic header that indicates a JAR (ZIP) file. */ private static final byte[] JAR_MAGIC = { 'P', 'K', 3, 4 }; @Override public boolean isValid() { return true; } @Override public List<String> list(URL url, String path) throws IOException { InputStream is = null; try { List<String> resources = new ArrayList<String>(); // First, try to find the URL of a JAR file containing the requested resource. If a JAR // file is found, then we'll list child resources by reading the JAR. URL jarUrl = findJarForResource(url); if (jarUrl != null) { is = jarUrl.openStream(); log.debug("Listing " + url); resources = listResources(new JarInputStream(is), path); } else { List<String> children = new ArrayList<String>(); try { if (isJar(url)) { // Some versions of JBoss VFS might give a JAR stream even if the resource // referenced by the URL isn't actually a JAR is = url.openStream(); // @SuppressWarnings("resource") JarInputStream jarInput = new JarInputStream(is); log.debug("Listing " + url); for (JarEntry entry; (entry = jarInput.getNextJarEntry()) != null;) { log.debug("Jar entry: " + entry.getName()); children.add(entry.getName()); } } else { /* * Some servlet containers allow reading from directory resources like a * text file, listing the child resources one per line. However, there is no * way to differentiate between directory and file resources just by reading * them. To work around that, as each line is read, try to look it up via * the class loader as a child of the current resource. If any line fails * then we assume the current resource is not a directory. */ is = url.openStream(); try(BufferedReader reader = new BufferedReader(new InputStreamReader(is))){ List<String> lines = new ArrayList<String>(); for (String line; (line = reader.readLine()) != null;) { log.debug("Reader entry: " + line); lines.add(line); if (getResources(path + "/" + line).isEmpty()) { lines.clear(); break; } } if (!lines.isEmpty()) { log.debug("Listing " + url); children.addAll(lines); } }; } } catch (FileNotFoundException e) { /* * For file URLs the openStream() call might fail, depending on the servlet * container, because directories can't be opened for reading. If that happens, * then list the directory directly instead. */ if ("file".equals(url.getProtocol())) { File file = new File(url.getFile()); log.debug("Listing directory " + file.getAbsolutePath()); if (file.isDirectory()) { log.debug("Listing " + url); children = Arrays.asList(file.list()); } } else { // No idea where the exception came from so rethrow it throw e; } } // The URL prefix to use when recursively listing child resources String prefix = url.toExternalForm(); if (!prefix.endsWith("/")) { prefix = prefix + "/"; } // Iterate over immediate children, adding files and recursing into directories for (String child : children) { String resourcePath = path + "/" + child; resources.add(resourcePath); URL childUrl = new URL(prefix + child); resources.addAll(list(childUrl, resourcePath)); } } return resources; } finally { try { if (is != null) { is.close(); } } catch (Exception e) {} } } /** * List the names of the entries in the given {@link JarInputStream} that begin with the * specified {@code path}. Entries will match with or without a leading slash. * * @param jar The JAR input stream * @param path The leading path to match * @return The names of all the matching entries * @throws IOException If I/O errors occur */ protected List<String> listResources(JarInputStream jar, String path) throws IOException { // Include the leading and trailing slash when matching names if (!path.startsWith("/")) { path = "/" + path; } if (!path.endsWith("/")) { path = path + "/"; } // Iterate over the entries and collect those that begin with the requested path List<String> resources = new ArrayList<String>(); for (JarEntry entry; (entry = jar.getNextJarEntry()) != null;) { if (!entry.isDirectory()) { // Add leading slash if it's missing String name = entry.getName(); if (!name.startsWith("/")) { name = "/" + name; } // Check file name if (name.startsWith(path)) { log.debug("Found resource: " + name); resources.add(name.substring(1)); // Trim leading slash } } } return resources; } /** * Attempts to deconstruct the given URL to find a JAR file containing the resource referenced * by the URL. That is, assuming the URL references a JAR entry, this method will return a URL * that references the JAR file containing the entry. If the JAR cannot be located, then this * method returns null. * * @param url The URL of the JAR entry. * @return The URL of the JAR file, if one is found. Null if not. * @throws MalformedURLException */ protected URL findJarForResource(URL url) throws MalformedURLException { log.debug("Find JAR URL: " + url); // If the file part of the URL is itself a URL, then that URL probably points to the JAR try { for (;;) { url = new URL(url.getFile()); log.debug("Inner URL: " + url); } } catch (MalformedURLException e) { // This will happen at some point and serves as a break in the loop } // Look for the .jar extension and chop off everything after that StringBuilder jarUrl = new StringBuilder(url.toExternalForm()); int index = jarUrl.lastIndexOf(".jar"); if (index >= 0) { jarUrl.setLength(index + 4); log.debug("Extracted JAR URL: " + jarUrl); } else { log.debug("Not a JAR: " + jarUrl); return null; } // Try to open and test it try { URL testUrl = new URL(jarUrl.toString()); if (isJar(testUrl)) { return testUrl; } else { // WebLogic fix: check if the URL's file exists in the filesystem. log.debug("Not a JAR: " + jarUrl); jarUrl.replace(0, jarUrl.length(), testUrl.getFile()); File file = new File(jarUrl.toString()); // File name might be URL-encoded if (!file.exists()) { try { file = new File(URLEncoder.encode(jarUrl.toString(), EncodeUtils.UTF_8)); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Unsupported encoding? UTF-8? That's unpossible."); } } if (file.exists()) { log.debug("Trying real file: " + file.getAbsolutePath()); testUrl = file.toURI().toURL(); if (isJar(testUrl)) { return testUrl; } } } } catch (MalformedURLException e) { log.warn("Invalid JAR URL: " + jarUrl); } log.debug("Not a JAR: " + jarUrl); return null; } /** * Converts a Java package name to a path that can be looked up with a call to * {@link ClassLoader#getResources(String)}. * * @param packageName The Java package name to convert to a path */ protected String getPackagePath(String packageName) { return packageName == null ? null : packageName.replace('.', '/'); } /** * Returns true if the resource located at the given URL is a JAR file. * * @param url The URL of the resource to test. */ protected boolean isJar(URL url) { return isJar(url, new byte[JAR_MAGIC.length]); } /** * Returns true if the resource located at the given URL is a JAR file. * * @param url The URL of the resource to test. * @param buffer A buffer into which the first few bytes of the resource are read. The buffer * must be at least the size of {@link #JAR_MAGIC}. (The same buffer may be reused * for multiple calls as an optimization.) */ protected boolean isJar(URL url, byte[] buffer) { InputStream is = null; try { is = url.openStream(); is.read(buffer, 0, JAR_MAGIC.length); if (Arrays.equals(buffer, JAR_MAGIC)) { log.debug("Found JAR: " + url); return true; } } catch (Exception e) { // Failure to read the stream means this is not a JAR } finally { try { if (is != null){ is.close(); } } catch (Exception e) { } } return false; } } /** * A {@link VFS} implementation that works with the VFS API provided by JBoss 6. * * @author Ben Gunter */ class JBoss6VFS extends VFS { private static final Log log = LogFactory.getLog(ClassUtils.class); /** A class that mimics a tiny subset of the JBoss VirtualFile class. */ static class VirtualFile { static Class<?> VirtualFile; static Method getPathNameRelativeTo, getChildrenRecursively; Object virtualFile; VirtualFile(Object virtualFile) { this.virtualFile = virtualFile; } String getPathNameRelativeTo(VirtualFile parent) { try { return invoke(getPathNameRelativeTo, virtualFile, parent.virtualFile); } catch (IOException e) { // This exception is not thrown by the called method log.error("This should not be possible. VirtualFile.getPathNameRelativeTo() threw IOException."); return null; } } List<VirtualFile> getChildren() throws IOException { List<?> objects = invoke(getChildrenRecursively, virtualFile); List<VirtualFile> children = new ArrayList<VirtualFile>(objects.size()); for (Object object : objects) { children.add(new VirtualFile(object)); } return children; } } /** A class that mimics a tiny subset of the JBoss VFS class. */ static class VFS { static Class<?> VFS; static Method getChild; static VirtualFile getChild(URL url) throws IOException { Object o = invoke(getChild, VFS, url); return o == null ? null : new VirtualFile(o); } } /** Flag that indicates if this VFS is valid for the current environment. */ private static Boolean valid; /** Find all the classes and methods that are required to access the JBoss 6 VFS. */ protected static synchronized void initialize() { if (valid == null) { // Assume valid. It will get flipped later if something goes wrong. valid = true; // Look up and verify required classes VFS.VFS = checkNotNull(getClass("org.jboss.vfs.VFS")); VirtualFile.VirtualFile = checkNotNull(getClass("org.jboss.vfs.VirtualFile")); // Look up and verify required methods VFS.getChild = checkNotNull(getMethod(VFS.VFS, "getChild", URL.class)); VirtualFile.getChildrenRecursively = checkNotNull(getMethod(VirtualFile.VirtualFile, "getChildrenRecursively")); VirtualFile.getPathNameRelativeTo = checkNotNull(getMethod(VirtualFile.VirtualFile, "getPathNameRelativeTo", VirtualFile.VirtualFile)); // Verify that the API has not changed checkReturnType(VFS.getChild, VirtualFile.VirtualFile); checkReturnType(VirtualFile.getChildrenRecursively, List.class); checkReturnType(VirtualFile.getPathNameRelativeTo, String.class); } } /** * Verifies that the provided object reference is null. If it is null, then this VFS is marked * as invalid for the current environment. * * @param object The object reference to check for null. */ protected static <T> T checkNotNull(T object) { if (object == null) { setInvalid(); } return object; } /** * Verifies that the return type of a method is what it is expected to be. If it is not, then * this VFS is marked as invalid for the current environment. * * @param method The method whose return type is to be checked. * @param expected A type to which the method's return type must be assignable. * @see Class#isAssignableFrom(Class) */ protected static void checkReturnType(Method method, Class<?> expected) { if (method != null && !expected.isAssignableFrom(method.getReturnType())) { log.error("Method " + method.getClass().getName() + "." + method.getName() + "(..) should return " + expected.getName() + " but returns " // + method.getReturnType().getName() + " instead."); setInvalid(); } } /** Mark this {@link VFS} as invalid for the current environment. */ protected static void setInvalid() { if (JBoss6VFS.valid != null && JBoss6VFS.valid) { log.debug("JBoss 6 VFS API is not available in this environment."); JBoss6VFS.valid = false; } } static { initialize(); } @Override public boolean isValid() { return valid; } @Override public List<String> list(URL url, String path) throws IOException { VirtualFile directory; directory = VFS.getChild(url); if (directory == null) { return Collections.emptyList(); } if (!path.endsWith("/")) { path += "/"; } List<VirtualFile> children = directory.getChildren(); List<String> names = new ArrayList<String>(children.size()); for (VirtualFile vf : children) { String relative = vf.getPathNameRelativeTo(directory); names.add(path + relative); } return names; } }
12、ReflectUtils
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Date; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.poi.ss.usermodel.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jeesite.common.lang.DateUtils; import com.jeesite.common.lang.ObjectUtils; /** * 反射工具类. * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. */ @SuppressWarnings("rawtypes") 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); private static Class baseEntityClass = null; /** * 调用Getter方法, * 支持多级,如:对象名.对象名.方法, * 支持静态类及方法调用, * 支持Map */ @SuppressWarnings("unchecked") public static <E> E invokeGetter(Object obj, String propertyName) { Object object = obj; for (String name : StringUtils.split(propertyName, ".")){ if (obj instanceof Map){ object = ((Map)obj).get(name); }else{ String methodName = GETTER_PREFIX + StringUtils.capitalize(name); object = invokeMethod(object, methodName, new Class[] {}, new Object[] {}); } } return (E)object; } /** * 调用Setter方法,仅匹配方法名, * 支持多级,如:对象名.对象名.方法, * 支持静态类及方法调用, * 支持Map */ @SuppressWarnings("unchecked") 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){ if (obj instanceof Map){ object = ((Map)obj).get(names[i]); }else{ String methodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); Object childObj = invokeMethod(object, methodName, new Class[] {}, new Object[] {}); // 如果 get 获取对象为空,并且返回值类型继承自 BaseEntity,则 new 对象,并通过 set 赋予它 if (childObj == null && object != null){ Method method = getAccessibleMethod(object, methodName, new Class[] {}); if (method != null) { Class<?> returnType = method.getReturnType(); try { if (baseEntityClass == null) { baseEntityClass = Class.forName("com.jeesite.common.entity.BaseEntity"); } if (baseEntityClass.isAssignableFrom(returnType)) { childObj = returnType.getDeclaredConstructor().newInstance(); methodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); invokeMethodByName(object, methodName, new Object[] { childObj }); } } catch (Exception e) { e.printStackTrace(); } } } object = childObj; } }else{ if (obj instanceof Map){ ((Map)obj).put(names[i], value); }else{ String methodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); invokeMethodByName(object, methodName, 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) { //throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); if (obj != 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) { //throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); if (obj != null) { logger.debug("在 [" + (obj.getClass() == Class.class ? obj : obj.getClass()) + "] 中,没有找到 [" + methodName + "] 方法 "); } return null; } try { return (E)method.invoke(obj.getClass() == Class.class ? null : 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) { // 如果为空不报错,直接返回空。 // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); if (obj != null) { logger.debug("在 [" + (obj.getClass() == Class.class ? obj : 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] = ObjectUtils.toString(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] = ObjectUtils.toInteger(args[i]); }else if (cs[i] == Long.class){ args[i] = ObjectUtils.toLong(args[i]); }else if (cs[i] == Double.class){ args[i] = ObjectUtils.toDouble(args[i]); }else if (cs[i] == Float.class){ args[i] = ObjectUtils.toFloat(args[i]); }else if (cs[i] == Date.class){ if (args[i] instanceof String){ args[i] = DateUtils.parseDate(args[i]); }else{ // POI Excel 日期格式转换 args[i] = DateUtil.getJavaDate((Double)args[i]); } } } } return (E)method.invoke(obj.getClass() == Class.class ? null : 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 // Validate.notNull(obj, "object can't be null"); if (obj == null){ return null; } Validate.notBlank(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) {//NOSONAR // Field不在当前类定义,继续向上转型 continue;// new add } } 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 // Validate.notNull(obj, "object can't be null"); if (obj == null){ return null; } Class<?> clazz = obj.getClass(); if (clazz == Class.class){ clazz = (Class) obj; } Validate.notBlank(methodName, "methodName can't be blank"); for (Class<?> searchType = clazz; searchType != Object.class; searchType = searchType.getSuperclass()) { try { Method method = searchType.getDeclaredMethod(methodName, parameterTypes); makeAccessible(method); return method; } catch (NoSuchMethodException e) { // Method不在当前类定义,继续向上转型 continue;// new add } } 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 // Validate.notNull(obj, "object can't be null"); if (obj == null){ return null; } Class<?> clazz = obj.getClass(); if (clazz == Class.class){ clazz = (Class) obj; } Validate.notBlank(methodName, "methodName can't be blank"); for (Class<?> searchType = clazz; 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, * 如 public UserDao extends CrudDao<User> * @param clazz The class to introspect * @return the first generic declaration, or Object.class if cannot be determined */ @SuppressWarnings("unchecked") public static <T> Class<T> getClassGenricType(final Class clazz) { return getClassGenricType(clazz, 0); } /** * 通过反射,获得Class定义中声明的父类的泛型参数的类型, * 如无法找到,返回Object.class, * 如 public UserDao extends CrudDao<User, Long> * @param clazz clazz The class to introspect * @param index the Index of the generic ddeclaration,start from 0. * @return the index generic declaration, or Object.class if cannot be determined */ 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]; } /** * 获取类的Class,如果为内部类,则返回上级类Class */ 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); } }
13、ObjectUtils
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.nustaq.serialization.FSTConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.core.NamedThreadLocal; /** * 对象操作工具类,继承 org.apache.commons.lang3.ObjectUtils 类 * @author ThinkGem * @version 2020-3-29 */ public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils { private static Logger logger = LoggerFactory.getLogger(ObjectUtils.class); private static final boolean isJavaSerialize; static { String[] ver = StringUtils.split(System.getProperty("java.version"), '.'); isJavaSerialize = ver.length > 0 && Integer.parseInt(ver[0]) > 1; } /** * 转换为 Double 类型 */ public static Double toDouble(final Object val) { if (val == null) { return 0D; } try { String str = val.toString(); if (StringUtils.contains(str, "*")) { Double number = null, d = null; for (String s : StringUtils.split(str, "*")) { d = Double.parseDouble(StringUtils.trim(s)); if (number == null) { number = d; } else { number *= d; } } return number; } return Double.parseDouble(StringUtils.trim(str)); } catch (Exception e) { return 0D; } } /** * 转换为 Float 类型 */ public static Float toFloat(final Object val) { return toDouble(val).floatValue(); } /** * 转换为 Long 类型 */ public static Long toLong(final Object val) { return toDouble(val).longValue(); } /** * 转换为 Integer 类型 */ public static Integer toInteger(final Object val) { return toDouble(val).intValue(); } /** * 转换为 Boolean 类型 'true', 'on', 'y', 't', 'yes' or '1' * (case insensitive) will return true. Otherwise, false is returned. */ public static Boolean toBoolean(final Object val) { if (val == null) { return false; } return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString()); } /** * 转换为字符串 */ public static String toString(final Object obj) { return toString(obj, StringUtils.EMPTY); } /** * 转换为字符串,如果对象为空,则使用 defaultVal 值 */ public static String toString(final Object obj, final String defaultVal) { return obj == null ? defaultVal : obj.toString(); } /** * 转换为字符串,忽略空值。如 null 字符串,则被认为空值,如下: * "" to "" ; null to "" ; "null" to "" ; "NULL" to "" ; "Null" to "" */ public static String toStringIgnoreNull(final Object val) { return ObjectUtils.toStringIgnoreNull(val, StringUtils.EMPTY); } /** * 转换为字符串,忽略空值。如 null 字符串,则被认为空值,如下: * "" to defaultVal ; null to defaultVal ; "null" to defaultVal ; "NULL" to defaultVal ; "Null" to defaultVal */ public static String toStringIgnoreNull(final Object val, String defaultVal) { String str = ObjectUtils.toString(val); return !"".equals(str) && !"null".equals(str.trim().toLowerCase()) ? str : defaultVal; } /** * 拷贝一个对象(但是子对象无法拷贝) * @param source * @param ignoreProperties */ public static Object copyBean(Object source, String... ignoreProperties){ if (source == null){ return null; } try { Object target = source.getClass().getDeclaredConstructor().newInstance(); BeanUtils.copyProperties(source, target, ignoreProperties); return target; } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { throw ExceptionUtils.unchecked(e); } } /** * 克隆一个对象(完全拷贝) * @param source */ public static Object cloneBean(Object source){ if (source == null){ return null; } byte[] bytes = ObjectUtils.serialize(source); Object target = ObjectUtils.unserialize(bytes); return target; } /** * 序列化对象 * @param object * @return */ public static byte[] serialize(Object object) { try { if (isJavaSerialize) { return ObjectUtils.serializeJava(object); }else { return ObjectUtils.serializeFst(object); } } catch (Exception e) { logger.error("serialize", e); } return null; } /** * 反序列化对象 * @param bytes * @return */ public static Object unserialize(byte[] bytes) { try { if (isJavaSerialize) { return ObjectUtils.unserializeJava(bytes); }else { return ObjectUtils.unserializeFst(bytes); } } catch (Exception e) { logger.error("unserialize", e); } return null; } /** * 序列化对象 * @param object * @return */ public static byte[] serializeJava(Object object) { if (object == null){ return null; } long beginTime = System.currentTimeMillis(); byte[] bytes = null; try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos);) { oos.writeObject(object); bytes = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } long totalTime = System.currentTimeMillis() - beginTime; if (totalTime > 30000){ logger.warn(object.getClass() + " serialize time: " + TimeUtils.formatDateAgo(totalTime)); } return bytes; } /** * 反序列化对象 * @param bytes * @return */ public static Object unserializeJava(byte[] bytes) { if (bytes == null){ return null; } long beginTime = System.currentTimeMillis(); Object object = null; if (bytes.length > 0) { try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais);) { object = ois.readObject(); } catch (Exception e) { e.printStackTrace(); } } long totalTime = System.currentTimeMillis() - beginTime; if (totalTime > 30000 && object != null){ logger.warn(object.getClass() + " unserialize time: " + TimeUtils.formatDateAgo(totalTime)); } return object; } private static ThreadLocal<FSTConfiguration> fstConfiguration = new NamedThreadLocal<FSTConfiguration>("FSTConfiguration") { public FSTConfiguration initialValue() { return FSTConfiguration.createDefaultConfiguration(); } }; /** * FST 序列化对象 * @param object * @return */ public static byte[] serializeFst(Object object) { if (object == null){ return null; } long beginTime = System.currentTimeMillis(); byte[] bytes = fstConfiguration.get().asByteArray(object); long totalTime = System.currentTimeMillis() - beginTime; if (totalTime > 30000){ logger.warn(object.getClass() + " fst serialize time: " + TimeUtils.formatDateAgo(totalTime)); } return bytes; } /** * FST 反序列化对象 * @param bytes * @return */ public static Object unserializeFst(byte[] bytes) { if (bytes == null){ return null; } long beginTime = System.currentTimeMillis(); Object object = fstConfiguration.get().asObject(bytes); long totalTime = System.currentTimeMillis() - beginTime; if (totalTime > 30000 && object != null){ logger.warn(object.getClass() + " fst unserialize time: " + TimeUtils.formatDateAgo(totalTime)); } return object; } }
14、MDCUtil
import org.slf4j.MDC; /** * 日志相关工具类 */ public class MDCUtil { private MDCUtil() { } private static final String STR_THREAD_ID = "traceId"; /** * 初始化日志参数并保存在线程副本中 */ public static void init() { String uuid = StringUtil.getUUID(); MDC.put(STR_THREAD_ID, uuid); } /** * 移除线程号和线程副本 */ public static void remove() { MDC.remove(STR_THREAD_ID); } }
15、
查看代码
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
public class MacUtil {
/**
* 获取本机的Mac地址
*
* @return
*/
public static String getMac() {
try {
Process proces = Runtime.getRuntime().exec("ifconfig /all");
InputStreamReader ir = new InputStreamReader(proces.getInputStream());
LineNumberReader lnr = new LineNumberReader(ir);
String line;
while ((line = lnr.readLine()) != null) {
if (line.indexOf("PhysicalAddress") > 0) {
String macAddr = line.substring(line.indexOf("-") - 2);
return macAddr;
}
}
} catch (Exception e) {
}
return null;
}
private static String getMACAddress() throws UnknownHostException, SocketException {
// 获取本机的InetAddress对象
InetAddress inetAddress = InetAddress.getLocalHost();
// 获得网络接口对象(即网卡),并得到mac地址,mac地址存在于一个byte数组中
byte[] mac = NetworkInterface.getByInetAddress(inetAddress).getHardwareAddress();
// 下面代码是把mac地址拼装成String
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mac.length; i++) {
if (i != 0) {
sb.append("-");
}
// mac[i] & 0xFF 是为了把byte转化为正整数
String s = Integer.toHexString(mac[i] & 0xFF);
sb.append(s.length() == 1 ? 0 + s : s);
}
// 把字符串所有小写字母改为大写成为正规的mac地址并返回
return sb.toString().toUpperCase();
}
public static void main(String[] args) throws SocketException, UnknownHostException {
String mac = getMACAddress();
System.out.println(mac);
}
}
END.