首页 > 编程语言 >HuTool JAVA 工具类神器

HuTool JAVA 工具类神器

时间:2023-10-21 14:23:58浏览次数:43  
标签:DateUtil JAVA String HuTool 神器 date new id name


版权声明:本文为CSDN博主「有多勉为其难」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/abst122/article/details/124091375

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;

Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
请移步官网:https://hutool.cn/
不得不说,hutool真的是好用,大大提高开发效率,使代码没有那么臃肿,太妙了,以下只是我在开发中遇到的,并不全

StrUtil, DateUtil, BeanUtil, NUmberUtil, HttpUtil, CaptchaUtil等

安装
1. maven
请认准官网最新依赖

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>

常用工具类

1. 类型转换工具类-Convert

Convert类可以说是一个工具方法类,里面封装了针对Java常见类型的转换,用于简化类型转换。Convert类中大部分方法为toXXX,参数为Object,可以实现将任意可能的类型转换为指定类型。同时支持第二个参数defaultValue用于在转换失败时返回一个默认值。

//转换为字符串
int a = 1;
String aStr = Convert.toStr(a);
//转换为指定类型数组
String[] b = { "1", "2", "3", "4" };
Integer[] intArray = Convert.toIntArray(b);
//转换为日期对象
String dateStr = "2022-09-28";
Date date = Convert.toDate(dateStr);
//转换为列表
String[] strArr = {"a", "b", "c", "d"};
List<String> strList = Convert.toList(String.class, strArr);
Object[] a = {"a", "你", "好", "", 1};
List<?> list = Convert.convert(List.class, a);
//从4.1.11开始可以这么用
List<?> list = Convert.toList(a);

2. 日期时间工具-DateUtil

转换

Date、long、Calendar之间的相互转换

//获取当前时间
Date date = DateUtil.date();
//Calendar类型时间转为Date
Date date2 = DateUtil.date(Calendar.getInstance());
//时间戳转为Date
Date date3 = DateUtil.date(System.currentTimeMillis());
//当前时间字符串,格式:yyyy-MM-dd HH:mm:ss
String now = DateUtil.now();
//当前日期字符串,格式:yyyy-MM-dd
String today= DateUtil.today();
// 时间格式转为时间戳
Date date1 = DateUtil.parse("2023-06-21");
long time = date1.getTime();
System.out.println("time = " + time);

字符串转日期
DateUtil.parse方法会自动识别一些常用格式,包括:

yyyy-MM-dd HH:mm:ss

yyyy/MM/dd HH:mm:ss
yyyy.MM.dd HH:mm:ss
yyyy年MM月dd日 HH时mm分ss秒
yyyy-MM-dd
yyyy/MM/dd
yyyy.MM.dd
HH:mm:ss
HH时mm分ss秒
yyyy-MM-dd HH:mm
yyyy-MM-dd HH:mm:ss.SSS

String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr);

我们也可以使用自定义日期格式转化:

String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr, "yyyy-MM-dd");

格式化日期输出

String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr);

//结果 2017/03/01
String format = DateUtil.format(date, "yyyy/MM/dd");

//常用格式的格式化,结果:2017-03-01
String formatDate = DateUtil.formatDate(date);

//结果:2017-03-01 00:00:00
String formatDateTime = DateUtil.formatDateTime(date);

//结果:00:00:00
String formatTime = DateUtil.formatTime(date);

获取Date对象的某个部分

Date date = DateUtil.date();
//获得年的部分
DateUtil.year(date);
//获得月份,从0开始计数
DateUtil.month(date);
//获得月份枚举
DateUtil.monthEnum(date);
//.....

开始和结束时间

有的时候我们需要获得每天的开始时间、结束时间,每月的开始和结束时间等等,DateUtil也提供了相关方法:

String dateStr = "2017-03-01 22:33:23";
Date date = DateUtil.parse(dateStr);

//一天的开始,结果:2017-03-01 00:00:00
Date beginOfDay = DateUtil.beginOfDay(date);

//一天的结束,结果:2017-03-01 23:59:59
Date endOfDay = DateUtil.endOfDay(date);

日期时间偏移

日期或时间的偏移指针对某个日期增加或减少分、小时、天等等,达到日期变更的目的。Hutool也针对其做了大量封装

String dateStr = "2017-03-01 22:33:23";
Date date = DateUtil.parse(dateStr);

//结果:2017-03-03 22:33:23
Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);

//常用偏移,结果:2017-03-04 22:33:23
DateTime newDate2 = DateUtil.offsetDay(date, 3);

//常用偏移,结果:2017-03-01 19:33:23
DateTime newDate3 = DateUtil.offsetHour(date, -3);

针对当前时间,提供了简化的偏移方法(例如昨天、上周、上个月等):

//昨天
DateUtil.yesterday()
//明天
DateUtil.tomorrow()
//上周
DateUtil.lastWeek()
//下周
DateUtil.nextWeek()
//上个月
DateUtil.lastMonth()
//下个月
DateUtil.nextMonth()

日期时间差

有时候我们需要计算两个日期之间的时间差(相差天数、相差小时数等等),Hutool将此类方法封装为between方法:

String dateStr1 = "2017-03-01 22:33:23";
Date date1 = DateUtil.parse(dateStr1);

String dateStr2 = "2017-04-01 23:33:23";
Date date2 = DateUtil.parse(dateStr2);

//相差一个月,31天
long betweenDay = DateUtil.between(date1, date2, DateUnit.DAY);

格式化时间差

有时候我们希望看到易读的时间差,比如XX天XX小时XX分XX秒,此时使用DateUtil.formatBetween方法:

//Level.MINUTE表示精确到分
String formatBetween = DateUtil.formatBetween(between, Level.MINUTE);
//输出:31天1小时
Console.log(formatBetween);

