Руководство по API Hutool

Java

     Представить сверхмощный отечественный продуктИнструменты Java — Hutool. Hutool — это библиотека классов набора инструментов Java, которая инкапсулирует методы JDK, такие как файлы, потоки, шифрование и дешифрование, транскодирование, регуляризация, многопоточность и XML, для формирования различных классов инструментов Util. Он подходит для многих проектов и веб-разработки и не имеет связи с другими фреймворками.

=========================================================

1. Инструмент времени Hutool — DateUtil

1.1 Введение в классы времени и даты

  • DateUtilПредоставляет набор статических методов для операций даты и времени.
  • DateTimeОбеспечивает инкапсуляцию, аналогичную объектам даты и времени в Joda-Time, наследуя Date
  • FastDateFormatОбеспечивает поддержку потокового форматирования и синтаксического анализа строки даты для объектов Date. Этот объект не нуждается в восприятии при фактическом использовании, и соответствующие операции инкапсулированы в соответствующие методы DateUtil и DateTime.
  • DateBetweenКласс для вычисления двух временных интервалов, помимо того, что он используется для создания новых объектов, связанные операции также были инкапсулированы в связанных методах DateUtil и DateTime.
  • TimeIntervalПростой класс таймера, который часто используется для расчета времени выполнения определенного фрагмента кода. Он обеспечивает расчет времени, затраченного на выполнение, в различных единицах, включая миллисекунды, секунды, минуты, часы, дни и недели. объект был инкапсулирован в DateUtil.
  • DatePatternПредоставляет общие режимы форматирования даты, включая String и FastDateFormat.

     в основном необходимо понимать класс DateUtil, класс DateTime и класс DatePattern, которые могут работать с большинством операций со временем и датой.

1.2 Класс инструментов времени DateUtil

    DateUtil — все статические методы, вот некоторыеПростой способ;

now():String //当前日期时间 yyyy-MM-dd hh:mm:ss
today():String //今天日期 yyyy-MM-dd

date():DateTime 
    /*当前时间的DateTime对象(相当于new DateTime()或者new Date()),
    此外还提供一个重载方法,传递long类型参数,是给定一个Unix时间戳,
    返回这个时间戳的时间。*/
lastWeek():DateTime //上周今天(往前7天)
lastMonth():DateTime //上个月今天(往前一个月)
nextWeek():DateTime //下周今天(往后7天)
nextMonth():DateTime //下个月今天(往后一个月)
yesterday():DateTime //昨天同时
tomorrow():DateTime //明天同时

currentSeconds():long //毫秒数

thisYear():int //年份
thisMonth():int //月份(从0开始)
thisWeekOfMonth():int //本月周次(从1开始)
thisWeekOfYear():int //本年周次(从1开始)
thisDayOfMonth():int //本月第几天(从1开始)
thisDayOfWeek():int //本周第几天(从1开始)
thisHour(boolean is24HourClock):int //当前小时
thisMinute():int //当前分
thisSecond():int //当前秒

1.3 Преобразование между датами и строками

1.3.1 Разбор строк даты

     преобразует некоторые строки фиксированного формата --> объекты даты:

yyyy-MM-dd hh:mm:ss
yyyy-MM-dd
hh:mm:ss
yyyy-MM-dd hh:mm

如果你的日期格式不是这几种格式,则需要指定日期格式,对于以上格式还有专门的方法对应:
    parseDateTime parseDate ParseTime


DateUtil.parse()
DateUtil.parse(String,String) //Date 转换为指定格式的Date对象

1.3.2 Форматирование дат

需要将日期时间格式化输出,Hutool提供了一些方法实现:
    DateUtil.formatDateTime(Date date):String //将返回“yyyy-MM-dd hh:mm:ss”格式字符串
    DateUtil.formatDate(Date date):String //将返回“yyyy-MM-dd“格式字符串
    DateUtil.formatTime(Date date):String //将返回“hh:mm:ss“格式字符串
    DateUtil.format(Date,String):String //将返回指定格式的字符串

1.4 Время начала и окончания

    Hutool может легко получить время начала и время окончания определенного дня/месяца/года:

beginOfDay(Date):Date 一天开始时刻
endOfDay(Date):Date 一天结束时刻

beginOfMonth(Date):Date
endOfMonth(Date):Date
	 
beginOfYear(Date):Date
endOfYear(Date):Date

getBeginTimeOfDay 获得给定日期当天的开始时间,开始时间是00:00
getEndTimeOfDay 获得给定日期当天的结束时间,结束时间是23:59。

     Если вам нужно указать дату для смещения, используйте offsiteDay, offsiteWeek, offsiteMonth, чтобы получить указанную датусмещение датыДень, неделя смещения, месяц смещения, указанное смещение является положительным числом для смещения в будущее и отрицательным числом для смещения в истории.
     Если приведенное выше не соответствует требованиям смещения, используйте спецификацию смещения offsiteDate, где параметр calendarField представляет собой степень детализации смещения (часы, дни, месяцы и т. д.) с использованием констант в классе Calendar.

1.5 Временной интервал

1.between方法
    Hutool可以方便的计算时间间隔,使用 DateUtil.between(Date begin,Date end,DateUnit):long 
计算间隔,方法有三个参数,前两个分别是开始时间和结束时间,第三个参数是DateUnit的枚举,
表示差值以什么为单位。

    DateUnit的取值可以是DateUnit.DAY(天),DateUnit.HOUR(小时),DateUnit.WEEK(周),
DateUnit.SECOND(秒),DateUnit.MINUTE(分钟);

2.formatBetween方法
    也可以将差值转为指定具体的格式,比如 XX天XX小时XX分钟XX秒 这样的格式,可以使用
DateUtil.formatBetween(Date begin,Date end,Level):String  方法,有三个参数,
前两个依然是开始和结束时间,第三个参数表示精确度,比如Level.SECOND表示精确到秒,
即XX天XX小时XX分钟XX秒的格式。

3.diff方法
    返回两个日期的时间差,参数diffField定义了这个差的单位,单位的定义在DateUtil的常量中,
例如DateUtil.SECOND_MS表示两个日期相差的秒数。

1.6 Рассчитать возраст

     С помощью Hutool вы можете мгновенно рассчитать свой возраст. Вам все еще нужно беспокоиться о ложном возрасте? Нет, Hutool говорит, что столько, сколько. Мы можем использовать следующий метод:

age(Date begin,Date end):int 出生和去世日期计算年龄
ageOfNow(String birthday):int 计算到当前日期的年龄
ageOfNow(Date birthday):int 计算到当前日期的年龄

1.7 Определение високосных лет

использоватьDateUtil.isLeapYear(in year):boolean Определяет, является ли год високосным.

1.8 DateTime

     Разобраться с DateUtil, а затем посмотреть на DateTime должно быть очень просто, потому что большинство методов в DateTime похожи на DateUtil. Класс DateTime наследуется от java.util.Date, который может полностью заменить использование Date и имеет другие практичные методы!

     Давайте сначала разберемся с методом построения DateTime:

方法一:使用new
DateTime dt=new DateTime();   //创建当前时刻
DateTime dt=new DateTime(Date date);   //使用Date对象构造
DateTime dt=new DateTime(long timeMillis);   //使用毫秒数构造

方法二:使用of()方法
DateTime dt=DateTime.of();

方法三:使用now()方法
DateTime dt=DateTime.now();          //创建当前时刻

DateTime里面还有两个非常实用的方法,就是before(Date when):boolean 和 after(Date when):boolean,
它们可以判断时间的先后。

1.9 DatePattern

     Наконец, давайте взглянем на класс DatePattern, который в основном предоставляет некоторыеУказанный формат времени и даты (оба имеют тип String), в том числе различие регионов выражено:

格式化模板: 
    DatePattern.CHINESE_DATE_PATTERN //yyyy年MM月dd日
    DatePattern.NORM_DATE_PATTERN //yyyy-MM-dd
    DatePattern.NORM_TIME_PATTERN //HH:mm:ss
    DatePattern.NORM_DATETIME_PATTERN //yyyy-MM-dd HH:mm:ss
    DatePattern.UTC_PATTERN //yyyy-MM-dd'T'HH:mm:ss'Z'
    DatePattern.PURE_DATE_PATTERN //yyyyMMdd
    DatePattern.PURE_TIME_PATTERN //HHmmss
    DatePattern.PURE_DATETIME_PATTERN //yyyyMMddHHmmss
作者:「612星球的一只天才猪」路小磊 
原文链接:https://blog.csdn.net/tianc_pig/article/details/87826810
          https://my.oschina.net/looly/blog/268552
来源:CSDN oschina

=========================================================

