0
点赞
收藏
分享

微信扫一扫

Java/Spring项目常用工具类整理【精华,强烈推荐收藏】

一、不同类型数据

1.1 Json


1.2 字符串

package com.gemenyaofei.integration.domain.common.utils;

import cn.hutool.core.text.StrFormatter;
import com.alibaba.fastjson.JSON;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author ljh
 * @Date 2022/11/8
 * @Desc StringUtils
 */

public class StringUtils extends org.apache.commons.lang3.StringUtils {
    private static String EMAIL = "^([a-zA-Z0-9]*[-_.]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$";
    private static Pattern P_EMAIL;
    private static Pattern P_MOBILE;
    private static Pattern P_USERNAME;
    private static final String NULLSTR = "";
    private static final char SEPARATOR = '_';
    private static final String START = "*";
    private static final String QUESTION = "?";
    private static final String COMMA = ",";

    public StringUtils() {
    }

    public static <T> T nvl(T value, T defaultValue) {
        return value != null ? value : defaultValue;
    }

    public static boolean isEmpty(Collection<?> coll) {
        return isNull(coll) || coll.isEmpty();
    }

    public static boolean isNotEmpty(Collection<?> coll) {
        return !isEmpty(coll);
    }

    public static boolean isEmpty(Object[] objects) {
        return isNull(objects) || objects.length == 0;
    }

    public static boolean isNotEmpty(Object[] objects) {
        return !isEmpty(objects);
    }

    public static boolean isEmpty(Map<?, ?> map) {
        return isNull(map) || map.isEmpty();
    }

    public static boolean isNotEmpty(Map<?, ?> map) {
        return !isEmpty(map);
    }

    public static boolean isEmpty(String str) {
        return isNull(str) || "".equals(str.trim());
    }

    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    public static boolean isNull(Object object) {
        return object == null;
    }

    public static boolean isNotNull(Object object) {
        return !isNull(object);
    }

    public static boolean isArray(Object object) {
        return isNotNull(object) && object.getClass().isArray();
    }

    public static String trim(String str) {
        return str == null ? "" : str.trim();
    }

    public static String substring(String str, int start) {
        if (str == null) {
            return "";
        } else {
            if (start < 0) {
                start += str.length();
            }

            if (start < 0) {
                start = 0;
            }

            return start > str.length() ? "" : str.substring(start);
        }
    }

    public static String substring(String str, int start, int end) {
        if (str == null) {
            return "";
        } else {
            if (end < 0) {
                end += str.length();
            }

            if (start < 0) {
                start += str.length();
            }

            if (end > str.length()) {
                end = str.length();
            }

            if (start > end) {
                return "";
            } else {
                if (start < 0) {
                    start = 0;
                }

                if (end < 0) {
                    end = 0;
                }

                return str.substring(start, end);
            }
        }
    }

    public static String format(String template, Object... params) {
        return !isEmpty(params) && !isEmpty(template) ? StrFormatter.format(template, params) : template;
    }

    public static String toUnderScoreCase(String str) {
        if (str == null) {
            return null;
        } else {
            StringBuilder sb = new StringBuilder();
            boolean preCharIsUpperCase = true;
            boolean curreCharIsUpperCase = true;
            boolean nexteCharIsUpperCase = true;

            for(int i = 0; i < str.length(); ++i) {
                char c = str.charAt(i);
                if (i > 0) {
                    preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
                } else {
                    preCharIsUpperCase = false;
                }

                curreCharIsUpperCase = Character.isUpperCase(c);
                if (i < str.length() - 1) {
                    nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
                }

                if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
                    sb.append('_');
                } else if (i != 0 && !preCharIsUpperCase && curreCharIsUpperCase) {
                    sb.append('_');
                }

                sb.append(Character.toLowerCase(c));
            }

            return sb.toString();
        }
    }

    public static <T> T cast(Object obj) {
        return (T) obj;
    }

    public static String upperCaseFirst(String name) {
        return isBlank(name) ? name : name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    public static String lowerCaseFirst(String name) {
        return isBlank(name) ? name : name.substring(0, 1).toLowerCase() + name.substring(1);
    }

    public static Boolean isEmail(String email) {
        Matcher m = P_EMAIL.matcher(email);
        return m.matches();
    }

    public static boolean isMobileNO(String mobiles) {
        Matcher m = P_MOBILE.matcher(mobiles);
        return m.matches();
    }

    public static String humpToUnderline(String string) {
        StringBuilder stringBuilder = new StringBuilder(string);
        int num = 0;

        for(int i = 0; i < string.length(); ++i) {
            if (Character.isUpperCase(string.charAt(i))) {
                stringBuilder.insert(i + num, "_");
                ++num;
            }
        }

        return stringBuilder.toString();
    }

    public static boolean isHttpUrl(String path) {
        return startsWithIgnoreCase(path, "http");
    }

    public static String numberAfterFillZero(String str, int length) {
        return str + String.format("%0" + (length - str.length()) + "d", 0);
    }

    public static String numberBeforeFillZero(String str, int length) {
        return String.format("%0" + length + "d", str);
    }

    public static String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }

    public static boolean inStringIgnoreCase(String str, String... strs) {
        if (str != null && strs != null) {
            String[] var2 = strs;
            int var3 = strs.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                String s = var2[var4];
                if (str.equalsIgnoreCase(trim(s))) {
                    return true;
                }
            }
        }

        return false;
    }

    public static String convertToCamelCase(String name) {
        StringBuilder result = new StringBuilder();
        if (name != null && !name.isEmpty()) {
            if (!name.contains("_")) {
                return name.substring(0, 1).toUpperCase() + name.substring(1);
            } else {
                String[] camels = name.split("_");
                String[] var3 = camels;
                int var4 = camels.length;

                for(int var5 = 0; var5 < var4; ++var5) {
                    String camel = var3[var5];
                    if (!camel.isEmpty()) {
                        result.append(camel.substring(0, 1).toUpperCase());
                        result.append(camel.substring(1).toLowerCase());
                    }
                }

                return result.toString();
            }
        } else {
            return "";
        }
    }

    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        } else {
            s = s.toLowerCase();
            StringBuilder sb = new StringBuilder(s.length());
            boolean upperCase = false;

            for(int i = 0; i < s.length(); ++i) {
                char c = s.charAt(i);
                if (c == '_') {
                    upperCase = true;
                } else if (upperCase) {
                    sb.append(Character.toUpperCase(c));
                    upperCase = false;
                } else {
                    sb.append(c);
                }
            }

            return sb.toString();
        }
    }

    public static boolean matches(String str, List<String> strs) {
        if (!isEmpty(str) && !isEmpty((Collection)strs)) {
            Iterator var2 = strs.iterator();

            String testStr;
            do {
                if (!var2.hasNext()) {
                    return false;
                }

                testStr = (String)var2.next();
            } while(!matches(str, testStr));

            return true;
        } else {
            return false;
        }
    }

    public static boolean matches(String str, String... strs) {
        if (!isEmpty(str) && !isEmpty((Object[])strs)) {
            String[] var2 = strs;
            int var3 = strs.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                String testStr = var2[var4];
                if (matches(str, testStr)) {
                    return true;
                }
            }

            return false;
        } else {
            return false;
        }
    }

    public static boolean matches(String str, String pattern) {
        if (!isEmpty(pattern) && !isEmpty(str)) {
            pattern = pattern.replaceAll("\\s*", "");
            int beginOffset = 0;
            String remainingURI = str;
            String prefixPattern = "";
            String suffixPattern = "";
            boolean result = false;

            do {
                int formerStarOffset = indexOf(pattern, "*", beginOffset);
                prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());
                result = remainingURI.contains(prefixPattern);
                if (formerStarOffset == -1) {
                    return result;
                }

                if (!result) {
                    return false;
                }

                if (!isEmpty(prefixPattern)) {
                    remainingURI = substringAfter(str, prefixPattern);
                }

                int latterStarOffset = indexOf(pattern, "*", formerStarOffset + 1);
                suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());
                result = remainingURI.contains(suffixPattern);
                if (!result) {
                    return false;
                }

                if (!isEmpty(suffixPattern)) {
                    remainingURI = substringAfter(str, suffixPattern);
                }

                beginOffset = latterStarOffset + 1;
            } while(!isEmpty(suffixPattern) && !isEmpty(remainingURI));

            return true;
        } else {
            return false;
        }
    }

    static {
        P_EMAIL = Pattern.compile(EMAIL);
        P_MOBILE = Pattern.compile("^((1[3-8][0-9]))\\d{8}$");
        P_USERNAME = Pattern.compile("^([a-zA-Z][a-zA-Z0-9]*[-_.]?[a-zA-Z0-9]+)*$");
    }
}


1.3 集合


1.4 时间日期

package com.gemenyaofei.integration.app.utils;

import com.gemenyaofei.common.core.utils.StringUtils;
import com.gemenyaofei.integration.domain.common.exception.BizException;
import com.gemenyaofei.integration.domain.common.exception.ErrorCodeEnum;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Stream;

/**
 * @Author ljh
 * @Date 2021/8/26
 * @Desc 时间, 日期相关工具类
 */
public class DateTimeUtils {

    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String DATE_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";

    /**
     * yyyyMMddHHmmss
     */
    public static final String DATE_FORMAT_FULL_CODE = "yyyyMMddHHmmss";

    /**
     * yyyy/MM/dd HH:mm:ss
     */
    public static final String DATE_FORMAT_FULL_SLASH = "yyyy/MM/dd HH:mm:ss";

    /**
     * yyyy-MM-dd
     */
    public static final String DATE_FORMAT_YMD = "yyyy-MM-dd";

    /**
     * yyyy-MM-dd
     */
    public static final String DATE_FORMAT_YM = "yyyy-MM";

    /**
     * yyyy/MM/dd
     */
    public static final String DATE_FORMAT_YMD_SLASH = "yyyy/MM/dd";

    /**
     * yyyyMMdd
     */
    public static final String DATE_FORMAT_YMD_CODE = "yyyyMMdd";

    /**
     * yyyy-MM
     */
    public static final String DATE_FORMAT_YYMM = "yyyy-MM";

    /**
     * yyyy/MM
     */
    public static final String DATE_FORMAT_YYMM_SLASH = "yyyy/MM";

    /**
     * yyyy
     */
    public static final String DATE_FORMAT_YY = "yyyy";

    /**
     * MM
     */
    public static final String DATE_FORMAT_MM = "MM";

    /**
     * HH:mm:ss
     */
    public static final String DATE_FORMAT_HMS = "HH:mm:ss";

    /**
     * HH:mm
     */
    public static final String DATE_FORMAT_HHMM = "HH:mm";

    /**
     * mm:ss
     */
    public static final String DATE_FORMAT_MMSS = "mm:ss";

    /**
     * HH
     */
    public static final String DATE_FORMAT_HH = "HH";

    /**
     * yyyy-MM-dd'T'HH:mm:ss.SSSXXX 2001-07-04T12:08:56.235-07:00
     */
    public static final String DATE_FORMAT_FULL_UTCSX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    /**
     * yyyy-MM-dd'T'HH:mm:ss.SSSZ 2001-07-04T12:08:56.235-0700
     */
    public static final String DATE_FORMAT_FULL_UTCSZ = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";

    /**
     * 13位时间戳(毫秒级)
     */
    public static final String DATE_FORMAT_LONG_MS = "longms";

    /**
     * 10位时间戳(秒级)
     */
    public static final String DATE_FORMAT_LONG_S = "longs";

    /**
     * 正则匹配日期时间表达式
     */
    public static final String REGEX_YMD = "[0-9]{4}-[0-9]{2}-[0-9]{2}";
    public static final String REGEX_YMD_HMS = "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}";
    public static final String REGEX_YMD_HMS_SSSXXX = "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}[\\+\\-][0-9]{2}[\\:][0-9]{2}";
    public static final String REGEX_YMD_HMS_SSSZ = "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}[\\+\\-][0-9]{4}";