星座和属相

// "摩羯座"
String zodiac = DateUtil.getZodiac(Month.JANUARY.getValue(), 19);

// "狗"
String chineseZodiac = DateUtil.getChineseZodiac(1994);

其它

//年龄
DateUtil.ageOfNow("1990-01-30");

//是否闰年
DateUtil.isLeapYear(2017);

//获得指定月份的总天数
DateUtil.lengthOfMonth(6,false);

3. 日期时间对象-DateTime

新建对象

DateTime对象包含众多的构造方法,构造方法支持的参数有:

Date
Calendar
String(日期字符串,第二个参数是日期格式)
long 毫秒数
构建对象有两种方式:DateTime.of()new DateTime()

Date date = new Date();

//new方式创建
DateTime time = new DateTime(date);
Console.log(time);

//of方式创建
DateTime now = DateTime.now();
DateTime dt = DateTime.of(date);

使用对象

DateTime的成员方法与DateUtil中的静态方法所对应,因为是成员方法,因此可以使用更少的参数操作日期时间。

示例:获取日期成员(年、月、日等)

DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT);

//年,结果:2017
int year = dateTime.year();

//季度(非季节),结果:Season.SPRING
Season season = dateTime.seasonEnum();

//月份,结果:Month.JANUARY
Month month = dateTime.monthEnum();

//日,结果:5
int day = dateTime.dayOfMonth();

更多成员方法请参阅API文档。

对象的可变性
DateTime对象默认是可变对象(调用offset、setField、setTime方法默认变更自身),但是这种可变性有时候会引起很多问题(例如多个地方共用DateTime对象)。我们可以调用setMutable(false)方法使其变为不可变对象。在不可变模式下,offset、setField方法返回一个新对象,setTime方法抛出异常。

DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT);

//默认情况下DateTime为可变对象,此时offset == dateTime
DateTime offset = dateTime.offset(DateField.YEAR, 0);

//设置为不可变对象后变动将返回新对象,此时offset != dateTime
dateTime.setMutable(false);
offset = dateTime.offset(DateField.YEAR, 0);

格式化为字符串

调用toString()方法即可返回格式为yyyy-MM-dd HH:mm:ss的字符串,调用toString(String format)可以返回指定格式的字符串。

DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT);
//结果:2017-01-05 12:34:23
String dateStr = dateTime.toString();

//结果:2017/01/05

4. LocalDateTime工具-LocalDateTimeUtil

从Hutool的5.4.x开始,Hutool加入了针对JDK8+日期API的封装,此工具类的功能包括LocalDateTime和LocalDate的解析、格式化、转换等操作。

日期转换

String dateStr = "2020-01-23T12:23:56";
DateTime dt = DateUtil.parse(dateStr);

// Date对象转换为LocalDateTime
LocalDateTime of = LocalDateTimeUtil.of(dt);

// 时间戳转换为LocalDateTime
of = LocalDateTimeUtil.ofUTC(dt.getTime());

日期字符串解析

// 解析ISO时间
LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");


// 解析自定义格式时间
localDateTime = LocalDateTimeUtil.parse("2020-01-23", DatePattern.NORM_DATE_PATTERN);

解析同样支持LocalDate

LocalDate localDate = LocalDateTimeUtil.parseDate("2020-01-23");

// 解析日期时间为LocalDate,时间部分舍弃
localDate = LocalDateTimeUtil.parseDate("2020-01-23T12:23:56", DateTimeFormatter.ISO_DATE_TIME);

日期格式化

LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");

// "2020-01-23 12:23:56"
String format = LocalDateTimeUtil.format(localDateTime, DatePattern.NORM_DATETIME_PATTERN);

日期偏移

final LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");

// 增加一天
// "2020-01-24T12:23:56"
LocalDateTime offset = LocalDateTimeUtil.offset(localDateTime, 1, ChronoUnit.DAYS);

如果是减少时间,offset第二个参数传负数即可:

// "2020-01-22T12:23:56"
offset = LocalDateTimeUtil.offset(localDateTime, -1, ChronoUnit.DAYS);

计算时间间隔

LocalDateTime start = LocalDateTimeUtil.parse("2019-02-02T00:00:00");
LocalDateTime end = LocalDateTimeUtil.parse("2020-02-02T00:00:00");

Duration between = LocalDateTimeUtil.between(start, end);

// 365
between.toDays();

一天的开始和结束

LocalDateTime localDateTime = LocalDateTimeUtil.parse("2020-01-23T12:23:56");

// "2020-01-23T00:00"
LocalDateTime beginOfDay = LocalDateTimeUtil.beginOfDay(localDateTime);

// "2020-01-23T23:59:59.999999999"
LocalDateTime endOfDay = LocalDateTimeUtil.endOfDay(localDateTime);

