mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix code
This commit is contained in:
@@ -29,9 +29,9 @@ public class AnnotationProxy<T extends Annotation> implements Annotation, Invoca
|
||||
*
|
||||
* @param annotation 注解
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public AnnotationProxy(T annotation) {
|
||||
this.annotation = annotation;
|
||||
//noinspection unchecked
|
||||
this.type = (Class<T>) annotation.annotationType();
|
||||
this.attributes = initAttributes();
|
||||
}
|
||||
|
@@ -74,13 +74,13 @@ public class AnnotationUtil {
|
||||
* @return 注解对象数组
|
||||
* @since 5.8.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] getAnnotations(AnnotatedElement annotationEle, boolean isToCombination, Class<T> annotationType) {
|
||||
final Annotation[] annotations = getAnnotations(annotationEle, isToCombination,
|
||||
(annotation -> null == annotationType || annotationType.isAssignableFrom(annotation.getClass())));
|
||||
|
||||
final T[] result = ArrayUtil.newArray(annotationType, annotations.length);
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
//noinspection unchecked
|
||||
result[i] = (T) annotations[i];
|
||||
}
|
||||
return result;
|
||||
|
@@ -34,6 +34,7 @@ public class BeanToMapCopier extends AbsCopier<Object, Map> {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map copy() {
|
||||
Class<?> actualEditable = source.getClass();
|
||||
@@ -73,7 +74,6 @@ public class BeanToMapCopier extends AbsCopier<Object, Map> {
|
||||
|
||||
// 目标赋值
|
||||
if(null != sValue || false == copyOptions.ignoreNullValue){
|
||||
//noinspection unchecked
|
||||
target.put(sFieldName, sValue);
|
||||
}
|
||||
});
|
||||
|
@@ -23,18 +23,18 @@ public class Base16Codec implements Encoder<byte[], char[]>, Decoder<CharSequenc
|
||||
*
|
||||
* @param lowerCase 是否小写
|
||||
*/
|
||||
public Base16Codec(boolean lowerCase) {
|
||||
public Base16Codec(final boolean lowerCase) {
|
||||
this.alphabets = (lowerCase ? "0123456789abcdef" : "0123456789ABCDEF").toCharArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] encode(byte[] data) {
|
||||
public char[] encode(final byte[] data) {
|
||||
final int len = data.length;
|
||||
final char[] out = new char[len << 1];//len*2
|
||||
// two characters from the hex value.
|
||||
for (int i = 0, j = 0; i < len; i++) {
|
||||
out[j++] = alphabets[(0xF0 & data[i]) >>> 4];// 高位
|
||||
out[j++] = alphabets[0x0F & data[i]];// 低位
|
||||
out[j++] = hexDigit(data[i] >> 4);// 高位
|
||||
out[j++] = hexDigit(data[i]);// 低位
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -79,12 +79,12 @@ public class Base16Codec implements Encoder<byte[], char[]>, Decoder<CharSequenc
|
||||
* @param ch char值
|
||||
* @return Unicode表现形式
|
||||
*/
|
||||
public String toUnicodeHex(char ch) {
|
||||
return "\\u" +//
|
||||
alphabets[(ch >> 12) & 15] +//
|
||||
alphabets[(ch >> 8) & 15] +//
|
||||
alphabets[(ch >> 4) & 15] +//
|
||||
alphabets[(ch) & 15];
|
||||
public String toUnicodeHex(final char ch) {
|
||||
return "\\u" +
|
||||
hexDigit(ch >> 12) +
|
||||
hexDigit(ch >> 8) +
|
||||
hexDigit(ch >> 4) +
|
||||
hexDigit(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,10 +94,21 @@ public class Base16Codec implements Encoder<byte[], char[]>, Decoder<CharSequenc
|
||||
* @param b byte
|
||||
*/
|
||||
public void appendHex(StringBuilder builder, byte b) {
|
||||
int high = (b & 0xf0) >>> 4;//高位
|
||||
int low = b & 0x0f;//低位
|
||||
builder.append(alphabets[high]);
|
||||
builder.append(alphabets[low]);
|
||||
//高位
|
||||
builder.append(hexDigit(b >> 4));
|
||||
//低位
|
||||
builder.append(hexDigit(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将byte值转为16进制
|
||||
*
|
||||
* @param b byte
|
||||
* @return hex char
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public char hexDigit(final int b) {
|
||||
return alphabets[b & 0x0f];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +119,7 @@ public class Base16Codec implements Encoder<byte[], char[]>, Decoder<CharSequenc
|
||||
* @return 一个整数
|
||||
* @throws UtilException 当ch不是一个合法的十六进制字符时,抛出运行时异常
|
||||
*/
|
||||
private static int toDigit(char ch, int index) {
|
||||
private static int toDigit(final char ch, final int index) {
|
||||
int digit = Character.digit(ch, 16);
|
||||
if (digit < 0) {
|
||||
throw new UtilException("Illegal hexadecimal character {} at index {}", ch, index);
|
||||
|
@@ -1,13 +1,15 @@
|
||||
package cn.hutool.core.codec;
|
||||
|
||||
import cn.hutool.core.text.CharPool;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Serializable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.BitSet;
|
||||
|
||||
@@ -30,33 +32,11 @@ import java.util.BitSet;
|
||||
* @author looly
|
||||
* @since 5.7.16
|
||||
*/
|
||||
public class PercentCodec implements Serializable {
|
||||
public class PercentCodec implements Encoder<byte[], byte[]>, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 从已知PercentCodec创建PercentCodec,会复制给定PercentCodec的安全字符
|
||||
*
|
||||
* @param codec PercentCodec
|
||||
* @return PercentCodec
|
||||
*/
|
||||
public static PercentCodec of(PercentCodec codec) {
|
||||
return new PercentCodec((BitSet) codec.safeCharacters.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建PercentCodec,使用指定字符串中的字符作为安全字符
|
||||
*
|
||||
* @param chars 安全字符合集
|
||||
* @return PercentCodec
|
||||
*/
|
||||
public static PercentCodec of(CharSequence chars) {
|
||||
final PercentCodec codec = new PercentCodec();
|
||||
final int length = chars.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
codec.addSafe(chars.charAt(i));
|
||||
}
|
||||
return codec;
|
||||
}
|
||||
private static final char DEFAULT_SIZE = 256;
|
||||
private static final char ESCAPE_CHAR = CharPool.PERCENT;
|
||||
|
||||
/**
|
||||
* 存放安全编码
|
||||
@@ -75,7 +55,7 @@ public class PercentCodec implements Serializable {
|
||||
* [a-zA-Z0-9]默认不被编码
|
||||
*/
|
||||
public PercentCodec() {
|
||||
this(new BitSet(256));
|
||||
this(new BitSet(DEFAULT_SIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,68 +68,33 @@ public class PercentCodec implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加安全字符<br>
|
||||
* 安全字符不被编码
|
||||
* 检查给定字符是否为安全字符
|
||||
*
|
||||
* @param c 字符
|
||||
* @return this
|
||||
* @return {@code true}表示安全,否则非安全字符
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public PercentCodec addSafe(char c) {
|
||||
safeCharacters.set(c);
|
||||
return this;
|
||||
public boolean isSafe(char c) {
|
||||
return this.safeCharacters.get(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除安全字符<br>
|
||||
* 安全字符不被编码
|
||||
*
|
||||
* @param c 字符
|
||||
* @return this
|
||||
*/
|
||||
public PercentCodec removeSafe(char c) {
|
||||
safeCharacters.clear(c);
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public byte[] encode(byte[] bytes) {
|
||||
// 初始容量计算,简单粗暴假设所有byte都需要转义,容量是三倍
|
||||
final ByteBuffer buffer = ByteBuffer.allocate(bytes.length * 3);
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
encodeTo(buffer, bytes[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加安全字符到挡墙的PercentCodec
|
||||
*
|
||||
* @param codec PercentCodec
|
||||
* @return this
|
||||
*/
|
||||
public PercentCodec or(PercentCodec codec) {
|
||||
this.safeCharacters.or(codec.safeCharacters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合当前PercentCodec和指定PercentCodec为一个新的PercentCodec,安全字符为并集
|
||||
*
|
||||
* @param codec PercentCodec
|
||||
* @return 新的PercentCodec
|
||||
*/
|
||||
public PercentCodec orNew(PercentCodec codec) {
|
||||
return of(this).or(codec);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否将空格编码为+<br>
|
||||
* 如果为{@code true},则将空格编码为"+",此项只在"application/x-www-form-urlencoded"中使用<br>
|
||||
* 如果为{@code false},则空格编码为"%20",此项一般用于URL的Query部分(RFC3986规范)
|
||||
*
|
||||
* @param encodeSpaceAsPlus 是否将空格编码为+
|
||||
* @return this
|
||||
*/
|
||||
public PercentCodec setEncodeSpaceAsPlus(boolean encodeSpaceAsPlus) {
|
||||
this.encodeSpaceAsPlus = encodeSpaceAsPlus;
|
||||
return this;
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将URL中的字符串编码为%形式
|
||||
*
|
||||
* @param path 需要编码的字符串
|
||||
* @param charset 编码, {@code null}返回原字符串,表示不编码
|
||||
* @param path 需要编码的字符串
|
||||
* @param charset 编码, {@code null}返回原字符串,表示不编码
|
||||
* @param customSafeChar 自定义安全字符
|
||||
* @return 编码后的字符串
|
||||
*/
|
||||
@@ -158,7 +103,7 @@ public class PercentCodec implements Serializable {
|
||||
return StrUtil.str(path);
|
||||
}
|
||||
|
||||
final StringBuilder rewrittenPath = new StringBuilder(path.length());
|
||||
final StringBuilder rewrittenPath = new StringBuilder(path.length() * 3);
|
||||
final ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||
final OutputStreamWriter writer = new OutputStreamWriter(buf, charset);
|
||||
|
||||
@@ -184,7 +129,7 @@ public class PercentCodec implements Serializable {
|
||||
byte[] ba = buf.toByteArray();
|
||||
for (byte toEncode : ba) {
|
||||
// Converting each byte in the buffer
|
||||
rewrittenPath.append('%');
|
||||
rewrittenPath.append(ESCAPE_CHAR);
|
||||
HexUtil.appendHex(rewrittenPath, toEncode, false);
|
||||
}
|
||||
buf.reset();
|
||||
@@ -192,4 +137,132 @@ public class PercentCodec implements Serializable {
|
||||
}
|
||||
return rewrittenPath.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将单一byte转义到{@link ByteBuffer}中
|
||||
*
|
||||
* @param buffer {@link ByteBuffer}
|
||||
* @param b 字符byte
|
||||
*/
|
||||
private void encodeTo(final ByteBuffer buffer, final byte b) {
|
||||
if (safeCharacters.get(b)) {
|
||||
// 跳过安全字符
|
||||
buffer.put(b);
|
||||
} else if (encodeSpaceAsPlus && b == CharPool.SPACE) {
|
||||
// 对于空格单独处理
|
||||
buffer.put((byte) CharPool.PLUS);
|
||||
} else {
|
||||
buffer.put((byte) ESCAPE_CHAR);
|
||||
buffer.put((byte) Base16Codec.CODEC_UPPER.hexDigit(b >> 4));
|
||||
buffer.put((byte) Base16Codec.CODEC_UPPER.hexDigit(b));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PercentCodec}构建器<br>
|
||||
* 由于{@link PercentCodec}本身应该是只读对象,因此将此对象的构建放在Builder中
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static class Builder implements cn.hutool.core.builder.Builder<PercentCodec> {
|
||||
/**
|
||||
* 从已知PercentCodec创建PercentCodec,会复制给定PercentCodec的安全字符
|
||||
*
|
||||
* @param codec PercentCodec
|
||||
* @return PercentCodec
|
||||
*/
|
||||
public static Builder of(PercentCodec codec) {
|
||||
return new Builder(new PercentCodec((BitSet) codec.safeCharacters.clone()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建PercentCodec,使用指定字符串中的字符作为安全字符
|
||||
*
|
||||
* @param chars 安全字符合集
|
||||
* @return PercentCodec
|
||||
*/
|
||||
public static Builder of(CharSequence chars) {
|
||||
Builder builder = of(new PercentCodec());
|
||||
final int length = chars.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
builder.addSafe(chars.charAt(i));
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private final PercentCodec codec;
|
||||
|
||||
private Builder(PercentCodec codec) {
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加安全字符<br>
|
||||
* 安全字符不被编码
|
||||
*
|
||||
* @param c 字符
|
||||
* @return this
|
||||
*/
|
||||
public Builder addSafe(char c) {
|
||||
codec.safeCharacters.set(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加安全字符<br>
|
||||
* 安全字符不被编码
|
||||
*
|
||||
* @param chars 安全字符
|
||||
* @return this
|
||||
*/
|
||||
public Builder addSafes(String chars) {
|
||||
final int length = chars.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
addSafe(chars.charAt(i));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除安全字符<br>
|
||||
* 安全字符不被编码
|
||||
*
|
||||
* @param c 字符
|
||||
* @return this
|
||||
*/
|
||||
public Builder removeSafe(char c) {
|
||||
codec.safeCharacters.clear(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加安全字符到当前的PercentCodec
|
||||
*
|
||||
* @param otherCodec {@link PercentCodec}
|
||||
* @return this
|
||||
*/
|
||||
public Builder or(PercentCodec otherCodec) {
|
||||
codec.safeCharacters.or(otherCodec.safeCharacters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否将空格编码为+<br>
|
||||
* 如果为{@code true},则将空格编码为"+",此项只在"application/x-www-form-urlencoded"中使用<br>
|
||||
* 如果为{@code false},则空格编码为"%20",此项一般用于URL的Query部分(RFC3986规范)
|
||||
*
|
||||
* @param encodeSpaceAsPlus 是否将空格编码为+
|
||||
* @return this
|
||||
*/
|
||||
public Builder setEncodeSpaceAsPlus(boolean encodeSpaceAsPlus) {
|
||||
codec.encodeSpaceAsPlus = encodeSpaceAsPlus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PercentCodec build() {
|
||||
return codec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -115,9 +115,9 @@ public class UniqueKeySet<K, V> extends AbstractSet<V> implements Serializable {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
//noinspection unchecked
|
||||
return map.containsKey(this.uniqueGenerator.apply((V) o));
|
||||
}
|
||||
|
||||
@@ -151,9 +151,9 @@ public class UniqueKeySet<K, V> extends AbstractSet<V> implements Serializable {
|
||||
return modified;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
//noinspection unchecked
|
||||
return null != map.remove(this.uniqueGenerator.apply((V) o));
|
||||
}
|
||||
|
||||
|
@@ -101,15 +101,6 @@ public class FastByteArrayOutputStream extends OutputStream {
|
||||
return toString(CharsetUtil.defaultCharset());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为字符串
|
||||
* @param charsetName 编码
|
||||
* @return 字符串
|
||||
*/
|
||||
public String toString(String charsetName) {
|
||||
return toString(CharsetUtil.charset(charsetName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为字符串
|
||||
* @param charset 编码,null表示默认编码
|
||||
|
@@ -567,6 +567,7 @@ public class IoUtil extends NioUtil {
|
||||
* @throws IORuntimeException IO异常
|
||||
* @throws UtilException ClassNotFoundException包装
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T readObj(ValidateObjectInputStream in, Class<T> clazz) throws IORuntimeException, UtilException {
|
||||
if (in == null) {
|
||||
throw new IllegalArgumentException("The InputStream must not be null");
|
||||
@@ -575,7 +576,6 @@ public class IoUtil extends NioUtil {
|
||||
in.accept(clazz);
|
||||
}
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return (T) in.readObject();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
|
@@ -71,12 +71,12 @@ public class CamelCaseMap<K, V> extends FuncKeyMap<K, V> {
|
||||
*
|
||||
* @param emptyMapBuilder Map构造器,必须构造空的Map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
CamelCaseMap(MapBuilder<K, V> emptyMapBuilder) {
|
||||
super(emptyMapBuilder.build(), (key) -> {
|
||||
if (key instanceof CharSequence) {
|
||||
key = StrUtil.toCamelCase(key.toString());
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (K) key;
|
||||
});
|
||||
}
|
||||
|
@@ -71,12 +71,12 @@ public class CaseInsensitiveMap<K, V> extends FuncKeyMap<K, V> {
|
||||
*
|
||||
* @param emptyMapBuilder 被包装的自定义Map创建器
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
CaseInsensitiveMap(MapBuilder<K, V> emptyMapBuilder) {
|
||||
super(emptyMapBuilder.build(), (key)->{
|
||||
if (key instanceof CharSequence) {
|
||||
key = key.toString().toLowerCase();
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (K) key;
|
||||
});
|
||||
}
|
||||
|
@@ -24,9 +24,9 @@ public abstract class CustomKeyMap<K, V> extends TransMap<K, V> {
|
||||
super(emptyMap);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected V customValue(Object value) {
|
||||
//noinspection unchecked
|
||||
return (V)value;
|
||||
}
|
||||
}
|
||||
|
@@ -37,12 +37,12 @@ public class FuncKeyMap<K, V> extends CustomKeyMap<K, V> {
|
||||
* @param key KEY
|
||||
* @return 驼峰Key
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected K customKey(Object key) {
|
||||
if (null != this.keyFunc) {
|
||||
return keyFunc.apply(key);
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (K)key;
|
||||
}
|
||||
}
|
||||
|
@@ -53,21 +53,21 @@ public class FuncMap<K, V> extends TransMap<K, V> {
|
||||
* @param key KEY
|
||||
* @return 驼峰Key
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected K customKey(Object key) {
|
||||
if (null != this.keyFunc) {
|
||||
return keyFunc.apply(key);
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (K) key;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected V customValue(Object value) {
|
||||
if (null != this.valueFunc) {
|
||||
return valueFunc.apply(value);
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (V) value;
|
||||
}
|
||||
}
|
||||
|
@@ -69,9 +69,9 @@ public abstract class AbsTable<R, C, V> implements Table<R, C, V> {
|
||||
return new TransIter<>(cellSet().iterator(), Cell::getValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
//noinspection unchecked
|
||||
return containsValue((V) o);
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,6 @@ public class FormUrlencoded {
|
||||
* query中的value,默认除"-", "_", ".", "*"外都编码<br>
|
||||
* 这个类似于JDK提供的{@link java.net.URLEncoder}
|
||||
*/
|
||||
public static final PercentCodec ALL = PercentCodec.of(RFC3986.UNRESERVED)
|
||||
.removeSafe('~').addSafe('*').setEncodeSpaceAsPlus(true);
|
||||
public static final PercentCodec ALL = PercentCodec.Builder.of(RFC3986.UNRESERVED)
|
||||
.removeSafe('~').addSafe('*').setEncodeSpaceAsPlus(true).build();
|
||||
}
|
||||
|
@@ -14,29 +14,29 @@ public class RFC3986 {
|
||||
/**
|
||||
* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
|
||||
*/
|
||||
public static final PercentCodec GEN_DELIMS = PercentCodec.of(":/?#[]@");
|
||||
public static final PercentCodec GEN_DELIMS = PercentCodec.Builder.of(":/?#[]@").build();
|
||||
|
||||
/**
|
||||
* sub-delims = "!" / "$" / "{@code &}" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
||||
*/
|
||||
public static final PercentCodec SUB_DELIMS = PercentCodec.of("!$&'()*+,;=");
|
||||
public static final PercentCodec SUB_DELIMS = PercentCodec.Builder.of("!$&'()*+,;=").build();
|
||||
|
||||
/**
|
||||
* reserved = gen-delims / sub-delims<br>
|
||||
* see:<a href="https://www.ietf.org/rfc/rfc3986.html#section-2.2">https://www.ietf.org/rfc/rfc3986.html#section-2.2</a>
|
||||
*/
|
||||
public static final PercentCodec RESERVED = GEN_DELIMS.orNew(SUB_DELIMS);
|
||||
public static final PercentCodec RESERVED = PercentCodec.Builder.of(GEN_DELIMS).or(SUB_DELIMS).build();
|
||||
|
||||
/**
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"<br>
|
||||
* see: <a href="https://www.ietf.org/rfc/rfc3986.html#section-2.3">https://www.ietf.org/rfc/rfc3986.html#section-2.3</a>
|
||||
*/
|
||||
public static final PercentCodec UNRESERVED = PercentCodec.of(unreservedChars());
|
||||
public static final PercentCodec UNRESERVED = PercentCodec.Builder.of(unreservedChars()).build();
|
||||
|
||||
/**
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
*/
|
||||
public static final PercentCodec PCHAR = UNRESERVED.orNew(SUB_DELIMS).or(PercentCodec.of(":@"));
|
||||
public static final PercentCodec PCHAR = PercentCodec.Builder.of(UNRESERVED).or(SUB_DELIMS).addSafes(":@").build();
|
||||
|
||||
/**
|
||||
* segment = pchar<br>
|
||||
@@ -46,17 +46,17 @@ public class RFC3986 {
|
||||
/**
|
||||
* segment-nz-nc = SEGMENT ; non-zero-length segment without any colon ":"
|
||||
*/
|
||||
public static final PercentCodec SEGMENT_NZ_NC = PercentCodec.of(SEGMENT).removeSafe(':');
|
||||
public static final PercentCodec SEGMENT_NZ_NC = PercentCodec.Builder.of(SEGMENT).removeSafe(':').build();
|
||||
|
||||
/**
|
||||
* path = segment / "/"
|
||||
*/
|
||||
public static final PercentCodec PATH = SEGMENT.orNew(PercentCodec.of("/"));
|
||||
public static final PercentCodec PATH = PercentCodec.Builder.of(SEGMENT).addSafe('/').build();
|
||||
|
||||
/**
|
||||
* query = pchar / "/" / "?"
|
||||
*/
|
||||
public static final PercentCodec QUERY = PCHAR.orNew(PercentCodec.of("/?"));
|
||||
public static final PercentCodec QUERY = PercentCodec.Builder.of(PCHAR).addSafes("/?").build();
|
||||
|
||||
/**
|
||||
* fragment = pchar / "/" / "?"
|
||||
@@ -67,13 +67,13 @@ public class RFC3986 {
|
||||
* query中的value<br>
|
||||
* value不能包含"{@code &}",可以包含 "="
|
||||
*/
|
||||
public static final PercentCodec QUERY_PARAM_VALUE = PercentCodec.of(QUERY).removeSafe('&');
|
||||
public static final PercentCodec QUERY_PARAM_VALUE = PercentCodec.Builder.of(QUERY).removeSafe('&').build();
|
||||
|
||||
/**
|
||||
* query中的key<br>
|
||||
* key不能包含"{@code &}" 和 "="
|
||||
*/
|
||||
public static final PercentCodec QUERY_PARAM_NAME = PercentCodec.of(QUERY_PARAM_VALUE).removeSafe('=');
|
||||
public static final PercentCodec QUERY_PARAM_NAME = PercentCodec.Builder.of(QUERY_PARAM_VALUE).removeSafe('=').build();
|
||||
|
||||
/**
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
|
@@ -143,7 +143,7 @@ public class URLDecoder implements Serializable {
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream(bytes.length);
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream(bytes.length * 3);
|
||||
int b;
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
b = bytes[i];
|
||||
|
@@ -83,4 +83,12 @@ public interface CharPool {
|
||||
* 字符常量:艾特 {@code '@'}
|
||||
*/
|
||||
char AT = '@';
|
||||
/**
|
||||
* 字符常量:加号 {@code '+'}
|
||||
*/
|
||||
char PLUS = '+';
|
||||
/**
|
||||
* 字符常量:百分号 {@code '%'}
|
||||
*/
|
||||
char PERCENT = '%';
|
||||
}
|
||||
|
@@ -0,0 +1,18 @@
|
||||
package cn.hutool.core.codec;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PercentCodecTest {
|
||||
|
||||
@Test
|
||||
public void isSafeTest(){
|
||||
PercentCodec codec = PercentCodec.Builder.of("=").build();
|
||||
Assert.assertTrue(codec.isSafe('='));
|
||||
|
||||
codec = PercentCodec.Builder.of("=").or(PercentCodec.Builder.of("abc").build()).build();
|
||||
Assert.assertTrue(codec.isSafe('a'));
|
||||
Assert.assertTrue(codec.isSafe('b'));
|
||||
Assert.assertTrue(codec.isSafe('c'));
|
||||
}
|
||||
}
|
@@ -6,6 +6,12 @@ import org.junit.Test;
|
||||
|
||||
public class RFC3986Test {
|
||||
|
||||
@Test
|
||||
public void pacharTest(){
|
||||
final String encode = RFC3986.PCHAR.encode("=", CharsetUtil.UTF_8);
|
||||
Assert.assertEquals("=", encode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeQueryTest(){
|
||||
String encode = RFC3986.QUERY_PARAM_VALUE.encode("a=b", CharsetUtil.UTF_8);
|
||||
|
@@ -21,4 +21,12 @@ public class URLEncoderTest {
|
||||
String encode2 = URLEncoder.encodeQuery(body);
|
||||
Assert.assertEquals("+", encode2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeEmojiTest(){
|
||||
String emoji = "🐶😊😂🤣";
|
||||
String encode = URLEncoder.encodeAll(emoji);
|
||||
Assert.assertEquals("%F0%9F%90%B6%F0%9F%98%8A%F0%9F%98%82%F0%9F%A4%A3", encode);
|
||||
Assert.assertEquals(emoji, URLDecoder.decode(encode));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user