2. Строковый инструмент Hutool — StrUtil

    Палец струнного инструментаcn.hutool.core.util.StrUtilКласс, который инкапсулирует различные методы String и предоставляет другие удобные и практичные методы. Методы в StrUtil являются статическими методами.

2.1 Оценка того, является ли он пустым, по нескольким строкам

     Нуль здесь имеет два значения: одно — это нуль или "" (пустая строка), а другое — строка, состоящая из невидимых символов (невидимая строка), например строка, состоящая из пробелов (" "). Hutool предлагает различные методы для решения этих двух ситуаций.
похож наApache Commons LangStringUtil в , причина, по которой StrUtil используется вместо StringUtil, заключается в том, что первый короче, и я думаю, что аббревиатура Str глубоко укоренилась в сердцах людей. Мы не будем здесь приводить часто используемые методы, такие как isBlank, isNotBlank, isEmpty, isNotEmpty, а чтобы определить, пуста ли строка, я расскажу еще о нескольких полезных функциях.

Наиболее часто используемые методы показаны в следующей таблице:

isBlank(CharSequence arg0):boolean //判断字符串是否为null或者””或者是不可见字符串
isEmpty(charSequence arg0):boolean //判断字符串是否为null或者””
hasBlank(CharSequence…arg0):boolean //判断多个字符串中是否有null或者””或者是不可见字符串
hasEmpty(CharSequence…arg0):boolean //判断多个字符串中是否有null或者””

表单登录时,常用hasEmpty()方法。

2.2 подметод

Метод     sub() эквивалентен методу subString();
     имеет три параметра: первый — это перехватываемая строка, а последние два — позиции начала и конца. Одной из самых больших особенностей метода sub() является то, что уровень отказоустойчивости очень высок, и -1 означает последний символ, -2 означает предпоследний символ и так далее. И положение головы и хвоста также можно поменять местами.

String testStr="my name is smartPig";
String result01=StrUtil.sub(testStr, 0, 4); //my n
/*虽然是4-0,但是实际上还是算成0-4*/
String result02=StrUtil.sub(testStr, 4, 0); //my n
String result03=StrUtil.sub(testStr, -1, 3); //name is smartPi
String result04=StrUtil.sub(testStr, -4, 3); //name is smar

2.3 метод форматирования

format方法类似于JDBC中PreparedStatement中的?占位符,可以在字符串中使用”{}”作为占位符。
String testStr="{} name is smart{}";
String result=StrUtil.format(testStr, "my","Pig"); //my对应第一个{},Pig对应第二个{}
//结果如下:my name is smartPig

2.4 Удалить префикс и суффикс

    Hutool может удалить префикс/суффикс строки, эта функция очень удобна для удаления суффикса имени файла. Соответствующие методы следующие:

removeSuffix(CharSequence str, CharSequence suffix) //去除后缀
removeSuffixIgnoreCase(CharSequence str, CharSequence suffix) //去除后缀,忽略大小写

removePrefix(CharSequence str, CharSequence suffix) //去除前缀
removePrefixIgnoreCase(CharSequence str, CharSequence suffix) //去除前缀,忽略大小写

2.5 Строковые константы

 Hutool定义了一些字符常量,可以灵活使用。部分常量如下所示:
StrUtil.DOT //点.
StrUtil.DOUBLE_DOT //双点..
StrUtil.UNDERLINE //下划线_
StrUtil.EMPTY //横杠_
StrUtil.BACKSLASH //反斜杠\
StrUtil.DASHED //破折-
StrUtil.BRACKET_END //右中扩号]
StrUtil.BRACKET_START //左中括号[
StrUtil.COLON //冒号:
StrUtil.COMMA //逗号,
StrUtil.DELIM_END //右大括号}
StrUtil.DELIM_START //左大括号{

2.6 Строка в обратном порядке

  Hutool可以很容易的实现字符串逆序。可以使用StrUtil.reverse(String str):String方法。

2.7 методы кодирования и декодирования

把String.getByte(String charsetName)方法封装在这里了,原生的String.getByte()这个方法太坑了,使用系统编码,
经常会有人跳进来导致乱码问题,所以就加了这两个方法强制指定字符集了,包了个try抛出一个运行时异常,
省的我得在业务代码里处理那个恶心的UnsupportedEncodingException。
作者:「612星球的一只天才猪」路小磊 
原文链接:https://blog.csdn.net/tianc_pig/article/details/87944463
          https://my.oschina.net/looly/blog/262775
来源:CSDN oschina

=========================================================

3. Случайный инструмент Hutool — RandomUtil

Основные методы инструмента      random следующие:

RandomUtil.randomInt 获得指定范围内的随机数
RandomUtil.randomEle 随机获得列表中的元素
RandomUtil.randomString 获得一个随机的字符串(只包含数字和字符)
RandomUtil.randomNumbers 获得一个只包含数字的字符串
RandomUtil.randomNumber 获得一个随机数
RandomUtil.randomChar 获得随机字符

     Эти методы имеют некоторые перегруженные методы, как показано в следующей таблице:

randomInt():int //获得一个随机整数
randomInt(int limit):int //获得一个<limit的随机整数
randomInt(int min,int max):int //获得一个随机整数n(min<=n<max)

randomChar():char //获得一个随机字符
randomChar(Strint str):char //从指定字符串中获得一个随机字符

randomNumber():int //获得一个随机数
randomNumbers(int length):String //获得长度为length由数字组成的字符串

randomString(int length):String //获得一个长度为length的字符串,只包含数字和字符
randomString(String str,int length):String //从str中随机产生指定长度的字符串(所有字符来源于str)

randomEle(T array[]):T //从数组中随机获取一个数据
randomEle(List<T> list):T //从List中随机获取一个数据
randomEle(List<T> list,int limit):T //从List的前limit个中随机获取一个数据(limit从1开始)
作者:「612星球的一只天才猪」
原文链接:https://blog.csdn.net/tianc_pig/article/details/88034976
来源:CSDN

=========================================================

4. Штатный инструмент Hutool — ReUtil

4.1 Оценка соответствия

使用 isMatch(String regex,CharSequence content):boolean 
第一个参数是正则,第二个是匹配的内容。

4.2 Удалить соответствующий контент

delFirst(String regex,CharSequence content):String //删除匹配的第一个字符串,返回删除后的字符串

delAll(String regex,CharSequence content):String //删除匹配的所有字符串,返回删除后的字符串

4.3 Получите соответствующий контент

使用findAll(String regex, CharSequence content, int group): List<String>
可以获得所有匹配的内容

4.4 Замена соответствующего контента

使用replaceAll(CharSequence content, String regex, String replacementTemplate):String
可以替换匹配的内容。

4.4 Автоматическое экранирование специальных символов

使用escape(CharSequence arg0):String
可以将用于正则表达式中的某些特殊字符进行转义,变成转义字符。
作者:「612星球的一只天才猪」
原文链接:https://blog.csdn.net/tianc_pig/article/details/88134882
来源:CSDN

=========================================================

5. Инструмент пейджинга Hutool — PageUtil

PageUtil的静态方法
transToStartEnd(int,int):int[] 	//将页数和页容量转换为数据表中的起始位置
    /*第一个参数是页码数,第二个参数是每一页的容量,
    返回值是一个长度为2的数组,分别表示开始位置和结束位置。*/
    
    /*获得指定页的结果集
	@param pageNum 页数(从1开始)
	@param pageSize 每页容量	
	int startEnd[]=PageUtil.transToStartEnd(pageNum, pageSize);*/
	
totalPage(int,int):int 	//由总记录数和页容量获得页数
    //第一个参数是总的记录数,第二个参数是每页的容量,返回值是总页数。
    /*
        @param totalCount 总记录数
        @param pageSize 每页的记录数
	int totalPage = PageUtil.totalPage(totalCount, pageSize);*/

彩虹分页算法
    rainbow(int,int):int[] 
    //第一个参数表示当前页码,第二个参数表示总页数,这种情况默认是一次显示所有的页码
    //(这个方法个人觉得没有什么用)
    rainbow(int,int,int):int[] 
    //第一个参数表示当前页码,第二个参数表示总页数,第三个参数表示每一次最多显示的页数

Алгоритм радужного пейджинга применяется к веб-страницам, которым необходимо часто отображать [предыдущая страница] 1 2 3 4 5 [следующая страница] такие номера страниц, как правило, динамически обновлять отображаемый номер страницы в соответствии с текущим номером страницы, потому что каждый раз количество отображаемые номера страниц фиксированы.

/**
 * 测试分页彩虹算法
 * @param curPage 当前页数
 * @param totalPage 总页数
 */