其它
static boolean isSameDay(LocalDate date1, LocalDate date2)
比较两个日期是否为同一天
static boolean isSameDay(LocalDateTime date1, LocalDateTime date2)
比较两个日期是否为同一天
static boolean isWeekend(LocalDate localDate)
是否为周末(周六或周日)
static boolean isWeekend(LocalDateTime localDateTime)
是否为周末(周六或周日

5. 字符串工具-StrUtil

这个工具的用处类似于Apache Commons Lang中的StringUtil

常用的方法例如isBlank、isNotBlank、isEmpty、isNotEmpty、split等

// 将list集合用","拼接每个元素并返回String
String idStr = StrUtil.join(",", ids);

6. 数字工具-NumberUtil

加减乘除
NumberUtil.add 针对数字类型做加法
NumberUtil.sub 针对数字类型做减法
NumberUtil.mul 针对数字类型做乘法
NumberUtil.div 针对数字类型做除法,并提供重载方法用于规定除不尽的情况下保留小数位数和舍弃方式。
以上四种运算都会将double转为BigDecimal后计算,解决float和double类型无法进行精确计算的问题。这些方法常用于商业计算。

保留小数

保留小数的方法主要有两种:

  • NumberUtil.round 方法主要封装BigDecimal中的方法来保留小数,返回BigDecimal,这个方法更加灵活,可以选择四舍五入或者全部舍弃等模式

    double te1=123456.123456;
    double te2=123456.128456;
    Console.log(round(te1,4));//结果:123456.1235
    Console.log(round(te2,4));//结果:123456.1285

NumberUtil.roundStr 方法主要封装String.format方法,舍弃方式采用四舍五入

double te1=123456.123456;
double te2=123456.128456;
Console.log(roundStr(te1,2));//结果:123456.12
Console.log(roundStr(te2,2));//结果:123456.13

decimalFormat

针对 DecimalFormat.format进行简单封装。按照固定格式对double或long类型的数字做格式化操作。

long c=299792458;//光速
String format = NumberUtil.decimalFormat(",###", c);//299,792,458

格式中主要以 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。

0 -> 取一位整数
0.00 -> 取一位整数和两位小数
00.000 -> 取两位整数和三位小数
# -> 取所有整数部分
#.##% -> 以百分比方式计数,并取两位小数
#.#####E0 -> 显示为科学计数法,并取五位小数
,### -> 每三位以逗号进行分隔,例如:299,792,458
光速大小为每秒,###米 -> 将格式嵌入文本

是否为数字

  • NumberUtil.isNumber 是否为数字
  • NumberUtil.isInteger 是否为整数
  • NumberUtil.isDouble 是否为浮点数
  • NumberUtil.isPrimes 是否为质数

随机数
NumberUtil.generateRandomNumber 生成不重复随机数 根据给定的最小数字和最大数字,以及随机数的个数,产生指定的不重复的数组。
NumberUtil.generateBySet 生成不重复随机数 根据给定的最小数字和最大数字,以及随机数的个数,产生指定的不重复的数组。
整数列表
NumberUtil.range 方法根据范围和步进,生成一个有序整数列表。 NumberUtil.appendRange 将给定范围内的整数添加到已有集合中

其它
NumberUtil.factorial 阶乘
NumberUtil.sqrt 平方根
NumberUtil.divisor 最大公约数
NumberUtil.multiple 最小公倍数
NumberUtil.getBinaryStr 获得数字对应的二进制字符串
NumberUtil.binaryToInt 二进制转int
NumberUtil.binaryToLong 二进制转long
NumberUtil.compare 比较两个值的大小
NumberUtil.toStr 数字转字符串,自动并去除尾小数点儿后多余的0
NumberUtil.isIn(BigDecimal value, BigDecimal minInclude, BigDecimal maxInclude)检查值是否在指定范围内(值,最小值(包含),最大值(包含))

7. 唯一ID工具-IdUtil

在分布式环境中,唯一ID生成应用十分广泛,生成方法也多种多样,Hutool针对一些常用生成策略做了简单封装。

唯一ID生成器的工具类,涵盖了:

  • UUID
  • ObjectId(MongoDB)
  • Snowflake(Twitter)

UUID

UUID全称通用唯一识别码(universally unique identifier),JDK通过java.util.UUID提供了 Leach-Salz 变体的封装。在Hutool中,生成一个UUID字符串方法如下:

//生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
String uuid = IdUtil.randomUUID();

//生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42
String simpleUUID = IdUtil.simpleUUID();

说明
Hutool重写java.util.UUID的逻辑,对应类为cn.hutool.core.lang.UUID,使生成不带-的UUID字符串不再需要做字符替换,性能提升一倍左右。

ObjectId
ObjectId是MongoDB数据库的一种唯一ID生成策略,是UUID version1的变种,详细介绍可见:服务化框架-分布式Unique ID的生成方法一览。

Hutool针对此封装了cn.hutool.core.lang.ObjectId,快捷创建方法为:

//生成类似:5b9e306a4df4f8c54a39fb0c
String id = ObjectId.next();

//方法2:从Hutool-4.1.14开始提供
String id2 = IdUtil.objectId();

Snowflake

分布式系统中,有一些需要使用全局唯一ID的场景,有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。Twitter的Snowflake 算法就是这种生成器。

使用方法如下:

//参数1为终端ID
//参数2为数据中心ID
Snowflake snowflake = IdUtil.getSnowflake(1, 1);
long id = snowflake.nextId();

//简单使用
long id = IdUtil.getSnowflakeNextId();
String id = snowflake.getSnowflakeNextIdStr();

注意
IdUtil.createSnowflake每次调用会创建一个新的Snowflake对象,不同的Snowflake对象创建的ID可能会有重复,因此请自行维护此对象为单例,或者使用IdUtil.getSnowflake使用全局单例对象。

8. 身份证工具-IdcardUtil
IdcardUtil现在支持大陆15位、18位身份证,港澳台10位身份证。

工具中主要的方法包括:

isValidCard 验证身份证是否合法
convert15To18 身份证15位转18位
getBirthByIdCard 获取生日
getAgeByIdCard 获取年龄
getYearByIdCard 获取生日年
getMonthByIdCard 获取生日月
getDayByIdCard 获取生日天
getGenderByIdCard 获取性别
getProvinceByIdCard 获取省份

String ID_18 = "321083197812162119";
String ID_15 = "150102880730303";

//是否有效
boolean valid = IdcardUtil.isValidCard(ID_18);
boolean valid15 = IdcardUtil.isValidCard(ID_15);

//转换
String convert15To18 = IdcardUtil.convert15To18(ID_15);
Assert.assertEquals(convert15To18, "150102198807303035");//断言

//年龄
DateTime date = DateUtil.parse("2017-04-10");

int age = IdcardUtil.getAgeByIdCard(ID_18, date);
Assert.assertEquals(age, 38);

int age2 = IdcardUtil.getAgeByIdCard(ID_15, date);
Assert.assertEquals(age2, 28);

//生日
String birth = IdcardUtil.getBirthByIdCard(ID_18);
Assert.assertEquals(birth, "19781216");

String birth2 = IdcardUtil.getBirthByIdCard(ID_15);
Assert.assertEquals(birth2, "19880730");

//省份
String province = IdcardUtil.getProvinceByIdCard(ID_18);
Assert.assertEquals(province, "江苏");

String province2 = IdcardUtil.getProvinceByIdCard(ID_15);
Assert.assertEquals(province2, "内蒙古");

9. JSON工具-JSONUtil

JSON字符串创建

JSONUtil.toJsonStr可以将任意对象(Bean、Map、集合等)直接转换为JSON字符串。 如果对象是有序的Map等对象,则转换后的JSON字符串也是有序的。

SortedMap<Object, Object> sortedMap = new TreeMap<Object, Object>() {
private static final long serialVersionUID = 1L;
{
put("attributes", "a");
put("b", "b");
put("c", "c");
}};

JSONUtil.toJsonStr(sortedMap);

结果:

{"attributes":"a","b":"b","c":"c"}

如果我们想获得格式化后的JSON,则:

JSONUtil.toJsonPrettyStr(sortedMap);

结果:

{
"attributes": "a",
"b": "b",
"c": "c"
}

JSON字符串解析

String html = "{\"name\":\"Something must have been changed since you leave\"}";
JSONObject jsonObject = JSONUtil.parseObj(html);
jsonObject.getStr("name");

XML字符串转换为JSON

String s = "<sfzh>123</sfzh><sfz>456</sfz><name>aa</name><gender>1</gender>";
JSONObject json = JSONUtil.parseFromXml(s);

json.get("sfzh");
json.get("name");

JSON转换为XML

final JSONObject put = JSONUtil.createObj()
.set("aaa", "你好")
.set("键2", "test");

// <aaa>你好</aaa><键2>test</键2>
final String s = JSONUtil.toXmlStr(put);

JSON转Bean

我们先定义两个较为复杂的Bean(包含泛型)

@Data
public class ADT {
private List<String> BookingCode;
}

@Data
public class Price {
private List<List<ADT>> ADT;
}

String json = "{\"ADT\":[[{\"BookingCode\":[\"N\",\"N\"]}]]}";

Price price = JSONUtil.toBean(json, Price.class);

//
price.getADT().get(0).get(0).getBookingCode().get(0);

JSON转List

List<ShopType> typeList = query().orderByAsc("sort").list();

// 将ShopType转为String
String jsonStr = JSONUtil.toJsonStr(typeList);

// 4.保存到redis
// string类型
stringRedisTemplate.opsForValue().set(CACHE_SHOP_TYPE_KEY,jsonStr);

String shopTypeJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_TYPE_KEY);
if (StrUtil.isNotBlank(shopTypeJson)) {
// 2.存在直接返回
List<ShopType> shopTypes = JSONUtil.toList(shopTypeJson, ShopType.class);
return Result.ok(shopTypes);
}

