Java常用工具类整合

一、字符串相关


StringUtils

  1. isEmpty()    判断字符串是否为空(在cs为null,""的情况下返回true)

        public static boolean isEmpty(final CharSequence cs) {
            return cs == null || cs.length() == 0;
        } 
  2. isBlank()    判断字符串是否为空(在cs为null,"","  "的情况下返回true)
        public static boolean isBlank(final CharSequence cs) {
            int strLen;
            if (cs == null || (strLen = cs.length()) == 0) {
                return true;
            }
            for (int i = 0; i < strLen; i++) {
                if (!Character.isWhitespace(cs.charAt(i))) {
                    return false;
                }
            }
            return true;
        }
  3. equals()   判断两个字符串是否为空,两者都是null也会返回true,区分大小写
        public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
            if (cs1 == cs2) {
                return true;
            }
            if (cs1 == null || cs2 == null) {
                return false;
            }
            if (cs1.length() != cs2.length()) {
                return false;
            }
            if (cs1 instanceof String && cs2 instanceof String) {
                return cs1.equals(cs2);
            }
            // Step-wise comparison
            final int length = cs1.length();
            for (int i = 0; i < length; i++) {
                if (cs1.charAt(i) != cs2.charAt(i)) {
                    return false;
                }
            }
            return true;
        }
  4. join()    合并数组为单一字符串,可传分隔符
  5. spit()    分割字符串
  6. trimToNull:trim后为空字符串则转换为null
  7. replace:替换字符串
  8. capitalize:首字符大写

二、I/O相关

  1. org.apache.commons.io.IOUtils

    closeQuietly:关闭一个IO流、socket、或者selector且不抛出异常,通常放在finally块
    toString:转换IO流、 Uri、 byte[]为String
    copy:IO流数据复制,从输入流写到输出流中,最大支持2GB
    toByteArray:从输入流、URI获取byte[]
    write:把字节. 字符等写入输出流
    toInputStream:把字符转换为输入流
    readLines:从输入流中读取多行数据,返回List<String>
    copyLarge:同copy,支持2GB以上数据的复制
    lineIterator:从输入流返回一个迭代器,根据参数要求读取的数据量,全部读取,如果数据不够,则失败

  2. org.apache.commons.io.FileUtils


    readFileToString:以字符形式读取文件内容

    deleteQueitly:删除文件或文件夹且不会抛出异常
    copyFile:复制文件
    writeStringToFile:把字符写到目标文件,如果文件不存在,则创建
    forceMkdir:强制创建文件夹,如果该文件夹父级目录不存在,则创建父级
    write:把字符写到指定文件中
    listFiles:列举某个目录下的文件(根据过滤器)
    copyDirectory:复制文件夹
    forceDelete:强制删除文件

  3. org.apache.commons.io.FilenameUtils


     

    getExtension:返回文件后缀名
    getBaseName:返回文件名,不包含后缀名
    getName:返回文件全名
    concat:按命令行风格组合文件路径(详见方法注释)
    removeExtension:删除后缀名
    normalize:使路径正常化
    wildcardMatch:匹配通配符
    seperatorToUnix:路径分隔符改成unix系统格式的,即/
    getFullPath:获取文件路径,不包括文件名
    isExtension:检查文件后缀名是不是传入参数(List<String>)中的一个

三、集合/数组相关

  1.  org.apache.commons.lang3.ArrayUtils


    contains:是否包含某字符串

    addAll:添加整个数组
    clone:克隆一个数组
    isEmpty:是否空数组
    add:向数组添加元素
    subarray:截取数组
    indexOf:查找某个元素的下标
    isEquals:比较数组是否相等
    toObject:基础类型数据数组转换为对应的Object数组

  2.   org.apache.commons.collections.CollectionUtils


     isEmpty:是否为空

    select:根据条件筛选集合元素
    transform:根据指定方法处理集合元素,类似List的map()
    filter:过滤元素,类似List的filter()
    find:基本和select一样
    collect:和transform 差不多一样,但是返回新数组
    forAllDo:调用每个元素的指定方法
    isEqualCollection:判断两个集合是否一致 

四、具体实例

Java自带工具方法:

 1、List集合拼接成以逗号分隔的字符串

// 如何把list集合拼接成以逗号分隔的字符串 a,b,c 
List<String> list = Arrays.asList("a", "b", "c");  
// 第一种方法,可以用stream流 
String join = list.stream().collect(Collectors.joining(","));  
System.out.println(join); // 输出 a,b,c 
// 第二种方法,其实String也有join方法可以实现这个功能 
String join = String.join(",", list);  
System.out.println(join); // 输出 a,b,c 

2、比较两个字符串是否相等,忽略大小写

if (strA.equalsIgnoreCase(strB)) {  
  System.out.println("相等");  
}

3、比较两个对象是否相等【当我们用 equals 比较两个对象是否相等的时候,还需要对左边的对象进行判空,不然可能会报空指针异常,我们可以用 java.util 包下 Objects 封装好的比较是否相等的方法】

Objects.equals(strA, strB);

4、两个 List 集合取交集

List<String> list1 = new ArrayList<>();  
list1.add("a");  
list1.add("b");  
list1.add("c");  
List<String> list2 = new ArrayList<>();  
list2.add("a");  
list2.add("b");  
list2.add("d");  
list1.retainAll(list2);  
System.out.println(list1);
// 输出[a, b]

apache commons 工具类库:

5、包装临时对象【当一个方法需要返回两个及以上字段时,我们一般会封装成一个临时对象返回,现在有了 Pair 和 Triple 就不需要了】

// 返回两个字段 
ImmutablePair<Integer, String> pair = ImmutablePair.of(1, "yideng");  
System.out.println(pair.getLeft() + "," + pair.getRight()); // 输出 1,yideng 
// 返回三个字段 
ImmutableTriple<Integer, String, Date> triple = ImmutableTriple.of(1, "yideng", new Date());  
System.out.println(triple.getLeft() + "," + triple.getMiddle() + "," + triple.getRight()); // 输出 1,yideng,Wed Apr 07 23:30:00 CST 2021

6、commons-io 文件流处理

File file = new File("demo1.txt");  
// 读取文件 
List<String> lines = FileUtils.readLines(file, Charset.defaultCharset());  
// 写入文件 
FileUtils.writeLines(new File("demo2.txt"), lines);  
// 复制文件 
FileUtils.copyFile(srcFile, destFile); 

7、common-beanutils 操作对象

// 设置对象属性
User user = new User();  
BeanUtils.setProperty(user, "id", 1);  
BeanUtils.setProperty(user, "name", "yideng");  
System.out.println(BeanUtils.getProperty(user, "name")); // 输出 yideng 
System.out.println(user); // 输出 {"id":1,"name":"yideng"}