    public static final String REGEX_YMD_SLASH = "[0-9]{4}/[0-9]{2}/[0-9]{2}";
    public static final String REGEX_YMD_HMS_SLASH = "[0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}";
    public static final String REGEX_YMD_CODE = "[0-9]{8}";
    public static final String REGEX_YMD_HMS_CODE = "[0-9]{14}";
    public static final String REGEX_TIMESTAMP_MS = "[0-9]{13}";
    public static final String REGEX_TIMESTAMP_S = "[0-9]{10}";

    /**
     * 获得今日时间戳 yyyyMMddHHmmss格式字符串
     *
     * @return String
     */
    public static String getCurrentTimeStamp() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_FULL_CODE);
        LocalDateTime today = LocalDateTime.now();
        return today.format(df);
    }

    /**
     * 将Date转换为yyyyMMddHHmmss格式字符串
     *
     * @return String
     */
    public static String dateFormatFull(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT_FULL_CODE);
        return simpleDateFormat.format(date);
    }

    /**
     * 将Date转换为字符串
     *
     * @return String
     */
    public static String dateToStr(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }

    /**
     * 将yyyyMMddHHmmss转换Date为格式字符串
     *
     * @return String
     */
    public static Date fullToDate(String timestamp) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT_FULL_CODE);
        Date date = null;
        try {
            date = format.parse(timestamp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 字符串去掉符号,转换为14位yyyyMMddHHmmss时间字符串,补充时间为最开始
     *
     * @param time 必须是年份日期开头的日期时间类型
     * @return
     */
    public static String strFormatStartTime(String time) {
        String regEx = "[^0-9]";
        time = time.replaceAll(regEx, "");
        if (time.length() < 14) {
            return StringUtils.numberAfterFillZero(time, 14);
        }
        return time;
    }

    /**
     * 字符串去掉符号,转换为14位时间yyyyMMddHHmmss时间字符串,补充时间为最后
     *
     * @param time 必须是年份日期开头的日期时间类型
     * @return
     */
    public static String strFormatEndTime(String time) {
        String regEx = "[^0-9]";
        time = time.replaceAll(regEx, "");
        if (time.length() < 8) {
            time = StringUtils.numberAfterFillZero(time, 8);
            time = time + "595959";
            return time;
        }
        return StringUtils.numberAfterFillZero(time, 14);
    }

    /**
     * 获得今日日期 yyyy-MM-dd格式字符串
     *
     * @return String
     */
    public static String getToday() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate today = LocalDate.now();
        String nowDate = today.format(df);
        return nowDate;
    }

    /**
     * 获得当前日期时间 yyyy-MM-dd HH:mm:ss格式字符串
     *
     * @return String
     */
    public static String getCurrentDateTime() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_FULL);
        LocalDateTime dateTime = LocalDateTime.now();
        String nowDateTime = dateTime.format(df);
        return nowDateTime;
    }

    /**
     * 获得当前日期时间 yyyy-MM-dd HH:mm:ss格式字符串
     *
     * @return String
     */
    public static String getDateFormatStrFromDate(String dateFormat, Date date) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        Instant instant = date.toInstant();
        LocalDateTime dateTime = LocalDateTime.ofInstant(instant,ZoneId.systemDefault());
        return dateTime.format(df);
    }

    /**
     * 获取当天开始时间 2019-06-12 00:00:00 LocalDateTime类型
     *
     * @return LocalDateTime
     */
    public static LocalDateTime getTodayBeginTime() {
        LocalDate currentDay = LocalDate.now();
        return LocalDateTime.of(currentDay, LocalTime.MIN);
    }

    /**
     * localdatetime转换为13位时间戳
     *
     * @param localDateTime 转换格式
     * @return
     */
    public static Long localDateTimeToLong(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * localdatetime转换为10位时间戳
     *
     * @param localDateTime 转换格式
     * @return
     */
    public static Long localDateTimeToLongs(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 获取当天时间的前一天
     *
     * @param dateFormat 转换格式
     * @return
     */
    public static String getYesterdayByFormat(String dateFormat) {
        return LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern(dateFormat));
    }

    /**
     * 根据localDateTime获取前一天
     *
     * @param localDateTime 时间
     * @return
     */
    public static Long getYesterdayToLong(LocalDateTime localDateTime) {
        return localDateTime.plusDays(-1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 根据localDateTime获取前一天
     *
     * @param localDateTime 时间
     * @return
     */
    public static Long getYesterdayToLongs(LocalDateTime localDateTime) {
        return localDateTime.plusDays(-1).atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 获取当天时间的前一天开始时间
     *
     * @param dateFormat 转换格式
     * @return
     */
    public static String getYesterdayBeginByFormat(String dateFormat) {
        return getTodayBeginTime().plusDays(-1).format(DateTimeFormatter.ofPattern(dateFormat));
    }

    /**
     * 获取当天时间的前一天结束时间
     *
     * @param dateFormat 转换格式
     * @return
     */
    public static String getYesterdayEndByFormat(String dateFormat) {
        return getTodayEndTime().plusDays(-1).format(DateTimeFormatter.ofPattern(dateFormat));
    }

    /**
     * 获取当天结束时间 2019-06-12 23:59:59
     *
     * @return LocalDateTime
     */
    public static LocalDateTime getTodayEndTime() {
        LocalDate currentDay = LocalDate.now();
        return LocalDateTime.of(currentDay, LocalTime.MAX);
    }

    /**
     * LocalDate转化为指定格式字符串
     *
     * @param fromDate
     * @param dateFormat yyyy-MM-dd | yyyy/MM/dd | yyyyMMdd | yyyy-MM | yyyy/MM | yyyyMM
     * @return
     */
    public static String localDate2Str(LocalDate fromDate, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        String dateStr = fromDate.format(df);
        return dateStr;
    }

    /**
     * LocalDateTime转化为指定格式字符串
     *
     * @param fromDateTime
     * @param dateTimeFormat yyyy-MM-dd HH:mm:ss | yyyy/MM/dd HH:mm:ss | yyyyMMdd HH:mm:ss | ...
     * @return
     */
    public static String localDateTime2Str(LocalDateTime fromDateTime, String dateTimeFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateTimeFormat);
        String localTime = fromDateTime.format(df);
        return localTime;
    }

    /**
     * 日期格式字符串转化为指定格式的LocalDate日期
     *
     * @param beginDate  yyyy-MM-dd | yyyy/MM/dd | yyyyMMdd
     * @param dateFormat yyyy-MM-dd | yyyy/MM/dd | yyyyMMdd
     * @return
     */
    public static LocalDate str2LocalDate(String beginDate, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            LocalDate fromDate = LocalDate.parse(beginDate, df);
            return fromDate;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 时间格式字符串转化为指定格式的LocalDateTime时间
     *
     * @param beginDateTime yyyy-MM-dd HH:mm:ss | yyyy/MM/dd HH:mm:ss | yyyyMMdd HH:mm:ss
     * @param dateFormat    yyyy-MM-dd HH:mm:ss | yyyy/MM/dd HH:mm:ss | yyyyMMdd HH:mm:ss
     * @return
     */
    public static LocalDateTime str2LocalDateTime(String beginDateTime, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            LocalDateTime fromDateTime = LocalDateTime.parse(beginDateTime, df);
            return fromDateTime;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Date转为LocalDateTime
     *
     * @param date Date类型
     * @return LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * Long 毫秒级 类型时间戳转化为LocalDateTime
     *
     * @param dateTimeLong 毫秒数
     * @return LocalDateTime
     */
    public static LocalDateTime longms2LocalDateTime(Long dateTimeLong) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTimeLong), ZoneId.systemDefault());
    }

    /**
     * Long 秒级 类型时间戳转化为LocalDateTime
     *
     * @param dateTimeLong 毫秒数
     * @return LocalDateTime
     */
    public static LocalDateTime longs2LocalDateTime(Long dateTimeLong) {
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(dateTimeLong), ZoneId.systemDefault());
    }

    /**
     * Long类型时间戳转化为时间字符串
     *
     * @param dateTimeLong 毫秒数
     * @return string
     */
    public static String longToStr(Long dateTimeLong, String dateFormat) {
        if (dateTimeLong == null) {
            return null;
        }
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern(dateFormat);
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTimeLong), ZoneId.systemDefault()));
    }

    /**
     * Long类型时间戳转化为时间字符串
     *
     * @param dateTimeLong 秒数
     * @return string
     */
    public static String intTimeToStr(Integer dateTimeLong, String dateFormat) {
        if (dateTimeLong == null) {
            return null;
        }
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern(dateFormat);
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochSecond(dateTimeLong), ZoneId.systemDefault()));
    }

    /**
     * 日期时间str转为日期str (yyyy-MM-dd HH:mm:ss -> yyyy-MM-dd)
     *
     * @param fullDate yyyy-MM-dd HH:mm:ss格式字符串
     * @return yyyy-MM-dd格式字符串
     */
    public static String fullDate2Date(String fullDate) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_FULL);
        LocalDate localDate = LocalDateTime.parse(fullDate, df).toLocalDate();
        return localDate2Str(localDate, DATE_FORMAT_YMD);
    }

    /**
     * 日期格式转换
     *
     * @param day  年月日格式字符串
     * @param fmt1 当前格式 yyyy-MM-dd | yyyy/MM/dd | yyyyMMdd
     * @param fmt2 期望转换的格式 yyyy-MM-dd | yyyy/MM/dd | yyyyMMdd
     * @return String
     */
    public static String dateFormatConvert(String day, String fmt1, String fmt2) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(fmt2);
        return str2LocalDate(day, fmt1).format(dtf);
    }

    /**
     * 日期时间格式转换
     *
     * @param dayTime 年月日时分秒格式字符串
     * @param fmt1    当前格式 yyyy-MM-dd HH:mm:ss | yyyy/MM/dd HH:mm:ss | yyyyMMddHHmmss
     * @param fmt2    期望转换的格式 yyyy-MM-dd HH:mm:ss | yyyy/MM/dd HH:mm:ss | yyyyMMddHHmmss
     * @return String
     */
    public static String dateTimeFormatConvert(String dayTime, String fmt1, String fmt2) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(fmt2);
        return str2LocalDateTime(dayTime, fmt1).format(dtf);
    }

    /**
     * 日期加减天数
     *
     * @param day yyyy-MM-dd格式字符串
     * @param d   整数(正为加,负为减)
     * @return String
     */
    public static String addDays(String day, int d) {
        LocalDate localDate = str2LocalDate(day, DATE_FORMAT_YMD).plusDays(d);
        return localDate2Str(localDate, DATE_FORMAT_YMD);
    }

    /**
     * 日期时间加减天数
     *
     * @param dayTime yyyy-MM-dd HH:mm:ss格式字符串
     * @param d       天数(正为加,负为减)
     * @return String
     */
    public static String addTimeDays(String dayTime, int d) {
        LocalDateTime localDateTime = str2LocalDateTime(dayTime, DATE_FORMAT_FULL).plusDays(d);
        return localDateTime2Str(localDateTime, DATE_FORMAT_FULL);
    }

    /**
     * 时间加减分钟数
     *
     * @param dayTime yyyy-MM-dd HH:mm:ss格式字符串
     * @param min     分钟数(正为加,负为减)
     * @return String
     */
    public static String addMinutes(String dayTime, long min) {
        LocalDateTime localDateTime = str2LocalDateTime(dayTime, DATE_FORMAT_FULL).plusMinutes(min);
        return localDateTime2Str(localDateTime, DATE_FORMAT_FULL);
    }

    /**
     * 日期加减周数 获取某日前几周或后几周的日期
     *
     * @param day  yyyy-MM-dd格式字符串
     * @param week 周数(正为加,负为减)
     * @return String
     */
    public static String addWeeks(String day, long week) {
        LocalDate localDate = str2LocalDate(day, DATE_FORMAT_YMD).plusWeeks(week);
        return localDate2Str(localDate, DATE_FORMAT_YMD);
    }

    /**
     * 日期加减月数
     *
     * @param day   yyyy-MM-dd格式字符串
     * @param month 月数(正为加,负为减)
     * @return String
     */
    public static String addMonths(String day, long month) {
        LocalDate localDate = str2LocalDate(day, DATE_FORMAT_YMD).plusMonths(month);
        return localDate2Str(localDate, DATE_FORMAT_YMD);
    }

    /**
     * 日期加减年数
     *
     * @param day  yyyy-MM-dd格式字符串
     * @param year 年数(正为加,负为减)
     * @return String
     */
    public static String addYears(String day, long year) {
        LocalDate localDate = str2LocalDate(day, DATE_FORMAT_YMD).plusYears(year);
        return localDate2Str(localDate, DATE_FORMAT_YMD);
    }

    /**
     * 获取两日期的间隔天数
     *
     * @param start yyyy-MM-dd格式字符串
     * @param end   yyyy-MM-dd格式字符串
     * @return long
     */
    public static long getDaysInterval(String start, String end) {
        return (str2LocalDate(end, DATE_FORMAT_YMD).toEpochDay() - str2LocalDate(start, DATE_FORMAT_YMD).toEpochDay());
    }

    /**
     * 获取两日期时间的间隔秒数
     *
     * @param start yyyy-MM-dd HH:mm:ss格式字符串
     * @param end   yyyy-MM-dd HH:mm:ss格式字符串
     * @return long
     */
    public static long getSecondsInterval(String start, String end) {
        Duration between = Duration.between(str2LocalDateTime(start, DATE_FORMAT_FULL), str2LocalDateTime(end, DATE_FORMAT_FULL));
        return between.getSeconds();
    }

    /**
     * 获取两个日期间隔的所有日期
     *
     * @param start yyyy-MM-dd格式字符串
     * @param end   yyyy-MM-dd格式字符串
     * @return List<String>
     */
    public static List<String> getDayArrayBetween(String start, String end) {
        List<String> list = new ArrayList<>();
        LocalDate localDateStart = str2LocalDate(start, DATE_FORMAT_YMD);
        LocalDate localDate1End = str2LocalDate(end, DATE_FORMAT_YMD);
        long distance = ChronoUnit.DAYS.between(localDateStart, localDate1End);
        if (distance < 1) {
            return list;
        }
        Stream.iterate(localDateStart, d -> d.plusDays(1)).limit(distance + 1).forEach(x -> list.add(localDate2Str(x, DATE_FORMAT_YMD)));
        return list;
    }

    /**
     * 获取日期一定范围内的所有日期
     *
     * @param day   yyyy-MM-dd格式字符串
     * @param range 负数代表前几天  正数代表后几天
     * @return List<String>
     */
    public static List<String> getDayArrayRange(String day, int range) {
        List<String> list = new ArrayList<>();
        LocalDate localDateStart = str2LocalDate(day, DATE_FORMAT_YMD);
        LocalDate localDate1End = str2LocalDate(addDays(day, range), DATE_FORMAT_YMD);
        if (range > 0) {
            long distance = ChronoUnit.DAYS.between(localDateStart, localDate1End);
            if (distance < 1) {
                return list;
            }

            Stream.iterate(localDateStart, d -> d.plusDays(1)).limit(distance + 1).forEach(x -> list.add(localDate2Str(x, DATE_FORMAT_YMD)));
            return list;

        } else {
            long distance = ChronoUnit.DAYS.between(localDate1End, localDateStart);
            if (distance < 1) {
                return list;
            }

            Stream.iterate(localDateStart, d -> d.minusDays(1)).limit(distance + 1).forEach(x -> list.add(localDate2Str(x, DATE_FORMAT_YMD)));
            Collections.reverse(list);
            return list;
        }
    }

    /**
     * 日期时间比较大小
     *
     * @param start yyyy-MM-dd HH:mm:ss格式字符串
     * @param end   yyyy-MM-dd HH:mm:ss格式字符串
     * @return true: start > end | false: start < end
     */
    public static boolean compareDateTime(String start, String end) {
        return str2LocalDateTime(start, DATE_FORMAT_FULL).isAfter(str2LocalDateTime(end, DATE_FORMAT_FULL));
    }

    /**
     * 日期比较大小
     *
     * @param start yyyy-MM-dd格式字符串
     * @param end   yyyy-MM-dd格式字符串
     * @return true: start > end | false: start < end
     */
    public static boolean compareDate(String start, String end) {
        return str2LocalDate(start, DATE_FORMAT_YMD).isAfter(str2LocalDate(end, DATE_FORMAT_YMD));
    }

    /**
     * 获得一年后的日期字符串
     */
    public static String getOneYearLaterDate(String beginDate, String dateFormat) {
        LocalDate fromDate = str2LocalDate(beginDate, dateFormat);
        if (fromDate != null) {
            LocalDate toDate = fromDate.plus(1, ChronoUnit.YEARS);
            return localDate2Str(toDate, dateFormat);
        }
        return null;
    }

    /**
     * 获得一年后的日期时间字符串
     */
    public static String getOneYearLaterDateTime(String beginDate, String dateFormat) {
        LocalDateTime fromDate = str2LocalDateTime(beginDate, dateFormat);
        if (fromDate != null) {
            LocalDateTime toDate = fromDate.plus(1, ChronoUnit.YEARS);
            return localDateTime2Str(toDate, dateFormat);
        }
        return null;
    }

    /**
     * 获取本周第一天(周一) yyyy-MM-dd格式字符串
     *
     * @return String
     */
    public static String getFirstDayOfCurrentWeek() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate d1 = LocalDate.now().plusWeeks(0).with(DayOfWeek.MONDAY);
        String nowDate = d1.format(df);
        return nowDate;
    }

    /**
     * 获取本周开始时间 2019-06-10 00:00:00 LocalDateTime类型
     *
     * @return LocalDateTime
     */
    public static LocalDateTime getWeekBeginTime() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        int currentOrdinal = currentDateTime.getDayOfWeek().ordinal();
        return currentDateTime.minusDays(currentOrdinal)
                .withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 获取本周最后一天(周日) yyyy-MM-dd格式字符串
     *
     * @return String
     */
    public static String getLastDayOfCurrentWeek() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate d2 = LocalDate.now().plusWeeks(0).with(DayOfWeek.SUNDAY);
        String nowDate = d2.format(df);
        return nowDate;
    }

    /**
     * 获取本周结束时间 2019-06-16 23:59:59
     *
     * @return LocalDateTime
     */
    public static LocalDateTime getWeekEndTime() {
        LocalDateTime currentDateTime = LocalDateTime.now();
        int currentOrdinal = currentDateTime.getDayOfWeek().ordinal();
        return currentDateTime.plusDays(6 - currentOrdinal)
                .withHour(23).withMinute(59).withSecond(59).withNano(999999999);
    }

    /**
     * 获取本周 周几所在的日期 yyyy-MM-dd格式字符串
     *
     * @return String
     * @desc 参数w值范围1~7, 如:w=2 返回本周周二的日期
     */
    public static String getWeekDay(int w) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate d2 = LocalDate.now().plusWeeks(0).with(DayOfWeek.of(w));
        return d2.format(df);
    }

    /**
     * 返回今天是周几
     *
     * @return 1 | 2 | 3 | 4 | 5 | 6 | 7
     */
    public static Integer getTodayIndexOfWeek() {
        return LocalDate.now().getDayOfWeek().getValue();
    }

    /**
     * 返回某日是周几
     *
     * @param day yyyy-MM-dd格式
     * @return 1 | 2 | 3 | 4 | 5 | 6 | 7
     */
    public static Integer getDayIndexOfWeek(String day) {
        return str2LocalDate(day, DATE_FORMAT_YMD).getDayOfWeek().getValue();
    }

    /**
     * 返回本周周一至周日日期数组
     *
     * @return [yyyy-MM-dd, ... ,yyyy-MM-dd]
     */
    public static List<String> getArrayOfCurrentWeek() {
        List<String> list = new ArrayList<>();
        Stream.iterate(1, n -> n + 1).limit(7).forEach(x -> list.add(getWeekDay(x)));
        return list;
    }

    /**
     * 返回本周周一至今日日期数组
     *
     * @return [yyyy-MM-dd, ... ,yyyy-MM-dd]
     */
    public static List<String> getTodayArrayOfCurrentWeek() {
        List<String> list = new ArrayList<>();
        Integer week = LocalDate.now().getDayOfWeek().getValue();
        Stream.iterate(1, n -> n + 1).limit(week).forEach(x -> list.add(getWeekDay(x)));
        return list;
    }

    /**
     * 获取本月第一天 yyyy-MM-dd格式字符串
     *
     * @return
     */
    public static String getFirstDayOfCurrentMonth() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate first = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        String date = first.format(df);
        return date;
    }

    /**
     * 获取本月最后一天 yyyy-MM-dd格式字符串
     *
     * @return
     */
    public static String getLastDayOfCurrentMonth() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate last = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        String date = last.format(df);
        return date;
    }

    /**
     * 获取本年第一天 yyyy-MM-dd格式字符串
     *
     * @return
     */
    public static String getFirstDayOfCurrentYear() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate first = LocalDate.now().plusYears(0).with(TemporalAdjusters.firstDayOfYear());
        String date = first.format(df);
        return date;
    }

    /**
     * 获取本年最后一天 yyyy-MM-dd格式字符串
     *
     * @return
     */
    public static String getLastDayOfCurrentYear() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(DATE_FORMAT_YMD);
        LocalDate last = LocalDate.now().plusYears(0).with(TemporalAdjusters.lastDayOfYear());
        String date = last.format(df);
        return date;
    }

    /**
     * 获得毫秒数
     *
     * @param localDateTime
     * @return
     */
    public static long getTimestampOfDateTime(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return instant.toEpochMilli();
    }

    /**
     * 根据出生日期(yyyy-MM-dd)字符串计算年龄
     *
     * @param birthDay
     * @return
     */
    public static Integer getAgeByBirthDay(String birthDay) {
        LocalDate birthDate = str2LocalDate(birthDay, DATE_FORMAT_YMD);
        LocalDate currentDate = LocalDate.now();
        if (birthDate != null) {
            if (currentDate.isBefore(birthDate)) {
                return 0;
            } else {
                return birthDate.until(currentDate).getYears();
            }
        }
        return null;
    }

    /**
     * 判断闰年平年
     * 闰年算法: 四年一闰,百年不闰,四百年再闰
     *
     * @param year yyyy-MM-dd格式字符串
     * @return true闰年 | false平年
     */
    public static boolean checkLeapYear(String year) {
        return str2LocalDate(year, DATE_FORMAT_YMD).isLeapYear();
    }

    /**
     * 获取当前日期所在季度的开始日期 或 结束日期
     * 一年四季, 第一季度:1月-3月, 第二季度:4月-6月, 第三季度:7月-9月, 第四季度:10月-12月
     *
     * @param first true表示查询本季度开始日期  false表示查询本季度结束日期
     * @return
     */
    public static LocalDate getStartOrEndDayOfQuarter(boolean first) {
        LocalDate today = LocalDate.now();
        Month month = today.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        Month endMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
        if (first) {
            return LocalDate.of(today.getYear(), firstMonthOfQuarter, 1);
        } else {
            return LocalDate.of(today.getYear(), endMonthOfQuarter, endMonthOfQuarter.length(today.isLeapYear()));
        }
    }

    /**
     * 获取某日所在季度的开始日期 或 结束日期
     * 一年四季, 第一季度:1月-3月, 第二季度:4月-6月, 第三季度:7月-9月, 第四季度:10月-12月
     *
     * @param day   yyyy-MM-dd格式字符串
     * @param first true表示查询本季度开始日期  false表示查询本季度结束日期
     * @return
     */
    public static LocalDate getSomedayStartOrEndOfQuarter(String day, boolean first) {
        LocalDate date = str2LocalDate(day, DATE_FORMAT_YMD);
        Month month = date.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        Month endMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
        if (first) {
            return LocalDate.of(date.getYear(), firstMonthOfQuarter, 1);
        } else {
            return LocalDate.of(date.getYear(), endMonthOfQuarter, endMonthOfQuarter.length(date.isLeapYear()));
        }
    }

    public static LocalDateTime paraStartTime(List<String> times) {
        if (times == null || times.isEmpty()) {
            return null;
        }
        return str2LocalDateTime(strFormatStartTime(times.get(0)), DATE_FORMAT_FULL_CODE);
    }

    public static LocalDateTime paraEndTime(List<String> times) {
        if (times == null || times.isEmpty() || times.size() <= 1) {
            return null;
        }
        return str2LocalDateTime(strFormatEndTime(times.get(1)), DATE_FORMAT_FULL_CODE);
    }

    /**
     * 国际时间转换为时间戳
     *
     * @param dateTime 格式: yyyy-MM-dd'T'HH:mm:ss.SSSXXX, 例:2022-01-06T12:12:26.000+00:00
     * @param isMs     true 是毫秒级, false是秒级
     * @return
     */
    public static Long internationalToTimeStamp(String dateTime, boolean isMs) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT_FULL_UTCSX);
        try {
            Date date = format.parse(dateTime);
            if (isMs) {
                return date.getTime();
            } else {
                return date.getTime() / 1000;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 时间戳字符串转换为long时间戳
     *
     * @param dateTime
     * @return
     */
    public static Long longTimeStrToLong(String dateTime) {
        try {
            return Long.valueOf(dateTime);
        } catch (Exception e) {
            return DateTimeUtils.internationalToTimeStamp(dateTime, true);
        }
    }

    /**
     * yyyy-MM-dd HH:mm:ss 转换为时间戳 毫秒级
     *
     * @param dateTime 格式: 2022-01-06 20:02:00
     * @return
     */
    public static Long formatfullToLong(String dateTime) {
        LocalDateTime localDateTime = str2LocalDateTime(dateTime, DATE_FORMAT_FULL);
        if (localDateTime != null) {
            return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        }
        return null;
    }

    /**
     * 根据时间字符串判断时间格式
     *
     * @param date
     * @return
     */
    public static String getDatetimeFormat(String date) throws BizException {
        date = date.trim();

        //yyyy-MM-dd HH:mm:ss
        if (Pattern.compile(REGEX_YMD_HMS).matcher(date).matches()) {
            return DATE_FORMAT_FULL;
        }

        //yyyy/MM/dd HH:mm:ss
        if (Pattern.compile(REGEX_YMD_HMS_SLASH).matcher(date).matches()) {
            return DATE_FORMAT_FULL_SLASH;
        }

        //yyyyMMddHHmmss
        if (Pattern.compile(REGEX_YMD_HMS_CODE).matcher(date).matches()) {
            return DATE_FORMAT_FULL_CODE;
        }

        //yyyy-MM-dd
        if (Pattern.compile(REGEX_YMD).matcher(date).matches()) {
            return DATE_FORMAT_YMD;
        }

        //yyyy/MM/dd
        if (Pattern.compile(REGEX_YMD_SLASH).matcher(date).matches()) {
            return DATE_FORMAT_YMD_SLASH;
        }

        //yyyyMMdd
        if (Pattern.compile(REGEX_YMD_CODE).matcher(date).matches()) {
            return DATE_FORMAT_YMD_CODE;
        }

        //yyyy-MM-dd'T'HH:mm:ss.SSSXXX
        if (Pattern.compile(REGEX_YMD_HMS_SSSXXX).matcher(date).matches()) {
            return DATE_FORMAT_FULL_UTCSX;
        }

        //yyyy-MM-dd'T'HH:mm:ss.SSS Z
        if (Pattern.compile(REGEX_YMD_HMS_SSSZ).matcher(date).matches()) {
            return DATE_FORMAT_FULL_UTCSZ;
        }

        //13位时间戳
        if (Pattern.compile(REGEX_TIMESTAMP_MS).matcher(date).matches()) {
            return DATE_FORMAT_LONG_MS;
        }

        //10位时间戳
        if (Pattern.compile(REGEX_TIMESTAMP_S).matcher(date).matches()) {
            return DATE_FORMAT_LONG_S;
        }

        throw new BizException(ErrorCodeEnum.SYS_ERR, "无法识别的日期时间格式");
    }


    /**
     * LocalDateTime时间类转换为时间格式字符串
     *
     * @param dateTime 时间
     * @param format   转换格式
     * @return
     */
    public static String localDateTimeToStr(LocalDateTime dateTime, String format) {
        switch (format) {
            case DATE_FORMAT_LONG_MS:
                return localDateTimeToLong(dateTime).toString();
            case DATE_FORMAT_LONG_S:
                return localDateTimeToLongs(dateTime).toString();
            default:
                return localDateTime2Str(dateTime, format);
        }
    }

    /**
     * string字符串 按照格式变更为 localDateTime类型
     *
     * @param time   字符串时间
     * @param format 转换格式
     * @return
     */
    public static LocalDateTime strToLocalDateTime(String time, String format) {
        switch (format) {
            case DATE_FORMAT_LONG_MS:
                return longms2LocalDateTime(longTimeStrToLong(time));
            case DATE_FORMAT_LONG_S:
                return longs2LocalDateTime(longTimeStrToLong(time));
            case DATE_FORMAT_FULL:
            case DATE_FORMAT_FULL_SLASH:
                return str2LocalDateTime(time, format);
            default:
                return Optional.ofNullable(str2LocalDate(time, format)).map(t->LocalDateTime.of(t, LocalTime.MIN)).orElse(null);
        }
    }

    /**
     * cst转换Str
     * @param cstTime Thu Apr 01 00:00:00 CST 2021
     * @param format 转换格式
     */
    public static String cstToStr(String cstTime, String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(Date.parse(cstTime));
    }


    /**
     * 在[beginStr,endStr]只随机生成时间,不包含日期
     * 在没有添加日期格式时,默认为1970-01-01
     * @param beginStr
     * @param endStr
     * @return
     */
    public static LocalTime randomTime(String beginStr,String endStr){
        try {
            DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm:ss");
            LocalTime beginTime = LocalTime.parse(beginStr, format);
            LocalTime endTime = LocalTime.parse(endStr, format);

            if (beginTime.isAfter(endTime)) {
                return null;
            }

            long randDateTime = random(beginTime.toNanoOfDay(), endTime.toNanoOfDay());
            return LocalTime.ofNanoOfDay(randDateTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return LocalTime.now();
    }

    /**
     * 随机生成时间
     * 使用Math.random()方法---返回一个在介于(0,1)的随机数
     * @param begin
     * @param end
     * @return
     */
    private static long random(long begin, long end) {
        long rand = begin + (long)(Math.random()*(end - begin));
        if (rand  == begin || rand  == end) {
            return random(begin, end);
        }
        return rand;
    }

}




1.5 Stream流

package com.gemenyaofei.integration.domain.common.utils;

import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * @Author ljh
 * @Date 2022/11/23
 * @Desc Stream操作相关工具类
 */
public class StreamUtils {

    /**
     * 获取list中第一个符合条件的对象
     *
     * @param srcList    对象list
     * @param filterFunc 条件
     * @param <T>        对象类型
     * @return 属性list
     */
    public static <T> T findFirst(List<T> srcList, Predicate<? super T> filterFunc) {
        if (CollectionUtils.isEmpty(srcList)) {
            return null;
        }
        return srcList.stream().filter(filterFunc).findFirst().orElse(null);
    }

    /**
     * 将List转换为string拼接
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <R>     属性类型
     * @return 属性list
     */
    public static <T, R> String toStr(List<T> srcList, Function<? super T, ? extends R> mapper, String separator) {
        if (CollectionUtils.isEmpty(srcList)) {
            return "";
        }
        return srcList.stream().map(mapper).filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(separator));
    }

    /**
     * 将Set转换为string拼接
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <R>     属性类型
     * @return 属性list
     */
    public static <T, R> String toStr(Set<T> srcList, Function<? super T, ? extends R> mapper, String separator) {
        if (CollectionUtils.isEmpty(srcList)) {
            return "";
        }
        return srcList.stream().map(mapper).filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining(separator));
    }

    /**
     * 提取对象中的某一个属性
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <R>     属性类型
     * @return 属性list
     */
    public static <T, R> List<R> toList(List<T> srcList, Function<? super T, ? extends R> mapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptyList();
        }
        return srcList.stream().map(mapper).collect(Collectors.toList());
    }

    /**
     * 提取对象中的某一个属性
     *
     * @param srcList 对象list
     * @param <T>     对象类型
     * @return 属性list
     */
    public static <T> List<T> toFilterList(List<T> srcList, Predicate<? super T> predicate) {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptyList();
        }
        return srcList.stream().filter(predicate).collect(Collectors.toList());
    }

    /**
     * 提取map中的list
     *
     * @param srcList 对象list
     * @param <T>     对象类型
     * @return 属性list
     */
    public static <K,T> List<T> flatMapList(Map<K, List<T>> srcList) {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptyList();
        }
        return srcList.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
    }

    /**
     * 提取对象中的某一个属性
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <R>     属性类型
     * @return 属性list
     */
    public static <T, R> List<R> toDistinctList(List<T> srcList, Function<? super T, ? extends R> mapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptyList();
        }
        return srcList.stream().map(mapper).distinct().collect(Collectors.toList());
    }

    /**
     * 提取对象中的某一个属性
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <R>     属性类型
     * @return 属性list
     */
    public static <T, R> List<String> toLowerCaseList(List<T> srcList, Function<? super T, ? extends R> mapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptyList();
        }
        return srcList.stream().map(mapper).map(Object::toString).map(String::toLowerCase).distinct().collect(Collectors.toList());
    }

    /**
     * 提取对象中的某一个属性,去重
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <R>     属性类型
     * @return 属性set
     */
    public static <T, R> Set<R> toSet(List<T> srcList, Function<? super T, ? extends R> mapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptySet();
        }
        return srcList.stream().map(mapper).collect(Collectors.toSet());
    }

    /**
     * 构建 属性:对象  map
     *
     * @param srcList 对象list
     * @param mapper  对象::get属性名
     * @param <T>     对象类型
     * @param <K>     属性类型
     * @return 属性:对象 map
     */
    public static <T, K> Map<K, T> toMap(List<T> srcList, Function<? super T, ? extends K> mapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return new HashMap<>();
        }
        return srcList.stream().collect(Collectors.toMap(mapper, v -> v, (v1, v2) -> v1));
    }

    /**
     * 构建 属性:属性  map
     *
     * @param srcList 对象list
     * @param mapper1 对象::get属性名
     * @param mapper2 对象::get属性名
     * @param <T>     对象类型
     * @param <K>     属性类型
     * @param <U>     属性类型
     * @return 属性:属性 map
     */
    public static <T, K, U> Map<K, U> toMap(List<T> srcList,
                                            Function<? super T, ? extends K> mapper1,
                                            Function<? super T, ? extends U> mapper2) {
        if (CollectionUtils.isEmpty(srcList)) {
            return new HashMap<>();
        }
        return srcList.stream().collect(Collectors.toMap(mapper1, mapper2, (v1, v2) -> v1));
    }

    /**
     * 按特定规则筛选集合元素,返回List,过滤输入集合的null对象
     *
     * @param <T>       对象类型
     * @param source    对象集合
     * @param predicate 筛选条件
     * @return
     */
    public <T> List<T> filter(Collection<T> source, Predicate<T> predicate) {
        if (CollectionUtils.isEmpty(source)) {
            return new ArrayList<>(0);
        }
        return source.stream().filter(Objects::nonNull).filter(predicate).collect(Collectors.toList());
    }

    /**
     * 按匹配条件返回某一个对象,过滤输入集合的null对象
     *
     * @param <T>       对象类型
     * @param source    对象集合
     * @param predicate 匹配条件
     * @return
     */
    public <T> T findAny(Collection<T> source, Predicate<T> predicate) {
        if (CollectionUtils.isEmpty(source)) {
            return null;
        }
        return source.stream().filter(Objects::nonNull).filter(predicate).findAny().orElse(null);
    }

    /**
     * 判断集合是否有元素符合匹配条件
     *
     * @param <T>       对象类型
     * @param source    对象集合
     * @param predicate 匹配条件
     * @return
     */
    public <T> boolean anyMatch(Collection<T> source, Predicate<T> predicate) {
        if (CollectionUtils.isEmpty(source)) {
            return false;
        }
        return source.stream().anyMatch(predicate);
    }

    /**
     * list分组
     *
     * @param srcList   对象list
     * @param keyMapper 分组属性
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Map<R, List<T>> groupBy(List<T> srcList, Function<? super T, ? extends R> keyMapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return new HashMap<>();
        }
        return srcList.stream().collect(Collectors.groupingBy(keyMapper));
    }

    /**
     * list分组
     *
     * @param srcList   对象list
     * @param keyMapper 分组属性
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Map<R, List<T>> toFilterGroupBy(List<T> srcList,
                                                         Predicate<? super T> predicate,
                                                         Function<? super T, ? extends R> keyMapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return new HashMap<>();
        }
        return srcList.stream().filter(predicate).collect(Collectors.groupingBy(keyMapper));
    }

    /**
     * list分组
     *
     * @param srcList   对象list
     * @param keyMapper 分组属性
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R, U> Map<R, Map<U, List<T>>> toMap2(List<T> srcList,
                                                Function<? super T, ? extends R> keyMapper,
                                                Function<? super T, ? extends U> keyMapper2) {
        if (CollectionUtils.isEmpty(srcList)) {
            return new HashMap<>();
        }
        return srcList.stream().collect(Collectors.groupingBy(keyMapper, Collectors.groupingBy(keyMapper2)));
    }

    /**
     * list分组
     *
     * @param list   对象list
     * @param keyMapper 分组属性
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R, U> Map<R, List<U>> groupByMapList(List<T> list,
                                                           Function<? super T, ? extends R> keyMapper,
                                                           Function<? super T, ? extends U> valueMapper) {
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        return list.stream().collect(Collectors.groupingBy(keyMapper, Collectors.mapping(valueMapper, Collectors.toList())));
    }

    /**
     * list分组
     *
     * @param srcList   对象list
     * @param keyMapper 分组属性
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R, U> Map<R, Set<U>> groupByMapSet(List<T> srcList,
                                                      Function<? super T, ? extends R> keyMapper,
                                                      Function<? super T, ? extends U> mapper) {
        if (CollectionUtils.isEmpty(srcList)) {
            return new HashMap<>();
        }
        return srcList.stream().collect(Collectors.groupingBy(keyMapper, Collectors.mapping(mapper, Collectors.toSet())));
    }

    /**
     * 切割 -> 操作 -> 归并
     *
     * @param source
     * @param maxSize
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<T> splitListConvert(final Collection<R> source, final int maxSize,
                                                  Function<List<R>, List<T>> mapper) {
        if (CollectionUtils.isEmpty(source)) {
            return new ArrayList<>(0);
        }
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize must be positive");
        }

        final int size = source.size();
        if (size <= maxSize) {
            if (source instanceof List) {
                return mapper.apply((List<R>) source);
            }
            return mapper.apply(new ArrayList<>(source));
        }

        final int step = (size + maxSize - 1) / maxSize;

        List<T> list = IntStream.range(0, step)
                .mapToObj(i -> source.stream().skip(i * maxSize).limit(maxSize).collect(Collectors.toList())).map(mapper)
                .filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList());
        return list;
    }
}



二、类和对象(反射)

2.1 BeanUtils


2.2 反射执行方法-ReflectionUtil

package com.gemenyaofei.integration.domain.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @Author ljh
 * @Date 2022/11/28
 * @Desc 通过反射执行方法的工具类
 */