readXXX

这类方法主要是从JSON文件中读取JSON对象的快捷方法。包括:

  • readJSON
  • readJSONObject
  • readJSONArray

其它方法
除了上面中常用的一些方法,JSONUtil还提供了一些JSON辅助方法:

quote 对所有双引号做转义处理(使用双反斜杠做转义)
wrap 包装对象,可以将普通任意对象转为JSON对象
formatJsonStr 格式化JSON字符串,此方法并不严格检查JSON的格式正确与否

10. 二维码工具-QrCodeUtil

引入zxing

考虑到Hutool的非强制依赖性,因此zxing需要用户自行引入:

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>

说明 zxing-3.3.3是此文档编写时的最新版本,理论上你引入的版本应与此版本一致或比这个版本新。

生成二维码

在此我们将Hutool主页的url生成为二维码,微信扫一扫可以看到H5主页哦:

// 生成指定url对应的二维码到文件,宽和高都是300像素
QrCodeUtil.generate("https://blog.csdn.net/abst122", 300, 300, FileUtil.file("d:/qrcode.jpg"));

自定义参数(since 4.1.2)

基本参数设定
通过QrConfig可以自定义二维码的生成参数,例如长、宽、二维码的颜色、背景颜色、边距等参数,使用方法如下:

QrConfig config = new QrConfig(300, 300);
// 设置边距,既二维码和背景之间的边距
config.setMargin(3);
// 设置前景色,既二维码颜色(青色)
config.setForeColor(Color.CYAN.getRGB());
// 设置背景色(灰色)
config.setBackColor(Color.GRAY.getRGB());

// 生成二维码到文件,也可以到流
QrCodeUtil.generate("https://blog.csdn.net/abst122", config, FileUtil.file("e:/qrcode.jpg"));

附带logo小图标

QrCodeUtil.generate(//
"https://blog.csdn.net/abst122", //二维码内容
QrConfig.create().setImg("e:/logo_small.jpg"), //附带logo
FileUtil.file("e:/qrcodeWithLogo.jpg")//写出到的文件
);

调整纠错级别

很多时候,二维码无法识别,这时就要调整纠错级别。纠错级别使用zxing的ErrorCorrectionLevel枚举封装,包括:L、M、Q、H几个参数,由低到高。低级别的像素块更大,可以远距离识别,但是遮挡就会造成无法识别。高级别则相反,像素块小,允许遮挡一定范围,但是像素块更密集。