// 对象和 map 互转
// 对象转map 
Map<String, String> map = BeanUtils.describe(user);  
System.out.println(map); // 输出 {"id":"1","name":"yideng"} 
// map转对象 
User newUser = new User();  
BeanUtils.populate(newUser, map);  
System.out.println(newUser); // 输出 {"id":1,"name":"yideng"}

Google Guava 工具类库

8、创建集合

List<String> list = Lists.newArrayList();  
List<Integer> list = Lists.newArrayList(1, 2, 3);  
// 反转list 
List<Integer> reverse = Lists.reverse(list);  
System.out.println(reverse); // 输出 [3, 2, 1] 
// list集合元素太多,可以分成若干个集合,每个集合10个元素 
List<List<Integer>> partition = Lists.partition(list, 10);  
  
Map<String, String> map = Maps.newHashMap();  
Set<String> set = Sets.newHashSet(); 

9、Multimap 一个 key 可以映射多个 value 的 HashMap

Multimap<String, Integer> map = ArrayListMultimap.create();  
map.put("key", 1);  
map.put("key", 2);  
Collection<Integer> values = map.get("key");  
System.out.println(map); // 输出 {"key":[1,2]} 
// 还能返回你以前使用的臃肿的Map 
Map<String, Collection<Integer>> collectionMap = map.asMap(); 

10、BiMap 一种连 value 也不能重复的 HashMap

BiMap<String, String> biMap = HashBiMap.create();  
// 如果value重复,put方法会抛异常,除非用forcePut方法 
biMap.put("key","value");  
System.out.println(biMap); // 输出 {"key":"value"} 
// 既然value不能重复,何不实现个翻转key/value的方法,已经有了 
BiMap<String, String> inverse = biMap.inverse();  
System.out.println(inverse); // 输出 {"value":"key"}

11、Table 一种有两个 key 的 HashMap

// 一批用户,同时按年龄和性别分组 
Table<Integer, String, String> table = HashBasedTable.create();  
table.put(18, "男", "yideng");  
table.put(18, "女", "Lily");  
System.out.println(table.get(18, "男")); // 输出 yideng 
// 这其实是一个二维的Map,可以查看行数据 
Map<String, String> row = table.row(18);  
System.out.println(row); // 输出 {"男":"yideng","女":"Lily"} 
// 查看列数据 
Map<Integer, String> column = table.column("男");  
System.out.println(column); // 输出 {18:"yideng"}

12、Multiset 一种用来计数的 Set

Multiset<String> multiset = HashMultiset.create();  
multiset.add("apple");  
multiset.add("apple");  
multiset.add("orange");  
System.out.println(multiset.count("apple")); // 输出 2 
// 查看去重的元素 
Set<String> set = multiset.elementSet();  
System.out.println(set); // 输出 ["orange","apple"] 
// 还能查看没有去重的元素 
Iterator<String> iterator = multiset.iterator();  
while (iterator.hasNext()) {  
    System.out.println(iterator.next());  
}  
// 还能手动设置某个元素出现的次数 
multiset.setCount("apple", 5);  

13、Java8 时间处理类

package com.ai.oss.utils;

import org.apache.commons.compress.utils.Lists;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.List;

/**
 * java1.8 的新特性,解决SimpleDateFormat的线程问题
 * Instant代替 Date,LocalDateTime代替 Calendar
 * 注意:如果是共享变量,则可能会出现线程问题。
 * @author helin
 * @date 2021/5/10 11:02
 * @description 基于Java8的Lambda日期处理工具类
 */
public class DataUtil {

    // 时间元素
    private static final String YEAR = "year";
    private static final String MONTH = "month";
    private static final String WEEK = "week";
    private static final String DAY = "day";
    private static final String HOUR = "hour";
    private static final String MINUTE = "minute";
    private static final String SECOND = "second";

    // 星期元素
    private static final String MONDAY = "MONDAY";// 星期一
    private static final String TUESDAY = "TUESDAY";// 星期二
    private static final String WEDNESDAY = "WEDNESDAY";// 星期三
    private static final String THURSDAY = "THURSDAY";// 星期四
    private static final String FRIDAY = "FRIDAY";// 星期五
    private static final String SATURDAY = "SATURDAY";// 星期六
    private static final String SUNDAY = "SUNDAY";// 星期日

    // 根据指定格式显示日期和时间
    private static final DateTimeFormatter yyyyMMdd_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter yyyyMMddHH_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");
    private static final DateTimeFormatter yyyyMMddHHmm_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    private static final DateTimeFormatter yyyyMMddHHmmss_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter HHmmss_EN = DateTimeFormatter.ofPattern("HH:mm:ss");
    private static final DateTimeFormatter yyyyMMdd_CN = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    private static final DateTimeFormatter yyyyMMddHH_CN = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时");
    private static final DateTimeFormatter yyyyMMddHHmm_CN = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分");
    private static final DateTimeFormatter yyyyMMddHHmmss_CN = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒");
    private static final DateTimeFormatter HHmmss_CN = DateTimeFormatter.ofPattern("HH时mm分ss秒");