public class ReflectionUtil {

    private static Logger logger = LoggerFactory.getLogger(ReflectionUtil.class);

    /**
     * *通过反射的方式调用对象方法
     *
     * @param object     服务对象
     * @param methodName 调用方法
     * @param args       方法参数(具有顺序性)
     */
    public static void invokeMethod(Object object, String methodName, Object[] args)
            throws Exception {
        logger.debug(" invokeMethod start : 服务对象={},调用方法={} ", new Object[]{object, methodName});
        Class<?>[] paramClasses = null;
        if (args.length > 0) {
            paramClasses = new Class<?>[args.length];
            for (int i = 0; i < args.length; i++) {
                paramClasses[i] = args[i] instanceof List ? List.class : args[i].getClass();
            }
        }
        Method method = object.getClass().getMethod(methodName, paramClasses);
        method.setAccessible(true);
        method.invoke(object, args);
        logger.debug(" invokeMethod end ");
    }
}



三、复杂操作

3.1 异步工具类

1、异步任务执行类

package com.gemenyaofei.integration.domain.model.dto;

import com.gemenyaofei.integration.domain.common.utils.ReflectionUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author ljh
 * @Date 2022/11/28
 * @Desc 异步任务类
 */
@Slf4j
public class AsyncTask implements Runnable {

