add ProxySelector

This commit is contained in:
Looly 2024-11-29 17:21:08 +08:00
parent 5b129a1a8f
commit c2ea26e40d
19 changed files with 252 additions and 156 deletions

View File

@ -105,17 +105,6 @@ public class CronUtil {
return id;
}
/**
* 加入定时任务
*
* @param schedulingPattern 定时任务执行时间的crontab表达式
* @param task 任务
* @return 定时任务ID
*/
public static String schedule(final String schedulingPattern, final Runnable task) {
return scheduler.schedule(schedulingPattern, task);
}
/**
* 批量加入配置文件中的定时任务
*

View File

@ -238,17 +238,6 @@ public class Scheduler implements Serializable {
return this;
}
/**
* 新增Task使用随机UUID
*
* @param pattern {@link CronPattern}对应的String表达式
* @param task {@link Runnable}
* @return ID
*/
public String schedule(final String pattern, final Runnable task) {
return schedule(pattern, new RunnableTask(task));
}
/**
* 新增Task使用随机UUID
*

View File

@ -26,12 +26,12 @@ public class AddAndRemoveMainTest {
CronUtil.setMatchSecond(true);
CronUtil.start(false);
CronUtil.getScheduler().clear();
final String id = CronUtil.schedule("*/2 * * * * *", (Runnable) () -> Console.log("task running : 2s"));
final String id = CronUtil.schedule("*/2 * * * * *", () -> Console.log("task running : 2s"));
ThreadUtil.sleep(3000);
CronUtil.remove(id);
Console.log("Task Removed");
CronUtil.schedule("*/3 * * * * *", (Runnable) () -> Console.log("New task add running : 3s"));
CronUtil.schedule("*/3 * * * * *", () -> Console.log("New task add running : 3s"));
Console.log("New Task added.");
}
}

View File