    // 本地时间显示格式:区分中文和外文显示
    private static final DateTimeFormatter shotDate = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
    private static final DateTimeFormatter fullDate = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
    private static final DateTimeFormatter longDate = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
    private static final DateTimeFormatter mediumDate = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);

    /**
     * 获取当前日期
     * @return yyyy-MM-dd
     */
    public static String getNowDate_EN() {
        return String.valueOf(LocalDate.now());
    }

    /**
     * 获取当前日期
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String getNowTime_EN() {
        return LocalDateTime.now().format(yyyyMMddHHmmss_EN);
    }

    /**
     * 获取当前日期
     * @return yyyy-MM-dd HH
     */
    public static String getNowTime_EN_yMdH() {
        return LocalDateTime.now().format(yyyyMMddHH_EN);
    }

    /**
     * 获取当前日期
     * @return yyyy年MM月dd日
     */
    public static String getNowTime_CN_yMdH() {
        return LocalDateTime.now().format(yyyyMMddHH_CN);
    }

    /**
     * 获取当前日期
     * @return yyyy-MM-dd HH:mm
     */
    public static String getNowTime_EN_yMdHm() {
        return LocalDateTime.now().format(yyyyMMddHHmm_EN);
    }

    /**
     * 获取当前日期
     * @return yyyy年MM月dd日HH时mm分
     */
    public static String getNowTime_CN_yMdHm() {
        return LocalDateTime.now().format(yyyyMMddHHmm_CN);
    }

    /**
     * 获取当前日期
     * @return HH时mm分ss秒
     */
    public static String getNowTime_CN_HHmmss() {
        return LocalDateTime.now().format(HHmmss_CN);
    }

    /**
     * 根据日期格式,获取当前时间
     *
     * @param formatStr 日期格式<br>
     *        <li>yyyy</li>
     *        <li>yyyy-MM-dd</li>
     *        <li>yyyy-MM-dd HH:mm:ss</li>
     *        <li>HH:mm:ss</li>
     */
    public static String getTime(String formatStr) {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(formatStr));
    }

    /**
     * 获取当前日期
     * @return  yyyy年mm月dd日
     */
    public static String getNowDate_CN() {
        return LocalDate.now().format(yyyyMMdd_CN);
    }

    /**
     * 获取当前日期
     * @return yyyy年MM月dd日HH时mm分ss秒
     */
    public static String getNowTime_CN() {
        return LocalDateTime.now().format(yyyyMMddHHmmss_CN);
    }

    /**
     * 简写本地当前日期:yy-M-dd
     * 例如:21-5-10为2021年05月10日
     * @return yy-M-dd
     */
    public static String getNowLocalTime_shot() {
        return LocalDateTime.now().format(shotDate);
    }

    /**
     *  根据当地日期显示格式:yyyy年M月dd日 星期几
     * @return 例如:2021年5月10日 星期一
     */
    public static String getNowLocalTime_full() {
        return LocalDateTime.now().format(fullDate);
    }

    /**
     *  根据当地显示日期格式:yyyy年M月dd日
     * @return 例如:2021年5月10日
     */
    public static String getNowLocalTime_long() {
        return LocalDateTime.now().format(longDate);
    }

    /**
     * 根据当地显示日期格式:yyyy-M-dd
     * @return 例如:2021-5-10
     */
    public static String getNowLocalTime_medium() {
        return LocalDateTime.now().format(mediumDate);
    }

    /**
     * 获取当前日期的节点时间(年,月,周,日,时,分,秒)
     *
     * @param node 日期中的节点元素(年,月,周,日,时,分,秒)
     * @return 节点数字,如创建此方法的时间:年 2019,月 3,日 30,周 6
     */
    public static Integer getNodeTime(String node) {
        System.out.println();
        LocalDateTime today = LocalDateTime.now();
        int resultNode;
        switch (node) {
            case YEAR:
                resultNode = today.getYear();
                break;
            case MONTH:
                resultNode = today.getMonthValue();
                break;
            case WEEK:
                resultNode = transformWeekEN2Num(String.valueOf(today.getDayOfWeek()));
                break;
            case DAY:
                resultNode = today.getDayOfMonth();
                break;
            case HOUR:
                resultNode = today.getHour();
                break;
            case MINUTE:
                resultNode = today.getMinute();
                break;
            case SECOND:
                resultNode = today.getSecond();
                break;
            default:
                // 当前日期是当前年的第几天。例如:2019/1/3是2019年的第三天
                resultNode = today.getDayOfYear();
                break;
        }
        return resultNode;
    }

    /**
     * 将英文星期转换成数字
     *
     * @param enWeek 英文星期
     * @return int,如果数字小于0,则检查,看是否输入错误 or 入参为null
     */
    public static int transformWeekEN2Num(String enWeek) {
        if (MONDAY.equals(enWeek)) {
            return 1;
        } else if (TUESDAY.equals(enWeek)) {
            return 2;
        } else if (WEDNESDAY.equals(enWeek)) {
            return 3;
        } else if (THURSDAY.equals(enWeek)) {
            return 4;
        } else if (FRIDAY.equals(enWeek)) {
            return 5;
        } else if (SATURDAY.equals(enWeek)) {
            return 6;
        } else if (SUNDAY.equals(enWeek)) {
            return 7;
        } else {
            return -1;
        }
    }

    /**
     * 获取当前日期之后(之后)的节点事件<br>
     * <ul>
     * 比如当前时间为:2019-03-30 10:20:30
     * </ul>
     * <li>node="hour",num=5L:2019-03-30 15:20:30</li>
     * <li>node="day",num=1L:2019-03-31 10:20:30</li>
     * <li>node="year",num=1L:2020-03-30 10:20:30</li>
     *
     * @param node 节点元素(“year”,"month","week","day","huor","minute","second")
     * @param num 第几天(+:之后,-:之前)
     * @return 之后或之后的日期
     */
    public static String getAfterOrPreNowTime(String node, Long num) {
        LocalDateTime now = LocalDateTime.now();
        if (HOUR.equals(node)) {
            return now.plusHours(num).format(yyyyMMddHHmmss_EN);
        } else if (DAY.equals(node)) {
            return now.plusDays(num).format(yyyyMMddHHmmss_EN);
        } else if (WEEK.equals(node)) {
            return now.plusWeeks(num).format(yyyyMMddHHmmss_EN);
        } else if (MONTH.equals(node)) {
            return now.plusMonths(num).format(yyyyMMddHHmmss_EN);
        } else if (YEAR.equals(node)) {
            return now.plusYears(num).format(yyyyMMddHHmmss_EN);
        } else if (MINUTE.equals(node)) {
            return now.plusMinutes(num).format(yyyyMMddHHmmss_EN);
        } else if (SECOND.equals(node)) {
            return now.plusSeconds(num).format(yyyyMMddHHmmss_EN);
        } else {
            return "Node is Error!";
        }
    }

    /**
     * 获取与当前日期相距num个之后(之前)的日期<br>
     * <ul>
     * 比如当前时间为:2019-03-30 10:20:30的格式日期
     * <li>node="hour",num=5L:2019-03-30 15:20:30</li>
     * <li>node="day",num=1L:2019-03-31 10:20:30</li>
     * <li>node="year",num=1L:2020-03-30 10:20:30</li>
     * </ul>
     *
     * @param dtf 格式化当前时间格式(dtf = yyyyMMddHHmmss_EN)
     * @param node 节点元素(“year”,"month","week","day","huor","minute","second")
     * @param num (+:之后,-:之前)
     * @return 之后之前的日期
     */
    public static String getAfterOrPreNowTimePlus(DateTimeFormatter dtf, String node, Long num) {
        LocalDateTime now = LocalDateTime.now();
        if (HOUR.equals(node)) {
            return now.plusHours(num).format(dtf);
        } else if (DAY.equals(node)) {
            return now.plusDays(num).format(dtf);
        } else if (WEEK.equals(node)) {
            return now.plusWeeks(num).format(dtf);
        } else if (MONTH.equals(node)) {
            return now.plusMonths(num).format(dtf);
        } else if (YEAR.equals(node)) {
            return now.plusYears(num).format(dtf);
        } else if (MINUTE.equals(node)) {
            return now.plusMinutes(num).format(dtf);
        } else if (SECOND.equals(node)) {
            return now.plusSeconds(num).format(dtf);
        } else {
            return "Node is Error!";
        }
    }

    /**
     * 当前时间的hour,minute,second之后(之前)的时刻
     *
     * @param node 时间节点元素(hour,minute,second)
     * @param num 之后(之后)多久时,分,秒(+:之后,-:之前)
     * @return HH:mm:ss 字符串
     */
    public static String getAfterOrPreNowTimeSimp(String node, Long num) {
        LocalTime now = LocalTime.now();
        if (HOUR.equals(node)) {
            return now.plusHours(num).format(HHmmss_EN);
        } else if (MINUTE.equals(node)) {
            return now.plusMinutes(num).format(HHmmss_EN);
        } else if (SECOND.equals(node)) {
            return now.plusSeconds(num).format(HHmmss_EN);
        } else {
            return "Node is Error!";
        }
    }

    /**
     * 检查重复事件,比如生日
     *
     * @param dayOfMonth month
     */
    public static boolean isBirthday(int month, int dayOfMonth) {
        MonthDay birthDay = MonthDay.of(month, dayOfMonth);
        MonthDay curMonthDay = MonthDay.from(LocalDate.now());// MonthDay只存储了月、日。
        return birthDay.equals(curMonthDay);
    }

    /**
     * 获取当前日期第index日之后(之前)的日期(yyyy-MM-dd)
     *
     * @param index 第index天
     * @return 日期字符串:yyyy-MM-dd
     */
    public static String getAfterOrPreDayDate(int index) {
        return LocalDate.now().plus(index, ChronoUnit.DAYS).format(yyyyMMdd_EN);
    }

    /**
     * 获取当前日期第index周之前(之后)的日期(yyyy-MM-dd)
     * @param index 第index周(+:之后,-:之前)
     * @return 日期字符串:yyyy-MM-dd
     */
    public static String getAfterOrPreWeekDate(int index) {
        return LocalDate.now().plus(index, ChronoUnit.WEEKS).format(yyyyMMdd_EN);
    }

    /**
     * 获取当前日期第index月之前(之后)的日期(yyyy-MM-dd)
     *
     * @param index 第index月(+:之后,-:之前)
     * @return 日期字符串:yyyy-MM-dd
     */
    public static String getAfterOrPreMonthDate(int index) {
        return LocalDate.now().plus(index, ChronoUnit.MONTHS).format(yyyyMMdd_EN);
    }

    /**
     * 获取当前日期第index年之前(之后)的日期(yyyy-MM-dd)
     *
     * @param index 第index年(+:之后,-:之前)
     * @return 日期字符串:yyyy-MM-dd
     */
    public static String getAfterOrPreYearDate(int index) {
        return LocalDate.now().plus(index, ChronoUnit.YEARS).format(yyyyMMdd_EN);
    }

    /**
     * 获取指定日期之前之后的第index的日,周,月,年的日期
     *
     * @param date 指定日期格式:yyyy-MM-dd
     * @param node 时间节点元素(日周月年)
     * @param index 之前之后第index个日期
     * @return yyyy-MM-dd 日期字符串
     */
    public static String getAfterOrPreDate(String date, String node, int index) {
        date = date.trim();
        if (DAY.equals(node)) {
            return LocalDate.parse(date).plus(index, ChronoUnit.DAYS).format(yyyyMMdd_EN);
        } else if (WEEK.equals(node)) {
            return LocalDate.parse(date).plus(index, ChronoUnit.WEEKS).format(yyyyMMdd_EN);
        } else if (MONTH.equals(node)) {
            return LocalDate.parse(date).plus(index, ChronoUnit.MONTHS).format(yyyyMMdd_EN);
        } else if (YEAR.equals(node)) {
            return LocalDate.parse(date).plus(index, ChronoUnit.YEARS).format(yyyyMMdd_EN);
        } else {
            return "Wrong date format!";
        }
    }

    /**
     * 检测:输入年份是否是闰年?
     *
     * @param date 日期格式:yyyy-MM-dd
     * @return true:闰年,false:平年
     */
    public static boolean isLeapYear(String date) {
        return LocalDate.parse(date.trim()).isLeapYear();
    }

    /**
     * 计算两个日期字符串之间相差多少个周期(天,月,年)
     *
     * @param date1 yyyy-MM-dd
     * @param date2 yyyy-MM-dd
     * @param node 三者之一:(day,month,year)
     * @return 相差多少周期
     */
    public static int peridCount(String date1, String date2, String node) {
        date1 = date1.trim();
        date2 = date2.trim();
        if (DAY.equals(node)) {
            return Period.between(LocalDate.parse(date1), LocalDate.parse(date2)).getDays();
        } else if (MONTH.equals(node)) {
            return Period.between(LocalDate.parse(date1), LocalDate.parse(date2)).getMonths();
        } else if (YEAR.equals(node)) {
            return Period.between(LocalDate.parse(date1), LocalDate.parse(date2)).getYears();
        } else {
            return 0;
        }
    }

    /**
     * 切割日期。按照周期切割成小段日期段。例如: <br>
     *
     * @param startDate 开始日期(yyyy-MM-dd)
     * @param endDate 结束日期(yyyy-MM-dd)
     * @param period 周期(天,周,月,年)
     * @return 切割之后的日期集合
     *          <li>startDate="2019-02-28",endDate="2019-03-05",period="day"</li>
     *          <li>结果为:[2019-02-28, 2019-03-01, 2019-03-02, 2019-03-03, 2019-03-04, 2019-03-05]</li><br>
     *          <li>startDate="2019-02-28",endDate="2019-03-25",period="week"</li>
     *          <li>结果为:[2019-02-28,2019-03-06, 2019-03-07,2019-03-13, 2019-03-14,2019-03-20,
     *          2019-03-21,2019-03-25]</li><br>
     *          <li>startDate="2019-02-28",endDate="2019-05-25",period="month"</li>
     *          <li>结果为:[2019-02-28,2019-02-28, 2019-03-01,2019-03-31, 2019-04-01,2019-04-30,
     *          2019-05-01,2019-05-25]</li><br>
     *          <li>startDate="2019-02-28",endDate="2020-05-25",period="year"</li>
     *          <li>结果为:[2019-02-28,2019-12-31, 2020-01-01,2020-05-25]</li><br>
     */
    public static List<String> getPieDateRange(String startDate, String endDate, String period) {
        List<String> result = Lists.newArrayList();
        LocalDate end = LocalDate.parse(endDate, yyyyMMdd_EN);
        LocalDate start = LocalDate.parse(startDate, yyyyMMdd_EN);
        LocalDate tmp = start;
        switch (period) {
            case DAY:
                while (start.isBefore(end) || start.isEqual(end)) {
                    result.add(start.toString());
                    start = start.plusDays(1);
                }
                break;
            case WEEK:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    if (tmp.plusDays(6).isAfter(end)) {
                        result.add(tmp + "," + end);
                    } else {
                        result.add(tmp + "," + tmp.plusDays(6));
                    }
                    tmp = tmp.plusDays(7);
                }
                break;
            case MONTH:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    LocalDate lastDayOfMonth = tmp.with(TemporalAdjusters.lastDayOfMonth());
                    if (lastDayOfMonth.isAfter(end)) {
                        result.add(tmp + "," + end);
                    } else {
                        result.add(tmp + "," + lastDayOfMonth);
                    }
                    tmp = lastDayOfMonth.plusDays(1);
                }
                break;
            case YEAR:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    LocalDate lastDayOfYear = tmp.with(TemporalAdjusters.lastDayOfYear());
                    if (lastDayOfYear.isAfter(end)) {
                        result.add(tmp + "," + end);
                    } else {
                        result.add(tmp + "," + lastDayOfYear);
                    }
                    tmp = lastDayOfYear.plusDays(1);
                }
                break;
            default:
                break;
        }
        return result;
    }

    /**
     * 指定日期月的最后一天(yyyy-MM-dd)
     *
     * @param curDate 日期格式(yyyy-MM-dd)
     * @param firstOrLast true:第一天,false:最后一天
     * 
     */
    public static String getLastDayOfMonth(String curDate, boolean firstOrLast) {
        if (firstOrLast) {
            return LocalDate.parse(curDate, yyyyMMdd_EN).with(TemporalAdjusters.firstDayOfMonth()).toString();
        } else {
            return LocalDate.parse(curDate, yyyyMMdd_EN).with(TemporalAdjusters.lastDayOfMonth()).toString();
        }
    }

    /**
     * 指定日期年的最后一天(yyyy-MM-dd)
     *
     * @param curDate 指定日期(格式:yyyy-MM-dd)
     * @param firstOrLast true:第一天,false:最后一天
     * @return 例如:日期年的第一天:2021-01-01 日期年的最后一天:2021-12-31
     */
    public static String getLastDayOfYear(String curDate, boolean firstOrLast) {
        if (firstOrLast) {
            return LocalDate.parse(curDate, yyyyMMdd_EN).with(TemporalAdjusters.firstDayOfYear()).toString();
        } else {
            return LocalDate.parse(curDate, yyyyMMdd_EN).with(TemporalAdjusters.lastDayOfYear()).toString();
        }
    }

    /**
     * 获取下一个星期的日期
     *
     * @param curDay yyyy-MM-dd
     * @param dayOfWeek monday:1~sunday:7
     * @param isContainCurDay 是否包含当天,true:是,false:不包含
     * @return 日期(yyyy-MM-dd)
     */
    public static String getNextWeekDate(String curDay, int dayOfWeek, boolean isContainCurDay) {
        dayOfWeek = dayOfWeek < 1 || dayOfWeek > 7 ? 1 : dayOfWeek;
        if (isContainCurDay) {
            return LocalDate.parse(curDay).with(TemporalAdjusters.nextOrSame(DayOfWeek.of(dayOfWeek))).toString();
        } else {
            return LocalDate.parse(curDay).with(TemporalAdjusters.next(DayOfWeek.of(dayOfWeek))).toString();
        }
    }

    /**
     * 获取上一个星期的日期
     *
     * @param curDay 指定日期(yyyy-MM-dd)
     * @param dayOfWeek 数字范围(monday:1~sunday:7)
     * @param isCurDay 是否包含当天,true:是,false:不包含
     * @return 日期(yyyy-MM-dd)
     */
    public static String getPreWeekDate(String curDay, int dayOfWeek, boolean isCurDay) {
        dayOfWeek = dayOfWeek < 1 || dayOfWeek > 7 ? 1 : dayOfWeek;
        if (isCurDay) {
            return LocalDate.parse(curDay).with(TemporalAdjusters.previousOrSame(DayOfWeek.of(dayOfWeek))).toString();
        } else {
            return LocalDate.parse(curDay).with(TemporalAdjusters.previous(DayOfWeek.of(dayOfWeek))).toString();
        }
    }

    /**
     * 获取指定日期当月的最后或第一个星期日期
     *
     * @param curDay 指定日期(yyyy-MM-dd)
     * @param dayOfWeek 周几(1~7)
     * @param lastOrFirst true:最后一个,false本月第一个
     * @return 日期(yyyy-MM-dd)
     */
    public static String getFirstOrLastWeekDate(String curDay, int dayOfWeek, boolean lastOrFirst) {
        dayOfWeek = dayOfWeek < 1 || dayOfWeek > 7 ? 1 : dayOfWeek;
        if (lastOrFirst) {
            return LocalDate.parse(curDay).with(TemporalAdjusters.lastInMonth(DayOfWeek.of(dayOfWeek))).toString();
        } else {
            return LocalDate.parse(curDay).with(TemporalAdjusters.firstInMonth(DayOfWeek.of(dayOfWeek))).toString();
        }
    }

    public static void main(String[] args) {
        System.out.println("===================");
        System.out.println("获取当前日期:"+getNowTime_EN_yMdH());
        System.out.println("获取当前日期:"+getNowTime_CN_yMdH());
        System.out.println("获取当前日期:"+getNowTime_EN_yMdHm());
        System.out.println("获取当前日期:"+getNowTime_CN_yMdHm());
        System.out.println("获取当前日期:"+getNowTime_CN_HHmmss());
        System.out.println("获取当前日期:"+getTime("HH:mm:ss"));
        System.out.println("获取当前日期:"+getNowLocalTime_shot());
        System.out.println("获取当前日期:"+getNowLocalTime_full());
        System.out.println("获取当前日期:"+getNowLocalTime_long());
        System.out.println("获取当前日期:"+getNowLocalTime_medium());
        System.out.println("获取当前日期:"+getNowTime_CN());
        System.out.println("获取当前日期:"+getNowTime_EN());
        System.out.println("获取当前日期:"+getNowDate_CN());
        System.out.println("===================");
        String curDate = getNowDate_EN(); // 指定日期
        System.out.println("日期:"+getNowDate_EN());
        System.out.println("日期月的第一天:"+getLastDayOfMonth(curDate, true));
        System.out.println("日期月的最后一天:"+getLastDayOfMonth(curDate, false));
        System.out.println("日期年的第一天:"+getLastDayOfYear(curDate, true));
        System.out.println("日期年的最后一天:"+getLastDayOfYear(curDate, false));
        System.out.println("===================");
        String startDate = "2021-02-28", endDate = "2021-03-05";
        System.out.println(startDate+"和"+endDate+"按日切割:"+getPieDateRange(startDate, endDate, DAY));
        System.out.println("===================");
        System.out.println("获取2021-05-10的下一个星期:"+getNextWeekDate("2021-05-10", 1, false));
        System.out.println("2021-01-12和2021-02-15按周切割:"+getPieDateRange("2021-01-12", "2021-02-15", WEEK));
        System.out.println("===================");
        System.out.println("获取2021-04-02的第一个星期的周一:"+getFirstOrLastWeekDate("2021-04-02", 0, false));
        System.out.println("获取2021-04-02的上一个星期的周二(不包含当天):"+getPreWeekDate("2021-04-02", 2, false));
        System.out.println("获取2021-04-02的下一个星期的周二:"+getNextWeekDate("2021-04-02", 2, false));
        System.out.println("===================");
        System.out.println("当前时间戳:" + Instant.now());
        System.out.println("当前时间:" + LocalDateTime.now());
        System.out.println("===================");
        System.out.println("计算2021-01-30和2021-03-31相差几个月:"+peridCount("2021-01-30", "2021-03-31", MONTH));
        System.out.println("2020-03-31是否为闰年:"+isLeapYear("2020-03-31"));
        System.out.println("当今是否为闰年:"+LocalDate.now().isLeapYear());
        System.out.println("===================");
        System.out.println("获取2021-03-10前一周:"+getAfterOrPreDate("2021-03-10", WEEK, -1));
        System.out.println("获取当前日期五天前:"+getAfterOrPreDayDate(-5));
        System.out.println("获取当前日期三天前:"+getAfterOrPreDayDate(-3));
        System.out.println("获取当前日期六天后:"+getAfterOrPreDayDate(6));
        System.out.println("获取当前日期后第6年:"+getAfterOrPreYearDate(6));
        System.out.println("获取当前日期后第1周:"+getAfterOrPreWeekDate(1));
        System.out.println("===================");
        System.out.println("7月13日(生日)是否是今天:"+isBirthday(7, 13));
        System.out.println("===================");
        LocalDate date0 = LocalDate.of(2021, Month.OCTOBER, 31);
        LocalDate date = LocalDate.of(2021, 3, 31);
        System.out.println("当前日期等不等于2021年09月31日:"+date0.equals(LocalDate.now()));
        System.out.println("年-月-日:"+date.getYear() + "-" + date.getMonthValue() + "-" + date.getDayOfMonth());
        System.out.println("获取当前日期节点年份:"+getNodeTime("year"));
        System.out.println(transformWeekEN2Num(null));
        System.out.println("===================");
    }
}