    // 服务对象
    private Object object;
    // 调用方法
    private String methodName;
    // 方法参数(具有顺序性)
    private Object[] args;

    public AsyncTask(Object object, String methodName, Object[] args) {
        this.object = object;
        this.methodName = methodName;
        this.args = args;
    }

    @Override
    public void run() {
        try {
            ReflectionUtil.invokeMethod(object, methodName, args);
        } catch (Exception e) {
            log.error("异步调用异常:object:{},methodName:{},args:{}",object, methodName, args);
            log.error(e.getMessage());
        }
    }
}

2、获取容器中的Bean

package com.gemenyaofei.integration.domain.common.helper;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @Author ljh
 * @Date 2022/11/28
 * @Desc 从Spring容器中获取Bean的工具类
 */
@Component
public class SpringContextHelper implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextHelper.applicationContext = applicationContext;
    }

    public static Object getBean(Class<?> clazz) throws BeansException {
        return applicationContext.getBean(clazz);
    }

    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }
}

3、通过反射执行方法

见2.2

4、异步任务工具类

package com.gemenyaofei.integration.domain.common.utils;

import com.gemenyaofei.integration.domain.common.helper.SpringContextHelper;
import com.gemenyaofei.integration.domain.model.dto.AsyncTask;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author ljh
 * @Date 2022/11/28
 * @Desc 异步任务工具类
 */