QrConfig config = new QrConfig();
// 高纠错级别
config.setErrorCorrection(ErrorCorrectionLevel.H);
QrCodeUtil.generate("https://blog.csdn.net/abst122", config, FileUtil.file("e:/qrcodeCustom.jpg"));

识别二维码

// decode -> "https://blog.csdn.net/abst122"
String decode = QrCodeUtil.decode(FileUtil.file("d:/qrcode.jpg"));

11. 系统属性调用-SystemUtil

此工具是针对System.getProperty(name)的封装,通过此工具,可以获取如下信息:

Java Virtual Machine Specification信息

SystemUtil.getJvmSpecInfo();

Java Virtual Machine Implementation信息

SystemUtil.getJvmInfo();

Java Specification信息

SystemUtil.getJavaSpecInfo();

Java Implementation信息

SystemUtil.getJavaInfo();

Java运行时信息

SystemUtil.getJavaRuntimeInfo();

系统信息

SystemUtil.getOsInfo();

用户信息

SystemUtil.getUserInfo();

当前主机网络地址信息

SystemUtil.getHostInfo();

运行时信息,包括内存总大小、已用大小、可用大小等

SystemUtil.getRuntimeInfo();

12. JWT(Hutool-jwt)

JWT工具-JWTUtil

JWT创建

Map<String, Object> map = new HashMap<String, Object>() {
private static final long serialVersionUID = 1L;
{
put("uid", Integer.parseInt("123"));
put("expire_time", System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 15);
}
};

JWTUtil.createToken(map, "1234".getBytes());

JWT解析

String rightToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9." +
"eyJzdWIiOiIxMjM0NTY3ODkwIiwiYWRtaW4iOnRydWUsIm5hbWUiOiJsb29seSJ9." +
"U2aQkC2THYV9L0fTN-yBBI7gmo5xhmvMhATtu8v0zEA";

final JWT jwt = JWTUtil.parseToken(rightToken);

jwt.getHeader(JWTHeader.TYPE);
jwt.getPayload("sub");

JWT验证

String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." +
"eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE2MjQwMDQ4MjIsInVzZXJJZCI6MSwiYXV0aG9yaXRpZXMiOlsiUk9MRV_op5LoibLkuozlj7ciLCJzeXNfbWVudV8xIiwiUk9MRV_op5LoibLkuIDlj7ciLCJzeXNfbWVudV8yIl0sImp0aSI6ImQ0YzVlYjgwLTA5ZTctNGU0ZC1hZTg3LTVkNGI5M2FhNmFiNiIsImNsaWVudF9pZCI6ImhhbmR5LXNob3AifQ." +
"aixF1eKlAKS_k3ynFnStE7-IRGiD5YaqznvK2xEjBew";

JWTUtil.verify(token, "123456".getBytes());

JWT验证-JWTValidator

验证算法

算法的验证包括两个方面

  1. 验证header中算法ID和提供的算法ID是否一致
  2. 调用JWT.verify验证token是否正确

// 创建JWT Token
final String token = JWT.create()
.setNotBefore(DateUtil.date())
.setKey("123456".getBytes())
.sign();

// 验证算法
JWTValidator.of(token).validateAlgorithm(JWTSignerUtil.hs256("123456".getBytes()));

验证时间
对于时间类载荷,有单独的验证方法,主要包括:

生效时间(JWTPayload#NOT_BEFORE)不能晚于当前时间
失效时间(JWTPayload#EXPIRES_AT)不能早于当前时间
签发时间(JWTPayload#ISSUED_AT)不能晚于当前时间
一般时间线是:

(签发时间)---------(生效时间)---------(当前时间)---------(失效时间)

签发时间和生效时间一般没有前后要求,都早于当前时间即可。

final String token = JWT.create()
// 设置签发时间
.setIssuedAt(DateUtil.date())
.setKey("123456".getBytes())
.sign();

// 由于只定义了签发时间,因此只检查签发时间
JWTValidator.of(token).validateDate(DateUtil.date());

13. BeanUtil

其实这个才是最常用的

bean转bean

// 1. 将user中所有属性赋值给UserDTO已有饿属性
UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);

// 2. 忽略某个属性方式一
CopyOptions copyOptions = new CopyOptions();
// 2.1 忽略id
copyOptions.setIgnoreProperties("id");
BeanUtil.copyProperties(templateVO, template, copyOptions);

// 3. 忽略某个属性方式二
BeanUtil.copyProperties(copyOptions, OpinionExcelVO.class,"id");

// 4.忽略某个属性方式三
Commodity newCommodity = new Commodity();
CopyOptions copyOptions = new CopyOptions();
String[] properties = new String[]{"id", "commodityAreaList", "commodityAttributeList", "unitPriceAndPicList", "commodityRemark", "commodityShopList"};
copyOptions.setIgnoreProperties(properties);
BeanUtil.copyProperties(commodity, newCommodity, copyOptions);

// 5.忽略某个属性方式四
BeanUtil.copyProperties(commodity, newCommodity, new String[]{"id", "commodityAreaList", "commodityAttributeList", "unitPriceAndPicList", "commodityRemark", "commodityShopList"});

// 6.忽略null不复制
BeanUtil.copyProperties(request,order, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));

bean转map

SubPerson person = new SubPerson();
person.setAge(14);
person.setOpenid("11213232");
person.setName("测试A11");
person.setSubName("sub名字");

Map<String, Object> map = BeanUtil.beanToMap(person);

如果报错

 

@Data
public class UserDTO {
private Long id;
private String nickName;
private String icon;
}

Map<String, Object> userMap = BeanUtil.beanToMap(userDTO);

这里UserDTO中有Long类型将会抛出异常,不能将Long转换为String,这时,可以手动去转,也可以改为

Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
CopyOptions.create()
.setIgnoreNullValue(true)
.setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));