14、返回结果类

package com.ai.oss.utils;

import lombok.Data;

@Data
public class OperateResult {

    private boolean success = true;

    private Object data;

    private String message;

    private String code = "0";

    public OperateResult(boolean success, String msg, Object data, String code) {
        this.success = success;
        this.message = msg;
        this.data = data;
        this.code = code;
    }

    public OperateResult(boolean success, String msg, Object data) {
        this(success, msg, data, "0");
    }

    public OperateResult(boolean success, String msg) {
        this(success, msg, null, "0");

    }

    public static OperateResult success(Object data) {
        OperateResult operateResult = new OperateResult(true, "", data);
        return operateResult;
    }

    public static OperateResult success() {
        OperateResult operateResult = new OperateResult(true, "");
        return operateResult;
    }

    public static OperateResult failure(String msg) {
        OperateResult operateResult = new OperateResult(true, msg);
        return operateResult;
    }
}

15、返回结果枚举

package com.ai.oss.utils;

public enum ResultCode {
    /* 成功状态码 */
    SUCCESS(0,"操作成功!"),

    /* 错误状态码 */
    FAIL(-1,"操作失败!"),

    /* 参数错误:10001-19999 */
    PARAM_IS_INVALID(10001, "参数无效"),
    PARAM_IS_BLANK(10002, "参数为空"),
    PARAM_TYPE_BIND_ERROR(10003, "参数格式错误"),
    PARAM_NOT_COMPLETE(10004, "参数缺失"),