public static String rainbowPage(int curPage,int totalPage) {
	int rainbow[]=PageUtil.rainbow(curPage,totalPage);
	return Arrays.toString(rainbow);
}

/**
 * 测试分页彩虹算法
 * @param curPage 当前页数
 * @param totalPage 总页数
 * @param size 每次显示的页数量
 */
public static String rainbowPage(int curPage,int totalPage,int size) {
	int rainbow[]=PageUtil.rainbow(curPage,totalPage,size);
	return Arrays.toString(rainbow);
}

MyBatis предоставляет инструменты пейджинга и поддерживает пейджинг плагинов.

作者:「612星球的一只天才猪」
原文链接:https://blog.csdn.net/tianc_pig/article/details/88628323
来源:CSDN

=========================================================

6. Инструмент коллекции Hutool — CollectionUtil

     в основном увеличивает количество операций с массивами и коллекциями.

6.1 Метод соединения

     Преобразует коллекцию в строку.Этот метод довольно распространен и является обратным методом StrUtil.split. Параметры этого метода поддерживают набор объектов различных типов, а метод toString() вызывается при окончательном подключении каждого объекта. следующее:

String[] col= new String[]{a,b,c,d,e};
String str = CollectionUtil.join(col, "#"); //str -> a#b#c#d#e

6.2 Методы sortPageAll, sortPageAll2

Функция      заключается в следующем: поместить несколько заданных коллекций в список (список), отсортировать в соответствии с заданным объектом Comparator, а затем разбить данные на страницы. Этот метод очень похож на сортировку и листание после запроса нескольких таблиц в базе данных, и смысл этого метода тоже здесь. Функции и результаты sortPageAll2 и sortPageAll одинаковы. Разница в том, что sortPageAll2 использует класс BoundedPriorityQueue для хранения объединенного списка. Я не знаю, какой из них имеет лучшую производительность, поэтому все они зарезервированы. следующее:

Comparator<Integer> comparator = new Comparator<Integer>(){ //Integer比较器
	@Override
	public int compare(Integer o1, Integer o2) {
		return o1.compareTo(o2);
	}
};

//新建三个列表,CollectionUtil.newArrayList方法表示新建ArrayList并填充元素
List<Integer> list1 = CollectionUtil.newArrayList(1, 2, 3);
List<Integer> list2 = CollectionUtil.newArrayList(4, 5, 6);
List<Integer> list3 = CollectionUtil.newArrayList(7, 8, 9);

//参数表示把list1,list2,list3合并并按照从小到大排序后,取0~2个(包括第0个,不包括第2个),结果是[1,2]
@SuppressWarnings("unchecked")
List<Integer> result = CollectionUtil.sortPageAll(0, 2, comparator, list1, list2, list3);
System.out.println(result);     //输出 [1,2]

6.3 Метод sortEntrySetToList

     в основном правEntry<Long, Long>Сортировка по значению Value, использование которого более ограничено

6.4 Метод popPart

     Этот метод передает объект стека, а затем извлекает указанное количество объектов-элементов. Pop относится к методу pop(), который будет удален из исходного стека.

6.5 методы newHashMap, newHashSet, newArrayList

     Эти методы предназначены для создания новой структуры данных.Тип элемента структуры данных зависит от типа вашей переменной следующим образом:

HashMap<String, String> map = CollectionUtil.newHashMap();
HashSet<String> set = CollectionUtil.newHashSet();
ArrayList<String> list = CollectionUtil.newArrayList();

6.6 метод добавления

Добавить элемент в конец заданного массива.На самом деле List.add() тоже реализован таким образом.Смысл этого метода в том,что он используется только при добавлении небольшого количества элементов,потому что System.arraycopy используется внутренне, и массив копируется каждый раз, когда он вызывается. Этот метод также используется в некоторых случаях, когда можно использовать только массивы, устраняя необходимость сначала преобразовать в список, добавить элементы, а затем преобразовать в массив.

6.7 метод изменения размера

     Повторно отрегулируйте размер данных. Если скорректированный размер меньше исходного, обрежьте его. Если он больше исходного, дополнительная позиция будет пустой. (Кажется, List будет использовать аналогичный метод при расширении)

6.8 Метод addAll

     Объединяет несколько данных в один массив

6.9 Метод диапазона

     Этот метод получен из синтаксического сахара в Python. Учитывая начало, конец и шаг, будет сгенерирована арифметическая последовательность (список)

int[] a1 = CollectionUtil.range(6);       //[0,1,2,3,4,5]
int[] a2 = CollectionUtil.range(4, 7);    //[4,5,6]
int[] a3 = CollectionUtil.range(4, 9, 2); //[4,6,8]

6.10 подметод

     Нарезка коллекции, другие типы коллекций будут преобразованы в список, инкапсулирован метод List.subList, автоматически исправлены такие проблемы, как выход за границы, и полностью исключено исключение IndexOutOfBoundsException.

6.11 Методы isEmpty, isNotEmpty

     определяет, пуста ли коллекция (включая null и коллекции без элементов).

6.12 почтовый метод

     Этот метод также является синтаксическим сахаром, полученным из Python.Для двух наборов элементы в двух наборах соответствуют один к одному, чтобы стать картой. Этот метод также имеет перегруженный метод, который может передавать символы, а затем, учитывая разделитель, строка будет разбита на список.

String[] keys = new String[]{"a", "b", "c"};
Integer[] values = new Integer[]{1, 2, 3};
Map<String, Integer> map = CollectionUtil.zip(keys,values);
System.out.println(map);    // {b=2, c=3, a=1}

String a = "a,b,c";
String b = "1,2,3";
Map<String, String> map2 = CollectionUtil.zip(a,b, ",");
System.out.println(map2);   // {b=2, c=3, a=1}
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/262786
来源:oschina

=========================================================

7. Инструменты обработки, такие как Hutool - ClassUtil

     в основном инкапсулирует некоторые методы отражения, и наиболее полезным методом в этом классе является метод scanPackage, который сканирует все классы в пути к классам, что является одной из функций Spring и в основном является основой для сканирования классов в фреймворке Hulu.

7.1 метод scanPackage

     Единственным параметром этого метода является имя пакета, а возвращаемым результатом является этот пакет и все классы подпакетов. Этот метод очень прост в использовании, но процесс более сложен.Сканирование пакета сначала вызывает метод getClassPaths для получения ClassPath, а затем сканирует ClassPath.Если это каталог, сканируйте файлы классов или jar-файлы в каталог. Если это пакет jar, получите имя класса непосредственно из пакета jar. Роль этого метода очевидна, он заключается в поиске всех классов, в Spring для внедрения зависимостей, в Hulu используется для поиска класса Action. Конечно, вы также можете передать объект ClassFilter для фильтрации нежелательных классов.

7.2 Метод getMethods

     Этот метод аналогичен методу getMethods объекта Class, но возвращает только имя (строку) метода, а инкапсуляция очень проста.

7.3 Метод getClassPaths

     Этот метод предназначен для получения ClassPath текущего потока, ядром является вызов Thread.currentThread().getContextClassLoader().getResources.

7.4 Метод getJavaClassPaths

     Этот метод используется для получения ClassPath, определенного системной переменной java.

7.5 метод синтаксического анализа

Этот метод инкапсулирует принудительное преобразование типа.Сначала будет вызван метод приведения самого объекта.Если не получится,то будет пробовать является ли он базовым типом (int,long,double,float и т.д.), и если он не удается, он попытается использовать дату, число и поток байтов.Короче говоря, это более инклюзивный метод преобразования типов, избавляющий нас от утомительных попыток много раз, не зная типа.

7.6 метод parseBasic

     Этот метод вызывается методом parse, который специально используется для преобразования строки набора символов в объект базового типа (Integer, Double и т. д.). Можно сказать, что это универсальный метод преобразования. Названия методов JDK слишком неуклюжи. Например, если вы хотите преобразовать в Long, вам нужно вызвать метод Long.parseLong. Имейте только этот метод.

7.7 метод castToPrimitive

     Этот метод довольно неудобный. Он состоит в том, чтобы изменить класс Integer на int.class, что кажется бесполезным. Я забыл, где его использовать. Если вы можете использовать его, это будет здорово.

7.8 Методы getClassLoader и getContextClassLoader

     Последний просто получает ClassLoader текущего потока, а первый получает ClassLoader класса ClassUtil в случае сбоя получения.

7.9 метод newInstance

     создает экземпляр объекта и инкапсулирует метод Class.forName(clazz).newInstance().

7.10 метод cloneObj

     клонирует объект. Для некоторых объектов, которые не реализуют интерфейс Cloneable, клонировать действительно сложно.Например, при инкапсуляции клиента Redis клонировать объект конфигурации в принципе невозможно, поэтому я написал этот метод.Принцип использования ObjectOutputStream для скопируйте поток объектов.

