All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sinszm.common.util.CommonUtils Maven / Gradle / Ivy

package com.sinszm.common.util;

import com.sinszm.common.Response;
import com.sinszm.common.exception.ApiException;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.util.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.UndeclaredThrowableException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.regex.Pattern;

/**
 * 常规工具
 *
 * @author chenjianbo
 */
public final class CommonUtils {

    private CommonUtils() {
    }

    private static final String REG_IPV4 = "^((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|(" +
            "(1\\d{2})|([1-9]?\\d)))$";

    private static final String REG_DOMAIN = "^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\" +
            ".[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$";

    private static final String REG_MOBILE = "^1\\d{10}$";

    private static final String REG_NUMBER = "[0-9]+";

    public static final char[] AC = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N',
            'O', 'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y', 'Z'
    };

    /**
     * IP地址正则验证
     *
     * @param ip    ip字符串
     * @return      是否符合
     */
    public static boolean isIPv4(String ip) {
        return StringUtils.hasText(ip) && Pattern.matches(REG_IPV4, ip);
    }

    /**
     * 域名地址正则验证
     *
     * @param domain    域名地址
     * @return          是否符合
     */
    public static boolean isDomain(String domain) {
        return StringUtils.hasText(domain) && Pattern.matches(REG_DOMAIN, domain);
    }

    /**
     * 验证手机号
     *
     * @param mobile    手机号
     * @return          是否符合
     */
    public static boolean isMobile(String mobile) {
        return StringUtils.hasText(mobile) && Pattern.matches(REG_MOBILE, mobile);
    }

    /**
     * 验证数字
     *
     * @param number    数字字符串
     * @return          是否符合
     */
    public static boolean isNumber(String number) {
        return StringUtils.hasText(number) && Pattern.matches(REG_NUMBER, number);
    }

    /**
     * 生成一次性密码(6位)
     *
     * @return  随机字符串
     */
    public static String getOneTimePassword() {
        return getOneTimePassword(6);
    }

    /**
     * 生成指定位数一次性密码
     *
     * @param length    长度:4,6,8,10
     * @return          随机字符串
     */
    public static String getOneTimePassword(int length) {
        return OneTimePwdUtil.generateTOTP(
                UUID.randomUUID().toString().replaceAll("-", ""),
                System.currentTimeMillis() + "",
                length
        );
    }

    /**
     * 生成MD5字符串
     * @param arg   字符串
     * @return      字符串对应编码串
     */
    public synchronized static String MD5(String arg) {
        try {
            char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                    'a', 'b', 'c', 'd', 'e', 'f'};
            MessageDigest mdTemp = DigestUtils.getMd5Digest();
            mdTemp.update(arg.getBytes(StandardCharsets.UTF_8));
            return getHexString(mdTemp, hexDigits);
        }catch (Exception e) {
            e.printStackTrace(System.err);
        }
        return "";
    }

    /**
     * SHA1签名方式
     * @param arg   字符串
     * @return      字符串对应编码串
     */
    public synchronized static String SHA1(String arg) {
        final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
                '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            final MessageDigest mdTemp = DigestUtils.getSha1Digest();
            mdTemp.update(arg.getBytes(StandardCharsets.UTF_8));
            return getHexString(mdTemp, hexDigits);
        } catch (Exception e) {
            return "";
        }
    }

    private static String getHexString(MessageDigest mdTemp, char[] hexDigits) {
        byte[] md = mdTemp.digest();
        int j = md.length;
        char[] buf = new char[j * 2];
        int k = 0;
        for (byte byte0 : md) {
            buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
            buf[k++] = hexDigits[byte0 & 0xf];
        }
        return new String(buf);
    }

    /**
     * Base64 编码
     * @param str   字符串
     * @return      字符串对应编码串
     */
    public static String base64Encode(String str) {
        return Base64.getEncoder().encodeToString(
                str.getBytes(StandardCharsets.UTF_8)
        );
    }

    /**
     * Base64 解码
     * @param str   字符串
     * @return      字符串对应编码串
     */
    public static String base64Decode(String str) {
        return new String(
                Base64.getDecoder().decode(str),
                StandardCharsets.UTF_8
        );
    }

    /**
     * 时间格式化为字符串精确到毫秒
     *
     * @param date  时间
     * @return      yyyy-MM-dd HH:mm:ss.SSS
     */
    public static String formatTime2Millisecond(Date date) {
        return String.format("%tF %tT.%tL", date, date, date);
    }

    /**
     * 时间格式化为字符串精确到秒
     *
     * @param date  时间
     * @return      yyyy-MM-dd HH:mm:ss
     */
    public static String formatTime2Second(Date date) {
        return String.format("%tF %tT", date, date);
    }

    /**
     * 时间格式化为字符串精确到日
     *
     * @param date  时间
     * @return      yyyy-MM-dd
     */
    public static String formatTime2Day(Date date) {
        return String.format("%tF", date);
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return      天数
     */
    public static long daysBetween(Date start, Date end) {
        LocalDateTime arg0 = LocalDateTime.ofInstant(start.toInstant(), ZoneId.systemDefault());
        LocalDateTime arg1 = LocalDateTime.ofInstant(end.toInstant(), ZoneId.systemDefault());
        return Duration.between(arg0, arg1).toDays();
    }

    /**
     * 计算年龄
     *
     * @param date  生日
     * @return      年龄
     */
    public static long age(Date date) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        return dateTime.until(now, ChronoUnit.YEARS);
    }

    /**
     * 计算两个日期之间相差的小时数
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return      小时数
     */
    public static long hoursBetween(Date start, Date end) {
        LocalDateTime arg0 = LocalDateTime.ofInstant(start.toInstant(), ZoneId.systemDefault());
        LocalDateTime arg1 = LocalDateTime.ofInstant(end.toInstant(), ZoneId.systemDefault());
        return Duration.between(arg0, arg1).toHours();
    }

    /**
     * 元数据添0补位
     *
     * @param arg   源数据
     * @param len   位数
     * @return      结果
     */
    public synchronized static String frontCompWithZore(int arg, int len) {
        return String.format("%0" + len + "d", arg);
    }

    /**
     * 获取jar运行目录
     *
     * @param clz   参数
     * @return      运行目录
     */
    public static String getJarDir(Class clz) {
        ApplicationHome h = new ApplicationHome(clz);
        File jarF = h.getSource();
        return jarF.getParentFile().toString();
    }

    /**
     * 日志打印工具
     *
     * @param name  参数
     * @return      日志对象
     */
    public static Logger logger(String name) {
        return LoggerFactory.getLogger(StringUtils.isEmpty(name) ? "default boot" : name);
    }

    /**
     * 十进制转三十六进制
     *
     * @param n     十进制值
     * @return      三十六进制结果
     */
    public static String intToAc(long n) {
        StringBuilder s = new StringBuilder(16);
        String a;
        while (n != 0) {
            s.append(AC[(int) (n % 36)]);
            n = n / 36;
        }
        a = s.reverse().toString();
        return StringUtils.isEmpty(a) ? "0" : a;
    }

    /**
     * UUID规则返回
     *
     * @return 32位唯一字符串
     */
    public static String uuid() {
        return UUID.randomUUID()
                .toString()
                .toUpperCase()
                .replace("-", "");
    }

    /**
     * 用于List通过forEach得到下标和对象
     *
     * @param consumer  参数
     * @param        泛型类型
     * @return          带序号数据
     */
    public static  Consumer consumerWithIndex(BiConsumer consumer) {
        class Obj {
            int i;
        }
        Obj obj = new Obj();
        return t -> {
            int index = obj.i++;
            consumer.accept(t, index);
        };
    }

    /**
     * 判断字符串是否为空
     * @param arg0
     * @return
     */
    public static boolean isEmpty(String arg0) {
        return StringUtils.isEmpty(org.apache.commons.lang.StringUtils.trimToEmpty(arg0));
    }

    private static final class OneTimePwdUtil {

        private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};

        private static byte[] hmacSha(String crypto, byte[] keyBytes, byte[] text) {
            try {
                Mac hmac;
                hmac = Mac.getInstance(crypto);
                SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
                hmac.init(macKey);
                return hmac.doFinal(text);
            } catch (GeneralSecurityException gse) {
                throw new UndeclaredThrowableException(gse);
            }
        }

        private static byte[] hexStr2Bytes(String hex) {
            byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();
            byte[] ret = new byte[bArray.length - 1];
            System.arraycopy(bArray, 1, ret, 0, ret.length);
            return ret;
        }

        static String generateTOTP(String key,
                                   String time,
                                   int digits) {
            return generateTOTP(key, time, digits, "HmacSHA1");
        }

        public static String generateTOTP256(String key,
                                             String time,
                                             int digits) {
            return generateTOTP(key, time, digits, "HmacSHA256");
        }

        public static String generateTOTP512(String key,
                                             String time,
                                             int digits) {
            return generateTOTP(key, time, digits, "HmacSHA512");
        }

        static String generateTOTP(String key,
                                   String time,
                                   int digits,
                                   String crypto) {
            StringBuilder result;

            StringBuilder timeBuilder = new StringBuilder(time);
            while (timeBuilder.length() < 16) {
                timeBuilder.insert(0, "0");
            }
            time = timeBuilder.toString();

            byte[] msg = hexStr2Bytes(time);
            byte[] k = hexStr2Bytes(key);

            byte[] hash = hmacSha(crypto, k, msg);

            int offset = hash[hash.length - 1] & 0xf;

            int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16)
                    | ((hash[offset + 2] & 0xff) << 8)
                    | (hash[offset + 3] & 0xff);

            int otp = binary % DIGITS_POWER[digits];

            result = new StringBuilder(Integer.toString(otp));
            while (result.length() < digits) {
                result.insert(0, "0");
            }
            return result.toString();
        }

    }

    /**
     * 获取当前线程id
     * @return  线程号
     */
    public static Long getThreadId() {
        try {
            return Thread.currentThread().getId();
        } catch (Exception e) {
            return -1L;
        }
    }

    /**
     * 获取当前进程id
     * @return  进程号
     */
    public static Long getProcessId() {
        try {
            RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
            String name = runtime.getName();
            String pid = name.substring(0, name.indexOf('@' ));
            return Long.parseLong(pid);
        } catch (Exception e) {
            return -1L;
        }
    }

    /**
     * 简便方法返回数据
     *
     * @param supplier  自定义返回数据函数
     * @return          结果
     */
    public static Response warpResponse(Supplier supplier) {
        try {
            return Response.success(supplier.get());
        } catch (Exception e) {
            if (e instanceof ApiException) {
                throw (ApiException)e;
            }
            throw e;
        }
    }

}