    /* 用户错误:20001-29999*/
    USER_NOT_LOGGED_IN(20001, "用户未登录,请先登录"),
    USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
    USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
    USER_NOT_EXIST(20004, "用户不存在"),
    USER_HAS_EXISTED(20005, "用户已存在"),

    /* 业务错误:30001-39999 */
    BUSINESS_GROUP_NO_ALLOWED_DEL(30001, "应用分组已经被应用使用,不能删除"),
    BUSINESS_THEME_NO_ALLOWED_DEL(30002, "主题已经被用户使用,不能删除"),
    BUSINESS_THEME_NO_ALLOWED_DISABLE(30003, "主题已经被用户使用,不能停用"),
    BUSINESS_THEME_DEFAULT_NO_ALLOWED_DEL(30004, "默认主题,不能删除"),
    BUSINESS_THEME_NO_ALLOWED_UPDATE(30005, "主题已经被用户使用,不能修改图片信息"),
    BUSINESS_IS_TOP(30040, "已经到最顶部"),
    BUSINESS_IS_BOTTOM(30041, "已经到最底部"),
    BUSINESS_NAME_EXISTED(30051, "名称已存在"),

    /* 系统错误:40001-49999 */
    SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"),
    UPLOAD_ERROR(40002, "系统异常,上传文件失败"),
    FILE_MAX_SIZE_OVERFLOW(40003, "上传尺寸过大"),
    FILE_ACCEPT_NOT_SUPPORT(40004, "上传文件格式不支持"),
    SET_UP_AT_LEAST_ONE_ADMIN(40005, "至少指定一个管理员"),
    URL_INVALID(40006, "地址不合法"),
    LINK_AND_LOGOUT_NO_MATCH(40006, "主页地址和注销地址IP不一致"),
    IP_AND_PORT_EXISTED(40007, "当前IP和端口已经被占中"),
    LINK_IS_REQUIRED(40008, "生成第三方token认证信息: 主页地址不能为空,请完善信息"),
    ONLY_ROOT_DEPARTMENT(40009, "组织机构只能存在一个根机构"),
    DEPART_CODE_EXISTED(40010, "组织机构编码已存在"),
    DEPART_CONTAINS_USERS(40011, "该机构下是存在用户,不允许删除"),
    DEPART_CONTAINS_SON(40012, "该机构下是存在子级机构,不允许删除"),
    DEPART_PARENT_IS_SELF(40013, "选择的父机构不能为本身"),
    DICT_EXIST_DEPEND(40014, "该字典数据存在详情依赖,不允许删除"),
    DICT_DETAIL_LOCK(40015, "该字典数据被锁定,不允许修改或删除"),
    DEPART_CODE_EXISTED_WITH_ARGS(40016, "组织机构编码【{0}】系统已存在"),