@ -86,7 +86,8 @@ public class CronTest {
@Test
@Disabled
public void addAndRemoveTest() {
final String id = CronUtil.schedule("*/2 * * * * *", (Runnable) () -> Console.log("task running : 2s"));
final String id = CronUtil.schedule("*/2 * * * * *",
() -> Console.log("task running : 2s"));
Console.log(id);
CronUtil.remove(id);

View File

@ -0,0 +1,16 @@
package org.dromara.hutool.cron.demo;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.cron.CronUtil;
public class SimpleDemo {
public static void main(String[] args) {
// 打开秒匹配
CronUtil.setMatchSecond(true);
// 添加任务
CronUtil.schedule("*/2 * * * * *",
() -> Console.log("Hutool task running!"));
// 启动
CronUtil.start();
}
}

View File

@ -0,0 +1,5 @@
/**
* 定时任务示例
*
*/
package org.dromara.hutool.cron.demo;

View File

@ -17,7 +17,7 @@
package org.dromara.hutool.http.client;
import org.dromara.hutool.http.HttpGlobalConfig;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.proxy.ProxyInfo;
import org.dromara.hutool.http.ssl.SSLInfo;
/**
@ -55,7 +55,7 @@ public class ClientConfig {
/**
* 代理
*/
private HttpProxy proxy;
private ProxyInfo proxy;
/**
* 是否遇到响应状态码3xx时自动重定向请求
*/
@ -189,7 +189,7 @@ public class ClientConfig {
*
* @return 代理
*/
public HttpProxy getProxy() {
public ProxyInfo getProxy() {
return proxy;
}
@ -201,16 +201,16 @@ public class ClientConfig {
* @return this
*/
public ClientConfig setHttpProxy(final String host, final int port) {
return setProxy(new HttpProxy(host, port));
return setProxy(new ProxyInfo(host, port));
}
/**
* 设置代理
*
* @param proxy 代理 {@link HttpProxy}
* @param proxy 代理 {@link ProxyInfo}
* @return this
*/
public ClientConfig setProxy(final HttpProxy proxy) {
public ClientConfig setProxy(final ProxyInfo proxy) {
this.proxy = proxy;
return this;
}

View File

@ -27,6 +27,7 @@ import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.message.BasicHeader;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert;
@ -42,11 +43,12 @@ import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.proxy.ProxyInfo;
import org.dromara.hutool.http.ssl.SSLInfo;
import java.io.IOException;
import java.net.PasswordAuthentication;
import java.net.ProxySelector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ -290,18 +292,20 @@ public class HttpClient4Engine extends AbstractClientEngine {
return;
}
final HttpProxy proxy = config.getProxy();
final ProxyInfo proxy = config.getProxy();
if (null != proxy) {
final HttpHost httpHost = new HttpHost(proxy.getHost(), proxy.getPort());
clientBuilder.setProxy(httpHost);
final ProxySelector proxySelector = proxy.getProxySelector();
if(null != proxySelector){
clientBuilder.setRoutePlanner(new SystemDefaultRoutePlanner(proxySelector));
}
final PasswordAuthentication auth = proxy.getAuth();
if (null != auth) {
// 代理验证
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(httpHost),
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(new HttpHost(proxy.getAuthHost(), proxy.getAuthPort())),
new UsernamePasswordCredentials(auth.getUserName(), String.valueOf(auth.getPassword())));
clientBuilder.setDefaultCredentialsProvider(credsProvider);
clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
}
}

View File

@ -47,7 +47,7 @@ import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.proxy.ProxyInfo;
import org.dromara.hutool.http.ssl.SSLInfo;
import java.io.IOException;
@ -296,16 +296,15 @@ public class HttpClient5Engine extends AbstractClientEngine {
return;
}
final HttpProxy proxy = config.getProxy();
final ProxyInfo proxy = config.getProxy();
if (null != proxy) {
final HttpHost httpHost = new HttpHost(proxy.getHost(), proxy.getPort());
clientBuilder.setProxy(httpHost);
clientBuilder.setProxySelector(proxy.getProxySelector());
final PasswordAuthentication auth = proxy.getAuth();
if (null != auth) {
// 代理验证
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(httpHost),
new AuthScope(new HttpHost(proxy.getAuthHost(), proxy.getAuthPort())),
new UsernamePasswordCredentials(auth.getUserName(), auth.getPassword()));
clientBuilder.setDefaultCredentialsProvider(credsProvider);
}

View File

@ -19,6 +19,7 @@ package org.dromara.hutool.http.client.engine.jdk;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.net.url.UrlBuilder;
import org.dromara.hutool.core.net.url.UrlUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.text.split.SplitUtil;
import org.dromara.hutool.core.util.ObjUtil;
@ -31,9 +32,12 @@ import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.meta.HttpStatus;
import org.dromara.hutool.http.meta.Method;
import org.dromara.hutool.http.proxy.ProxyInfo;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.util.List;
/**
@ -125,8 +129,14 @@ public class JdkClientEngine extends AbstractClientEngine {
private JdkHttpConnection buildConn(final Request message) {
final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of);
final URL url = message.handledUrl().toURL();
Proxy proxy = null;
final ProxyInfo proxyInfo = config.getProxy();
if(null != proxyInfo){
proxy = proxyInfo.selectFirst(UrlUtil.toURI(url));
}
final JdkHttpConnection conn = JdkHttpConnection
.of(message.handledUrl().toURL(), config.getProxy())
.of(url, proxy)
.setConnectTimeout(config.getConnectionTimeout())
.setReadTimeout(config.getReadTimeout())
.setMethod(message.method())//

View File

@ -27,13 +27,14 @@ import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody;
import org.dromara.hutool.http.client.cookie.InMemoryCookieStore;
import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.proxy.HttpProxy;
import org.dromara.hutool.http.proxy.ProxyInfo;
import org.dromara.hutool.http.ssl.SSLInfo;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.PasswordAuthentication;
import java.net.ProxySelector;
import java.util.concurrent.TimeUnit;
/**
@ -178,10 +179,13 @@ public class OkHttpEngine extends AbstractClientEngine {
* @param config 配置
*/
private static void setProxy(final OkHttpClient.Builder builder, final ClientConfig config) {
final HttpProxy proxy = config.getProxy();
if (null != proxy) {
builder.proxy(proxy);
final PasswordAuthentication auth = proxy.getAuth();
final ProxyInfo proxyInfo = config.getProxy();
if (null != proxyInfo) {
final ProxySelector proxySelector = proxyInfo.getProxySelector();
if(null != proxySelector){
builder.proxySelector(proxySelector);
}
final PasswordAuthentication auth = proxyInfo.getAuth();
if (null != auth) {
builder.proxyAuthenticator(new BasicProxyAuthenticator(auth));
}

View File

@ -1,95 +0,0 @@
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.http.proxy;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
/**
* HTTP代理提供代理地址和代理端口的持有
*
* @author looly
* @since 6.0.0
*/
public class HttpProxy extends Proxy {
private final String host;
private final int port;
private PasswordAuthentication auth;
/**
* 构造
*
* @param host 域名或IP
* @param port 端口
*/
public HttpProxy(final String host, final int port) {
super(Type.HTTP, new InetSocketAddress(host, port));
this.host = host;
this.port = port;
}
/**
* 获取域名或IP
*
* @return 域名或IP
*/
public String getHost() {
return host;
}
/**
* 获取端口
*
* @return 端口
*/
public int getPort() {
return port;
}
/**
* 设置代理验证信息
*
* @param user 用户名
* @param pass 密码
* @return this
*/
public HttpProxy setAuth(final String user, final char[] pass) {
return setAuth(new PasswordAuthentication(user, pass));
}
/**
* 设置代理验证信息
*
* @param auth {@link PasswordAuthentication}
* @return this
*/
public HttpProxy setAuth(final PasswordAuthentication auth) {
this.auth = auth;
return this;
}
/**
* 获取代理验证信息
*
* @return {@link PasswordAuthentication}
*/
public PasswordAuthentication getAuth() {
return this.auth;
}
}

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2013-2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.http.proxy;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.http.HttpException;
import java.io.IOException;
import java.net.*;
import java.util.List;
/**
* 代理信息提供代理选择器和代理验证
*
* @author looly
* @since 6.0.0
*/
public class ProxyInfo {
private String authHost;
private int authPort;
private ProxySelector proxySelector;
private PasswordAuthentication auth;
/**
* 构造
*
* @param host 代理地址
* @param port 代理端口
*/
public ProxyInfo(final String host, final int port) {
this(new ProxySelector() {
@Override
public List<Proxy> select(final URI uri) {
return ListUtil.of(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)));
}
@Override
public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
throw new HttpException(ioe);
}
}, null);
this.authHost = host;
this.authPort = port;
}
/**
* 构造
*
* @param proxySelector {@link ProxySelector}
* @param auth 用户名和密码
*/
public ProxyInfo(final ProxySelector proxySelector, final PasswordAuthentication auth) {
this.proxySelector = proxySelector;
this.auth = auth;
}
/**
* 获取代理验证主机
*
* @return 代理验证主机
*/
public String getAuthHost() {
return authHost;
}
/**
* 设置代理验证主机
*
* @param authHost 代理验证主机
*/
public void setAuthHost(final String authHost) {
this.authHost = authHost;
}
/**
* 获取代理验证端口
*
* @return 代理验证端口
*/
public int getAuthPort() {
return authPort;
}
/**
* 设置代理验证端口
*
* @param authPort 代理验证端口
*/
public void setAuthPort(final int authPort) {
this.authPort = authPort;
}
/**
* 获取代理选择器
*
* @return {@link ProxySelector}
*/
public ProxySelector getProxySelector() {
return proxySelector;
}
/**
* 获取第一个代理<br>
* 如果代理选择器为空返回null
*
* @param uri {@link URI}
* @return {@link Proxy}
*/
public Proxy selectFirst(final URI uri){
if(null != proxySelector){
final List<Proxy> select = proxySelector.select(uri);
if(CollUtil.isNotEmpty(select)){
return select.get(0);
}
}
return null;
}
/**
* 设置代理选择器
*
* @param proxySelector {@link ProxySelector}
* @return this
*/
public ProxyInfo setProxySelector(final ProxySelector proxySelector) {
this.proxySelector = proxySelector;
return this;
}
/**
* 设置代理验证信息
*
* @param user 用户名
* @param pass 密码
* @return this
*/
public ProxyInfo setAuth(final String user, final char[] pass) {
return setAuth(new PasswordAuthentication(user, pass));
}
/**
* 设置代理验证信息
*
* @param auth {@link PasswordAuthentication}
* @return this
*/
public ProxyInfo setAuth(final PasswordAuthentication auth) {
this.auth = auth;
return this;
}
/**
* 获取代理验证信息
*
* @return {@link PasswordAuthentication}
*/
public PasswordAuthentication getAuth() {
return this.auth;
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.dromara.hutool.http;
package org.dromara.hutool.http.client;
import org.dromara.hutool.core.codec.binary.Base64;
import org.dromara.hutool.core.io.IORuntimeException;
@ -22,8 +22,7 @@ import org.dromara.hutool.core.io.StreamProgress;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.http.client.HttpDownloader;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.HttpGlobalConfig;
import org.dromara.hutool.http.client.engine.ClientEngineFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;

View File

@ -14,10 +14,9 @@
* limitations under the License.
*/
package org.dromara.hutool.http;
package org.dromara.hutool.http.client;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.client.engine.jdk.JdkClientEngine;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

View File

@ -3,10 +3,12 @@ package org.dromara.hutool.http.client;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.http.client.engine.ClientEngineFactory;
import org.dromara.hutool.http.meta.Method;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class IssueIB1QHQTest {
@Test
@Disabled
void requestByOkHttpTest() {
for (int i = 0; i < 3; i++) {
String response = ClientEngineFactory.createEngine("OkHttp")

View File

@ -14,10 +14,10 @@
* limitations under the License.
*/
package org.dromara.hutool.http;
package org.dromara.hutool.http.client;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.http.client.Request;
import org.dromara.hutool.http.HttpUtil;
import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.meta.Method;
import org.dromara.hutool.json.JSONUtil;

View File

@ -14,10 +14,9 @@
* limitations under the License.
*/
package org.dromara.hutool.http;
package org.dromara.hutool.http.html;
import org.dromara.hutool.core.regex.ReUtil;
import org.dromara.hutool.http.html.HtmlUtil;
import org.dromara.hutool.http.meta.ContentTypeUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,9 @@
* limitations under the License.
*/
package org.dromara.hutool.http;
package org.dromara.hutool.http.meta;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.http.meta.ContentType;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;