public class AsyncTaskUtil {

    private volatile static ThreadPoolTaskExecutor threadPoolTaskExecutor;

    private static final ReentrantLock LOCK = new ReentrantLock();

    private static ThreadPoolTaskExecutor getThreadPoolTaskExecutor() {
        if (threadPoolTaskExecutor == null) {
            LOCK.lock();
            try {
                if (threadPoolTaskExecutor == null) {
                    threadPoolTaskExecutor = (ThreadPoolTaskExecutor) SpringContextHelper.getBean("threadPoolTaskExecutor");
                }
            } finally {
                LOCK.unlock();
            }
        }
        return threadPoolTaskExecutor;
    }

    public static void asyncTask(Object object, String methodName, Object[] args) {
        AsyncTask asyncTask = new AsyncTask(object, methodName, args);
        asyncTask(asyncTask);
    }

    public static void asyncTask(Runnable asyncTask) {
        getThreadPoolTaskExecutor().execute(asyncTask);
    }

    public static <T> Future<T> asyncTask(Callable<T> callableTask) {
        return getThreadPoolTaskExecutor().submit(callableTask);
    }

}




3.2 HTTP调用

1、请求参数实体类

package com.gemenyaofei.integration.app.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.http.util.Args;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author ljh
 * @Date 2021/11/18
 * @Desc HttpRequest 类
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class HttpRequestParam {
    /**
     * 接口地址
     */
    protected String url;
    /**
     * 接口请求方式 get post put delete
     */
    protected String method;
    /**
     * 请求头
     */
    protected Map<String, String> headers;
    /**
     * 表单参数
     */
    protected Map<String, Object> params;
    /**
     * body-json参数
     */
    protected String body;
    /**
     * body-json参数
     */
    protected File file;

    public HttpRequestParam(Builder builder) {
        this.url = builder.url;
        this.method = builder.method;
        this.headers = builder.headers;
        this.params = builder.params;
        this.body = builder.body;
        this.file = builder.file;
    }

    public String url() {
        return this.url;
    }

    public String method() {
        return this.method;
    }

    public Map<String, String> headers() {
        return this.headers;
    }

    public Map<String, Object> params() {
        return this.params;
    }

    public String body() {
        return this.body;
    }

    public File file() {
        return this.file;
    }

    public Builder newBuilder() {
        return new Builder(this);
    }

    @Override
    public String toString() {
        return "HttpRequest{url=" + this.url + ", method=" + this.method + ", headers=" + this.headers + ", params=" + this.params + ", body=" + this.body + '}';
    }


    public static class Builder {
        String url;
        String method;
        Map<String, String> headers;
        Map<String, Object> params;
        String body;
        File file;

        public Builder() {
            this.method = "GET";
        }

        Builder(HttpRequestParam httpRequest) {
            this.url = httpRequest.url;
            this.method = httpRequest.method;
            this.headers = (Map) (httpRequest.headers.isEmpty() ? Collections.emptyMap() : new LinkedHashMap(httpRequest.headers));
            this.params = (Map) (httpRequest.params.isEmpty() ? Collections.emptyMap() : new LinkedHashMap(httpRequest.params));
            this.body = httpRequest.body;
            this.file = httpRequest.file;
        }

        public Builder url(String url) {
            if (url == null) {
                throw new NullPointerException("url == null");
            } else {
                this.url = url;
                return this;
            }
        }

        public Builder header(Map<String, String> headers) {
            this.headers = headers;
            return this;
        }

        public Builder addHeader(String name, String value) {
            Args.notNull(name, "Header name");
            if (this.headers == null) {
                this.headers = new HashMap<>(16);
            }
            this.headers.put(name, value);
            return this;
        }

        public Builder removeHeader(String name) {
            this.headers.remove(name);
            return this;
        }

        public Builder params(Map<String, Object> params) {
            this.params = params;
            return this;
        }

        public Builder body(String body) {
            this.body = body;
            return this;
        }

        public Builder file(File file) {
            this.file = file;
            return this;
        }

        public Builder get() {
            return this.method("GET");
        }

        public Builder post() {
            return this.method("POST");
        }

        public Builder delete() {
            return this.method("DELETE");
        }

        public Builder put() {
            return this.method("PUT");
        }

        public Builder patch() {
            return this.method("PATCH");
        }

        public Builder method(String method) {
            if (method == null) {
                throw new NullPointerException("method == null");
            } else if (method.length() == 0) {
                throw new IllegalArgumentException("method.length() == 0");
            } else {
                this.method = method;
                return this;
            }
        }

        public HttpRequestParam build() {
            if (this.url == null) {
                throw new IllegalStateException("url == null");
            } else {
                return new HttpRequestParam(this);
            }
        }
    }
}

2、响应实体类

package com.gemenyaofei.integration.domain.common.entity;

import lombok.Data;

import java.io.Serializable;

/**
 * @Author ljh
 * @Date 2021/9/6
 * @Desc 封装httpClient响应结果
 */
@Data
public class HttpClientResult implements Serializable {

    /**
     * 响应状态码,200成功
     */
    private Integer code;

    /**
     * 响应成功/失败
     */
    private Boolean success;

    /**
     * 响应数据
     */
    private String responseBody;

    /**
     * 异常信息
     */
    private String errorMsg;



    public HttpClientResult(int code, String responseBody) {
        this.code = code;
        this.responseBody = responseBody;
    }

    public HttpClientResult(int code) {
        this.code = code;
    }

    public HttpClientResult(int code, String responseBody, String errorMsg) {
        this.code = code;
        this.responseBody = responseBody;
        this.errorMsg = errorMsg;
    }

    public HttpClientResult() {
    }
}

3、调用工具类

package com.gemenyaofei.integration.app.utils;


import cn.hutool.json.JSONUtil;
import com.gemenyaofei.integration.app.dto.HttpRequestParam;
import com.gemenyaofei.integration.domain.common.entity.HttpClientResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.zookeeper.Shell;
import org.bouncycastle.jce.exception.ExtIOException;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @Author huangqianqian
 * @Date 2021/9/6
 * @Desc httpClient工具类
 */
