mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix comment
This commit is contained in:
parent
052c45537b
commit
0220a1c55e
@ -32,8 +32,17 @@ import java.util.Map;
|
||||
public class AnnotationProxy<T extends Annotation> implements Annotation, InvocationHandler, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 注解
|
||||
*/
|
||||
private final T annotation;
|
||||
/**
|
||||
* 注解类型
|
||||
*/
|
||||
private final Class<T> type;
|
||||
/**
|
||||
* 注解属性
|
||||
*/
|
||||
private final Map<String, Object> attributes;
|
||||
|
||||
/**
|
||||
|
@ -37,7 +37,13 @@ import java.util.Map;
|
||||
public class DynaBean implements Cloneable, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* bean类
|
||||
*/
|
||||
private final Class<?> beanClass;
|
||||
/**
|
||||
* bean对象
|
||||
*/
|
||||
private Object bean;
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,13 @@ import org.dromara.hutool.core.util.ObjUtil;
|
||||
*/
|
||||
public abstract class AbsCopier<S, T> implements Copier<T> {
|
||||
|
||||
/**
|
||||
* 来源对象
|
||||
*/
|
||||
protected final S source;
|
||||
/**
|
||||
* 目标对象
|
||||
*/
|
||||
protected final T target;
|
||||
/**
|
||||
* 拷贝选项
|
||||
|
@ -46,7 +46,9 @@ public class SimpleCache<K, V> implements Iterable<Map.Entry<K, V>>, Serializabl
|
||||
* 池
|
||||
*/
|
||||
private final Map<Mutable<K>, V> rawMap;
|
||||
// 乐观读写锁
|
||||
/**
|
||||
* 乐观读写锁
|
||||
*/
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
/**
|
||||
* 写的时候每个key一把锁,降低锁的粒度
|
||||
|
@ -42,6 +42,9 @@ import java.util.stream.Collectors;
|
||||
public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 缓存Map
|
||||
*/
|
||||
protected Map<Mutable<K>, CacheObj<K, V>> cacheMap;
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,13 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
public class CacheObj<K, V> implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 键
|
||||
*/
|
||||
protected final K key;
|
||||
/**
|
||||
* 值对象
|
||||
*/
|
||||
protected final V obj;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +29,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
||||
/**
|
||||
* 一些特殊缓存,例如使用了LinkedHashMap的缓存,由于get方法也会改变Map的结构,导致无法使用读写锁
|
||||
*/
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
|
@ -25,12 +25,14 @@ import java.util.concurrent.locks.StampedLock;
|
||||
* @author looly
|
||||
* @since 5.7.15
|
||||
*/
|
||||
public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
||||
public abstract class StampedCache<K, V> extends AbstractCache<K, V> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// 乐观锁,此处使用乐观锁解决读多写少的场景
|
||||
// get时乐观读,再检查是否修改,修改则转入悲观读重新读一遍,可以有效解决在写时阻塞大量读操作的情况。
|
||||
// see: https://www.cnblogs.com/jiagoushijuzi/p/13721319.html
|
||||
/**
|
||||
* 乐观锁,此处使用乐观锁解决读多写少的场景<br>
|
||||
* get时乐观读,再检查是否修改,修改则转入悲观读重新读一遍,可以有效解决在写时阻塞大量读操作的情况。<br>
|
||||
* see: https://www.cnblogs.com/jiagoushijuzi/p/13721319.html
|
||||
*/
|
||||
protected final StampedLock lock = new StampedLock();
|
||||
|
||||
@Override
|
||||
@ -163,7 +165,7 @@ public abstract class StampedCache<K, V> extends AbstractCache<K, V>{
|
||||
|
||||
// 无效移除
|
||||
co = removeWithoutLock(key);
|
||||
if(isUpdateCount){
|
||||
if (isUpdateCount) {
|
||||
missCount.increment();
|
||||
}
|
||||
} finally {
|
||||
|
@ -22,7 +22,9 @@ import org.dromara.hutool.core.lang.Assert;
|
||||
*/
|
||||
public class Caesar {
|
||||
|
||||
// 26个字母表
|
||||
/**
|
||||
* 26个字母表
|
||||
*/
|
||||
public static final String TABLE = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
|
||||
|
||||
/**
|
||||
|
@ -47,6 +47,17 @@ import java.util.stream.LongStream;
|
||||
*/
|
||||
public class Hashids implements Encoder<long[], String>, Decoder<String, long[]> {
|
||||
|
||||
/**
|
||||
* 默认编解码字符串
|
||||
*/
|
||||
public static final char[] DEFAULT_ALPHABET = {
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
|
||||
};
|
||||
|
||||
private static final int LOTTERY_MOD = 100;
|
||||
private static final double GUARD_THRESHOLD = 12;
|
||||
private static final double SEPARATOR_THRESHOLD = 3.5;
|
||||
@ -54,14 +65,6 @@ public class Hashids implements Encoder<long[], String>, Decoder<String, long[]>
|
||||
private static final int MIN_ALPHABET_LENGTH = 16;
|
||||
private static final Pattern HEX_VALUES_PATTERN = Pattern.compile("[\\w\\W]{1,12}");
|
||||
|
||||
// 默认编解码字符串
|
||||
public static final char[] DEFAULT_ALPHABET = {
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
|
||||
};
|
||||
// 默认分隔符
|
||||
private static final char[] DEFAULT_SEPARATORS = {
|
||||
'c', 'f', 'h', 'i', 's', 't', 'u', 'C', 'F', 'H', 'I', 'S', 'T', 'U'
|
||||
|
@ -26,6 +26,9 @@ import java.util.*;
|
||||
*/
|
||||
public class IterChain<T> implements Iterator<T>, Chain<Iterator<T>, IterChain<T>> {
|
||||
|
||||
/**
|
||||
* 所有的Iterator
|
||||
*/
|
||||
protected final List<Iterator<T>> allIterators = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@ -68,6 +71,9 @@ public class IterChain<T> implements Iterator<T>, Chain<Iterator<T>, IterChain<T
|
||||
|
||||
// ---------------------------------------------------------------- interface
|
||||
|
||||
/**
|
||||
* 当前位置
|
||||
*/
|
||||
protected int currentIter = -1;
|
||||
|
||||
@Override
|
||||
|
@ -29,7 +29,13 @@ import java.util.List;
|
||||
*/
|
||||
public class Partition<T> extends AbstractList<List<T>> {
|
||||
|
||||
/**
|
||||
* 被分区的列表
|
||||
*/
|
||||
protected final List<T> list;
|
||||
/**
|
||||
* 每个分区的长度
|
||||
*/
|
||||
protected final int size;
|
||||
|
||||
/**
|
||||
@ -54,7 +60,7 @@ public class Partition<T> extends AbstractList<List<T>> {
|
||||
public int size() {
|
||||
// 此处采用动态计算,以应对list变
|
||||
final int size = this.size;
|
||||
if(0 == size){
|
||||
if (0 == size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,16 @@ import java.util.function.Predicate;
|
||||
* 自定义加入前检查的{@link LinkedBlockingQueue},给定一个检查函数,在加入元素前检查此函数<br>
|
||||
* 原理是通过Runtime#freeMemory()获取剩余内存,当剩余内存低于指定的阈值时,不再加入。
|
||||
*
|
||||
* @param <E> 元素类型
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class CheckedLinkedBlockingQueue<E> extends LinkedBlockingQueue<E> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 检查函数
|
||||
*/
|
||||
protected final Predicate<E> checker;
|
||||
|
||||
/**
|
||||
@ -42,7 +46,7 @@ public class CheckedLinkedBlockingQueue<E> extends LinkedBlockingQueue<E> {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param c 初始集合
|
||||
* @param c 初始集合
|
||||
* @param checker 检查函数
|
||||
*/
|
||||
public CheckedLinkedBlockingQueue(final Collection<? extends E> c, final Predicate<E> checker) {
|
||||
|
@ -30,7 +30,13 @@ import java.util.Objects;
|
||||
public class NullComparator<T> implements Comparator<T>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 是否{@code null}最大,排在最后
|
||||
*/
|
||||
protected final boolean nullGreater;
|
||||
/**
|
||||
* 实际比较器
|
||||
*/
|
||||
protected final Comparator<T> comparator;
|
||||
|
||||
/**
|
||||
|
@ -32,6 +32,9 @@ import java.lang.reflect.Type;
|
||||
public class ReferenceConverter extends AbstractConverter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static ReferenceConverter INSTANCE = new ReferenceConverter();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -29,18 +29,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* 4. INC 自增计数器。确保同一秒内产生objectId的唯一性。
|
||||
* </pre>
|
||||
*
|
||||
* <table summary="" border="1">
|
||||
* <tr>
|
||||
* <td>时间戳</td>
|
||||
* <td>随机数</td>
|
||||
* <td>自增计数器</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>4</td>
|
||||
* <td>4</td>
|
||||
* <td>4</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* <pre>
|
||||
* | 时间戳 | 随机数 | 自增计数器 |
|
||||
* | 4 | 4 | 4 |
|
||||
* </pre>
|
||||
* <p>
|
||||
* 参考:<a href="https://github.com/mongodb/mongo-java-driver/blob/master/bson/src/main/org/bson/types/ObjectId.java">...</a>
|
||||
*
|
||||
|
@ -46,7 +46,9 @@ public class SeataSnowflake implements Generator<Long>, Serializable {
|
||||
|
||||
// 节点ID长度
|
||||
private static final int NODE_ID_BITS = 10;
|
||||
// 节点ID的最大值,1023
|
||||
/**
|
||||
* 节点ID的最大值,1023
|
||||
*/
|
||||
protected static final int MAX_NODE_ID = ~(-1 << NODE_ID_BITS);
|
||||
// 时间戳长度
|
||||
private static final int TIMESTAMP_BITS = 41;
|
||||
|
@ -53,10 +53,14 @@ public class Snowflake implements Generator<Long>, Serializable {
|
||||
*/
|
||||
public static final long DEFAULT_TWEPOCH = 1288834974657L;
|
||||
private static final long WORKER_ID_BITS = 5L;
|
||||
// 最大支持机器节点数0~31,一共32个
|
||||
/**
|
||||
* 最大支持机器节点数0~31,一共32个
|
||||
*/
|
||||
protected static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
|
||||
private static final long DATA_CENTER_ID_BITS = 5L;
|
||||
// 最大支持数据中心节点数0~31,一共32个
|
||||
/**
|
||||
* 最大支持数据中心节点数0~31,一共32个
|
||||
*/
|
||||
protected static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
|
||||
// 序列号12位(表示只允许序号的范围为:0-4095)
|
||||
private static final long SEQUENCE_BITS = 12L;
|
||||
|
@ -26,6 +26,9 @@ import java.nio.CharBuffer;
|
||||
*/
|
||||
public class ReaderWrapper extends Reader implements Wrapper<Reader> {
|
||||
|
||||
/**
|
||||
* 原始Reader
|
||||
*/
|
||||
protected final Reader raw;
|
||||
|
||||
/**
|
||||
|
@ -29,6 +29,9 @@ public class CRC16 implements Checksum, Serializable {
|
||||
|
||||
private final CRC16Checksum crc16;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public CRC16() {
|
||||
this(new CRC16IBM());
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ public abstract class CRC16Checksum implements Checksum, Serializable {
|
||||
*/
|
||||
protected int wCRCin;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public CRC16Checksum(){
|
||||
reset();
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ import org.dromara.hutool.core.io.StreamProgress;
|
||||
*/
|
||||
public abstract class IoCopier<S, T> {
|
||||
|
||||
/**
|
||||
* 缓存大小
|
||||
*/
|
||||
protected final int bufferSize;
|
||||
/**
|
||||
* 拷贝总数
|
||||
|
@ -30,7 +30,13 @@ import java.nio.charset.StandardCharsets;
|
||||
public class FileWrapper implements Wrapper<File>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 被包装的文件
|
||||
*/
|
||||
protected File file;
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
protected Charset charset;
|
||||
|
||||
/**
|
||||
|
@ -21,26 +21,43 @@ package org.dromara.hutool.core.io.file;
|
||||
* Windows系统换行符:"\r\n"
|
||||
* </pre>
|
||||
*
|
||||
* @author Looly
|
||||
* @see #MAC
|
||||
* @see #LINUX
|
||||
* @see #WINDOWS
|
||||
* @author Looly
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public enum LineSeparator {
|
||||
/** Mac系统换行符:"\r" */
|
||||
|
||||
/**
|
||||
* Mac系统换行符:"\r"
|
||||
*/
|
||||
MAC("\r"),
|
||||
/** Linux系统换行符:"\n" */
|
||||
/**
|
||||
* Linux系统换行符:"\n"
|
||||
*/
|
||||
LINUX("\n"),
|
||||
/** Windows系统换行符:"\r\n" */
|
||||
/**
|
||||
* Windows系统换行符:"\r\n"
|
||||
*/
|
||||
WINDOWS("\r\n");
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param lineSeparator 换行符
|
||||
*/
|
||||
LineSeparator(final String lineSeparator) {
|
||||
this.value = lineSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取换行符值
|
||||
*
|
||||
* @return 值
|
||||
*/
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
@ -32,9 +32,15 @@ import java.net.URL;
|
||||
public class UrlResource implements Resource, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* URL
|
||||
*/
|
||||
protected URL url;
|
||||
private long lastModified = 0;
|
||||
/**
|
||||
* 资源名称
|
||||
*/
|
||||
protected String name;
|
||||
private long lastModified = 0;
|
||||
|
||||
//-------------------------------------------------------------------------------------- Constructor start
|
||||
|
||||
|
@ -56,6 +56,9 @@ public enum DataUnit {
|
||||
*/
|
||||
TERABYTES("TB", DataSize.ofTerabytes(1));
|
||||
|
||||
/**
|
||||
* 单位名称列表
|
||||
*/
|
||||
public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};
|
||||
|
||||
private final String suffix;
|
||||
|
@ -12,34 +12,74 @@
|
||||
|
||||
package org.dromara.hutool.core.io.watch;
|
||||
|
||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
|
||||
/**
|
||||
* 监听异常
|
||||
* @author Looly
|
||||
*
|
||||
*/
|
||||
public class WatchException extends RuntimeException {
|
||||
public class WatchException extends HutoolException {
|
||||
private static final long serialVersionUID = 8068509879445395353L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param e 异常
|
||||
*/
|
||||
public WatchException(final Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
super(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
*/
|
||||
public WatchException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param messageTemplate 消息模板
|
||||
* @param params 参数
|
||||
*/
|
||||
public WatchException(final String messageTemplate, final Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
super(messageTemplate, params);
|
||||
}
|
||||
|
||||
public WatchException(final String message, final Throwable throwable) {
|
||||
super(message, throwable);
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
* @param cause 被包装的子异常
|
||||
*/
|
||||
public WatchException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public WatchException(final Throwable throwable, final String messageTemplate, final Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
* @param cause 被包装的子异常
|
||||
* @param enableSuppression 是否启用抑制
|
||||
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||
*/
|
||||
public WatchException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param cause 被包装的子异常
|
||||
* @param messageTemplate 消息模板
|
||||
* @param params 参数
|
||||
*/
|
||||
public WatchException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||
super(cause, messageTemplate, params);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,13 @@ public class MutableEntry<K, V> extends AbsEntry<K, V> implements Mutable<Map.En
|
||||
return new MutableEntry<>(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 键
|
||||
*/
|
||||
protected K key;
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
protected V value;
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,13 @@ import org.dromara.hutool.core.text.StrUtil;
|
||||
*/
|
||||
public class DefaultSegment<T extends Number> implements Segment<T> {
|
||||
|
||||
/**
|
||||
* 起始位置
|
||||
*/
|
||||
protected T beginIndex;
|
||||
/**
|
||||
* 结束位置
|
||||
*/
|
||||
protected T endIndex;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +42,13 @@ public class Pair<L, R> implements Serializable, Cloneable {
|
||||
return new Pair<>(left, right);
|
||||
}
|
||||
|
||||
/**
|
||||
* 左值(第一个值)
|
||||
*/
|
||||
protected L left;
|
||||
/**
|
||||
* 右值(第二个值)
|
||||
*/
|
||||
protected R right;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +42,9 @@ public class Triple<L, M, R> extends Pair<L, R> {
|
||||
return new Triple<>(left, middle, right);
|
||||
}
|
||||
|
||||
/**
|
||||
* 中值
|
||||
*/
|
||||
protected M middle;
|
||||
|
||||
/**
|
||||
@ -57,6 +60,7 @@ public class Triple<L, M, R> extends Pair<L, R> {
|
||||
}
|
||||
|
||||
// region ----- getXXX
|
||||
|
||||
/**
|
||||
* 获取中值
|
||||
*
|
||||
|
@ -22,6 +22,9 @@ package org.dromara.hutool.core.lang.wrapper;
|
||||
*/
|
||||
public class SimpleWrapper<T> implements Wrapper<T> {
|
||||
|
||||
/**
|
||||
* 原始对象
|
||||
*/
|
||||
protected final T raw;
|
||||
|
||||
/**
|
||||
|
@ -10,28 +10,10 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This package contains an implementation of a bounded
|
||||
* {@link java.util.concurrent.ConcurrentMap} data structure.
|
||||
* <p>
|
||||
* {@link org.dromara.hutool.core.map.concurrent.Weigher} is a simple interface
|
||||
* for determining how many units of capacity an entry consumes. Depending on
|
||||
* which concrete Weigher class is used, an entry may consume a different amount
|
||||
* of space within the cache. The
|
||||
* {@link org.dromara.hutool.core.map.concurrent.Weighers} class provides
|
||||
* utility methods for obtaining the most common kinds of implementations.
|
||||
* <p>
|
||||
* {@link org.dromara.hutool.core.map.concurrent.ConcurrentLinkedHashMap#listener} provides the
|
||||
* ability to be notified when an entry is evicted from the map. An eviction
|
||||
* occurs when the entry was automatically removed due to the map exceeding a
|
||||
* capacity threshold. It is not called when an entry was explicitly removed.
|
||||
* <p>
|
||||
* The {@link org.dromara.hutool.core.map.concurrent.ConcurrentLinkedHashMap}
|
||||
* class supplies an efficient, scalable, thread-safe, bounded map. As with the
|
||||
* <tt>Java Collections Framework</tt> the "Concurrent" prefix is used to
|
||||
* indicate that the map is not governed by a single exclusion lock.
|
||||
* 并发Map工具类
|
||||
*
|
||||
* @see <a href="http://code.google.com/p/concurrentlinkedhashmap/">
|
||||
* http://code.google.com/p/concurrentlinkedhashmap/</a>
|
||||
* @author Looly
|
||||
*/
|
||||
package org.dromara.hutool.core.map.concurrent;
|
||||
|
@ -158,8 +158,8 @@ public class NumberValidator {
|
||||
*
|
||||
* @param s 校验的字符串, 只能含有 正负号、数字字符 和 {@literal X/x}
|
||||
* @return 是否为 {@link Integer}类型
|
||||
* @apiNote 6.0.0 支持8进制和16进制
|
||||
* @see Integer#decode(String)
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static boolean isInteger(final String s) {
|
||||
if (!isNumber(s)) {
|
||||
@ -185,7 +185,7 @@ public class NumberValidator {
|
||||
*
|
||||
* @param s 校验的字符串, 只能含有 正负号、数字字符、{@literal X/x} 和 后缀{@literal L/l}
|
||||
* @return 是否为 {@link Long}类型
|
||||
* @apiNote 6.0.0 支持8进制和16进制数字
|
||||
* @since 6.0.0
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static boolean isLong(final String s) {
|
||||
|
@ -104,6 +104,9 @@ public class MultipartRequestInputStream extends BufferedInputStream {
|
||||
|
||||
// ---------------------------------------------------------------- data header
|
||||
|
||||
/**
|
||||
* 最后的头部信息
|
||||
*/
|
||||
protected UploadFileHeader lastHeader;
|
||||
|
||||
/**
|
||||
|
@ -31,9 +31,6 @@ public class UploadSetting {
|
||||
/** 扩展名是允许列表还是禁止列表 */
|
||||
protected boolean isAllowFileExts = true;
|
||||
|
||||
public UploadSetting() {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------- Setters and Getters start
|
||||
/**
|
||||
* @return 获得最大文件大小,-1表示无限制
|
||||
|
@ -25,16 +25,28 @@ import java.nio.charset.Charset;
|
||||
*/
|
||||
public abstract class AbsServiceLoader<S> implements ServiceLoader<S> {
|
||||
|
||||
/**
|
||||
* 路径前缀
|
||||
*/
|
||||
protected final String pathPrefix;
|
||||
/**
|
||||
* 服务类
|
||||
*/
|
||||
protected final Class<S> serviceClass;
|
||||
/**
|
||||
* 自定义类加载器
|
||||
*/
|
||||
protected final ClassLoader classLoader;
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
protected final Charset charset;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param pathPrefix 路径前缀
|
||||
* @param serviceClass 服务名称
|
||||
* @param serviceClass 服务类
|
||||
* @param classLoader 自定义类加载器, {@code null}表示使用默认当前的类加载器
|
||||
* @param charset 编码,默认UTF-8
|
||||
*/
|
||||
|
@ -471,17 +471,17 @@ public class EasyStream<T> extends AbstractEnhancedWrappedStream<T, EasyStream<T
|
||||
public interface Builder<T> extends Consumer<T>, org.dromara.hutool.core.lang.builder.Builder<EasyStream<T>> {
|
||||
|
||||
/**
|
||||
* Adds an element to the unwrap being built.
|
||||
* Adds an element to the unwrap being built.<br>
|
||||
* The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* accept(t)
|
||||
* return this;
|
||||
* }</pre>
|
||||
*
|
||||
* @param t the element to add
|
||||
* @param t 需要添加的元素
|
||||
* @return {@code this} builder
|
||||
* @throws IllegalStateException if the builder has already transitioned to
|
||||
* the built state
|
||||
* @implSpec The default implementation behaves as if:
|
||||
* <pre>{@code
|
||||
* accept(t)
|
||||
* return this;
|
||||
* }</pre>
|
||||
*/
|
||||
default Builder<T> add(final T t) {
|
||||
accept(t);
|
||||
|
@ -214,7 +214,7 @@ public class StreamUtil {
|
||||
public static <T> Stream<T> iterate(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||
Objects.requireNonNull(next);
|
||||
Objects.requireNonNull(hasNext);
|
||||
return StreamSupport.stream(IterateSpliterator.create(seed, hasNext, next), false);
|
||||
return StreamSupport.stream(IterateSpliterator.of(seed, hasNext, next), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -305,7 +305,7 @@ public class StreamUtil {
|
||||
return Stream.empty();
|
||||
}
|
||||
Objects.requireNonNull(predicate);
|
||||
return createStatefulNewStream(source, DropWhileSpliterator.create(source.spliterator(), predicate));
|
||||
return createStatefulNewStream(source, DropWhileSpliterator.of(source.spliterator(), predicate));
|
||||
}
|
||||
|
||||
// region ----- 私有方法
|
||||
|
@ -263,11 +263,7 @@ public interface TransformableWrappedStream<T, S extends TransformableWrappedStr
|
||||
// region ============ peek ============
|
||||
|
||||
/**
|
||||
* 返回与指定函数将元素作为参数执行后组成的流。操作带下标
|
||||
*
|
||||
* @param action 指定的函数
|
||||
* @return 返回叠加操作后的FastStream
|
||||
* @apiNote 该方法存在的意义主要是用来调试
|
||||
* 返回与指定函数将元素作为参数执行后组成的流。操作带下标,该方法存在的意义主要是用来调试。
|
||||
* 当你需要查看经过操作管道某处的元素和下标,可以执行以下操作:
|
||||
* <pre>{@code
|
||||
* Stream.of("one", "two", "three", "four")
|
||||
@ -277,6 +273,9 @@ public interface TransformableWrappedStream<T, S extends TransformableWrappedStr
|
||||
* .peekIdx((e,i) -> System.out.println("Mapped value: " + e + " Mapped idx:" + i))
|
||||
* .collect(Collectors.toList());
|
||||
* }</pre>
|
||||
*
|
||||
* @param action 指定的函数
|
||||
* @return 返回叠加操作后的FastStream
|
||||
*/
|
||||
default S peekIdx(final BiConsumer<? super T, Integer> action) {
|
||||
Objects.requireNonNull(action);
|
||||
|
@ -188,21 +188,19 @@ public interface WrappedStream<T, S extends WrappedStream<T, S>> extends Stream<
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回与指定函数将元素作为参数执行后组成的流。
|
||||
* 这是一个无状态中间操作
|
||||
*
|
||||
* @param action 指定的函数
|
||||
* @return 返回叠加操作后的FastStream
|
||||
* @apiNote 该方法存在的意义主要是用来调试
|
||||
* 当你需要查看经过操作管道某处的元素,可以执行以下操作:
|
||||
* 返回与指定函数将元素作为参数执行后组成的流。这是一个无状态中间操作<br>
|
||||
* 该方法存在的意义主要是用来调试。当你需要查看经过操作管道某处的元素,可以执行以下操作:
|
||||
* <pre>{@code
|
||||
* .of("one", "two", "three", "four")
|
||||
* .filter(e -> e.length() > 3)
|
||||
* .peek(e -> System.out.println("Filtered value: " + e))
|
||||
* .peek(e -> Console.log("Filtered value: " + e))
|
||||
* .map(String::toUpperCase)
|
||||
* .peek(e -> System.out.println("Mapped value: " + e))
|
||||
* .peek(e -> Console.log("Mapped value: " + e))
|
||||
* .collect(Collectors.toList());
|
||||
* }</pre>
|
||||
*
|
||||
* @param action 指定的函数
|
||||
* @return 返回叠加操作后的FastStream
|
||||
*/
|
||||
@Override
|
||||
default S peek(final Consumer<? super T> action) {
|
||||
|
@ -21,12 +21,21 @@ import java.util.function.Predicate;
|
||||
* dropWhile 的 Spliterator
|
||||
* <p>借鉴自StreamEx</p>
|
||||
*
|
||||
* @param <T> 元素类型
|
||||
* @author emptypoint
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class DropWhileSpliterator<T> implements Spliterator<T> {
|
||||
|
||||
public static <T> DropWhileSpliterator<T> create(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
||||
/**
|
||||
* 创建
|
||||
*
|
||||
* @param source {@link Spliterator}
|
||||
* @param predicate 断言
|
||||
* @param <T> 元素类型
|
||||
* @return DropWhileSpliterator
|
||||
*/
|
||||
public static <T> DropWhileSpliterator<T> of(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
||||
return new DropWhileSpliterator<>(source, predicate);
|
||||
}
|
||||
|
||||
@ -34,7 +43,13 @@ public class DropWhileSpliterator<T> implements Spliterator<T> {
|
||||
private final Predicate<? super T> predicate;
|
||||
private boolean isFound = false;
|
||||
|
||||
private DropWhileSpliterator(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param source {@link Spliterator}
|
||||
* @param predicate 断言
|
||||
*/
|
||||
public DropWhileSpliterator(final Spliterator<T> source, final Predicate<? super T> predicate) {
|
||||
this.source = source;
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
@ -22,10 +22,23 @@ import java.util.function.UnaryOperator;
|
||||
/**
|
||||
* 无限有序流 的Spliterator
|
||||
*
|
||||
* @param <T> 流元素类型
|
||||
* @author VampireAchao
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class IterateSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
|
||||
|
||||
/**
|
||||
* @param seed 初始值
|
||||
* @param hasNext 是否有下一个断言
|
||||
* @param next 下一个值生产者
|
||||
* @param <T> 流元素类型
|
||||
* @return IterateSpliterator
|
||||
*/
|
||||
public static <T> IterateSpliterator<T> of(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||
return new IterateSpliterator<>(seed, hasNext, next);
|
||||
}
|
||||
|
||||
private final T seed;
|
||||
private final Predicate<? super T> hasNext;
|
||||
private final UnaryOperator<T> next;
|
||||
@ -34,20 +47,19 @@ public class IterateSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
|
||||
private boolean finished;
|
||||
|
||||
/**
|
||||
* Creates a spliterator reporting the given estimated size and
|
||||
* additionalCharacteristics.
|
||||
* 构造
|
||||
*
|
||||
* @param seed 初始值
|
||||
* @param hasNext 是否有下一个断言
|
||||
* @param next 下一个值生产者
|
||||
*/
|
||||
IterateSpliterator(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||
public IterateSpliterator(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||
super(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.IMMUTABLE);
|
||||
this.seed = seed;
|
||||
this.hasNext = hasNext;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public static <T> IterateSpliterator<T> create(final T seed, final Predicate<? super T> hasNext, final UnaryOperator<T> next) {
|
||||
return new IterateSpliterator<>(seed, hasNext, next);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(final Consumer<? super T> action) {
|
||||
Objects.requireNonNull(action);
|
||||
|
@ -437,7 +437,7 @@ public class AntPathMatcher {
|
||||
*/
|
||||
protected String[] tokenizePath(final String path) {
|
||||
return SplitUtil.split(path, this.pathSeparator, this.trimTokens, true)
|
||||
.toArray(new String[0]);
|
||||
.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -530,7 +530,7 @@ public class AntPathMatcher {
|
||||
* 提取参数
|
||||
*
|
||||
* @param pattern 模式
|
||||
* @param path 路径
|
||||
* @param path 路径
|
||||
* @return 参数
|
||||
*/
|
||||
public Map<String, String> extractUriTemplateVariables(final String pattern, final String path) {
|
||||
@ -548,22 +548,22 @@ public class AntPathMatcher {
|
||||
* the first pattern contains a file extension match (e.g., {@code *.html}).
|
||||
* In that case, the second pattern will be merged into the first. Otherwise,
|
||||
* an {@code IllegalArgumentException} will be thrown.
|
||||
* <p>Examples</p>
|
||||
* <table border="1" summary="">
|
||||
* <tr><th>Pattern 1</th><th>Pattern 2</th><th>Result</th></tr>
|
||||
* <tr><td>{@code null}</td><td>{@code null}</td><td> </td></tr>
|
||||
* <tr><td>/hotels</td><td>{@code null}</td><td>/hotels</td></tr>
|
||||
* <tr><td>{@code null}</td><td>/hotels</td><td>/hotels</td></tr>
|
||||
* <tr><td>/hotels</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
||||
* <tr><td>/hotels</td><td>bookings</td><td>/hotels/bookings</td></tr>
|
||||
* <tr><td>/hotels/*</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
||||
* <tr><td>/hotels/**</td><td>/bookings</td><td>/hotels/**/bookings</td></tr>
|
||||
* <tr><td>/hotels</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
||||
* <tr><td>/hotels/*</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
||||
* <tr><td>/hotels/**</td><td>{hotel}</td><td>/hotels/**/{hotel}</td></tr>
|
||||
* <tr><td>/*.html</td><td>/hotels.html</td><td>/hotels.html</td></tr>
|
||||
* <tr><td>/*.html</td><td>/hotels</td><td>/hotels.html</td></tr>
|
||||
* <tr><td>/*.html</td><td>/*.txt</td><td>{@code IllegalArgumentException}</td></tr>
|
||||
* <table border="1">
|
||||
* <caption>Examples</caption>
|
||||
* <tr><th>Pattern 1</th><th>Pattern 2</th><th>Result</th></tr>
|
||||
* <tr><td>{@code null}</td><td>{@code null}</td><td> </td></tr>
|
||||
* <tr><td>/hotels</td><td>{@code null}</td><td>/hotels</td></tr>
|
||||
* <tr><td>{@code null}</td><td>/hotels</td><td>/hotels</td></tr>
|
||||
* <tr><td>/hotels</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
||||
* <tr><td>/hotels</td><td>bookings</td><td>/hotels/bookings</td></tr>
|
||||
* <tr><td>/hotels/*</td><td>/bookings</td><td>/hotels/bookings</td></tr>
|
||||
* <tr><td>/hotels/**</td><td>/bookings</td><td>/hotels/**/bookings</td></tr>
|
||||
* <tr><td>/hotels</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
||||
* <tr><td>/hotels/*</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>
|
||||
* <tr><td>/hotels/**</td><td>{hotel}</td><td>/hotels/**/{hotel}</td></tr>
|
||||
* <tr><td>/*.html</td><td>/hotels.html</td><td>/hotels.html</td></tr>
|
||||
* <tr><td>/*.html</td><td>/hotels</td><td>/hotels.html</td></tr>
|
||||
* <tr><td>/*.html</td><td>/*.txt</td><td>{@code IllegalArgumentException}</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* @param pattern1 the first pattern
|
||||
@ -677,6 +677,12 @@ public class AntPathMatcher {
|
||||
|
||||
private final List<String> variableNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Create a new {@code AntPathStringMatcher} that will match the supplied {@code pattern}
|
||||
*
|
||||
* @param pattern the pattern to match against
|
||||
* @param caseSensitive 是否大小写不敏感
|
||||
*/
|
||||
public AntPathStringMatcher(final String pattern, final boolean caseSensitive) {
|
||||
this.rawPattern = pattern;
|
||||
this.caseSensitive = caseSensitive;
|
||||
@ -714,7 +720,7 @@ public class AntPathMatcher {
|
||||
this.exactMatch = false;
|
||||
patternBuilder.append(quote(pattern, end, pattern.length()));
|
||||
this.pattern = (this.caseSensitive ? Pattern.compile(patternBuilder.toString()) :
|
||||
Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));
|
||||
Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
}
|
||||
|
||||
@ -741,15 +747,15 @@ public class AntPathMatcher {
|
||||
if (uriTemplateVariables != null) {
|
||||
if (this.variableNames.size() != matcher.groupCount()) {
|
||||
throw new IllegalArgumentException("The number of capturing groups in the pattern segment " +
|
||||
this.pattern + " does not match the number of URI template variables it defines, " +
|
||||
"which can occur if capturing groups are used in a URI template regex. " +
|
||||
"Use non-capturing groups instead.");
|
||||
this.pattern + " does not match the number of URI template variables it defines, " +
|
||||
"which can occur if capturing groups are used in a URI template regex. " +
|
||||
"Use non-capturing groups instead.");
|
||||
}
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
final String name = this.variableNames.get(i - 1);
|
||||
if (name.startsWith("*")) {
|
||||
throw new IllegalArgumentException("Capturing patterns (" + name + ") are not " +
|
||||
"supported by the AntPathMatcher. Use the PathPatternParser instead.");
|
||||
"supported by the AntPathMatcher. Use the PathPatternParser instead.");
|
||||
}
|
||||
final String value = matcher.group(i);
|
||||
uriTemplateVariables.put(name, value);
|
||||
@ -769,18 +775,23 @@ public class AntPathMatcher {
|
||||
* {@link #getPatternComparator(String)}.
|
||||
* <p>In order, the most "generic" pattern is determined by the following:
|
||||
* <ul>
|
||||
* <li>if it's null or a capture all pattern (i.e. it is equal to "/**")</li>
|
||||
* <li>if the other pattern is an actual match</li>
|
||||
* <li>if it's a catch-all pattern (i.e. it ends with "**"</li>
|
||||
* <li>if it's got more "*" than the other pattern</li>
|
||||
* <li>if it's got more "{foo}" than the other pattern</li>
|
||||
* <li>if it's shorter than the other pattern</li>
|
||||
* <li>if it's null or a capture all pattern (i.e. it is equal to "/**")</li>
|
||||
* <li>if the other pattern is an actual match</li>
|
||||
* <li>if it's a catch-all pattern (i.e. it ends with "**"</li>
|
||||
* <li>if it's got more "*" than the other pattern</li>
|
||||
* <li>if it's got more "{foo}" than the other pattern</li>
|
||||
* <li>if it's shorter than the other pattern</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected static class AntPatternComparator implements Comparator<String> {
|
||||
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param path 路径
|
||||
*/
|
||||
public AntPatternComparator(final String path) {
|
||||
this.path = path;
|
||||
}
|
||||
@ -931,7 +942,7 @@ public class AntPathMatcher {
|
||||
public int getLength() {
|
||||
if (this.length == null) {
|
||||
this.length = (this.pattern != null ?
|
||||
VARIABLE_PATTERN.matcher(this.pattern).replaceAll("#").length() : 0);
|
||||
VARIABLE_PATTERN.matcher(this.pattern).replaceAll("#").length() : 0);
|
||||
}
|
||||
return this.length;
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ public abstract class AbstractFilter implements BloomFilter {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final BitSet bitSet;
|
||||
/**
|
||||
* 容量
|
||||
*/
|
||||
protected int size;
|
||||
|
||||
|
||||
|
@ -24,6 +24,9 @@ import org.dromara.hutool.core.text.replacer.LookupReplacer;
|
||||
public class Html4Escape extends XmlEscape {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ISO8859_1 转义字符
|
||||
*/
|
||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||
protected static final String[][] ISO8859_1_ESCAPE = { //
|
||||
{ "\u00A0", " " }, // non-breaking space
|
||||
@ -124,6 +127,9 @@ public class Html4Escape extends XmlEscape {
|
||||
{ "\u00FF", "ÿ" }, // <EFBFBD> - lowercase y, umlaut
|
||||
};
|
||||
|
||||
/**
|
||||
* HTML 4.01 extended entities.
|
||||
*/
|
||||
@SuppressWarnings("UnnecessaryUnicodeEscape")
|
||||
protected static final String[][] HTML40_EXTENDED_ESCAPE = {
|
||||
// <!-- Latin Extended-B -->
|
||||
|
@ -18,14 +18,22 @@ import org.dromara.hutool.core.text.replacer.LookupReplacer;
|
||||
* HTML4的UNESCAPE
|
||||
*
|
||||
* @author looly
|
||||
*
|
||||
*/
|
||||
public class Html4Unescape extends XmlUnescape {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected static final String[][] ISO8859_1_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.ISO8859_1_ESCAPE);
|
||||
protected static final String[][] HTML40_EXTENDED_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.HTML40_EXTENDED_ESCAPE);
|
||||
/**
|
||||
* ISO8859_1的UNESCAPE
|
||||
*/
|
||||
protected static final String[][] ISO8859_1_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.ISO8859_1_ESCAPE);
|
||||
/**
|
||||
* HTML40_EXTENDED的UNESCAPE
|
||||
*/
|
||||
protected static final String[][] HTML40_EXTENDED_UNESCAPE = InternalEscapeUtil.invert(Html4Escape.HTML40_EXTENDED_ESCAPE);
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public Html4Unescape() {
|
||||
super();
|
||||
addChain(new LookupReplacer(ISO8859_1_UNESCAPE));
|
||||
|
@ -34,6 +34,9 @@ import org.dromara.hutool.core.text.replacer.ReplacerChain;
|
||||
public class XmlEscape extends ReplacerChain {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* XML转义字符
|
||||
*/
|
||||
protected static final String[][] BASIC_ESCAPE = { //
|
||||
// {"'", "'"}, // " - single-quote
|
||||
{"\"", """}, // " - double-quote
|
||||
|
@ -24,8 +24,13 @@ import org.dromara.hutool.core.text.replacer.ReplacerChain;
|
||||
public class XmlUnescape extends ReplacerChain {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 基础反转义符
|
||||
*/
|
||||
protected static final String[][] BASIC_UNESCAPE = InternalEscapeUtil.invert(XmlEscape.BASIC_ESCAPE);
|
||||
// issue#1118
|
||||
/**
|
||||
* issue#1118,新增'反转义
|
||||
*/
|
||||
protected static final String[][] OTHER_UNESCAPE = new String[][]{new String[]{"'", "'"}};
|
||||
|
||||
/**
|
||||
|
@ -25,8 +25,17 @@ import java.io.Serializable;
|
||||
public abstract class TextFinder implements Finder, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 文本
|
||||
*/
|
||||
protected CharSequence text;
|
||||
/**
|
||||
* 结束位置
|
||||
*/
|
||||
protected int endIndex = -1;
|
||||
/**
|
||||
* 是否反向查找
|
||||
*/
|
||||
protected boolean negative;
|
||||
|
||||
/**
|
||||
|
@ -151,6 +151,15 @@ public abstract class StrTemplate {
|
||||
protected int fixedTextTotalLength;
|
||||
// endregion
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param template 字符串模板
|
||||
* @param escape 转义符
|
||||
* @param defaultValue 默认值
|
||||
* @param defaultValueHandler 默认值处理器
|
||||
* @param features 策略值
|
||||
*/
|
||||
protected StrTemplate(final String template, final char escape, final String defaultValue,
|
||||
final UnaryOperator<String> defaultValueHandler, final int features) {
|
||||
Assert.notNull(template, "String template cannot be null");
|
||||
@ -718,6 +727,11 @@ public abstract class StrTemplate {
|
||||
*/
|
||||
protected int features;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param template 字符串模板
|
||||
*/
|
||||
protected AbstractBuilder(final String template) {
|
||||
this.template = Objects.requireNonNull(template);
|
||||
// 策略值 初始为 全局默认策略
|
||||
|
@ -21,11 +21,15 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
||||
*/
|
||||
public abstract class AbstractPlaceholderSegment implements StrTemplateSegment {
|
||||
/**
|
||||
* 占位符变量
|
||||
* <p>例如:{@literal "???"->"???", "{}"->"{}", "{name}"->"name"}</p>
|
||||
* 占位符变量,例如:{@literal "???"->"???", "{}"->"{}", "{name}"->"name"}
|
||||
*/
|
||||
private final String placeholder;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param placeholder 占位符变量,例如:{@literal "???"->"???", "{}"->"{}", "{name}"->"name"}
|
||||
*/
|
||||
protected AbstractPlaceholderSegment(final String placeholder) {
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
@ -20,17 +20,23 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class IndexedPlaceholderSegment extends NamedPlaceholderSegment {
|
||||
/**
|
||||
* 下标值
|
||||
*/
|
||||
private final int index;
|
||||
/**
|
||||
* 下标值
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
public IndexedPlaceholderSegment(final String idxStr, final String wholePlaceholder) {
|
||||
super(idxStr, wholePlaceholder);
|
||||
this.index = Integer.parseInt(idxStr);
|
||||
}
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param idxStr 索引字符串变量
|
||||
* @param wholePlaceholder 占位符完整文本
|
||||
*/
|
||||
public IndexedPlaceholderSegment(final String idxStr, final String wholePlaceholder) {
|
||||
super(idxStr, wholePlaceholder);
|
||||
this.index = Integer.parseInt(idxStr);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
@ -19,18 +19,23 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class LiteralSegment implements StrTemplateSegment {
|
||||
/**
|
||||
* 模板中固定的一段文本
|
||||
*/
|
||||
private final String text;
|
||||
/**
|
||||
* 模板中固定的一段文本
|
||||
*/
|
||||
private final String text;
|
||||
|
||||
public LiteralSegment(final String text) {
|
||||
this.text = text;
|
||||
}
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public LiteralSegment(final String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
@Override
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,20 +20,25 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class NamedPlaceholderSegment extends AbstractPlaceholderSegment {
|
||||
/**
|
||||
* 占位符完整文本
|
||||
* <p>例如:{@literal "{name}"->"{name}"}</p>
|
||||
*/
|
||||
private final String wholePlaceholder;
|
||||
/**
|
||||
* 占位符完整文本
|
||||
* <p>例如:{@literal "{name}"->"{name}"}</p>
|
||||
*/
|
||||
private final String wholePlaceholder;
|
||||
|
||||
public NamedPlaceholderSegment(final String name, final String wholePlaceholder) {
|
||||
super(name);
|
||||
this.wholePlaceholder = wholePlaceholder;
|
||||
}
|
||||
/**
|
||||
* 构造
|
||||
* @param name 占位符变量
|
||||
* @param wholePlaceholder 占位符完整文本
|
||||
*/
|
||||
public NamedPlaceholderSegment(final String name, final String wholePlaceholder) {
|
||||
super(name);
|
||||
this.wholePlaceholder = wholePlaceholder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return wholePlaceholder;
|
||||
}
|
||||
@Override
|
||||
public String getText() {
|
||||
return wholePlaceholder;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,11 +21,17 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
||||
*/
|
||||
public class SinglePlaceholderSegment extends AbstractPlaceholderSegment {
|
||||
|
||||
private SinglePlaceholderSegment(final String placeholder) {
|
||||
super(placeholder);
|
||||
}
|
||||
private SinglePlaceholderSegment(final String placeholder) {
|
||||
super(placeholder);
|
||||
}
|
||||
|
||||
public static SinglePlaceholderSegment newInstance(final String placeholder) {
|
||||
return new SinglePlaceholderSegment(placeholder);
|
||||
}
|
||||
/**
|
||||
* 创建SinglePlaceholderSegment
|
||||
*
|
||||
* @param placeholder 占位符
|
||||
* @return SinglePlaceholderSegment
|
||||
*/
|
||||
public static SinglePlaceholderSegment of(final String placeholder) {
|
||||
return new SinglePlaceholderSegment(placeholder);
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,10 @@ package org.dromara.hutool.core.text.placeholder.segment;
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public interface StrTemplateSegment {
|
||||
/**
|
||||
* 获取文本值
|
||||
*
|
||||
* @return 文本值,对于固定文本Segment,返回文本值;对于单占位符Segment,返回占位符;对于有前后缀的占位符Segment,返回占位符完整文本,例如: "{name}"
|
||||
*/
|
||||
String getText();
|
||||
|
||||
/**
|
||||
* 获取文本值
|
||||
*
|
||||
* @return 文本值,对于固定文本Segment,返回文本值;对于单占位符Segment,返回占位符;对于有前后缀的占位符Segment,返回占位符完整文本,例如: "{name}"
|
||||
*/
|
||||
String getText();
|
||||
}
|
||||
|
@ -582,6 +582,10 @@ public class NamedPlaceholderStrTemplate extends StrTemplate {
|
||||
*/
|
||||
protected String suffix;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
* @param template 模板
|
||||
*/
|
||||
protected Builder(final String template) {
|
||||
super(template);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public class SinglePlaceholderStrTemplate extends StrTemplate {
|
||||
// 上一个解析的segment是否是固定文本,如果是,则需要和当前新的文本部分合并
|
||||
boolean lastIsLiteralSegment = false;
|
||||
// 复用的占位符变量
|
||||
final SinglePlaceholderSegment singlePlaceholderSegment = SinglePlaceholderSegment.newInstance(placeholder);
|
||||
final SinglePlaceholderSegment singlePlaceholderSegment = SinglePlaceholderSegment.of(placeholder);
|
||||
List<StrTemplateSegment> segments = null;
|
||||
while (true) {
|
||||
delimIndex = template.indexOf(placeholder, handledPosition);
|
||||
@ -200,6 +200,11 @@ public class SinglePlaceholderStrTemplate extends StrTemplate {
|
||||
*/
|
||||
protected String placeholder;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param template 字符串模板
|
||||
*/
|
||||
protected Builder(final String template) {
|
||||
super(template);
|
||||
}
|
||||
|
@ -12,39 +12,75 @@
|
||||
|
||||
package org.dromara.hutool.core.thread;
|
||||
|
||||
import org.dromara.hutool.core.exception.ExceptionUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
|
||||
/**
|
||||
* 工具类异常
|
||||
* 线程异常
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.17
|
||||
*/
|
||||
public class ThreadException extends RuntimeException {
|
||||
public class ThreadException extends HutoolException {
|
||||
private static final long serialVersionUID = 5253124428623713216L;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param e 异常
|
||||
*/
|
||||
public ThreadException(final Throwable e) {
|
||||
super(ExceptionUtil.getMessage(e), e);
|
||||
super(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
*/
|
||||
public ThreadException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param messageTemplate 消息模板
|
||||
* @param params 参数
|
||||
*/
|
||||
public ThreadException(final String messageTemplate, final Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params));
|
||||
super(messageTemplate, params);
|
||||
}
|
||||
|
||||
public ThreadException(final String message, final Throwable throwable) {
|
||||
super(message, throwable);
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
* @param cause 被包装的子异常
|
||||
*/
|
||||
public ThreadException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ThreadException(final String message, final Throwable throwable, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||
super(message, throwable, enableSuppression, writableStackTrace);
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param message 消息
|
||||
* @param cause 被包装的子异常
|
||||
* @param enableSuppression 是否启用抑制
|
||||
* @param writableStackTrace 堆栈跟踪是否应该是可写的
|
||||
*/
|
||||
public ThreadException(final String message, final Throwable cause, final boolean enableSuppression, final boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
public ThreadException(final Throwable throwable, final String messageTemplate, final Object... params) {
|
||||
super(StrUtil.format(messageTemplate, params), throwable);
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param cause 被包装的子异常
|
||||
* @param messageTemplate 消息模板
|
||||
* @param params 参数
|
||||
*/
|
||||
public ThreadException(final Throwable cause, final String messageTemplate, final Object... params) {
|
||||
super(cause, messageTemplate, params);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ import java.util.concurrent.locks.Lock;
|
||||
*/
|
||||
public class NoLock implements Lock{
|
||||
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static NoLock INSTANCE = new NoLock();
|
||||
|
||||
@Override
|
||||
|
77
pom.xml
77
pom.xml
@ -57,12 +57,12 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Kotlin适配,用于在测试和编译中使用kotlin代码 -->
|
||||
<!-- Kotlin适配,用于在测试中使用kotlin代码 -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<version>${kotlin-version}</version>
|
||||
<scope>provided</scope>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- 全局单元测试 -->
|
||||
<dependency>
|
||||
@ -100,6 +100,10 @@
|
||||
<name>VampireAchao</name>
|
||||
<email>VampireAchao@dromara.org</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>CherryRum</name>
|
||||
<email>yulin.1996@foxmail.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Emptypoint</name>
|
||||
<email>1215582715@qq.com</email>
|
||||
@ -116,10 +120,6 @@
|
||||
<name>Dazer007</name>
|
||||
<email>dazer007@163.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>CherryRum</name>
|
||||
<email>yulin.1996@foxmail.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Aihuahua</name>
|
||||
<email>aihuahua522@qq.com</email>
|
||||
@ -169,8 +169,10 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<source>${compile.version}</source>
|
||||
<target>${compile.version}</target>
|
||||
<!-- 编译时启用警告位置 -->
|
||||
<compilerArgument>-Xlint:unchecked</compilerArgument>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@ -214,46 +216,6 @@
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<tags>
|
||||
<tag>
|
||||
<name>apiNote</name>
|
||||
<placement>a</placement>
|
||||
<head>API Note:</head>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>implSpec</name>
|
||||
<placement>a</placement>
|
||||
<head>Implementation Requirements:</head>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>implNote</name>
|
||||
<placement>a</placement>
|
||||
<head>Implementation Note:</head>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>param</name>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>return</name>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>throws</name>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>since</name>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>version</name>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>serialData</name>
|
||||
</tag>
|
||||
<tag>
|
||||
<name>see</name>
|
||||
</tag>
|
||||
</tags>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 统一更新pom版本 -->
|
||||
<plugin>
|
||||
@ -277,6 +239,29 @@
|
||||
<check/>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- 用于生成模块化系统中的module-info.class,见:https://github.com/moditect/moditect -->
|
||||
<plugin>
|
||||
<groupId>org.moditect</groupId>
|
||||
<artifactId>moditect-maven-plugin</artifactId>
|
||||
<version>1.2.2.Final</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-module-infos</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>add-module-info</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<jvmVersion>9</jvmVersion>
|
||||
<module>
|
||||
<moduleInfo>
|
||||
<name>${Automatic-Module-Name}</name>
|
||||
</moduleInfo>
|
||||
</module>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user