将所有属性都转为String就不会报错了

map转bean

// 方式一
UserDTO userDTOC = BeanUtil.fillBeanWithMap(userMap, new UserDTO, false);
// 方式二
UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, UserDTO.class, false).newInstance();

将集合中每个属性赋值给新对象并加入List
static List copyToList(Collection<?> collection, Class targetType)
复制集合中的Bean属性
此方法遍历集合中每个Bean,复制其属性后加入一个新的List中。
static List copyToList(Collection<?> collection, Class targetType, CopyOptions copyOptions)
复制集合中的Bean属性
此方法遍历集合中每个Bean,复制其属性后加入一个新的List中。

Page<OpinionDO> all = opinionRepository.findAll(specification, page);
List<OpinionExcelVO> opinionExcelVOS = BeanUtil.copyToList(all.getContent(), OpinionExcelVO.class);

判断对象属性是否为null
static boolean isEmpty(Object bean, String… ignoreFieldNames)
判断Bean是否为空对象,空对象表示本身为null或者所有属性都为null
此方法不判断static属性

static boolean isNotEmpty(Object bean, String… ignoreFieldNames)
判断Bean是否为非空对象,非空对象表示本身不为null或者含有非null属性的对象

13. BooleanUtil

// 给定类是否为Boolean或者boolean
BooleanUtil.isBoolean(isMember);
// 判读isMember是否是false
BooleanUtil.isFalse(isMember);
// 判读isMember是否是true
BooleanUtil.isTrue(isMember);
// 转换字符串为boolean值
BooleanUtil.toBoolean(valueStr)

14. ListUtil

需要自己分页时使用page()

// 当前页数,每页总数,需要分页的lisrt
ListUtil.page(int pageNo, int pageSize, List<T> list)

15. CollUtil
isEmpty、isNotEmpty方法比较常用
判断集合是否为空(包括null和没有元素的集合)。

static <T,S extends T> boolean addIfAbsent(Collection collection, S object)
一个对象不为空且不存在于该集合中时,加入到该集合中
static Collection addAll(Collection collection, Iterator iterator)
加入全部

Set<String> set = new HashSet<>();
set.add("1,23,1");
System.out.println("set = " + set);
List<String> objects = new ArrayList<>();
objects.add("88jjj");
System.out.println("objects = " + objects);
CollUtil.addAll(set, objects);
System.out.println("set = " + set);

16. TreeUtil 树工具类

可以快速构建树结构

// 查询数据
List<CodeCategory> all = list();

CodeCategory uncategorizedNode = new CodeCategory();
uncategorizedNode.setId(-1L); // 假设使用负数作为"未分类"节点的id
uncategorizedNode.setName("未分类");
uncategorizedNode.setParentId(1L); // 父节点是全部
all.add(uncategorizedNode);

TreeNodeConfig config = new TreeNodeConfig();
//config可以配置属性字段名和排序等等
//config.setParentIdKey("parentId");
//config.setDeep(20);//最大递归深度 默认无限制