作者:路小磊
原文链接:https://my.oschina.net/looly/blog/268087
来源:oschina

=========================================================

8. Файловые инструменты, такие как Hutool — FileUtil

8.1 Введение

В инструментах Java операции с файлами также должны использоваться довольно часто, но операции Java с файлами включают потоки, поэтому это более громоздко, а различные потоки также ослепляют, поэтому я думаю, что в пакете util в большинстве проектов есть FileUtil. класс, и этот класс является сводкой многих FileUtils.

8.2 Соответствующий метод команды Linux

Эти методы названы в соответствии с командами Linux, что удобно для пользователей, знакомых с Linux, чтобы знать их имена, например:

ls 返回给定目录的所有文件对象列表,路径可以是相对ClassPath路径或者绝对路径,不可以是压缩包里的路径。
listFileNames 则是返回指定目录下的所有文件名,支持jar等压缩包。
touch 创建文件,如果给定路径父目录不存在,也一同创建。
del 删除文件或者目录,目录下有嵌套目录或者文件会一起删除。
mkdir 创建目录,父目录不存在自动创建。
createTempFile 创建临时文件,在程序运行完毕的时候,这个文件会被删除。
copy 复制文件或目录,目标文件对象可以是目录,自动用原文件名,可以选择是否覆盖目标文件。
move 移动文件或目录,原理是先复制,再删除原文件或目录
isExist 文件或者目录是否存在。

8.3 Общие методы

getAbsolutePath 获得绝对路径,如果给定路劲已经是绝对路径,返回原路径,否则根据ClassPath
        或者给定类的相对位置获得其绝对位置
close 对于实现了Closeable接口的对象,可以直接调用此方法关闭,且是静默关闭,关闭出错将不
        会有任何调试信息。这个方法也是使用非常频繁的,例如文件流的关闭等等。
equals 比较两个文件是否相同

8.4 Чтение и запись файлов

8.4.1 Запись файлов

getBufferedWriter 获得带缓存的写入对象,可以写字符串等。
getPrintWriter 对 getBufferedWriter的包装,可以有println等方法按照行写出。
getOutputStream 会的文件的写出流想对象。
writeString直接写字符串到文件,会覆盖之前的内容。
appendString 追加字符串到文本。
writeLines appendLines 覆盖写入和追加文本列表,每个元素都是一行。
writeBytes 写字节码。
writeStream 写流中的内容到文件里。

8.4.2 Чтение файла

getReader 获得带缓存的Reader对象。
readLines 按行读取文件中的数据,返回List,每一个元素都是一行文本。
load 按照给定的ReaderHandler对象读取文件中的数据,ReaderHandler是一个借口,实现后就可以操作Reader对象了,这个方法存在是为了避免用户手动调用close方法。
readString 直接读出文件中的所有文本。
readBytes 读字节码

8.4.3 Прочее

isModifed 文件是否被修改过,需要传入一个时间戳,用来比对最后修改时间。
getExtension 获得文件的扩展名。
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/288525
来源:oschina

=========================================================

9. Ограниченная приоритетная очередь Hutool — BoundedPriorityQueue

9.1 Происхождение

    Например: У меня есть таблица пользователей, эта таблица хэшируется в разные экземпляры базы данных по имени пользователя, я хочу узнать 5 самых популярных из этих пользователей, как это сделать? Вот как я это делаю:

在每个数据库实例上找出最热门的5个
将每个数据库实例上的这5条数据按照热门程度排序,最后取出前5条

     Этот процесс кажется простым, но вам нужно написать много кода на сервере приложений. Во-первых, вам нужно запросить N списков, добавить их в новый список, отсортировать их, а затем взять первые 5. Этот процесс не только громоздок для кода, но также включает в себя несколько списков, что является пустой тратой места. тогда,BoundedPriorityQueuе возник.

/**
 * 有界优先队列
 */
public class BoundedPriorityQueueDemo {
	public static void main(String[] args) {
		//初始化队列,设置队列的容量为5(只能容纳5个元素),
		//元素类型为integer使用默认比较器,在队列内部将按照从小到大排序
		BoundedPriorityQueue<Integer> queue = new BoundedPriorityQueue<Integer>(5);
        
                //初始化队列,使用自定义的比较器
		queue = new BoundedPriorityQueue<>(5, new Comparator<Integer>(){
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1.compareTo(o2);
			}
		});
		
		//定义了6个元素,当元素加入到队列中,会按照从小到大排序,
		//当加入第6个元素的时候,队列末尾(最大的元素)将会被抛弃
		int[] array = new int[]{5,7,9,2,3,8};
		for (int i : array) {
		    queue.offer(i);
		}
		
                //队列可以转换为List
		ArrayList<Integer> list = queue.toList();

		System.out.println(queue);
	}
}

原理: 设定好队列的容量,然后把所有的数据add或者offer进去(两个方法相同),就会得到前5条数据。
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/389940
来源:oschina

=========================================================

10. Инструмент временных задач Hutool — CronUtil

10.1 Происхождение

    Самые часто используемые временные задачи в Java:quartzДа, но этот фреймворк слишком велик, и в нем не нужно использовать столько всего, да и способ использования сложнее. Поэтому вместо этого они искали новую основу. б/у линуксcrontabВсем известно, что с помощью его временных выражений можно очень гибко определять время и частоту выполнения задач по времени (в Linux crontab работает с точностью до минут, а quaeta с точностью до секунд, но достаточно быть точным с точностью до минут. Вы можете использовать Timer, чтобы получить в секундах), а затем есть файл конфигурации crontab, в котором можно четко указать временные задачи. (Помните, когда Spring интегрировал кварц, XML был ослеплен.) Поэтому я нашел легкую структуру планирования — cron4j.

10.2 Упаковка

     Для того, чтобы скрыть содержимое этого фреймворка, он инкапсулирован.Так называемая инкапсуляция заключается в том, чтобы поместить планирование задач в конфигурационный файл, а затем запустить его (очень похоже на линуксовый crontab).

10.3 Файлы конфигурации

     Для проектов Maven сначала поместите файл cron4j.setting в папку src/main/resources/config (по умолчанию этот файл находится по этому пути), а затем поместите в файл правила синхронизации, правила следующие:

#注释
[包名]
TestJob = */10 * * * *
TestJob2 = */10 * * * *

第二行等号前面是要执行的定时任务类名,等号后面是定时表达式。
TestJob是一个实现了Runnable接口的类,在start()方法里就可以加逻辑。

     Что касается выражения задачи синхронизации, оно точно такое же, как выражение crontab в Linux, подробности см. здесь:woo woo woo.cn blog on.com/matching/arc Привет…

10.4 Запустите и закройте запланированное задание

     Вызовите CronUtil.start(), чтобы запустить службу запланированных задач, и CrontabUtil.stop(), чтобы остановить службу. Для динамического добавления запланированных задач используйте метод CronUtil.schedule(String schedulingPattern, Runnable task) (добавленные этим методом запланированные задачи не будут записаны в файл конфигурации).

作者:路小磊
原文链接:https://my.oschina.net/looly/blog/379677
来源:oschina

=========================================================

11. Класс преобразования типов Hutool — Convert

11.1 Класс преобразования типов Convert

     При разработке Java мы будем сталкиваться с различными проблемами преобразования типов, особенно пользовательских параметров, полученных из командной строки, параметров, полученных из HttpRequest и т. д. Эти параметры бывают разных типов, как их преобразовать? Обычный метод состоит в том, чтобы сначала преобразовать его в строку, а затем вызвать xxx.parseМетод xxx должен нести риск сбоя преобразования и должен добавить уровень try catch.Этот небольшой процесс будет выглядеть очень уродливым и раздутым в бизнес-коде, поэтому задача этого типа преобразования инкапсулирована в классе Conver. . . .

1. toStr、toInt、toLong、toDouble、toBool方法
    这几个方法基本代替了JDK的XXX.parseXXX方法,传入两个参数,第一个是Object类型的被转换的值,
    第二个参数是默认值。这些方法做转换并不抛出异常,当转换失败或者提供的值为null时,
    只会返回默认值,返回的类型全部使用了包装类,方便我们需要null的情况。

2. 半角转全角toSBC和全角转半角toDBC
    在很多文本的统一化中这两个方法非常有用,主要对标点符号的全角半角转换。
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/270829
来源:oschina

=========================================================

12. Одноэлементный пул Hutool — Singleton

12.1 Причины

Есть только два способа использования синглтона:

在对象里加个静态方法getInstance()来获取。
此方式可以参考 【转】线程安全的单例模式[https://my.oschina.net/looly/blog/152865] 这篇博客,
可分为饿汉和饱汉模式。

通过Spring这类容器统一管理对象,用的时候去对象池中拿。Spring也可以通过配置决定懒汉或者饿汉模式

Честно говоря, я предпочитаю второй, но Spring более правильно его внедряет, а не берет, поэтому я хочу сделать класс Singleton и поддерживать пул синглетонов, при использовании этого объекта singleton я могу напрямую его брать. . Я просто хочу изменить способ управления синглтонами.Я надеюсь, что управление синглтонами — это контейнерный инструмент, а не большой фреймворк, который может значительно упростить использование синглтона.

12.2 Использование

import com.xiaoleilu.hutool.Singleton;

/**
 * 单例样例
 */
public class SingletonDemo {
	/**
	 * 动物接口
	 */
	public static interface Animal{
		public void say();
	}
	
	/**
	 * 狗实现
	 */
	public static class Dog implements Animal{
		@Override
		public void say() {
			System.out.println("汪汪");
		}
	}
	
	/**
	 * 猫实现
	 */
	public static class Cat implements Animal{
		@Override
		public void say() {
			System.out.println("喵喵");
		}
	}
	
	public static void main(String[] args) {
		Animal dog = Singleton.get(Dog.class);
		Animal cat = Singleton.get(Cat.class);
		
		//单例对象每次取出为同一个对象,除非调用Singleton.destroy()或者remove方法
		System.out.println(dog == Singleton.get(Dog.class));		//true
		System.out.println(cat == Singleton.get(Cat.class));		//true
		
		dog.say();		//汪汪
		cat.say();		//喵喵
	}
}

12.2 Резюме

Если вам интересно, вы можете взглянуть на этот класс. Реализация очень проста. HashMap используется в качестве пула одноэлементных объектов, и объект создается через newInstance() (методы построения с параметрами не поддерживаются). он извлекает или создает объекты, он потокобезопасен (узкое место может возникнуть, когда количество одноэлементных объектов очень велико, а создание экземпляров одноэлементных объектов занимает очень много времени), учитывая, что блокировка с двойной проверкой используется, когда get, но он не является потокобезопасным, так что synchronized напрямую добавляется в качестве украшения, и здесь приветствуются предложения.

作者:路小磊
原文链接:https://my.oschina.net/looly/blog/284922
来源:oschina

=========================================================

13. Альтернатива свойствам Hutool — настройка

13.1 Предисловие

Существует множество ограничений на чтение файла Properties программой Properties, поставляемой с JDK.Во-первых, кодировка ISO8859-1 делает невозможным добавление значений и комментариев на китайском языке (японский плагин можно читать и писать в Eclipse, а его можно прочитать на сервере, это требует больших усилий), и он не поддерживает такие функции, как группировка переменных, поэтому существует класс Setting.

13.2 Происхождение

     Необходимость использования переменных в файлах конфигурации имеет долгую историю.В Spring класс PropertyPlaceholderConfigurer используется для замены переменных в файле свойств в ApplicationContext.xml. Впервые я узнал о концепции группировки в файле конфигурации /etc/rsyncd.conf Linux rsync и обнаружил, что это очень практично, и вы можете обратиться к Baidu.

Эти две функции позже были обнаружены в jodd's Props. Его класс расширения файла конфигурации очень мощный и даже поддерживает такие функции, как несколько строк. Я хотел использовать его напрямую, чтобы избежать повторного создания колеса, но обнаружил, что многие функции совершенно бесполезны. И удобной функции не нужно, поэтому было создано колесо настройки.

Пример формата файла конфигурации.setting

<!-- lang: shell -->
# -------------------------------------------------------------
# ----- Setting File with UTF8-----
# ----- 数据库配置文件 -----
# -------------------------------------------------------------

#中括表示一个分组,其下面的所有属性归属于这个分组,在此分组名为demo,也可以没有分组
[demo]
#自定义数据源设置文件,这个文件会针对当前分组生效,用于给当前分组配置单独的数据库连接池参数,
#没有则使用全局的配置
ds.setting.path = config/other.setting
#数据库驱动名,如果不指定,则会根据url自动判定
driver = com.mysql.jdbc.Driver
#JDBC url,必须
url = jdbc:mysql://fedora.vmware:3306/extractor
#用户名,必须
user = root${driver}
#密码,必须,如果密码为空,请填写 pass = 
pass = 123456

Файл конфигурации      можно разместить в любом месте Как найти конкретный класс Setting обеспечивает различные методы чтения в методе построения, которые будут представлены позже. Теперь поговорим о конкретном формате конфигурационного файла.Конфигурационный файл Setting аналогичен файлу Properties.Правила следующие:

  • Комментарии начинаются с #. Поддерживаются только однострочные комментарии. Пустые строки и нераспознанные пары ключ-значение также игнорируются. Их можно использовать в качестве комментариев, но рекомендуется указывать комментарии явно.

  • Пара ключ-значение представлена ​​ключом = значение, а ключ и значение будут обрезать пробелы при чтении, так что не беспокойтесь о пробелах.

  • Группировка — это содержимое, заключенное в квадратные скобки (например, [demo] в файле конфигурации), а строки под квадратными скобками — это содержимое этой группировки. Никакая группировка не эквивалентна пустой группировке символов, то есть [] . Если ключом является имя, группировка является группой, а ключ после группировки эквивалентен группе.имя.

  • Переменные поддерживаются, переменная по умолчанию называется{变量名},变量只能识别读入行的变量,例如第6行的变量在第三行无法读取,例如配置文件中的{driver} будет заменен на com.mysql.jdbc.Driver.Для повышения производительности конструктор укажет, следует ли включать подстановку переменных при создании параметра, который не включен по умолчанию.

<!-- lang: java -->
import java.io.IOException;

import com.xiaoleilu.hutool.CharsetUtil;
import com.xiaoleilu.hutool.FileUtil;
import com.xiaoleilu.hutool.Setting;

/**
 * Setting演示样例类
 */
public class SettingDemo {
	public static void main(String[] args) throws IOException {
		//-------------------------初始化
		//读取classpath下的XXX.setting,不使用变量
		Setting setting = new Setting("XXX.setting");
		
		//读取classpath下的config目录下的XXX.setting,不使用变量
		setting = new Setting("config/XXX.setting");
		
		//读取绝对路径文件/home/looly/XXX.setting(没有就创建,关于touch请查阅FileUtil)
		//第二个参数为自定义的编码,请保持与Setting文件的编码一致
		//第三个参数为是否使用变量,如果为true,则配置文件中的每个key都可以被之后的条目中的value引用形式为 ${key}
		setting = new Setting(FileUtil.touch("/home/looly/XXX.setting"), CharsetUtil.UTF_8, true);
		
		//读取与SettingDemo.class文件同包下的XXX.setting
		setting = new Setting("XXX.setting", SettingDemo.class, CharsetUtil.UTF_8, true);
		
		//--------------------------使用
		//获取key为name的值
		setting.getString("name");
		//获取分组为group下key为name的值
		setting.getString("name", "group1");
		//当获取的值为空(null或者空白字符时,包括多个空格),返回默认值
		setting.getStringWithDefault("name", "默认值");
		//完整的带有key、分组和默认值的获得值得方法
		setting.getStringWithDefault("name", "group1", "默认值");
		
		//如果想获得其它类型的值,可以调用相应的getXXX方法,参数相似
		
		//有时候需要在key对应value不存在的时候(没有这项设置的时候)告知用户,故有此方法打印一个debug日志
		setting.getWithLog("name");
		setting.getWithLog("name", "group1");
		
		//重新读取配置文件,可以启用一个定时器调用此方法来定时更新配置
		setting.reload();
		
		//当通过代码加入新的键值对的时候,调用store会保存到文件,但是会覆盖原来的文件,并丢失注释
		setting.setSetting("name1", "value");
		setting.store("/home/looly/XXX.setting");

		//获得所有分组名
		setting.getGroups();
		
		//将key-value映射为对象,原理是原理是调用对象对应的setXX方法
		//setting.toObject();
		
		//设定变量名的正则表达式。
		//Setting的变量替换是通过正则查找替换的,如果Setting中的变量名和其他冲突,
		//可以改变变量的定义方式
		//整个正则匹配变量名,分组1匹配key的名字
		setting.setVarRegex("\\$\\{(.*?)\\}");
	}
}

     Простая инкапсуляция Properties Props (доступно с версии 2.0.0)

Широкое использование свойств делает меня беспомощным, и иногда нелегко читать и легко записывать файл свойств, поэтому я просто инкапсулирую свойства, предоставляю удобный метод построения (совместимый с параметром Setting) и предоставляю метод getXXX, который согласован with Setting расширяет класс Properties. Класс Props наследуется от класса Properties, поэтому он может быть совместим с классом Properties. Он не будет подробно представлен. Если вам интересно, вы можете прочитать его.cn.hutool.setting.dialect.Props

作者:路小磊
原文链接:https://my.oschina.net/looly/blog/302407
来源:oschina

=========================================================

14. Hutool-крипто модуль

14.1 Используйте Hutool для реализации шифрования и дешифрования AES, DES

14.1.1 Введение

    AES и DES являются симметричными алгоритмами шифрования.Отправитель данных обрабатывает открытый текст (исходные данные) и ключ шифрования вместе со специальным алгоритмом шифрования, чтобы преобразовать его в сложный зашифрованный зашифрованный текст и отправить его. После того, как получатель получит зашифрованный текст, если он хочет интерпретировать исходный текст, ему необходимо расшифровать зашифрованный текст, используя ключ шифрования и алгоритм, обратный тому же алгоритму, чтобы восстановить его в читаемый открытый текст. В алгоритме симметричного шифрования используется только один ключ, и отправитель, и получатель используют этот ключ для шифрования и расшифровки данных, что требует от дешифратора заранее знать ключ шифрования.

    В мире Java необходимо использовать шифрование и дешифрование AES, DES.Шифровать объектДля построения системы шифрования и дешифрования этот объект перепаковывается в Hutool, что упрощает процесс шифрования и дешифрования.

14.1.2 Знакомство с Hutool

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

14.1.3 Использование

** AES加密解密

String content = "test中文"; 
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();//随机生成密钥
AES aes = SecureUtil.aes(key);//构建
byte[] encrypt = aes.encrypt(content);//加密
byte[] decrypt = aes.decrypt(encrypt);//解密

String encryptHex = aes.encryptHex(content);//加密为16进制表示
String decryptStr = aes.decryptStr(encryptHex);//解密为原字符串

** DES加密解密, DES的使用方式与AES基本一致

String content = "test中文";
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue()).getEncoded();//随机生成密钥
DES des = SecureUtil.des(key);//构建