@Slf4j
public class HttpClientUtils {

    /**
     * 编码格式。发送编码格式统一用UTF-8
     */
    private static final String ENCODING = "UTF-8";
    private static final String APPLICATION_JSON_UTF_8 = "application/json";
    private static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
    private static final String APPLICATION_MSWORD = "application/msword";

    /**
     * 设置连接超时时间,单位毫秒。
     */
    private static final int CONNECT_TIMEOUT = 6000;

    /**
     * 设置连接超时时间,单位毫秒。
     */
    private static final int CONNECTION_REQUEST_TIMEOUT = 1000;

    /**
     * 请求获取数据的超时时间(即响应时间),单位毫秒。
     */
    private static final int SOCKET_TIMEOUT = 60000;


    private HttpClientUtils() {
    }


    private static RequestConfig requestConfig = null;
//    private static final CloseableHttpClient GLOBAL_HTTP_CLIENT;

    static {
        // 存在连接超时和数据超时, 会导致请求卡住, 需要主动放弃
        requestConfig = RequestConfig.custom()
                // 设置连接超时时间, 单位毫秒
                .setConnectTimeout(CONNECT_TIMEOUT)
                // 请求获取数据的超时时间, 单位毫秒
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                // 如果访问一个接口, 多少时间内无法返回数据, 就直接放弃此次调用
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();

//        GLOBAL_HTTP_CLIENT = HttpClientBuilder.create()
//                // 全局请求超时策略
//                .setDefaultRequestConfig(config)
//                // 客户端连接池数量, 太多线程会导致线程上下文切换频繁, 开销也相当大
//                .setMaxConnTotal(100)
//                // 每个域名可占用的连接池数量, 考虑到部分接口访问的比较多, 超过会阻塞
//                .setMaxConnPerRoute(30)
//                .build();
    }


    /**
     * get请求,表单入参,非body
     *
     * @param url 接口地址
     * @return
     */
    public static HttpClientResult doGet(String url) {
        return executorRequest(new HttpRequestParam.Builder().url(url).get().build());
    }

    /**
     * get请求,表单入参,非body
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doGet(String url, Map<String, Object> paramMap) {
        return executorRequest(new HttpRequestParam.Builder().url(url).params(paramMap).get().build());
    }

    /**
     * get请求,表单入参,非body
     *
     * @param url      接口地址---new
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doGet(String url, Map<String, Object> paramMap, Map<String, String> headers) {
        return executorRequest(new HttpRequestParam.Builder().url(url).header(headers).params(paramMap).get().build());
    }

    /**
     * delete请求,表单入参,非body
     *
     * @param url 接口地址
     * @return
     */
    public static HttpClientResult doDelete(String url) {
        return executorRequest(new HttpRequestParam.Builder().url(url).delete().build());
    }

    /**
     * delete请求,表单入参,非body
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doDelete(String url, Map<String, Object> paramMap) {
        return executorRequest(new HttpRequestParam.Builder().url(url).params(paramMap).delete().build());
    }

    /**
     * delete请求,表单入参,非body---token
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doDelete(String url, Map<String, Object> paramMap, Map<String, String> headers) {
        return executorRequest(new HttpRequestParam.Builder().url(url).header(headers).params(paramMap).delete().build());
    }

    /**
     * put请求,表单入参,非body
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doPut(String url, Map<String, Object> paramMap) {
        return executorRequest(new HttpRequestParam.Builder().url(url).params(paramMap).put().build());
    }

    /**
     * post请求,表单入参,非body
     *
     * @param url 接口地址
     * @return
     */
    public static HttpClientResult doPost(String url) {
        return executorRequest(new HttpRequestParam.Builder().url(url).post().build());
    }

    /**
     * post请求,表单入参,非body
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doPost(String url, Map<String, Object> paramMap) {
        return executorRequest(new HttpRequestParam.Builder().url(url).params(paramMap).post().build());
    }


    /**
     * post请求,表单入参,非body
     *
     * @param url      接口地址----new
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doPost(String url, Map<String, Object> paramMap, Map<String, String> headers) {
        return executorRequest(new HttpRequestParam.Builder().url(url).header(headers).params(paramMap).post().build());
    }

    /**
     * post请求,表单入参,非body
     *
     * @param url  接口地址
     * @param json 入参
     * @return
     */
    public static HttpClientResult doPost(String url, String json) {
        return executorRequest(new HttpRequestParam.Builder().url(url).body(json).post().build());
    }


    /**
     * post请求,表单入参,非body
     *
     * @param url  接口地址--new
     * @param json 入参
     * @return
     */
    public static HttpClientResult doPost(String url, String json, Map<String, String> headers) {
        return executorRequest(new HttpRequestParam.Builder().url(url).header(headers).body(json).post().build());
    }

    /**
     * post请求,表单入参,非body
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    public static HttpClientResult doPostJson(String url, Map<String, Object> paramMap, Map<String, String> headers) {
        return executorRequest(new HttpRequestParam.Builder().url(url).header(headers).body(JSONUtil.toJsonStr(paramMap)).post().build());
    }


    /**
     * post请求,body入参(json字符串)
     *
     * @param url     接口地址
     * @param jsonStr json字符串
     * @return
     */
    public static HttpClientResult doPostJson(String url, String jsonStr, Map<String, String> headerMap) {
        log.info("doPost url:[{}], param:[{}]", url, jsonStr);
        HttpPost httpPost = new HttpPost(url);

        httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
        if (!MapUtils.isEmpty(headerMap)) {
            for (String key : headerMap.keySet()) {
                httpPost.addHeader(key, headerMap.get(key));
            }
        }

        StringEntity entity = new StringEntity(jsonStr, ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
        return executeHttp(httpPost);
    }

    /**
     * post请求,body入参(form-data)
     *
     * @param url      接口地址
     * @param formData 表单入参
     * @return
     */
    public static HttpClientResult doPostFormData(String url, Map<String, String> headerMap, List<NameValuePair> formData) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new UrlEncodedFormEntity(formData, StandardCharsets.UTF_8));
        //httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
        if (!MapUtils.isEmpty(headerMap)) {
            for (String key : headerMap.keySet()) {
                httpPost.addHeader(key, headerMap.get(key));
            }
        }
        return executeHttp(httpPost);
    }

    /**
     * 执行请求
     *
     * @param httpRequestParam
     * @return
     */
    public static HttpClientResult executorRequest(HttpRequestParam httpRequestParam) {
        log.info("executorRequest info:[{}]", httpRequestParam.toString());
        String method = httpRequestParam.method();
        switch (method) {
            case "GET":
                return doRequest(new HttpGet(), httpRequestParam);
            case "DELETE":
                return doRequest(new HttpDelete(), httpRequestParam);
            case "POST":
                return doEntityRequest(new HttpPost(), httpRequestParam);
            case "PUT":
                return doEntityRequest(new HttpPut(), httpRequestParam);
            case "PATCH":
                return doEntityRequest(new HttpPatch(), httpRequestParam);
            default:
                break;
        }
        return new HttpClientResult(500, "未知的请求方式");
    }

    public static HttpClientResult doEntityRequest(HttpEntityEnclosingRequestBase httpEntityRequestBase, HttpRequestParam httpRequestParam) {
        // 添加参数, 请求参数除body外最终都需要拼接到地址栏中
        Map<String, Object> paramMap = httpRequestParam.params();
        httpEntityRequestBase.setURI(
                paramMap == null || paramMap.isEmpty()
                        ? URI.create(httpRequestParam.url())
                        : buildUri(httpRequestParam.url(), paramMap));

        // 添加头内容
        addHeader(httpEntityRequestBase, httpRequestParam.headers(), httpRequestParam.body());

        // 添加body内容
        if (!StringUtils.isBlank(httpRequestParam.getBody())) {
            StringEntity requestEntity = new StringEntity(httpRequestParam.getBody(), "utf-8");
            requestEntity.setContentEncoding("UTF-8");
            httpEntityRequestBase.setEntity(requestEntity);
        }

        // 执行HTTP
        return executeHttp(httpEntityRequestBase);
    }

    /**
     * 根据 请求方式、接口地址、参数 执行executeHttp请求
     *
     * @return
     */
    private static HttpClientResult doRequest(HttpRequestBase httpBase, HttpRequestParam httpRequestParam) {
        if (MapUtils.isEmpty(httpRequestParam.params())) {
            httpBase.setURI(URI.create(httpRequestParam.url()));
        } else {
            httpBase.setURI(buildUri(httpRequestParam.url(), httpRequestParam.params()));
        }

        if (!MapUtils.isEmpty(httpRequestParam.headers())) {
            addHeader(httpBase, httpRequestParam.headers(), httpRequestParam.body());
        }
        return executeHttp(httpBase);
    }

    /**
     * 执行http请求 获取数据 并释放资源
     */
    private static HttpClientResult executeHttp(HttpRequestBase httpBase) {
        httpBase.setConfig(requestConfig);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse httpResponse = null;

        try {
            // 执行请求
            httpResponse = httpClient.execute(httpBase);
            //response = GLOBAL_HTTP_CLIENT.execute(httpBase);
            HttpClientResult result = getHttpClientResult(httpResponse, httpBase);
            log.info("executeHttp result:[{}]", result);
            return result;

        } catch (Exception e) {
            log.error("Failed to execute request or get response, message:[{}], Exception:[{}]", e.getMessage(), e);
            return new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR, null, "Failed to execute request or get response: " + e.toString());

        } finally {
            closeHttpClientAndResp(httpClient, httpResponse);
        }
    }

    /**
     * http请求结束,获取请求结果,封装结果
     *
     * @param response 请求结果
     * @param httpBase
     * @return
     * @throws IOException
     */
    private static HttpClientResult getHttpClientResult(CloseableHttpResponse response, HttpRequestBase httpBase) throws Exception {
        try {
            if (response == null || response.getStatusLine() == null) {
                return new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR, null, "response响应内容为空");
            }

            // 获取返回结果
            String content = "";
            if (response.getEntity() != null) {
                content = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8.name());
            }
//        response.getStatusLine().getStatusCode();
            // 返回响应结果
            return new HttpClientResult(response.getStatusLine().getStatusCode(), content, response.getStatusLine().getStatusCode() == HttpStatus.SC_OK ? null : "服务繁忙");
        } catch (Exception exception) {
            throw new Exception(exception);
        } finally {
            if (!httpBase.isAborted()) {
                httpBase.abort();
            }
        }
    }

    /**
     * http请求结束,释放资源
     */
    private static void closeHttpClientAndResp(CloseableHttpClient httpClient, CloseableHttpResponse httpResponse) {
        if (httpResponse != null) {
            try {
                httpResponse.close();
            } catch (IOException e) {
                log.error("Failed to close httpResponse {}", e.getLocalizedMessage(), e);
            }
        }
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (IOException e) {
                log.error("Failed to close httpClient {}", e.getLocalizedMessage(), e);
            }
        }
    }