// 设置权重排序
config.setWeightKey("sort");
List<Tree<Long>> treeNodes = TreeUtil.<CodeCategory, Long>build(all, 0L, config, (codeCategory, tree) -> {
tree.setId(codeCategory.getId());//必填属性
tree.setParentId(codeCategory.getParentId());//必填属性
tree.setName(codeCategory.getName());
// 扩展属性 ...
// 获取每个节的数量
Integer integer = itemMapper.selectCount(Wrappers.<Item>lambdaQuery().eq(Item::getId, "10001"));
tree.putExtra("count",integer);
tree.putExtra("full_id",codeCategory.getFullId());
tree.putExtra("createTime", DateUtil.format(codeCategory.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
});

1. 方案一:自己写递归

@Data
public class Tree1 {


private String id;

private String name;

private Integer age;

/**
* 上级id
*/
private String superiorId;

private String address;

/**
* 下级数据
*/
private List<Tree1> children;

public Tree1() {
}

public Tree1(String id, String name, Integer age, String superiorId, String address) {
this.id = id;
this.name = name;
this.age = age;
this.superiorId = superiorId;
this.address = address;
}

}

List<Tree1> list = new ArrayList<>();
Collections.addAll(list,
new Tree1("1", "第一级1", 10, "0", "第一级1地址"),
new Tree1("12", "第二级1", 20, "1", "第二级1地址"),
new Tree1("13", "第二级2", 21, "1", "第二级2地址"),
new Tree1("121", "第三级1", 30, "12", "第三级1地址"),
new Tree1("2", "第一级2", 10, "0", "第一级2地址"));

System.out.println(JSONUtil.toJsonStr(TreeUtils.queryTerr("0", list,
"id", "superiorId", "children")));

TreeUtils

/**
* 递归组装树结构
*
* @param superiorId 父级id
* @param list list数据
* @param currentLevelIdName id的名称
* @param superiorIdName 父级id的名称
* @param childrenName 下级集合的名称
* @return 组装完成的数据
* @throws IllegalAccessException
* @throws NoSuchFieldException
*/
public static List<?> queryTerr(Object superiorId, List<?> list,
String currentLevelIdName, String superiorIdName,
String childrenName) throws IllegalAccessException, NoSuchFieldException {

List<Object> children = new ArrayList<>();

for(Object t : list){

Field fieldSuperiorIdName = t.getClass().getDeclaredField(superiorIdName);
fieldSuperiorIdName.setAccessible(true);
Object tSuperior = fieldSuperiorIdName.get(t);
fieldSuperiorIdName.setAccessible(false);

if(superiorId.equals(tSuperior)){
children.add(t);

Field fieldCurrentLevelIdName = t.getClass().getDeclaredField(currentLevelIdName);
fieldCurrentLevelIdName.setAccessible(true);
Object tCuLeIdName = fieldCurrentLevelIdName.get(t);
fieldCurrentLevelIdName.setAccessible(false);

Field fieldEntity = t.getClass().getDeclaredField(childrenName);
fieldEntity.setAccessible(true);
fieldEntity.set(t, queryTerr(tCuLeIdName, list, currentLevelIdName, superiorIdName, childrenName));
fieldEntity.setAccessible(false);
}
}

return children;
}

 

[
{
"id": "1",
"name": "第一级1",
"age": 10,
"superiorId": "0",
"address": "第一级1地址",
"children": [
{
"id": "12",
"name": "第二级1",
"age": 20,
"superiorId": "1",
"address": "第二级1地址",
"children": [
{
"id": "121",
"name": "第三级1",
"age": 30,
"superiorId": "12",
"address": "第三级1地址",
"children": []
}
]
},
{
"id": "13",
"name": "第二级2",
"age": 21,
"superiorId": "1",
"address": "第二级2地址",
"children": []
}
]
},
{
"id": "2",
"name": "第一级2",
"age": 10,
"superiorId": "0",
"address": "第一级2地址",
"children": []
}
]

2. 方案二:使用TreeUtil

@Data
public class Tree2 {


private Long id;

private String name;

private Integer code;

/**
* 上级id
*/
private Long parentId;

/**
* 下级数据
*/
private List<Tree2> children;

public Tree2(Long id, String name, Integer code, Long parentId) {
this.id = id;
this.name = name;
this.code = code;
this.parentId = parentId;
}

public Tree2() {
}
}


//查询所有数据
List<Tree2> list = new ArrayList<>();
Collections.addAll(list,
new Tree2(1L, "广西壮族自治区", 100000, 0L),
new Tree2(2L, "南宁市", 450000, 1L),
new Tree2(3L, "桂林市", 450000, 1L),
new Tree2(4L, "良庆区", 30, 2L),
new Tree2(5L, "广州省", 30, 0L),
new Tree2(6L, "深圳", 30, 5L),
new Tree2(7L, "广州", 30, 5L),
new Tree2(8L, "桂林甲天下", 10, 3L));

TreeNodeConfig config = new TreeNodeConfig();
//config可以配置属性字段名和排序等等
//config.setParentIdKey("parentId");
//config.setDeep(20);//最大递归深度 默认无限制
// 配置权重排序
config.setWeightKey("name");
List<Tree<Long>> treeNodes = TreeUtil.build(list, 0L, config, (object, tree) -> {
tree.setId(object.getId());//必填属性
tree.setParentId(object.getParentId());//必填属性
tree.setName(object.getName());
// 扩展属性 ...
tree.putExtra("code",object.getCode());
});

System.out.println(JSONUtil.toJsonStr(treeNodes));

}

[
{
"id": 1,
"parentId": 0,
"name": "广西壮族自治区",
"code": 100000,
"children": [
{
"id": 2,
"parentId": 1,
"name": "南宁市",
"code": 450000,
"children": [
{
"id": 4,
"parentId": 2,
"name": "良庆区",
"code": 30
}
]
},
{
"id": 3,
"parentId": 1,
"name": "桂林市",
"code": 450000,
"children": [
{
"id": 8,
"parentId": 3,
"name": "桂林甲天下",
"code": 10
}
]
}
]
},
{
"id": 5,
"parentId": 0,
"name": "广州省",
"code": 30,
"children": [
{
"id": 6,
"parentId": 5,
"name": "深圳",
"code": 30
},
{
"id": 7,
"parentId": 5,
"name": "广州",
"code": 30
}
]
}
]

17. HttpUtil

请求并转换为字节数组

template:
url: https//:xxxx.doc

@Value("${template.url}")
String fileUrl;
byte[] bytes = HttpUtil.downloadBytes(fileUrl);

请求并下载到本地

@Value("${template.url}")
String fileUrl;
byte[] bytes = HttpUtil.downloadFile(fileUrl,"目标文件或目录",30*1000);

18. EmojiUtil

考虑到MySQL等数据库中普通的UTF8编码并不支持Emoji(只有utf8mb4支持),因此对于数据中的Emoji字符进行处理(转换、清除)变成一项必要工作。因此Hutool基于emoji-java库提供了Emoji工具实现。

这里只介绍两个常用的,需要看更多方法请查看hutoolapi文档

static boolean containsEmoji(String str) 是否包含Emoji表情的Unicode符

static String removeAllEmojis(String str) 去除字符串中所有的Emoji Unicode字符

// 判断是否包含Emoji表情的Unicode符
if(EmojiUtil.containsEmoji(request.getName())||EmojiUtil.containsEmoji(request.getTitle())){
return Wrapper.fail("输入参数存在非法字符,请重新输入。");
}

if(EmojiUtil.containsEmoji(request.getName())){
// 去除字符串中所有的Emoji Unicode字符
String resul = EmojiUtil.removeAllEmojis(request.getName());
}

19. PhoneUtil
常用方法:

static boolean isMobile(CharSequence value)验证是否为手机号码(中国大陆)
static boolean isMobileHk(CharSequence value)验证是否为手机号码(中国香港)
static boolean isMobileMo(CharSequence value)验证是否为手机号码(中国澳门)
static boolean isMobileTw(CharSequence value)验证是否为手机号码(中国台湾)
static boolean isPhone(CharSequence value)验证是否为座机号码+手机号码(CharUtil中国)+ 400 + 800电话 + 手机号号码(中国香港)

if(!phone){
return Wrapper.fail("输入的手机号存在非法字符,请重新输入。");
}

20. HttpRequest

HttpUtil就是对HttpRequest再次封装,HttpUtil中的get和post工具方法都是HttpRequest对象的封装,因此如果想更加灵活操作Http请求,可以使用HttpRequest。

发起post请求

String url="http://example.com/api/user";
HttpRequest request = HttpRequest.post(url)
.header("Content-Type", "application/json"); // 设置请求头
FaceRegisterRequest obj = new FaceRegisterRequest();
obj.setCattle_id("112233");
obj.setCattle_name("1111");
obj.setFace_img("1213");
// 构建请求参数
JSON parse = JSONUtil.parse(obj);
System.out.println("请求参数 = " + parse.toString());
request.body(parse.toString());// 设置请求体
// 发起请求
HttpResponse response = request.execute();

// 获取响应状态
int status = response.getStatus();
System.out.println("status = " + status);
if (status != 200) {
System.out.println("请求错误");
return;
}
// 获取响应body
String body = response.body();
System.out.println("响应body = " + body);
JSONObject jsonObject = JSONUtil.parseObj(body);
String code = jsonObject.get("code").toString();
System.out.println("code = " + code);
String message = jsonObject.get("message").toString();
System.out.println("message = " + message);
String data = jsonObject.get("data").toString();
System.out.println("data = " + data);
}