byte[] encrypt = des.encrypt(content);//加密解密
byte[] decrypt = des.decrypt(encrypt);

String encryptHex = des.encryptHex(content);//加密为16进制,解密为原字符串
String decryptStr = des.decryptStr(encryptHex);

14.1.4 Подробнее

    Hutool инкапсулирует все алгоритмы симметричного шифрования, поддерживаемые JDK.SymmetricCryptoкласс, два класса AES и DES являются упрощенными представлениями этого класса. Создав экземпляр этого класса и передав соответствующее перечисление алгоритма, вы можете использовать один и тот же метод для шифрования и расшифровки строк или объектов.

Перечень алгоритмов симметричного шифрования, поддерживаемых Hutool:

AES
ARCFOUR
Blowfish
DES
DESede
RC2
PBEWithMD5AndDES
PBEWithSHA1AndDESede
PBEWithSHA1AndRC2_40

Все эти перечисления вSymmetricAlgorithmперечислены в

对称加密对象的使用也非常简单:

String content = "test中文";

byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();//随机生成密钥

SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);//构建

byte[] encrypt = aes.encrypt(content);//加密
byte[] decrypt = aes.decrypt(encrypt);//解密

String encryptHex = aes.encryptHex(content);//加密为16进制表示
String decryptStr = aes.decryptStr(encryptHex);//解密为字符串
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/1504160
来源:oschina

14.2 Использование Hutool для обработки асимметричного шифрования, такого как RSA

14.2.1 Введение

Инструмент     Hutool — это внутренний набор инструментов Java с открытым исходным кодом, разработанный для упрощения утомительного процесса разработки Java.Модуль Hutool-crypto значительно упрощает шифрование и дешифрование JDK.
     В этой статье в основном рассказывается об использовании Hutool-crypto для упрощения асимметричного шифрования и дешифрования.
     Для асимметричного шифрования наиболее часто используются RSA и DSA.Объект AsymmetricCrypto используется в Hutool, чтобы отвечать за шифрование и дешифрование.
     Асимметричное шифрование имеет две концепции: открытый ключ и закрытый ключ.Закрытый ключ принадлежит ему самому и не может быть передан другим.Открытый ключ является открытым. В зависимости от приложения мы можем выбрать шифрование с разными ключами:

签名:使用私钥加密,公钥解密。用于让所有公钥所有者验证私钥所有者的身份并且用来防止私钥所有者发布的内容被篡改,
      但是不用来保证内容不被他人获得。

加密:用公钥加密,私钥解密。用于向公钥所有者发布信息,这个信息可能被他人篡改,但是无法被他人获得。

14.2.2 Использование

14.2.2.1 Знакомство с Hutool
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>4.1.2</version>
</dependency>

     В асимметричном шифровании мы можем использовать метод построения AsymmetricCrypto (алгоритм асимметричного алгоритма), чтобы получить его шифрование и дешифрование путем передачи различных перечислений алгоритмов.
     Разумеется, для удобства мы построили отдельные объекты для наиболее часто используемых алгоритмов RSA и DSA: RSA и DSA.

14.2.2.2 Основное использование

     Возьмите RSA в качестве примера, чтобы представить использование шифрования и дешифрования RSA.
     При создании объекта RSA вы можете передать открытый ключ или закрытый ключ.При использовании метода построения без аргументов Hutool автоматически сгенерирует случайную пару открытый-закрытый ключ-ключ:

RSA rsa = new RSA();

rsa.getPrivateKey()//获得私钥
rsa.getPrivateKeyBase64()

rsa.getPublicKey()//获得公钥
rsa.getPublicKeyBase64()

byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), 
            KeyType.PublicKey);//公钥加密,私钥解密
byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));

//私钥加密,公钥解密
byte[] encrypt2 = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);
byte[] decrypt2 = rsa.decrypt(encrypt2, KeyType.PublicKey);
Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt2, CharsetUtil.CHARSET_UTF_8));

     может быть полностью раздельным для шифрования и дешифрования, для объектов RSA, если используются только открытые или закрытые ключи, еще один параметр может быть нулевым

14.2.2.3 Самогенерируемая пара ключей
有时候想自助生成密钥对可以:
KeyPair pair = SecureUtil.generateKeyPair("RSA");
pair.getPrivate();
pair.getPublic();

     Самогенерируемая пара ключей имеет форму byte[], мы можем использовать метод Base64.encode, чтобы преобразовать ее в Base64 для удобного хранения в виде текста.
     Конечно, если вы используете объекты RSA, вы также можете использовать encryptStr и decryptStr для шифрования и расшифровки в строку.

14.2.3 Случаи

已知私钥和密文,如何解密密文?

String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIL7pbQ+5KKGYRhw7jE31hmA"
		+ "f8Q60ybd+xZuRmuO5kOFBRqXGxKTQ9TfQI+aMW+0lw/kibKzaD/EKV91107xE384qOy6IcuBfaR5lv39OcoqNZ"
		+ "5l+Dah5ABGnVkBP9fKOFhPgghBknTRo0/rZFGI6Q1UHXb+4atP++LNFlDymJcPAgMBAAECgYBammGb1alndta"
		+ "xBmTtLLdveoBmp14p04D8mhkiC33iFKBcLUvvxGg2Vpuc+cbagyu/NZG+R/WDrlgEDUp6861M5BeFN0L9O4hz"
		+ "GAEn8xyTE96f8sh4VlRmBOvVdwZqRO+ilkOM96+KL88A9RKdp8V2tna7TM6oI3LHDyf/JBoXaQJBAMcVN7fKlYP"
		+ "Skzfh/yZzW2fmC0ZNg/qaW8Oa/wfDxlWjgnS0p/EKWZ8BxjR/d199L3i/KMaGdfpaWbYZLvYENqUCQQCobjsuCW"
		+ "nlZhcWajjzpsSuy8/bICVEpUax1fUZ58Mq69CQXfaZemD9Ar4omzuEAAs2/uee3kt3AvCBaeq05NyjAkBme8SwB0iK"
		+ "kLcaeGuJlq7CQIkjSrobIqUEf+CzVZPe+AorG+isS+Cw2w/2bHu+G0p5xSYvdH59P0+ZT0N+f9LFAkA6v3Ae56OrI"
		+ "wfMhrJksfeKbIaMjNLS9b8JynIaXg9iCiyOHmgkMl5gAbPoH/ULXqSKwzBw5mJ2GW1gBlyaSfV3AkA/RJC+adIjsRGg"
		+ "JOkiRjSmPpGv3FOhl9fsBPjupZBEIuoMWOC8GXK/73DHxwmfNmN7C9+sIi4RBcjEeQ5F5FHZ";

