mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add IoCopier
This commit is contained in:
parent
9dd7b0a904
commit
c54f2a154a
@ -15,6 +15,7 @@
|
||||
* 【socket 】 SocketUtil增加connection方法
|
||||
* 【extra 】 JschUtil增加bindPort重载方法(issue#I44UTH@Github)
|
||||
* 【core 】 DefaultTrustManager改为继承X509ExtendedTrustManager
|
||||
* 【core 】 增加IoCopier
|
||||
|
||||
### 🐞Bug修复
|
||||
* 【core 】 改进NumberChineseFormatter算法,补充完整单元测试,解决零问题
|
||||
|
@ -3,6 +3,8 @@ package cn.hutool.core.io;
|
||||
import cn.hutool.core.collection.LineIter;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.io.copy.ReaderWriterCopier;
|
||||
import cn.hutool.core.io.copy.StreamCopier;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
@ -86,28 +88,21 @@ public class IoUtil extends NioUtil {
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static long copy(Reader reader, Writer writer, int bufferSize, StreamProgress streamProgress) throws IORuntimeException {
|
||||
char[] buffer = new char[bufferSize];
|
||||
long size = 0;
|
||||
int readSize;
|
||||
if (null != streamProgress) {
|
||||
streamProgress.start();
|
||||
}
|
||||
try {
|
||||
while ((readSize = reader.read(buffer, 0, bufferSize)) != EOF) {
|
||||
writer.write(buffer, 0, readSize);
|
||||
size += readSize;
|
||||
writer.flush();
|
||||
if (null != streamProgress) {
|
||||
streamProgress.progress(size);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
if (null != streamProgress) {
|
||||
streamProgress.finish();
|
||||
}
|
||||
return size;
|
||||
return copy(reader, writer, bufferSize, -1, streamProgress);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Reader中的内容复制到Writer中,拷贝后不关闭Reader
|
||||
*
|
||||
* @param reader Reader
|
||||
* @param writer Writer
|
||||
* @param bufferSize 缓存大小
|
||||
* @param streamProgress 进度处理器
|
||||
* @return 传输的byte数
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static long copy(Reader reader, Writer writer, int bufferSize, int count, StreamProgress streamProgress) throws IORuntimeException {
|
||||
return new ReaderWriterCopier(bufferSize, count, streamProgress).copy(reader, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,33 +141,23 @@ public class IoUtil extends NioUtil {
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static long copy(InputStream in, OutputStream out, int bufferSize, StreamProgress streamProgress) throws IORuntimeException {
|
||||
Assert.notNull(in, "InputStream is null !");
|
||||
Assert.notNull(out, "OutputStream is null !");
|
||||
if (bufferSize <= 0) {
|
||||
bufferSize = DEFAULT_BUFFER_SIZE;
|
||||
}
|
||||
return copy(in, out, bufferSize, -1, streamProgress);
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
if (null != streamProgress) {
|
||||
streamProgress.start();
|
||||
}
|
||||
long size = 0;
|
||||
try {
|
||||
for (int readSize; (readSize = in.read(buffer)) != EOF; ) {
|
||||
out.write(buffer, 0, readSize);
|
||||
size += readSize;
|
||||
if (null != streamProgress) {
|
||||
streamProgress.progress(size);
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
if (null != streamProgress) {
|
||||
streamProgress.finish();
|
||||
}
|
||||
return size;
|
||||
/**
|
||||
* 拷贝流,拷贝后不关闭流
|
||||
*
|
||||
* @param in 输入流
|
||||
* @param out 输出流
|
||||
* @param bufferSize 缓存大小
|
||||
* @param count 总拷贝长度
|
||||
* @param streamProgress 进度条
|
||||
* @return 传输的byte数
|
||||
* @throws IORuntimeException IO异常
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public static long copy(InputStream in, OutputStream out, int bufferSize, int count, StreamProgress streamProgress) throws IORuntimeException {
|
||||
return new StreamCopier(bufferSize, count, streamProgress).copy(in, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,14 +375,14 @@ public class IoUtil extends NioUtil {
|
||||
*/
|
||||
public static FastByteArrayOutputStream read(InputStream in, boolean isClose) throws IORuntimeException {
|
||||
final FastByteArrayOutputStream out;
|
||||
if(in instanceof FileInputStream){
|
||||
if (in instanceof FileInputStream) {
|
||||
// 文件流的长度是可预见的,此时直接读取效率更高
|
||||
try {
|
||||
out = new FastByteArrayOutputStream(in.available());
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
} else{
|
||||
} else {
|
||||
out = new FastByteArrayOutputStream();
|
||||
}
|
||||
try {
|
||||
@ -434,7 +419,7 @@ public class IoUtil extends NioUtil {
|
||||
final CharBuffer buffer = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
|
||||
try {
|
||||
while (-1 != reader.read(buffer)) {
|
||||
builder.append(buffer.flip().toString());
|
||||
builder.append(buffer.flip());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
@ -828,7 +813,7 @@ public class IoUtil extends NioUtil {
|
||||
/**
|
||||
* 转换为{@link BufferedInputStream}
|
||||
*
|
||||
* @param in {@link InputStream}
|
||||
* @param in {@link InputStream}
|
||||
* @param bufferSize buffer size
|
||||
* @return {@link BufferedInputStream}
|
||||
* @since 5.6.1
|
||||
@ -853,7 +838,7 @@ public class IoUtil extends NioUtil {
|
||||
/**
|
||||
* 转换为{@link BufferedOutputStream}
|
||||
*
|
||||
* @param out {@link OutputStream}
|
||||
* @param out {@link OutputStream}
|
||||
* @param bufferSize buffer size
|
||||
* @return {@link BufferedOutputStream}
|
||||
* @since 5.6.1
|
||||
@ -878,7 +863,7 @@ public class IoUtil extends NioUtil {
|
||||
/**
|
||||
* 转换为{@link BufferedReader}
|
||||
*
|
||||
* @param reader {@link Reader}
|
||||
* @param reader {@link Reader}
|
||||
* @param bufferSize buffer size
|
||||
* @return {@link BufferedReader}
|
||||
* @since 5.6.1
|
||||
@ -903,7 +888,7 @@ public class IoUtil extends NioUtil {
|
||||
/**
|
||||
* 转换为{@link BufferedWriter}
|
||||
*
|
||||
* @param writer {@link Writer}
|
||||
* @param writer {@link Writer}
|
||||
* @param bufferSize buffer size
|
||||
* @return {@link BufferedWriter}
|
||||
* @since 5.6.1
|
||||
@ -1291,7 +1276,7 @@ public class IoUtil extends NioUtil {
|
||||
* while (it.hasNext()) {
|
||||
* String line = it.nextLine();
|
||||
* // do something with line
|
||||
* }
|
||||
* }
|
||||
* } finally {
|
||||
* it.close();
|
||||
* }
|
||||
@ -1301,7 +1286,7 @@ public class IoUtil extends NioUtil {
|
||||
* @return {@link LineIter}
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public static LineIter lineIter(Reader reader){
|
||||
public static LineIter lineIter(Reader reader) {
|
||||
return new LineIter(reader);
|
||||
}
|
||||
|
||||
@ -1314,18 +1299,18 @@ public class IoUtil extends NioUtil {
|
||||
* while (it.hasNext()) {
|
||||
* String line = it.nextLine();
|
||||
* // do something with line
|
||||
* }
|
||||
* }
|
||||
* } finally {
|
||||
* it.close();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param in {@link InputStream}
|
||||
* @param in {@link InputStream}
|
||||
* @param charset 编码
|
||||
* @return {@link LineIter}
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public static LineIter lineIter(InputStream in, Charset charset){
|
||||
public static LineIter lineIter(InputStream in, Charset charset) {
|
||||
return new LineIter(in, charset);
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package cn.hutool.core.io;
|
||||
|
||||
/**
|
||||
* Stream进度条
|
||||
* @author Looly
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public interface StreamProgress {
|
||||
|
||||
@ -14,6 +14,7 @@ public interface StreamProgress {
|
||||
|
||||
/**
|
||||
* 进行中
|
||||
*
|
||||
* @param progressSize 已经进行的大小
|
||||
*/
|
||||
void progress(long progressSize);
|
||||
|
60
hutool-core/src/main/java/cn/hutool/core/io/copy/IoCopier.java
Executable file
60
hutool-core/src/main/java/cn/hutool/core/io/copy/IoCopier.java
Executable file
@ -0,0 +1,60 @@
|
||||
package cn.hutool.core.io.copy;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.io.StreamProgress;
|
||||
|
||||
/**
|
||||
* IO拷贝抽象,可自定义包括缓存、进度条等信息<br>
|
||||
* 此对象非线程安全
|
||||
*
|
||||
* @param <S> 拷贝源类型,如InputStream、Reader等
|
||||
* @param <T> 拷贝目标类型,如OutputStream、Writer等
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public abstract class IoCopier<S, T> {
|
||||
|
||||
protected final int bufferSize;
|
||||
/**
|
||||
* 拷贝总数
|
||||
*/
|
||||
protected final long count;
|
||||
|
||||
/**
|
||||
* 进度条
|
||||
*/
|
||||
protected StreamProgress progress;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小,< 0 表示默认{@link IoUtil#DEFAULT_BUFFER_SIZE}
|
||||
* @param count 拷贝总数
|
||||
* @param progress 进度条
|
||||
*/
|
||||
public IoCopier(int bufferSize, long count, StreamProgress progress) {
|
||||
this.bufferSize = bufferSize > 0 ? bufferSize : IoUtil.DEFAULT_BUFFER_SIZE;
|
||||
this.count = count;
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行拷贝
|
||||
*
|
||||
* @param source 拷贝源,如InputStream、Reader等
|
||||
* @param target 拷贝目标,如OutputStream、Writer等
|
||||
* @return 拷贝的实际长度
|
||||
*/
|
||||
public abstract long copy(S source, T target);
|
||||
|
||||
/**
|
||||
* 缓存大小,取默认缓存和目标长度最小值
|
||||
* @return 缓存大小
|
||||
*/
|
||||
protected int bufferSize(long count) {
|
||||
if(count < 0){
|
||||
count = Long.MAX_VALUE;
|
||||
}
|
||||
return Math.min(this.bufferSize, (int)count);
|
||||
}
|
||||
}
|
114
hutool-core/src/main/java/cn/hutool/core/io/copy/ReaderWriterCopier.java
Executable file
114
hutool-core/src/main/java/cn/hutool/core/io/copy/ReaderWriterCopier.java
Executable file
@ -0,0 +1,114 @@
|
||||
package cn.hutool.core.io.copy;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.io.StreamProgress;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* {@link Reader} 向 {@link Writer} 拷贝
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public class ReaderWriterCopier extends IoCopier<Reader, Writer> {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public ReaderWriterCopier() {
|
||||
this(IoUtil.DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小
|
||||
*/
|
||||
public ReaderWriterCopier(int bufferSize) {
|
||||
this(bufferSize, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小
|
||||
* @param count 拷贝总数
|
||||
*/
|
||||
public ReaderWriterCopier(int bufferSize, long count) {
|
||||
this(bufferSize, count, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小
|
||||
* @param count 拷贝总数
|
||||
* @param progress 进度条
|
||||
*/
|
||||
public ReaderWriterCopier(int bufferSize, long count, StreamProgress progress) {
|
||||
super(bufferSize, count, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long copy(Reader source, Writer target) {
|
||||
Assert.notNull(source, "InputStream is null !");
|
||||
Assert.notNull(target, "OutputStream is null !");
|
||||
|
||||
final StreamProgress progress = this.progress;
|
||||
if (null != progress) {
|
||||
progress.start();
|
||||
}
|
||||
final long size;
|
||||
try {
|
||||
size = doCopy(source, target, new char[bufferSize(this.count)], progress);
|
||||
target.flush();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
||||
if (null != progress) {
|
||||
progress.finish();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行拷贝,如果限制最大长度,则按照最大长度读取,否则一直读取直到遇到-1
|
||||
*
|
||||
* @param source {@link InputStream}
|
||||
* @param target {@link OutputStream}
|
||||
* @param buffer 缓存
|
||||
* @param progress 进度条
|
||||
* @return 拷贝总长度
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private long doCopy(Reader source, Writer target, char[] buffer, StreamProgress progress) throws IOException {
|
||||
long numToRead = this.count > 0 ? this.count : Long.MAX_VALUE;
|
||||
long total = 0;
|
||||
|
||||
int read;
|
||||
while (numToRead > 0) {
|
||||
read = source.read(buffer, 0, bufferSize(numToRead));
|
||||
if (read < 0) {
|
||||
// 提前读取到末尾
|
||||
break;
|
||||
}
|
||||
target.write(buffer, 0, read);
|
||||
|
||||
numToRead -= read;
|
||||
total += read;
|
||||
if (null != progress) {
|
||||
progress.progress(total);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
112
hutool-core/src/main/java/cn/hutool/core/io/copy/StreamCopier.java
Executable file
112
hutool-core/src/main/java/cn/hutool/core/io/copy/StreamCopier.java
Executable file
@ -0,0 +1,112 @@
|
||||
package cn.hutool.core.io.copy;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.io.StreamProgress;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* {@link InputStream} 向 {@link OutputStream} 拷贝
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public class StreamCopier extends IoCopier<InputStream, OutputStream> {
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*/
|
||||
public StreamCopier() {
|
||||
this(IoUtil.DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小
|
||||
*/
|
||||
public StreamCopier(int bufferSize) {
|
||||
this(bufferSize, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小
|
||||
* @param count 拷贝总数
|
||||
*/
|
||||
public StreamCopier(int bufferSize, long count) {
|
||||
this(bufferSize, count, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param bufferSize 缓存大小
|
||||
* @param count 拷贝总数
|
||||
* @param progress 进度条
|
||||
*/
|
||||
public StreamCopier(int bufferSize, long count, StreamProgress progress) {
|
||||
super(bufferSize, count, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long copy(InputStream source, OutputStream target) {
|
||||
Assert.notNull(source, "InputStream is null !");
|
||||
Assert.notNull(target, "OutputStream is null !");
|
||||
|
||||
final StreamProgress progress = this.progress;
|
||||
if (null != progress) {
|
||||
progress.start();
|
||||
}
|
||||
final long size;
|
||||
try {
|
||||
size = doCopy(source, target, new byte[bufferSize(this.count)], progress);
|
||||
target.flush();
|
||||
} catch (IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
|
||||
if (null != progress) {
|
||||
progress.finish();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行拷贝,如果限制最大长度,则按照最大长度读取,否则一直读取直到遇到-1
|
||||
*
|
||||
* @param source {@link InputStream}
|
||||
* @param target {@link OutputStream}
|
||||
* @param buffer 缓存
|
||||
* @param progress 进度条
|
||||
* @return 拷贝总长度
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private long doCopy(InputStream source, OutputStream target, byte[] buffer, StreamProgress progress) throws IOException {
|
||||
long numToRead = this.count > 0 ? this.count : Long.MAX_VALUE;
|
||||
long total = 0;
|
||||
|
||||
int read;
|
||||
while (numToRead > 0) {
|
||||
read = source.read(buffer, 0, bufferSize(numToRead));
|
||||
if (read < 0) {
|
||||
// 提前读取到末尾
|
||||
break;
|
||||
}
|
||||
target.write(buffer, 0, read);
|
||||
|
||||
numToRead -= read;
|
||||
total += read;
|
||||
if (null != progress) {
|
||||
progress.progress(total);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
7
hutool-core/src/main/java/cn/hutool/core/io/copy/package-info.java
Executable file
7
hutool-core/src/main/java/cn/hutool/core/io/copy/package-info.java
Executable file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* IO流拷贝相关封装相关封装
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
package cn.hutool.core.io.copy;
|
@ -78,8 +78,7 @@ public class Snowflake implements Serializable {
|
||||
* 构造,使用自动生成的工作节点ID和数据中心ID
|
||||
*/
|
||||
public Snowflake() {
|
||||
this(IdUtil.getWorkerId(IdUtil.getDataCenterId(MAX_DATA_CENTER_ID), MAX_WORKER_ID)
|
||||
, IdUtil.getDataCenterId(MAX_DATA_CENTER_ID));
|
||||
this(IdUtil.getWorkerId(IdUtil.getDataCenterId(MAX_DATA_CENTER_ID), MAX_WORKER_ID));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,12 @@ import java.security.cert.X509Certificate;
|
||||
*/
|
||||
public class DefaultTrustManager extends X509ExtendedTrustManager {
|
||||
|
||||
/**
|
||||
* 默认的全局单例默认信任管理器,,默认信任所有客户端和服务端证书
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public static DefaultTrustManager INSTANCE = new DefaultTrustManager();
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
|
@ -13,46 +13,24 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* {@link SSLContext}构建器
|
||||
* {@link SSLContext}构建器,可以自定义:<br>
|
||||
* <ul>
|
||||
* <li>协议(protocol),默认TLS</li>
|
||||
* <li>{@link KeyManager},默认空</li>
|
||||
* <li>{@link TrustManager},默认{@link DefaultTrustManager},即信任全部</li>
|
||||
* <li>{@link SecureRandom}</li>
|
||||
* </ul>
|
||||
*
|
||||
* 构建后可获得{@link SSLContext},通过调用{@link SSLContext#getSocketFactory()}获取{@link javax.net.ssl.SSLSocketFactory}
|
||||
*
|
||||
* @author Looly
|
||||
* @since 5.5.2
|
||||
*/
|
||||
public class SSLContextBuilder {
|
||||
|
||||
/**
|
||||
* Supports some version of SSL; may support other versions
|
||||
*/
|
||||
public static final String SSL = "SSL";
|
||||
/**
|
||||
* Supports SSL version 2 or later; may support other versions
|
||||
*/
|
||||
public static final String SSLv2 = "SSLv2";
|
||||
/**
|
||||
* Supports SSL version 3; may support other versions
|
||||
*/
|
||||
public static final String SSLv3 = "SSLv3";
|
||||
|
||||
/**
|
||||
* Supports some version of TLS; may support other versions
|
||||
*/
|
||||
public static final String TLS = "TLS";
|
||||
/**
|
||||
* Supports RFC 2246: TLS version 1.0 ; may support other versions
|
||||
*/
|
||||
public static final String TLSv1 = "TLSv1";
|
||||
/**
|
||||
* Supports RFC 4346: TLS version 1.1 ; may support other versions
|
||||
*/
|
||||
public static final String TLSv11 = "TLSv1.1";
|
||||
/**
|
||||
* Supports RFC 5246: TLS version 1.2 ; may support other versions
|
||||
*/
|
||||
public static final String TLSv12 = "TLSv1.2";
|
||||
public class SSLContextBuilder implements SSLProtocols {
|
||||
|
||||
private String protocol = TLS;
|
||||
private KeyManager[] keyManagers;
|
||||
private TrustManager[] trustManagers = {new DefaultTrustManager()};
|
||||
private TrustManager[] trustManagers = {DefaultTrustManager.INSTANCE};
|
||||
private SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
|
||||
@ -136,7 +114,7 @@ public class SSLContextBuilder {
|
||||
* @return {@link SSLContext}
|
||||
* @throws IORuntimeException 包装 GeneralSecurityException异常
|
||||
*/
|
||||
public SSLContext buildQuietly() throws IORuntimeException{
|
||||
public SSLContext buildQuietly() throws IORuntimeException {
|
||||
try {
|
||||
return build();
|
||||
} catch (GeneralSecurityException e) {
|
||||
|
40
hutool-core/src/main/java/cn/hutool/core/net/SSLProtocols.java
Executable file
40
hutool-core/src/main/java/cn/hutool/core/net/SSLProtocols.java
Executable file
@ -0,0 +1,40 @@
|
||||
package cn.hutool.core.net;
|
||||
|
||||
/**
|
||||
* SSL或TLS协议
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public interface SSLProtocols {
|
||||
|
||||
/**
|
||||
* Supports some version of SSL; may support other versions
|
||||
*/
|
||||
String SSL = "SSL";
|
||||
/**
|
||||
* Supports SSL version 2 or later; may support other versions
|
||||
*/
|
||||
String SSLv2 = "SSLv2";
|
||||
/**
|
||||
* Supports SSL version 3; may support other versions
|
||||
*/
|
||||
String SSLv3 = "SSLv3";
|
||||
|
||||
/**
|
||||
* Supports some version of TLS; may support other versions
|
||||
*/
|
||||
String TLS = "TLS";
|
||||
/**
|
||||
* Supports RFC 2246: TLS version 1.0 ; may support other versions
|
||||
*/
|
||||
String TLSv1 = "TLSv1";
|
||||
/**
|
||||
* Supports RFC 4346: TLS version 1.1 ; may support other versions
|
||||
*/
|
||||
String TLSv11 = "TLSv1.1";
|
||||
/**
|
||||
* Supports RFC 5246: TLS version 1.2 ; may support other versions
|
||||
*/
|
||||
String TLSv12 = "TLSv1.2";
|
||||
}
|
@ -14,6 +14,18 @@ import javax.net.ssl.TrustManager;
|
||||
*/
|
||||
public class SSLUtil {
|
||||
|
||||
/**
|
||||
* 创建{@link SSLContext},默认新人全部
|
||||
*
|
||||
* @param protocol SSL协议,例如TLS等
|
||||
* @return {@link SSLContext}
|
||||
* @throws IORuntimeException 包装 GeneralSecurityException异常
|
||||
* @since 5.7.8
|
||||
*/
|
||||
public static SSLContext createSSLContext(String protocol) throws IORuntimeException{
|
||||
return SSLContextBuilder.create().setProtocol(protocol).buildQuietly();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建{@link SSLContext}
|
||||
*
|
||||
|
@ -10,6 +10,7 @@ import cn.hutool.core.io.resource.MultiFileResource;
|
||||
import cn.hutool.core.io.resource.Resource;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.net.SSLUtil;
|
||||
import cn.hutool.core.net.url.UrlBuilder;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@ -887,11 +888,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
|
||||
*/
|
||||
public HttpRequest setSSLProtocol(String protocol) {
|
||||
Assert.notBlank(protocol, "protocol must be not blank!");
|
||||
try {
|
||||
setSSLSocketFactory(SSLSocketFactoryBuilder.create().setProtocol(protocol).build());
|
||||
} catch (Exception e) {
|
||||
throw new HttpException(e);
|
||||
}
|
||||
setSSLSocketFactory(SSLUtil.createSSLContext(protocol).getSocketFactory());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,7 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.SSLv3;
|
||||
import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv1;
|
||||
import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv11;
|
||||
import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv12;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.net.SSLProtocols;
|
||||
|
||||
/**
|
||||
* 兼容android低版本SSL连接<br>
|
||||
@ -20,9 +15,10 @@ import static cn.hutool.http.ssl.SSLSocketFactoryBuilder.TLSv12;
|
||||
public class AndroidSupportSSLFactory extends CustomProtocolsSSLFactory {
|
||||
|
||||
// Android低版本不重置的话某些SSL访问就会失败
|
||||
private static final String[] protocols = {SSLv3, TLSv1, TLSv11, TLSv12};
|
||||
private static final String[] protocols = {
|
||||
SSLProtocols.SSLv3, SSLProtocols.TLSv1, SSLProtocols.TLSv11, SSLProtocols.TLSv12};
|
||||
|
||||
public AndroidSupportSSLFactory() throws KeyManagementException, NoSuchAlgorithmException {
|
||||
public AndroidSupportSSLFactory() throws IORuntimeException {
|
||||
super(protocols);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.net.SSLUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
@ -7,8 +9,6 @@ import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* 自定义支持协议类型的SSLSocketFactory
|
||||
@ -24,12 +24,11 @@ public class CustomProtocolsSSLFactory extends SSLSocketFactory {
|
||||
* 构造
|
||||
*
|
||||
* @param protocols 支持协议列表
|
||||
* @throws KeyManagementException KeyManagementException
|
||||
* @throws NoSuchAlgorithmException 无此算法
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public CustomProtocolsSSLFactory(String... protocols) throws KeyManagementException, NoSuchAlgorithmException {
|
||||
public CustomProtocolsSSLFactory(String... protocols) throws IORuntimeException {
|
||||
this.protocols = protocols;
|
||||
this.base = SSLSocketFactoryBuilder.create().build();
|
||||
this.base = SSLUtil.createSSLContext(null).getSocketFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,7 +89,7 @@ public class CustomProtocolsSSLFactory extends SSLSocketFactory {
|
||||
* @param socket SSLSocket
|
||||
*/
|
||||
private void resetProtocols(SSLSocket socket) {
|
||||
if(ArrayUtil.isNotEmpty(this.protocols)){
|
||||
if (ArrayUtil.isNotEmpty(this.protocols)) {
|
||||
socket.setEnabledProtocols(this.protocols);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* 默认的SSLSocketFactory
|
||||
*
|
||||
@ -11,7 +8,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
*/
|
||||
public class DefaultSSLFactory extends CustomProtocolsSSLFactory {
|
||||
|
||||
public DefaultSSLFactory() throws KeyManagementException, NoSuchAlgorithmException {
|
||||
public DefaultSSLFactory() {
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpException;
|
||||
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* 默认的SSL配置,当用户未设置相关信息时,使用默认设置,默认设置为单例模式。
|
||||
* 默认的全局SSL配置,当用户未设置相关信息时,使用默认设置,默认设置为单例模式。
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.1.2
|
||||
@ -25,16 +22,11 @@ public class DefaultSSLInfo {
|
||||
|
||||
static {
|
||||
TRUST_ANY_HOSTNAME_VERIFIER = new TrustAnyHostnameVerifier();
|
||||
|
||||
try {
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
// 兼容android低版本SSL连接
|
||||
DEFAULT_SSF = new AndroidSupportSSLFactory();
|
||||
} else {
|
||||
DEFAULT_SSF = new DefaultSSLFactory();
|
||||
}
|
||||
} catch (KeyManagementException | NoSuchAlgorithmException e) {
|
||||
throw new HttpException(e);
|
||||
if (StrUtil.equalsIgnoreCase("dalvik", System.getProperty("java.vm.name"))) {
|
||||
// 兼容android低版本SSL连接
|
||||
DEFAULT_SSF = new AndroidSupportSSLFactory();
|
||||
} else {
|
||||
DEFAULT_SSF = new DefaultSSLFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.hutool.http.ssl;
|
||||
|
||||
import cn.hutool.core.net.SSLContextBuilder;
|
||||
import cn.hutool.core.net.SSLProtocols;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
@ -14,38 +15,10 @@ import java.security.SecureRandom;
|
||||
*
|
||||
* @author Looly
|
||||
* @see SSLContextBuilder
|
||||
* @deprecated 请使用 {@link SSLContextBuilder}
|
||||
*/
|
||||
public class SSLSocketFactoryBuilder {
|
||||
|
||||
/**
|
||||
* Supports some version of SSL; may support other versions
|
||||
*/
|
||||
public static final String SSL = SSLContextBuilder.SSL;
|
||||
/**
|
||||
* Supports SSL version 2 or later; may support other versions
|
||||
*/
|
||||
public static final String SSLv2 = SSLContextBuilder.SSLv2;
|
||||
/**
|
||||
* Supports SSL version 3; may support other versions
|
||||
*/
|
||||
public static final String SSLv3 = SSLContextBuilder.SSLv3;
|
||||
|
||||
/**
|
||||
* Supports some version of TLS; may support other versions
|
||||
*/
|
||||
public static final String TLS = SSLContextBuilder.TLS;
|
||||
/**
|
||||
* Supports RFC 2246: TLS version 1.0 ; may support other versions
|
||||
*/
|
||||
public static final String TLSv1 = SSLContextBuilder.TLSv1;
|
||||
/**
|
||||
* Supports RFC 4346: TLS version 1.1 ; may support other versions
|
||||
*/
|
||||
public static final String TLSv11 = SSLContextBuilder.TLSv11;
|
||||
/**
|
||||
* Supports RFC 5246: TLS version 1.2 ; may support other versions
|
||||
*/
|
||||
public static final String TLSv12 = SSLContextBuilder.TLSv12;
|
||||
@Deprecated
|
||||
public class SSLSocketFactoryBuilder implements SSLProtocols {
|
||||
|
||||
SSLContextBuilder sslContextBuilder;
|
||||
|
||||
|
@ -3,8 +3,8 @@ package cn.hutool.http;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.TimeInterval;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.net.SSLProtocols;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -98,7 +98,7 @@ public class HttpRequestTest {
|
||||
// 禁用缓存
|
||||
.disableCache()
|
||||
// 自定义SSL版本
|
||||
.setSSLProtocol(SSLSocketFactoryBuilder.TLSv12);
|
||||
.setSSLProtocol(SSLProtocols.TLSv12);
|
||||
Console.log(request.execute().body());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user