http://example.com/api/user发起了一条POST请求,请求体中包含了JSON格式的数据:

{
"cattle_id":"112233",
"cattle_name":"1111",
"face_img":"1213"
}

发起get请求

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", 1);
paramMap.put("name", "hutool");

String url = "http://example.com/api";
HttpRequest request = HttpUtil.createGet(url);
request.form(paramMap);

HttpResponse response = request.execute();
String result = response.body();
System.out.println(response.body());

根据代码,实际请求的url为 http://example.com/api?id=1&name=hutool。其中,参数id的值为1,参数name的值为hutool。

标签:DateUtil,JAVA,String,HuTool,神器,date,new,id,name
From: https://www.cnblogs.com/andy1234/p/17778896.html

相关文章

  • JavaScript 运算符
     算术运算符简表运算符描述例子x的运算结果y的运算结果在线实例(来源runoob.com)+加法x=y+275实例>>-减法x=y-235实例>>*乘法x=y*2105实例>>/除法x=y/22.55实例>>%取余数(模)x=y%215实例>>++ 自......
  • Java List数据结构底层实现与常用实现类解析
    一、JavaList数据结构的底层实现原理List是Java中最常用的数据结构之一,它可以按照元素的插入顺序有序存储一组对象。在Java中,List接口有多种不同的实现方式,每种方式都有自己的底层实现机制。1.1数组实现ArrayList是List接口最常用的实现类之一,它使用数组作为底层数据结构。ArrayL......
  • Java并发工具类CountDownLatch(倒计数器)
    CountDownLatch,倒计数器,有两个常见的应用场景:场景1:协调子线程结束动作:等待所有子线程运行结束CountDownLatch允许一个或多个线程等待其他线程完成操作。例如,我们很多人喜欢玩的王者荣耀,开黑的时候,得等所有人都上线之后,才能开打。CountDownLatch模仿这个场景:创建大乔、兰陵王、安......
  • Java 项目引入logback
    参考文档:https://www.cnblogs.com/songxingzhu/p/10119378.html <!--BeginLogBackLog--><!--https://mvnrepository.com/artifact/ch.qos.logback/logback-classic--><dependency><groupId>ch.qos.logback</g......
  • java项目实践-jsp-finter-监听器-day19
    目录1.jsp2.过滤器3.listener监听器1.jspservle逻辑处理方便html页面表现麻烦jsp页面表现方便但是逻辑处理麻烦JSP是一种页面技术JSP本质上是servlet类通过JSP引擎翻译成servletjsp约等于java+html注意:jsp不是访问静态的html文件index.jsp修改成如下代码:<%-......
  • javaparser java 源码扫描解析
    参考文档:https://www.bilibili.com/read/cv22893728/ 使用到的以来:<dependency><groupId>com.github.javaparser</groupId><artifactId>javaparser-core</artifactId><version>3.25.5</version></dependency>......
  • 基于Java的健身运动网站设计与实现
    (文章目录)具体实现截图主要功能:基于java(ssm)健身运动网站系统系统分为用户和管理员两个角色用户的主要功能有:1.用户注册和登陆系统2.查看健身知识3.查看健身器材介绍信息4.查看健身教练,在线预约教练5.查看健身课程,在线购买课程信息6.查看健身商品信息,在线购买健身商品,......
  • Java零基础入门-常量
    前言在学习Java语言的过程中,常量是一个非常重要的概念。它不仅在代码中被广泛应用,而且在Java面试中也是被常问到的知识点。因此,本篇文章将着重介绍Java中常量的相关知识,希望能够帮助Java初学者更好地掌握这个概念。摘要本文主要介绍Java中的常量。首先,我们将讲解常量的概念和作......
  • Java零基础入门-包装类
    前言Java是一种广泛使用的面向对象编程语言,它通过JVM(Java虚拟机)来实现跨平台。如果您刚刚开始学习Java编程语言,那么您可能会发现Java中的包装类是一个挑战。本文将对Java中的包装类进行详细介绍,以帮助您更好地理解Java编程语言。摘要在Java编程语言中,包装类用于将基本数据类型转......
  • Java零基础入门-自动拆箱
    前言Java作为目前最流行的编程语言之一,受到广泛的关注和应用。但是对于零基础的Java初学者来说,由于其语言复杂度较高,入门难度较大。特别是在处理数据类型时,自动拆箱这个概念更是容易让人产生困惑。因此,本文旨在对Java中的自动拆箱进行详细讲解,帮助初学者更好地理解和运用Java语言......