//    /**
//     * http请求结束,释放资源(当使用GLOBAL_HTTP_CLIENT执行时,用这段代码释放资源)
//     */
//    private static void closeHttpClientAndResp(HttpRequestBase httpBase, CloseableHttpResponse httpResponse) {
//        if (httpResponse != null) {
//            try {
//                httpResponse.close();
//            } catch (IOException e) {
//                log.error("Failed to close httpResponse {}", e.getLocalizedMessage(), e);
//            }
//        }
//        if (httpBase != null) {
//            httpBase.releaseConnection();
//        }
//    }

    /**
     * 接口地址拼接入参
     *
     * @param url      接口地址
     * @param paramMap 入参
     * @return
     */
    private static URI buildUri(String url, Map<String, Object> paramMap) {
        String param = URLEncodedUtils.format(setHttpParams(paramMap), StandardCharsets.UTF_8);
        return StringUtils.isEmpty(param) ? URI.create(url) : URI.create(url + "?" + param);
    }

    /**
     * 参数录入(注意 map中的数据最终都会变为字符串)
     *
     * @param paramMap 参数
     * @return
     */
    private static List<NameValuePair> setHttpParams(Map<String, Object> paramMap) {
        List<NameValuePair> nameValPair = new ArrayList<>();
        if (paramMap == null || paramMap.isEmpty()) {
            return nameValPair;
        }

        for (Map.Entry<String, Object> mapEntry : paramMap.entrySet()) {
            nameValPair.add(new BasicNameValuePair(mapEntry.getKey(), Optional.ofNullable(mapEntry.getValue()).map(Object::toString).orElse(null)));
        }
        return nameValPair;
    }

    /**
     * 执行http请求前,添加头内容
     *
     * @param httpRequestBase
     * @param headerMap
     * @param body
     */
    private static void addHeader(HttpRequestBase httpRequestBase, Map<String, String> headerMap, String body) {
        if (MapUtils.isEmpty(headerMap)) {
            httpRequestBase.addHeader(HTTP.CONTENT_TYPE, StringUtils.isEmpty(body) ? APPLICATION_X_WWW_FORM_URLENCODED : APPLICATION_JSON_UTF_8);

        } else {
            for (Map.Entry<String, String> headerEntry : headerMap.entrySet()) {
                httpRequestBase.addHeader(headerEntry.getKey(), headerEntry.getValue());
            }
            if (Objects.isNull(httpRequestBase.getFirstHeader(HTTP.CONTENT_TYPE))) {
                httpRequestBase.addHeader(HTTP.CONTENT_TYPE, StringUtils.isEmpty(body) ? APPLICATION_X_WWW_FORM_URLENCODED : APPLICATION_JSON_UTF_8);
            }
        }
    }


    /**
     * 针对url中拼接 {参数} 的请求,替换url参数路径
     *
     * @param url
     * @param param
     * @return
     */
    public static String matcherUrl(String url, Map<String, String> param) {
        String regex = "(?=\\{).*?(\\})";
        String fieldRegex = "\\{|\\}";
        //创建一个模式对象
        Pattern pattern = Pattern.compile(regex);
        //匹配字符串中的已编译模式
        Matcher matcher = pattern.matcher(url);

        List<String> fields = new ArrayList<>();
        while (matcher.find()) {
            fields.add(matcher.group());
        }

        if (!fields.isEmpty()) {
            for (String field : fields) {
                url = url.replace(field, param.getOrDefault(field.replaceAll(fieldRegex, ""), ""));
            }
        }
        return url;
    }
}


3.3 数据库查询

package com.gemenyaofei.integration.app.utils;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.gemenyaofei.integration.app.constant.DbDataSourceConst;
import com.gemenyaofei.integration.app.dto.vo.IntegrateDatasetVO;
import com.gemenyaofei.integration.client.base.dto.data.DsTableDetailViewDTO;
import com.gemenyaofei.integration.client.base.dto.data.DsTableFieldViewDTO;
import com.gemenyaofei.integration.domain.common.exception.BizException;
import com.gemenyaofei.integration.domain.common.exception.ErrorCodeEnum;
import com.gemenyaofei.integration.domain.common.utils.DataSourceUtil;
import com.gemenyaofei.integration.domain.common.utils.StringUtils;
import com.gemenyaofei.integration.domain.model.entities.DataSourceDbInfoEntity;
import com.gemenyaofei.integration.domain.model.enums.DbTypeEnum;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.sql.*;
import java.util.*;

/**
 * @Author: XiaoKY
 * @Description: 数据源连接工具类
 * @Data: Created in 17:58 2022/7/18
 */
@Slf4j
public class IntegrateConnectionUtils {

    private IntegrateConnectionUtils() {

    }

    private static final String SQLSERVER = "SQLSERVER";


    /**
     * 根据连接信息获取connection
     */
    // TODO 优化为连接池可复用
    public static Connection getConnection(DataSourceDbInfoEntity db) {
        if (Objects.isNull(db)) {
            log.info("数据源信息为空");
            throw new BizException(ErrorCodeEnum.BIZ_DB_CONNECTION_FAIL);
        }
        Connection conn = null;
        try {
            /*//1.加载驱动
            Class.forName(db.getDriverType());
            //2.获取连接
            conn = DriverManager.getConnection(Objects.requireNonNull(getJdbcURL(db)), db.getUsername(), db.getPassword());
            return DbTypeEnum.ORACLE.getDriver().equals(db.getDriverType()) || conn.isValid(5) ? conn : null;*/
             conn = DataSourceUtil.createJdbcDataSource(db).getConnection();
        } catch (Exception e) {
            log.warn(DbDataSourceConst.CONNBUILDINFO, e);
        }
        return conn;
    }