    /* 数据错误:50001-599999 */
    RESULT_DATA_NONE(50001, "数据未找到"),
    DATA_IS_WRONG(50002, "数据有误"),
    DATA_ALREADY_EXISTED(50003, "数据已存在"),

    /* 接口错误:60001-69999 */
    INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"),
    INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),
    INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),
    INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
    INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),
    INTERFACE_EXCEED_LOAD(60006, "接口负载过高"),


    /* 权限错误:70001-79999 */
    PERMISSION_UNAUTHENTICATED(70001,"此操作需要登陆系统!"),
    PERMISSION_UNAUTHORISE(70002,"权限不足,无权操作!"),
    PERMISSION_EXPIRE(70003,"登录状态过期!"),
    PERMISSION_TOKEN_EXPIRED(70004, "token已过期"),
    PERMISSION_LIMIT(70005, "访问次数受限制"),
    PERMISSION_TOKEN_INVALID(70006, "无效token"),
    PERMISSION_SIGNATURE_ERROR(70007, "签名失败");

    //操作代码
    int code;
    //提示信息
    String message;
    ResultCode(int code, String message){
        this.code = code;
        this.message = message;
    }

    public int code() {
        return code;
    }

    public String message() {
        return message;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

16、树形工具类

package com.ai.oss.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

@Slf4j
public class TreeTableUtil {
    /**
     * 把列表转换为树结构
     *
     * @param originalList      原始list数据
     * @param idFieldName       作为唯一标示的字段名称
     * @param pidFieldName      父节点标识字段名
     * @param childrenFieldName 子节点(列表)标识字段名
     * @return 树结构列表
     */
    public static <T> List<T> list2TreeList(List<T> originalList, String idFieldName, String pidFieldName,
                                            String childrenFieldName) {
        LinkedHashMap pm = new LinkedHashMap<>();
        originalList.stream().forEach(t -> {
            try {
                String id = BeanUtils.getProperty(t, idFieldName);
                pm.put(id,id);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                log.error(e.getMessage());
            }
        });
        // 获取根节点,即找出父节点为空的对象
        List<T> rootNodeList = new ArrayList<>();
        for (T t : originalList) {
            String parentId = null;
            try {
                parentId = BeanUtils.getProperty(t, pidFieldName);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                log.error(e.getMessage());
            }
            if (StringUtils.isBlank(parentId)) {
                rootNodeList.add(0, t);
            }else{
                boolean bool = true;
                if(pm.containsKey(parentId)){
                    bool = false;
                }
                if(bool) {
                    try {
                        BeanUtils.setProperty(t, pidFieldName, "");
                    }catch (Exception e){
                        log.error(e.getMessage());
                    }
                    rootNodeList.add(t);
                }
            }
        }

        // 将根节点从原始list移除,减少下次处理数据
        originalList.removeAll(rootNodeList);

        // 递归封装树
        try {
            packTree(rootNodeList, originalList, idFieldName, pidFieldName, childrenFieldName);
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return rootNodeList;
    }

    /**
     * 封装树(向下递归)
     *
     * @param parentNodeList    要封装为树的父节点对象集合
     * @param originalList      原始list数据
     * @param keyName           作为唯一标示的字段名称
     * @param pidFieldName      父节点标识字段名
     * @param childrenFieldName 子节点(列表)标识字段名
     */
    private static <T> void packTree(List<T> parentNodeList, List<T> originalList, String keyName,
                                     String pidFieldName, String childrenFieldName) throws Exception {
        for (T parentNode : parentNodeList) {
            // 找到当前父节点的子节点列表
            List<T> children = packChildren(parentNode, originalList, keyName, pidFieldName, childrenFieldName);
            if (children.isEmpty()) {
                continue;
            }

            // 将当前父节点的子节点从原始list移除,减少下次处理数据
            originalList.removeAll(children);

            // 开始下次递归
            packTree(children, originalList, keyName, pidFieldName, childrenFieldName);
        }
    }

    /**
     * 封装子对象
     *
     * @param parentNode        父节点对象
     * @param originalList      原始list数据
     * @param keyName           作为唯一标示的字段名称
     * @param pidFieldName      父节点标识字段名
     * @param childrenFieldName 子节点(列表)标识字段名
     */
    private static <T> List<T> packChildren(T parentNode, List<T> originalList, String keyName, String pidFieldName,
                                            String childrenFieldName) throws Exception {
        // 找到当前父节点下的子节点列表
        List<T> childNodeList = new ArrayList<>();
        String parentId = BeanUtils.getProperty(parentNode, keyName);
        for (T t : originalList) {
            String childNodeParentId = BeanUtils.getProperty(t, pidFieldName);
            if (parentId.equals(childNodeParentId)) {
                childNodeList.add(t);
            }
        }

        // 将当前父节点下的子节点列表写入到当前父节点下(给子节点列表字段赋值)
        if (!childNodeList.isEmpty()) {
            BeanUtils.setProperty(parentNode,childrenFieldName,childNodeList);
        }

        return childNodeList;
    }
}

16、加密工具类

package com.ai.oss.sso.utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

/**
 * @Author helin
 * @Date 2021/5/21 11:10
 * @Description NULL
 */
public class EnDes {
    public static final String KEY_SHA = "SHA";
    public static final String KEY_MD5 = "MD5";

    /**
     * MAC算法可选以下多种算法
     *
     * <pre>
     * HmacMD5
     * HmacSHA1
     * HmacSHA256
     * HmacSHA384
     * HmacSHA512
     * </pre>
     */
    public static final String KEY_MAC = "HmacMD5";

    /**
     * BASE64解密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /**
     * BASE64加密
     *
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /**
     * MD5加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {

        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);

        return md5.digest();

    }

    /**
     * SHA加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {

        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);

        return sha.digest();

    }

    /**
     * 初始化HMAC密钥
     *
     * @return
     * @throws Exception
     */
    public static String initMacKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);

        SecretKey secretKey = keyGenerator.generateKey();
        return encryptBASE64(secretKey.getEncoded());
    }

    /**
     * HMAC加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptHMAC(byte[] data, String key) throws Exception {

        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);

        return mac.doFinal(data);

    }
}
package com.ai.oss.sso.utils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author helin
 * @Date 2021/5/21 11:01
 * @Description NULL
 */
public class RSAUtil extends EnDes{
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 用私钥对信息生成数字签名
     *
     * @param data
     *            加密数据
     * @param privateKey
     *            私钥
     *
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        // 解密由base64编码的私钥
        byte[] keyBytes = decryptBASE64(privateKey);

        // 构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

        // 取私钥匙对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

        // 用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(priKey);
        signature.update(data);

        return encryptBASE64(signature.sign());
    }

    /**
     * 校验数字签名
     *
     * @param data
     *            加密数据
     * @param publicKey
     *            公钥
     * @param sign
     *            数字签名
     *
     * @return 校验成功返回true 失败返回false
     * @throws Exception
     *
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {

        // 解密由base64编码的公钥
        byte[] keyBytes = decryptBASE64(publicKey);

        // 构造X509EncodedKeySpec对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

        // 取公钥匙对象
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pubKey);
        signature.update(data);

        // 验证签名是否正常
        return signature.verify(decryptBASE64(sign));
    }

    /**
     * 解密<br>
     * 用私钥解密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, String key)
            throws Exception {
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);

        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }

    /**
     * 解密<br>
     * 用公钥解密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data, String key)
            throws Exception {
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);

        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);

        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

    /**
     * 加密<br>
     * 用公钥加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String key)
            throws Exception {
        // 对公钥解密
        byte[] keyBytes = decryptBASE64(key);

        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);

        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

    /**
     * 加密<br>
     * 用私钥加密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key)
            throws Exception {
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);

        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }

    /**
     * 取得私钥
     *
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PRIVATE_KEY);

        return encryptBASE64(key.getEncoded());
    }

    /**
     * 取得公钥
     *
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
        Key key = (Key) keyMap.get(PUBLIC_KEY);

        return encryptBASE64(key.getEncoded());
    }

    /**
     * 初始化密钥
     *
     * @return
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator
                .getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(2048);

        KeyPair keyPair = keyPairGen.generateKeyPair();

        // 公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        // 私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        Map<String, Object> keyMap = new HashMap<String, Object>(2);

        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
}
package com.ai.oss.sso.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import cn.hutool.core.codec.Base64Encoder;
import com.ai.oss.utils.DateHelper;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class RSAUtilTest {
    private static String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtTivFyv/LSQtCkil0Ct7RQaLPX6o1bqY5vlayz7Wyjqwkk9Mk3JDxebPMaU4rHlB5gzwfWSyQsuHs+hUaTw5dABhFdejUmeYdT5PiYEj2owOl+4UOkh/XxJ8lnwPGp/beVuCsTfQ8DCh/siJtkRVOJ8zli+PTkm6nCGYeRenZBabdHg0MwZCPYAaDGdbtM8CWVx1vZCWRtOeBnLJ5oXUXgoSkHjYwR3NJNe4KvVXxhCgKKyxsFQaVcDd0601/xhXgko8Lbxt/m+RrdNrrROU2Sy89qjb0z9N1sYTwgK4KD17j3Cl3iK1TusefRsKdk0fZLRQSh1044fC4Cn/K+SmpQIDAQAB";
    private static String privateKey = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC1OK8XK/8tJC0KSKXQK3tFBos9fqjVupjm+VrLPtbKOrCST0yTckPF5s8xpTiseUHmDPB9ZLJCy4ez6FRpPDl0AGEV16NSZ5h1Pk+JgSPajA6X7hQ6SH9fEnyWfA8an9t5W4KxN9DwMKH+yIm2RFU4nzOWL49OSbqcIZh5F6dkFpt0eDQzBkI9gBoMZ1u0zwJZXHW9kJZG054GcsnmhdReChKQeNjBHc0k17gq9VfGEKAorLGwVBpVwN3TrTX/GFeCSjwtvG3+b5Gt02utE5TZLLz2qNvTP03WxhPCArgoPXuPcKXeIrVO6x59Gwp2TR9ktFBKHXTjh8LgKf8r5KalAgMBAAECggEAXBa06sqBvleux5YJJJKj7nyXzyUI+Kr8vgqid7uz/En8pizD1f1vsSZLzYePGB36PcP/hUjhSQ4SJHsAQgXHkEoNC8NrjBl2oMWMN2y3YnxfghcKkl960j4br4DVUAtBxRaagCHD+/pKp6USTdvFjqNf3IbIhNj0ihiMWaSKfFIhn/dsuLxTZt9oN36XF9Vnv5S7487s8FKC0rHnzYGExcs9nx8LyRXvaHaWJzeOGTIGGP0XOQGfG9wBv8a2ZlgsQPEtsPWlTYYMnpDcW5TvN1275DcO9HfSGhMPbG0avFV9fBb2HWkC2GwiW2Aw//lEnnjjcuFGVccCZWJ90aEXwQKBgQDerOtHNx7i1V0yzgu9SFZZZULbXEQBPbXIi1v2CRSHsOZBfOvJCYUXiBxIrLrUmHjopxqvqY3rxVxVKRclWZdqpAzG4LqkFLYgppxVSPhb57WOkT5lYtOIKfBOLz2dd0mZN02/gJlrBX2gGBqTm8slCL2QTkRh9eVEN/zN4EqaFQKBgQDQV5bKYDvttu/sJg2XYRFTsIEqk4ULi0rXFAA/P8mbBwgSNpNVruWhH5KTDAR2dUHvda1XW+qgA0A7LuA2YatOh8/WN6ZhcgcIbyew5XASsreM1sbAXGXpCT8x8NrNq/4pvov20gQwGgG9N2fxlyze5UXToDahdcq2Nyu+71nOUQKBgAGHam4owLuJ/4PTylzYXE9s1JKxBX6Er/TakB0WXt+3pT0Z4HyW5iUNODR/iyDekyX1z8cZAPJ3fnTPPWtyPAntanELJfzub3m16yjiwWHQK3z5HlaP4Sf0McQ3qtKj+QtmR9Biz6redMheogAVd8WfU73j67BIgfR/9epr+dcpAoGAH7XlLqJdHL5mYCQel3bfw0QvNMLFUk9+MaRKsVXNIrp8QQFrhXQcYVzD23vNxhXs1jysCIrl+DrmcNuepshQ4aAMQ0evHE/VwDPi76rMVxw6kcYy9B5cKI8OvlQxiXJvOf1Voliu6H9c2mbvfDcNTlPJP/+3sPWTyA43q1UU7zECgYB5zlVHwpsUZ9vqiMcsavX87E4zT4v95uNY/9HZrQhQptPHSqlmX6O3RVXXssp3IOZyU9HjdnOZUhMOw9DOXZY9rHFyvjH5re9S0Q5RvuhvvgY/ra/hMUhZR2FlhKA2ckWmmOr5WsXy/N8BT4igZUlXNNchiiLTQ6CIW8ij28DyuQ==";

    public static void main(String arg[])  {
        try{
            System.out.println("私钥加密——公钥解密");
            String inputStr = "123";
            byte[]  data = inputStr.getBytes();

            byte[] encodedData = RSAUtil.encryptByPrivateKey(data, privateKey);

            BASE64Encoder base64 =new BASE64Encoder();
            String mw = base64.encode(encodedData);
            System.out.println("密文:"+mw);

            System.out.println(DateHelper.formatShortDate(new Date()));


            byte[] decodedData = RSAUtil
                    .decryptByPublicKey((new BASE64Decoder()).decodeBuffer(mw), publicKey);

            String outputStr = new String(decodedData);
            System.out.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);

            String param = "lU0c4SRO7vnpU_fTcQvA4H9Ad7w3qCX4EuQ86tm9ejri3RLsaUEvDqqGMvWcn6Mfr3OWWlcxrYcaVhJ5a9pMie-AftV8lMnqsnpiT1oKbLZ2cT03VCV943SvdbaaQqwmXdVzJ-2o-m6xUoY5w1FFh-ySvIWF_RUf3T1IeapOxgPQ9twl3_OzM84WCxSp9nXLv3S3_mRPdilk46T3jMlQiWizrEGHLkxgzDsP4rLAe8NVkMYqy53-vxMV71T1H3uDbamUt0q7E-DS_704OuBqMp3TBSUak07Epw9N50muWsfB8FxkJrXU0sOI4g9Q0059Hr-wqQQuUiIyNz45C_gKAA==";
            Base64.Decoder decoder  =  Base64.getUrlDecoder();
            byte[] bytes = decoder.decode(param);
            System.out.println(new String(bytes, StandardCharsets.UTF_8));

        }catch (Exception e){
            e.printStackTrace();
        }

    }

}

 

 

 

  

 

posted @ 2021-08-09 21:28  passex  阅读(42)  评论(0)    收藏  举报