RSA rsa = new RSA(PRIVATE_KEY, null);

String a = "2707F9FD4288CEF302C972058712F24A5F3EC62C5A14AD2FC59DAB93503AA0FA17113A020EE4EA35EB53F"
		+ "75F36564BA1DABAA20F3B90FD39315C30E68FE8A1803B36C29029B23EB612C06ACF3A34BE815074F5EB5AA3A"
		+ "C0C8832EC42DA725B4E1C38EF4EA1B85904F8B10B2D62EA782B813229F9090E6F7394E42E6F44494BB8";

byte[] aByte = HexUtil.decodeHex(a);
byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);
Assert.assertEquals("虎头闯杭州,多抬头看天,切勿只管种地", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/1523094
来源:oschina

=========================================================

15. Модуль ядра Hutool

    cn.hutool.core.beanDynaBean, BeanDesc, BeanDesc.PropDesc, BeanPath, BeanUtil под пакетом

15.1, DynaBean: Dynamic Bean, инкапсулирует объекты-экземпляры и выполняет вызовы отражения.

15.2, BeanDesc: описание информации о компоненте в качестве альтернативы BeanInfo.

15.3, BeanDesc.PropDesc: описание свойства

15.4, BeanPath: объект выражения пути к компоненту, используемый для проверки атрибутов.

15.5, BeanUtil: класс инструментов

作者:豢龙先生 
原文链接:https://blog.csdn.net/sanjun333/article/details/90645420
来源:CSDN

=========================================================

16. Модуль Hutool-http

     Используйте Hutool для сканирования информации из открытых источников Китая с открытым исходным кодом и демонстрации функции HTTP-запроса Hutool-http.

16.1 Страница анализа

    1.Открываем домашнюю страницу ощины, находим наиболее заметный модуль информации с открытым исходным кодом, а затем нажимаем «Еще», чтобы открыть раздел «Информация с открытым исходным кодом».

    2. Откройте отладчик F12, нажмите клавишу быстрого доступа F12, чтобы открыть отладчик Chrome, перейдите на вкладку «Сеть», а затем нажмите «Вся информация» на странице.
3. Так как страница списка ощины переворачивается выпадающим, то потянув вниз вызовет загрузку второй страницы.В это время тянем вниз и смотрим есть ли новый запрос в отладчике . Как показано на рисунке, мы обнаруживаем, что второй запрос — это вторая страница страницы списка.
    4.Открываем этот адрес запроса и видим чистый контент. Адрес, на который указывает красный прямоугольник, является содержимым второй страницы.Очевидно, что параметр p представляет собой номер страницы page.
    5. Щелкните правой кнопкой мыши, чтобы просмотреть исходный код, вы можете увидеть исходный код.
    6. Найдите исходный HTML-код раздела заголовка, а затем найдите раздел HTML, окружающий заголовок, чтобы узнать, сможете ли вы найти заголовок.
     После завершения анализа мы получили адрес страницы списка и соответствующие символы, которые могут найти заголовок (используются для извлечения заголовка с помощью обычного шаблона позже), и мы можем начать использовать кодировку Hutool.

16.2 Имитация HTTP-запроса для сканирования страниц

使用Hutool-http配合ReUtil请求并提取页面内容非常简单,代码如下:

//请求列表页
String listContent = HttpUtil.get("http://www.oschina.net/action/ajax/get_more_news_list?newsType=&p=2");
//使用正则获取所有标题
List<String> titles = ReUtil.findAll("<span class=\"text-ellipsis\">(.*?)</span>", listContent, 1);
for (String title : titles) {
	Console.log(title);//打印标题
}

第一行请求页面内容,第二行正则定位所有标题行并提取标题部分。

这里解释下正则部分:
ReUtil.findAll方法用于查找所有匹配正则表达式的内容部分,第二个参数1表示提取第一个括号(分组)中的内容,
0表示提取所有正则匹配到的内容。这个方法可以看下core模块中ReUtil章节了解详情。

<span class=\"text-ellipsis\">(.*?)</span>这个正则就是我们上面分析页面源码后得到的正则,
其中(.*?)表示我们需要的内容,.表示任意字符,*表示0个或多个,?表示最短匹配,整个正则的意思就是。
,以<span class=\"text-ellipsis\">开头,</span>结尾的中间所有字符,中间的字符要达到最短。
?的作用其实就是将范围限制到最小,不然</span>很可能匹配到后面去了。

16.2 Заключение

     Я должен сказать, что сканирование само по себе не сложно, особенно с помощью Hutool, чтобы сделать эту работу проще и быстрее, а сложность заключается в анализе страницы и поиске нужного нам контента.

Парсинг реального контента делится на две части:

  • Найти страницы со списком (на многих сайтах нет общей страницы со списком)
  • Запросить страницу списка и получить адрес страницы сведений
  • Запросите страницу сведений и используйте регулярное выражение, чтобы соответствовать тому, что нам нужно
  • Инвентаризация или сохранение контента в виде файла

И в процессе сканирования мы также столкнемся с различными проблемами, включая, помимо прочего:

  • Блокировать IP-адрес
  • К заголовку запроса предъявляются особые требования.
  • Особые требования к файлам cookie
  • код верификации
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/1575851
来源:oschina

=========================================================

17. Инструмент проверки кода Hutool — CaptchaUtil

     Используйте Hutool [Создать и проверить] Графическую капчу

17.1 Происхождение

     По мере того, как защита от атак становится все более и более комплексной, графический проверочный код становится простым и эффективным средством предотвращения атак и антисканирования, поэтому он используется все шире. Hutool абстрагирует реализацию кода проверки, а также предоставляет несколько простых реализаций кода проверки, что значительно снижает стоимость разработки сервера.
     Из-за огромного спроса на проверочные коды и накопления моих предыдущих проектов я добавил в Hutool функции генерации и проверки проверочных кодов.

17.2 Знакомство с Hutool

了解Hutool的更多信息请访问:http://hutool.cn/

<dependency>
    <groupId>com.xiaoleilu</groupId>
    <artifactId>hutool-all</artifactId>
    <version>3.2.3</version>
</dependency>

17.3 Введение

Функция кода подтверждения находится по адресуcom.hutool.captchaВ пакете основным интерфейсом является ICaptcha, который определяет следующие методы:

    createCode 创建验证码,实现类需同时生成随机验证码字符串和验证码图片
    getCode 获取验证码的文字内容
    verify 验证验证码是否正确,建议忽略大小写
    write 将验证码写出到目标流中

     Метод записи имеет только один OutputStream, и класс реализации ICaptcha может выполнять инкапсуляцию и запись в файл в соответствии с этим методом.
AbstractCaptcha — это абстрактный класс реализации ICaptcha.В этом классе реализованы такие методы, как генерация текста капчи, проверка без учета регистра, запись в поток и файл и т. д. Унаследовав этот абстрактный класс, необходимо только реализовать метод createImage для определить правила генерации графики.

17.4 Реализация классов

  • Проверочный код интерференции линейного сегмента LineCaptcha, сгенерированный эффект примерно такой:
//定义图形验证码的长和宽
LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
//LineCaptcha lineCaptcha = new LineCaptcha(200, 100, 4, 150);
//图形验证码写出,可以写出到文件,也可以写出到流
lineCaptcha.write("d:/line.png");
//验证图形验证码的有效性,返回boolean值
lineCaptcha.verify("1234");
  • CircleCaptcha круг интерференционная капча
//定义图形验证码的长、宽、验证码字符数、干扰元素个数
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);
//CircleCaptcha captcha = new CircleCaptcha(200, 100, 4, 20);
//图形验证码写出,可以写出到文件,也可以写出到流
captcha.write("d:/circle.png");
//验证图形验证码的有效性,返回boolean值
captcha.verify("1234");
  • ShearCaptcha Twisted Interference Captcha
//定义图形验证码的长、宽、验证码字符数、干扰线宽度
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);
//ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4);
//图形验证码写出,可以写出到文件,也可以写出到流
captcha.write("d:/shear.png");
//验证图形验证码的有效性,返回boolean值
captcha.verify("1234");
  • Запись в браузер (вывод сервлета)
ICaptcha captcha = ...;
captcha.write(response.getOutputStream());
//Servlet的OutputStream记得自行关闭!
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/1591079
来源:oschina

=========================================================

18. Используйте Hutool для ежедневной отправки работы

18.1 Используемые модули и инструменты