    /**
     * 关闭connection
     */
    public static void closeConnection(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    /**
     * 根据连接信息获取JdbcURL
     */
    public static String getJdbcURL(DataSourceDbInfoEntity db) {
        try {
            DbTypeEnum dbType = DbTypeEnum.valueOf(db.getDbType());
            switch (dbType) {
                case ORACLE:
                    return DbDataSourceConst.ORACLEURL + db.getHost() + ":" + db.getPort() + "/" + db.getDbName();
                case MYSQL:
                    return DbDataSourceConst.MYSQLURL + db.getHost() + ":" + db.getPort() + "/" + db.getDbName() +
                            "?useUnicode=true&characterEncoding=" + db.getCodeType() +
                            "&autoReconnect=true&failOverReadOnly=true&serverTimezone=UTC&useSSL=false";
                case POSTGRESQL:
                    return DbDataSourceConst.PGURL + db.getHost() + ":" + db.getPort() + "/" + db.getDbName()
                            + "?currentSchema=" + db.getSchema() // 不用写schema.table
                            + "&tcpKeepAlive=true" // 长连接保持,避免连接关闭问题
                            + "&socketTimeout=600" // 等待数据库响应时最多等待 600 秒
                            + "&loginTimeout=600" // 建立连接时最多等待 600 秒
                            + "&connectTimeout=600"; // 连接等待时长,最多等待600s
                case SQLSERVER:
                    return DbDataSourceConst.SQLSERVERURL + db.getHost() + ":" + db.getPort() + ";databaseName=" + db.getDbName();
                default:
                    throw new BizException(ErrorCodeEnum.DATABASE_TYPE_NOT_EXISTS);
            }
        } catch (NullPointerException e) {
            log.warn(DbDataSourceConst.URLBUILDINFO, e);
        }
        return null;
    }

    /**
     * 得到数据源下所有的表和视图信息
     *
     * @param dbSource 数据源实体信息
     * @return
     * @throws Exception
     */
    public static List<IntegrateDatasetVO> getDBTables(DataSourceDbInfoEntity dbSource) {
        List<IntegrateDatasetVO> integrateDatasetVOList = new ArrayList<>();
        Connection conn = null;
        String catalog = null;
        try {
            conn = getConnection(dbSource);
            if (Objects.nonNull(conn)) {
                catalog = conn.getCatalog();
            } else {
                throw new BizException(ErrorCodeEnum.BIZ_DB_CONNECTION_FAIL);
            }
            DatabaseMetaData metaData = conn.getMetaData();
            ResultSet itr;
            if (StringUtils.isNotEmpty(dbSource.getSchema())) {
                itr = metaData.getTables(catalog, dbSource.getSchema(), null, new String[]{"VIEW", "TABLE"});
            } else {
                itr = metaData.getTables(catalog, conn.getSchema(), null, new String[]{"VIEW", "TABLE"});
            }

            while (itr.next()) {
                IntegrateDatasetVO integrateDatasetVO = new IntegrateDatasetVO();
                integrateDatasetVO.setTableName(itr.getString("TABLE_NAME"));
                integrateDatasetVO.setDescription(itr.getString("REMARKS"));
                integrateDatasetVOList.add(integrateDatasetVO);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException(ErrorCodeEnum.SYS_ERR);
        } finally {
            closeConnection(conn);
        }
        return integrateDatasetVOList;
    }

    /**
     * 获得指定表的字段信息
     *
     * @param tableName              表名
     * @param dataSourceDbInfoEntity 数据源实体信息
     * @return
     */
    public static DsTableDetailViewDTO getDBColumns(String tableName, DataSourceDbInfoEntity dataSourceDbInfoEntity) {
        ArrayList<DsTableFieldViewDTO> dsTableFields = new ArrayList<>();
        DsTableDetailViewDTO dsTableDetailDTO = new DsTableDetailViewDTO();
        Connection conn = null;
        String tableSql = buildFetchStatement(dataSourceDbInfoEntity, tableName, 1);
        log.info("所执行的SQL为:{}", tableSql);
        HashMap<String, String> sqlserverFieldDict = new HashMap<>();
        HashMap<String, String> fieldDict = new HashMap<>();
        try {
            conn = getConnection(dataSourceDbInfoEntity);
            // 获取sqlserver字段描述的sql语句
            String sqlPlus = buildSqlOfSqlServerFindFiledDesc(dataSourceDbInfoEntity, tableName);
            // 获取字段的描述
            if (DbTypeEnum.SQLSERVER.getDBType().equals(dataSourceDbInfoEntity.getDbType())) {
                findSqlServer2FieldDescExecute(sqlserverFieldDict, conn, sqlPlus);
            } else {
                fieldDict = getFieldDict(conn, tableName, fieldDict);
            }

            // 获取字段的主键字段名
            String primaryKey = getPrimaryKeyName(conn, tableName);
            List<DsTableFieldViewDTO> fieldMetaDTO =
                    getAndBuildFieldMetaData(conn, tableSql, primaryKey, dataSourceDbInfoEntity, sqlserverFieldDict, fieldDict, dsTableFields);
            dsTableDetailDTO.setTableName(tableName);
            dsTableDetailDTO.setDsTableFieldVOList(fieldMetaDTO);
        } catch (Exception e) {
            log.error("tableName:" + tableName + ",查询执行{},", e.getMessage());
        } finally {
            closeConnection(conn);
        }
        return dsTableDetailDTO;
    }

    /**
     * 构建表字段的DTO:字段主键,字段描述,是否必填,字段名...
     *
     * @param conn                   数据源连接信息
     * @param tableSql               查询表sql语句
     * @param primaryKey             主键字段名
     * @param dataSourceDbInfoEntity 数据源信息
     * @param sqlserverFieldDict     数据库类型为sqlserver的字段字典
     * @param fieldDict              数据库不为sqlserver的字段字典
     * @param dsTableFields          DsTableFieldViewDTO 列表
     * @return
     */
    private static List<DsTableFieldViewDTO> getAndBuildFieldMetaData(Connection conn,
                                                                      String tableSql,
                                                                      String primaryKey,
                                                                      DataSourceDbInfoEntity dataSourceDbInfoEntity,
                                                                      HashMap<String, String> sqlserverFieldDict,
                                                                      HashMap<String, String> fieldDict,
                                                                      ArrayList<DsTableFieldViewDTO> dsTableFields) throws SQLException {
        PreparedStatement statement = null;
        try {
            statement = conn.prepareStatement(tableSql);
            //从结果集元数据获取字段信息
            ResultSetMetaData resultMeta = statement.getMetaData();
            // 设置字段的主键
            for (int i = 0; i < resultMeta.getColumnCount(); i++) {
                DsTableFieldViewDTO dsTableFieldViewDTO = new DsTableFieldViewDTO();
                if (StringUtils.isNotEmpty(primaryKey) && primaryKey.equals(resultMeta.getColumnName(i + 1))) {
                    dsTableFieldViewDTO.setIsPrimary(1);
                } else {
                    dsTableFieldViewDTO.setIsPrimary(0);
                }
                dsTableFieldViewDTO.setFieldName(resultMeta.getColumnName(i + 1));
                dsTableFieldViewDTO.setFieldType(resultMeta.getColumnTypeName(i + 1));
                // 字段是否可为空:0不可为空,1可为空
                dsTableFieldViewDTO.setIsRequiredField(resultMeta.isNullable(i + 1) == 0 ? Boolean.TRUE : Boolean.FALSE);
                // 设置字段的描述
                if (SQLSERVER.equals(dataSourceDbInfoEntity.getDbType())) {
                    dsTableFieldViewDTO.setFieldDesc(sqlserverFieldDict.get(resultMeta.getColumnName(i + 1)));
                } else {
                    dsTableFieldViewDTO.setFieldDesc(fieldDict.get(resultMeta.getColumnName(i + 1)));

                }
                dsTableFields.add(dsTableFieldViewDTO);
            }
        } catch (Exception e) {
            log.info("构建表详情信息失败:[{}]", e.getMessage());
            throw new BizException(ErrorCodeEnum.SYS_ERR);
        } finally {
            if (Objects.nonNull(statement)) {
                statement.close();
            }
        }
        return dsTableFields;
    }

    /**
     * 获得表的字段字典map: 键为字段名,值为字段描述
     *
     * @param conn      数据源连接信息
     * @param tableName 表名
     * @param fieldDict 字段初始化map字典
     * @return
     */
    private static HashMap<String, String> getFieldDict(Connection conn, String tableName, HashMap<String, String> fieldDict) {
        ResultSet columns = null;
        try {
            columns = conn.getMetaData().getColumns(conn.getCatalog(), "%", tableName, "%");
            // 获得字段的描述字典
            while (columns.next()) {
                String columnName = columns.getString("COLUMN_NAME");
                String remarks = columns.getString("REMARKS");
                if (StringUtils.isEmpty(remarks)) {
                    fieldDict.put(columnName, null);
                } else {
                    fieldDict.put(columnName, remarks);
                }
            }
        } catch (Exception e) {
            log.info("获取字段描述信息异常:[{}]", e.getMessage());
            throw new BizException(ErrorCodeEnum.SYS_ERR);
        }
        log.info("表[{}]的字段字典为:[{}]", tableName, JSON.toJSONString(fieldDict));
        return fieldDict;
    }

    /**
     * 得到表的主键字段名
     *
     * @param conn      连接信息
     * @param tableName 表名
     * @return
     */
    private static String getPrimaryKeyName(Connection conn, String tableName) {
        ResultSet primaryKeyResult = null;
        DatabaseMetaData dbMeta = null;
        String primaryKey = null;
        try {
            dbMeta = conn.getMetaData();
            // 得到字段的主键信息
            primaryKeyResult = dbMeta.getPrimaryKeys(conn.getCatalog(), conn.getSchema(), tableName);
            while (primaryKeyResult.next()) {
                primaryKey = primaryKeyResult.getString("COLUMN_NAME");
                log.info("表[{}]的字段主键名为[{}]", tableName, primaryKey);
            }
        } catch (Exception e) {
            log.info("查找表[{}]的主键信息未找到", tableName);
            throw new BizException(ErrorCodeEnum.SYS_ERR);
        }
        return primaryKey;
    }

    /**
     * 数据库类型为sqlserver时,获得表字段的描述信息
     *
     * @param fieldDescMap 键为字段名,值为字段描述
     * @param conn         数据源连接
     * @param sqlPlus      需要执行的sql
     */
    private static void findSqlServer2FieldDescExecute(HashMap<String, String> fieldDescMap, Connection conn, String sqlPlus) throws SQLException {
        PreparedStatement findFieldDesc = null;
        try {
            findFieldDesc = conn.prepareStatement(sqlPlus);
            ResultSet resultSet = findFieldDesc.executeQuery();
            while (resultSet.next()) {
                fieldDescMap.put(resultSet.getString("FIELD"), resultSet.getString("COMMENT"));
            }
        } catch (Exception e) {
            log.info("当前数据库类型为sqlserver,获取字段描述信息失败:[{}]", e.getMessage());
            throw new BizException(ErrorCodeEnum.SYS_ERR);
        } finally {
            if (Objects.nonNull(findFieldDesc)) {
                findFieldDesc.close();
            }
        }
    }

    /**
     * 当数据库类型为sqlserver时,根据下面的sql获取字段表述信息
     *
     * @param dataSourceDbInfoEntity 数据源信息
     * @param tableName              表名
     * @return
     */
    private static String buildSqlOfSqlServerFindFiledDesc(DataSourceDbInfoEntity dataSourceDbInfoEntity, String tableName) {
        if (SQLSERVER.equals(dataSourceDbInfoEntity.getDbType())) {
            String sqlPlus = " SELECT\n" +
                    "a.name FIELD,\n" +
                    "CASE\n" +
                    "\n" +
                    "WHEN EXISTS (\n" +
                    "SELECT\n" +
                    "1 \n" +
                    "FROM\n" +
                    "sysobjects \n" +
                    "WHERE\n" +
                    "xtype = 'PK' \n" +
                    "AND parent_obj = a.id \n" +
                    "AND name IN ( SELECT name FROM sysindexes WHERE indid IN ( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid = a.colid ) ) \n" +
                    ") THEN\n" +
                    "1 ELSE NULL \n" +
                    "END \"KEY\",\n" +
                    "b.name TYPE,\n" +
                    "COLUMNPROPERTY( a.id, a.name, 'PRECISION' ) LENGTH,\n" +
                    "CONVERT(nvarchar(50),isnull( d.[value], '' )) COMMENT \n" +
                    "FROM\n" +
                    "syscolumns a\n" +
                    "LEFT JOIN systypes b ON a.xusertype= b.xusertype\n" +
                    "INNER JOIN sysobjects c ON a.id= c.id \n" +
                    "AND c.xtype= 'U' \n" +
                    "AND c.name<> 'dtproperties'\n" +
                    "LEFT JOIN sys.extended_properties d ON a.id= d.major_id \n" +
                    "AND a.colid= d.minor_id \n" +
                    "WHERE\n" +
                    "c.name= '" + tableName + "'";
            log.info("生成的sql语句为:[{}]", sqlPlus);
            return sqlPlus;
        } else {
            return null;
        }
    }

    /**
     * 执行sql查询
     *
     * @param sql  需要执行的sql信息
     * @param conn 连接信息
     * @return
     */
    public static ResultSet executeSQL(String sql, Connection conn) throws SQLException {
        ResultSet res = null;
        Statement statement = null;

        try {
            if (conn.isClosed()) {
                log.info("conn is closed");
            }
            statement = conn.createStatement();
            res = statement.executeQuery(sql);
        } catch (SQLException e) {
            log.info("查询执行[{}]", e.getMessage());
        }
        return res;
    }

    public static String buildFetchStatement(DataSourceDbInfoEntity dataSourceDbInfoEntity, String dsTableName, Integer rowCount) {
        StringBuilder sql = new StringBuilder();
        String schema = Assert.notNull(dataSourceDbInfoEntity).getSchema();
        switch (dataSourceDbInfoEntity.getDbType()) {
            case "POSTGRESQL":
                sql.append("SELECT * FROM ").append(schema).append(".\"").append(dsTableName).append("\" limit ").append(rowCount);
                break;
            case "SQLSERVER":
                sql.append("SELECT TOP ").append(rowCount).append(" * FROM ").append(schema).append(".").append(dsTableName);
                break;
            case "ORACLE":
                sql.append("SELECT * FROM (SELECT * FROM  ").append(schema == null ? "" : schema + ".").append(dsTableName)
                        .append(" ) WHERE ROWNUM > 0 AND ROWNUM <= ").append(rowCount);
                break;
            default:
                break;
        }
        return new String(sql);
    }

    public static Map<String, String> fieldSearchSQL(DataSourceDbInfoEntity dataSourceDbInfoEntity, String dsTableName) {
        String sql = buildFetchStatement(dataSourceDbInfoEntity, dsTableName, 1);
        log.info("示例数据查询sql语句:[{}]", JSON.toJSONString(sql));
        List<Map<String, String>> sampleDataList = sampleData(dataSourceDbInfoEntity, sql);
        return sampleDataList!=null && sampleDataList.size() == 1 ? sampleDataList.get(0): new HashMap<>();
    }

    public static List<Map<String, String>> sampleData(DataSourceDbInfoEntity dataSourceDbInfoEntity, String sql) {
        List<Map<String, String>> resultList = Lists.newLinkedList();

        try (Connection conn = getConnection(dataSourceDbInfoEntity)){
            int columnCount = 0;
            ResultSet res = IntegrateConnectionUtils.executeSQL(sql, conn);
            ResultSetMetaData rsmd = res.getMetaData();
            columnCount = rsmd.getColumnCount();
            while(res.next()) {
                Map<String, String> resultMap = new HashMap<>();
                for (int i = 1; i <= columnCount; i++) {
                    try {
                        resultMap.put(rsmd.getColumnName(i), res.getString(i));
                    } catch (Exception e) {
                        resultMap.put(rsmd.getColumnName(i), null);
                    }
                }
                resultList.add(resultMap);
            }
        } catch (Exception e) {
            log.info("获取示例数据异常:", e.getMessage());
        }
        return resultList;
    }
}

3.4 Spring Bean的工具类

package com.gemenyaofei.metabase.model.core.utils;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.util.Map;

/**
 * @Description:
 * @author:ljh
 * @create: 2023-10-16 16:25
 */
@Component
public final class SpringUtils implements BeanFactoryPostProcessor {

    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws BeansException
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws BeansException
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getAliases(name);
    }

    /**
     * 获取aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        return (T) AopContext.currentProxy();
    }

    /**
     * 根据注解类型获取bean
     *
     * @param clz 注解类型
     * @return bean集合
     */
    public static Map<String, Object> getBeansByAnnotation(Class<? extends Annotation> clz) {
        return beanFactory.getBeansWithAnnotation(clz);
    }
}

3.5 线程休眠工具类

package com.gemenyaofei.metabase.lang.util;

import java.util.concurrent.TimeUnit;

public class SleepUtil {
    public static void  sleepSecond(long timeout)
    {
        try {
            TimeUnit.SECONDS.sleep(timeout);
        } catch (Exception e) {

        }
    }

    public static void  sleepMillisecond(long timeout)
    {
        try {
            TimeUnit.MILLISECONDS.sleep(timeout);
        } catch (Exception e) {

        }
    }
}




四、常用信息获取工具

4.1 获取本地ip

package com.gemenyaofei.metabase.sync.core.util;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * @ClassName: NetUtils
 * @Description: 获取当前ip地址工具
 * @author  ljh
 * @date 2022年09月05日
 * @Copyright gemenyaofei.com
 */
public class NetUtils {

    private  final static Logger logger = LoggerFactory.getLogger(NetUtils.class);

    /**
     * 获取本地ip
     * @return  ip地址
     */
    public static String getLocalAddress() {
        try {
            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
            List<String> ipv4Result = new ArrayList<String>();
            List<String> ipv6Result = new ArrayList<String>();
            while (enumeration.hasMoreElements()) {
                final NetworkInterface networkInterface = enumeration.nextElement();
                final Enumeration<InetAddress> en = networkInterface.getInetAddresses();
                while (en.hasMoreElements()) {
                    final InetAddress address = en.nextElement();
                    if (!address.isLoopbackAddress()) {
                        if (address instanceof Inet6Address) {
                            ipv6Result.add(normalizeHostAddress(address));
                        } else {
                            ipv4Result.add(normalizeHostAddress(address));
                        }
                    }
                }
            }

            // prefer ipv4
            if (!ipv4Result.isEmpty()) {
                for (String ip : ipv4Result) {
                    if (ip.startsWith("127.0")
//                            || ip.startsWith("192.168")
                     ) {
                        continue;
                    }

                    return ip;
                }

                return ipv4Result.get(ipv4Result.size() - 1);
            } else if (!ipv6Result.isEmpty()) {
                return ipv6Result.get(0);
            }
            final InetAddress localHost = InetAddress.getLocalHost();
            return normalizeHostAddress(localHost);
        } catch (Exception e) {
            logger.error("Failed to obtain local address", e);
        }

        return null;
    }

    /**
     * 将ip地址转换为字符
     * @param localHost   ip详情
     * @return  返回字符ip
     */
    public static String normalizeHostAddress(final InetAddress localHost) {
        if (localHost instanceof Inet6Address) {
            return "[" + localHost.getHostAddress() + "]";
        } else {
            return localHost.getHostAddress();
        }
    }

}






举报

相关推荐

0 条评论