cron模块,用于定时发送邮件
extra模块,MailUtil,用于发送邮件
poi模块,WordWriter,用于生成日报的word

18.2 Структура проекта

demo项目可以访问码云地址获取:https://gitee.com/loolly_admin/daily-work

src/main/java
    cn/hutool/example/dailyWork/
        DailyWorkGenerator.java ---- 日报生成器,用于生成Word文档
        MailSendTask.java       ---- 邮件发送任务,用于发送邮件
        DailyWorkMain.java      ---- 定时任务主程序,用于启动定时任务

src/main/resources
    config/
        cron.setting            ---- 定时任务配置文件
        mail.setting            ---- 邮箱配置文件

18.3 Реализация кода

1. Создавайте ежедневно Word

/** 标题字体 */
private static final Font TITLE_FONT = new Font("黑体", Font.PLAIN, 22);
/** 正文字体 */
private static final Font MAIN_FONT = new Font("宋体", Font.PLAIN, 14);


/**
 * 生成日报
 * 
 * @return 日报word文件
 */
public static File generate() {
	// 1、准备文件
	File wordFile = FileUtil.file(StrUtil.format("每日工作汇报_{}.docx", DateUtil.today()));
	if(FileUtil.exist(wordFile)) {
		// 如果文件存在,删除之(可能上次发送遗留)
		wordFile.delete();
	}
	
	// 生成并写出word
	Word07Writer writer = new Word07Writer(wordFile);
	writer.addText(ParagraphAlignment.CENTER, TITLE_FONT, "工作日报");
	writer.addText(MAIN_FONT, "");
	writer.addText(MAIN_FONT, "尊敬的领导:");
	writer.addText(MAIN_FONT, "    今天我在Hutool群里摸鱼,什么工作也没做。");
	
	writer.close();
	return wordFile;
}

2. Отправка электронных писем. Настройте информацию об исходящих сообщениях в mail.setting.

# 发件人(必须正确,否则发送失败)
from = Hutool<hutool@yeah.net>
# 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
user = hutool
# 密码
pass = XXXX

#使用 STARTTLS安全连接
startttlsEnable = true
#使用 SSL安全连接
sslEnable = true

=========================================================================
// 今天的日期,格式类似:2019-06-20
String today = DateUtil.today();

// 生成汇报Word
File dailyWorkDoc = DailyWorkGenerator.generate();
// 发送邮件
MailUtil.sendHtml("hutool@foxmail.com", StrUtil.format("{} 工作日报", today), "请见附件。", dailyWorkDoc);

StaticLog.debug("{} 工作日报已发送给领导!", today);

3. Запланированная отправка, добавьте только что отправленное электронное письмо в качестве запланированной задачи в файл конфигурации:

[cn.hutool.example.dailyWork]
# 每天下午6点定时发送
MailSendTask.execute = 00 00 18 * * *

4. Запускайте задачи на время

// 设置秒匹配(只有在定时任务精确到秒的时候使用)
CronUtil.setMatchSecond(true);
// 启动定时任务,自动加载配置文件中的内容
CronUtil.start();

5. Результаты

作者:路小磊
原文链接:https://my.oschina.net/looly/blog/3064203
来源:oschina

=========================================================

19. Модуль Hutool-лог

19.1 Классификация фреймворков ведения журналов Java

19.1.1 Бревенчатый фасад (Фасад)

* Slf4j     
    全称Simple Logging Facade for JAVA,真正的日志门面,只提供接口方法,当配合特定的日志实现时,
    需要引入相应的桥接包

* Common-logging 
    Apache提供的一个通用的日志接口,common-logging会通过动态查找的机制,在程序运行时自动找出真正
    使用的日志库,自己也自带一个功能很弱的日志实现。
    
* 差别:
    Common-logging 动态查找日志实现(程序运行时找出日志实现),
    Slf4j 则是静态绑定(编译时找到实现),动态绑定因为依赖ClassLoader寻找和载入日志实现,因此类似于
        OSGI那种使用独立ClassLoader就会造成无法使用的情况。
    
    Slf4j 支持参数化的log字符串,避免了之前为了减少字符串拼接的性能损耗而不得不写的
        if(logger.isDebugEnable()),现在可以直接写:logger.debug(“current user is: {}”, user)。

19.1.2 Реализация журнала

  • Log4j
        Log4j — вероятно, самая известная среда ведения журналов в мире Java, поддерживающая различные уровни вывода журнала для различных мест назначения.

  • LogBack
    Очередной шедевр от автора Log4j (я слышал, что терпеть не могу документ о зарядке и сделал опенсорс, нет необходимости в пакете моста, чтобы идеально адаптироваться к Slf4j), я чувствую, что на данный момент это лучший фреймворк логирования, и я использую его все время Производительность достаточно хороша.

Ведение журнала JDK было представлено начиная с JDK 1.4. Я должен сказать, что если вы пойдете в Google и загрузите компонент журнала, который поставляется с JDK, его не так просто использовать, как Log4j и LogBack. Нет файла конфигурации, и уровень лога не прост для понимания.приходится инкапсулировать самому.короче все избалованы Log4j.дизайн JDK не всем понятен.единственный плюс-нет необходимости вводить новые jar-пакеты .

19.1.3 Зачем нужен фасад

     Прочитав приведенное выше введение, если вы не являетесь ветераном (глубоко погруженным в) Java в течение многих лет, предполагается, что вы попадете в круг, то вы обязательно спросите, зачем вам фасад. С мобильным телефоном есть чехол для мобильного телефона, пленка для мобильного телефона и рамка такая же.Функция фасада состоит из трех слов: развязка. Грубо говоря, я использовал фреймворк для входа в проект, как я могу его изменить? Затем ищите лог построчно и меняйте его, думать об этом кошмар. Итак, фасад вышел, и фасад сказал, вы можете писать логи в моем формате, и писать логи куда хотите.Например, после добавления Slf4j-api, если вы хотите изменить структуру журнала, вы можете напрямую изменить пакет моста. Очень удобно.
     Если честно, то Slf4j в принципе сейчас может быть стандартом для ява логов, по нему все логи в принципе можно реализовать, но некоторые люди не убеждены и тоже пишут фасад фасада (да, этот человек я).

19.1.4 Фасад фасада

     Если вы читали исходный код Netty, рекомендуется просмотреть содержимое пакета io.netty.util.internal.logging, и вы обнаружите, что Netty снова инкапсулирует журнал.

19.2 Модуль журнала Hutool

无论是Netty的日志模块还是Hutool-log模块,思想类似于Common Logging,做动态日志实现查找,
然后找到相应的日志实现来写入日志,核心代码如下:

/**
 * 决定日志实现
 * @return 日志实现类
 */
public static Class<? extends AbstractLog> detectLog(){
	List<Class<? extends AbstractLog>> logClassList = Arrays.asList(
			Slf4jLog.class,
			Log4jLog.class, 
			Log4j2Log.class, 
			ApacheCommonsLog.class, 
			JdkLog.class
	);
	
	for (Class<? extends AbstractLog> clazz : logClassList) {
		try {
			clazz.getConstructor(Class.class).newInstance(LogFactory.class).info("Use Log Framework: [{}]", clazz.getSimpleName());
			return clazz;
		} catch (Error | Exception e) {
			continue;
		}
	}
	return JdkLog.class;
}

Создайте соответствующие реализации журнала по порядку. Если создание экземпляра не удается (обычно ClassNotFoundException), это означает, что jar не существует, затем создайте следующий экземпляр. После непрерывных попыток, если структура ведения журнала не введена, используйте JDK Logging (это обязательно будет), конечно, у этого метода тоже есть схожие проблемы с Common-loging, но он все равно очень полезен без cross-ClassLoader.

     Для ведения журнала JDK также были внесены некоторые изменения, чтобы он мог соответствовать уровню журнала Slf4j, чтобы свести к минимуму разницу между каждой структурой журнала. С другой стороны, если вы читали этот мой журнал, то вы, должно быть, поняли мою функцию автоматического распознавания имени класса, так что при копировании имени класса вам не нужно изменять строку кода в журнале, в все классы инициализация журнала имеет только это предложение:

Log log = LogFactory.get();
//=======实现方式 =======
/**
 * @return 获得调用者的日志
 * 通过堆栈引用获得当前类名。
 */
public static Log get() {
	return getLog(new Exception().getStackTrace()[1].getClassName());
}

/**
 * 日志统一接口
 */
public interface Log extends TraceLog, DebugLog, InfoLog, WarnLog, ErrorLog

这样就实现了单一使用,各个日志框架灵活引用的作用了。
作者:路小磊
原文链接:https://my.oschina.net/looly/blog/543000
来源:oschina

=========================================================