list = client.exec(request, parser, 0, 1);
+ System.out.println(list);
+ }
+
+ /** 测试自定义校验 */
+ public static void testChecker() {
+ HttpClient client = HttpClient.newInstance("http://localhost:8080/");
+ client.setHttpResponseChecker(
+ new HttpResponseChecker() {
+ @Override
+ public boolean isSuccess(HttpResponse response) {
+ return response.getStatusCode() == 201;
+ }
+
+ @Override
+ public String desc() {
+ return "不是201!!";
+ }
+ });
+ client.exec(HttpRequest.builder().path("").build());
+ }
+}
diff --git a/example/src/main/java/me/hekr/iotos/softgateway/sample/HttpServerSample.java b/example/src/main/java/me/hekr/iotos/softgateway/sample/HttpServerSample.java
new file mode 100644
index 0000000000000000000000000000000000000000..7bc5fa28fff177b681eb16e8fca3cdd6cb91fec2
--- /dev/null
+++ b/example/src/main/java/me/hekr/iotos/softgateway/sample/HttpServerSample.java
@@ -0,0 +1,42 @@
+package me.hekr.iotos.softgateway.sample;
+
+import java.util.Collections;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * http server
+ *
+ * 端口配置在 resources/application.yml 中
+ *
+ * @author iotos
+ */
+@SpringBootApplication
+@RestController
+public class HttpServerSample {
+ public static void main(String[] args) {
+ SpringApplication.run(HttpServerSample.class);
+ }
+
+ @GetMapping("/")
+ public Object get(Integer curPage, Integer pageSize) {
+ DeviceResponse response = new DeviceResponse();
+
+ if (curPage >= 3) {
+ response.setDevices(Collections.emptyList());
+ } else {
+ response.setDevices(Collections.singletonList(new Device()));
+ }
+ return response;
+ }
+
+ @GetMapping("/items")
+ public Object items(Integer curPage, Integer pageSize) {
+ if (curPage >= 3) {
+ return Collections.emptyList();
+ }
+ return Collections.singletonList(new Device());
+ }
+}
diff --git a/example/src/main/resources/application.yml b/example/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..04ea648477df4098d6f33b28a53561913b5b871e
--- /dev/null
+++ b/example/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+# http server port
+server.port: 8080
diff --git a/framework-common-utils/pom.xml b/framework-common-utils/pom.xml
index 06dba71fe17fb81c5515e23007096c9608caa05f..4e790bb1265fd1247290b4d86d22b56ad34e3cf1 100644
--- a/framework-common-utils/pom.xml
+++ b/framework-common-utils/pom.xml
@@ -5,7 +5,7 @@
iotos-soft-gateway
me.hekr.iotos.softgateway
- 3.1.0
+ 3.2.1-SNAPSHOT
4.0.0
diff --git a/framework-common-utils/src/main/java/me/hekr/iotos/softgateway/common/utils/ThreadPoolUtil.java b/framework-common-utils/src/main/java/me/hekr/iotos/softgateway/common/utils/ThreadPoolUtil.java
index be67393670139da08fc75fd8a47d0b283ee23e44..8274391582ce8ef7a12c65d2961b67caf1dfea5d 100644
--- a/framework-common-utils/src/main/java/me/hekr/iotos/softgateway/common/utils/ThreadPoolUtil.java
+++ b/framework-common-utils/src/main/java/me/hekr/iotos/softgateway/common/utils/ThreadPoolUtil.java
@@ -32,7 +32,7 @@ public class ThreadPoolUtil implements Closeable {
public static final ScheduledExecutorService DEFAULT_SCHEDULED =
(ScheduledExecutorService)
new Builder()
- .setPrefix("spring-schedule")
+ .setPrefix("default-scheduled")
.setCore(CORES * 4)
.setMax(32)
.setQueueSize(1000)
diff --git a/framework-core/pom.xml b/framework-core/pom.xml
index 59609321cf39a975d278650f6cc33bfbab83b814..699b48acd92af6d0318dae319f9986ffa0370c25 100644
--- a/framework-core/pom.xml
+++ b/framework-core/pom.xml
@@ -5,7 +5,7 @@
iotos-soft-gateway
me.hekr.iotos.softgateway
- 3.1.0
+ 3.2.1-SNAPSHOT
4.0.0
jar
diff --git a/framework-core/src/main/java/me/hekr/iotos/softgateway/core/config/IotOsConfig.java b/framework-core/src/main/java/me/hekr/iotos/softgateway/core/config/IotOsConfig.java
index 8f345c25f8ae9352bf063111d86f08d3c3334378..2514073a8b548ea5297fd2e1f165b3d414328c04 100644
--- a/framework-core/src/main/java/me/hekr/iotos/softgateway/core/config/IotOsConfig.java
+++ b/framework-core/src/main/java/me/hekr/iotos/softgateway/core/config/IotOsConfig.java
@@ -17,15 +17,21 @@ public class IotOsConfig {
@Getter private MqttConfig mqttConfig;
@Getter private GatewayConfig gatewayConfig;
+ /** mqtt 连接地址 */
@Value("${connect.mqtt.endpoint}")
private String endpoint;
- @Value("${connect.mqtt.connectionTimeout}")
+ /** mqtt 连接超时时间 秒 */
+ @Value("${connect.mqtt.connectionTimeout:10}")
private int connectionTimeout;
@Value("${connect.mqtt.keepAliveTime}")
private int keepAliveTime;
+ @Value("${connect.mqtt.klink.queue.size:10}")
+ @Getter
+ private int klinkQueueSize;
+
@Value("${gateway.pk}")
private String gatewayPk;
diff --git a/framework-core/src/main/java/me/hekr/iotos/softgateway/core/network/mqtt/MqttService.java b/framework-core/src/main/java/me/hekr/iotos/softgateway/core/network/mqtt/MqttService.java
index 8ac2ec3fc412450bda7d83aed6245288a2511ef7..347a749c4abf70b43eb15f97368417125f35fd05 100644
--- a/framework-core/src/main/java/me/hekr/iotos/softgateway/core/network/mqtt/MqttService.java
+++ b/framework-core/src/main/java/me/hekr/iotos/softgateway/core/network/mqtt/MqttService.java
@@ -11,6 +11,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
+import me.hekr.iotos.softgateway.common.utils.JsonUtil;
+import me.hekr.iotos.softgateway.common.utils.ThreadPoolUtil;
import me.hekr.iotos.softgateway.core.config.DeviceRemoteConfig;
import me.hekr.iotos.softgateway.core.config.IotOsConfig;
import me.hekr.iotos.softgateway.core.config.MqttConfig;
@@ -18,7 +20,6 @@ import me.hekr.iotos.softgateway.core.klink.DevLogin;
import me.hekr.iotos.softgateway.core.klink.DevLogout;
import me.hekr.iotos.softgateway.core.klink.KlinkDev;
import me.hekr.iotos.softgateway.core.listener.MqttConnectedListener;
-import me.hekr.iotos.softgateway.common.utils.JsonUtil;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
@@ -52,6 +53,20 @@ public class MqttService {
this.iotOsConfig = iotOsConfig;
initConfig(iotOsConfig);
publishExecutor.execute(this::startPublishTask);
+ ThreadPoolUtil.DEFAULT_SCHEDULED.scheduleAtFixedRate(
+ () -> {
+ int size = queue.size();
+ if (log.isDebugEnabled()) {
+ log.debug("klink 队列还有 {} 个", size);
+ }
+
+ if (size > iotOsConfig.getKlinkQueueSize()) {
+ log.warn("Klink 队列未及时消费,还有: {} 个记录", size);
+ }
+ },
+ 0,
+ 3,
+ TimeUnit.SECONDS);
}
private void initConfig(IotOsConfig iotOsConfig) throws MqttException {
@@ -137,6 +152,10 @@ public class MqttService {
/** @param klink 消息,发送的时候会被 toJson */
@SneakyThrows
public void publish(KlinkDev klink) {
+ if (log.isDebugEnabled()) {
+ log.debug("发送 klink: {}", JsonUtil.toJson(klink));
+ }
+
String pk = klink.getPk();
String devId = klink.getDevId();
Optional byPkAndDevId = DeviceRemoteConfig.getByPkAndDevId(pk, devId);
diff --git a/framework-network-common/pom.xml b/framework-network-common/pom.xml
index cdf6749ba033c9c48101fa1ea6f3f4f867ac9bd3..b9280d0ea85cafb14b9cac73e33999d906c489f1 100644
--- a/framework-network-common/pom.xml
+++ b/framework-network-common/pom.xml
@@ -5,7 +5,7 @@
iotos-soft-gateway
me.hekr.iotos.softgateway
- 3.1.0
+ 3.2.1-SNAPSHOT
4.0.0
diff --git a/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/AbstractClient.java b/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/AbstractClient.java
index 7d932302112d9806005759236b402205b5aaa10c..43139960aef50696d8140cd814bbc2ba3b9653fe 100644
--- a/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/AbstractClient.java
+++ b/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/AbstractClient.java
@@ -14,6 +14,7 @@ import io.netty.channel.socket.DatagramChannel;
import io.netty.handler.logging.LoggingHandler;
import java.net.InetSocketAddress;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import lombok.Getter;
import lombok.Setter;
@@ -71,6 +72,7 @@ public abstract class AbstractClient {
protected void init() {}
public void close() {
+ log.info("准备关闭服务 " + this.getClass().getName());
try {
preDestroy();
} catch (Exception e) {
@@ -78,7 +80,8 @@ public abstract class AbstractClient {
}
if (eventLoop != null) {
try {
- eventLoop.shutdownGracefully().syncUninterruptibly();
+ log.info("关闭 eventLoop");
+ eventLoop.shutdownGracefully(0, 10, TimeUnit.SECONDS);
log.info(" 成功关闭 client");
} catch (Exception e) {
log.error(e.getMessage(), e);
@@ -216,6 +219,10 @@ public abstract class AbstractClient {
/** 直到连接成功 */
protected void loopConnect() {
+ if (eventLoop.isShuttingDown() || eventLoop.isShutdown() || eventLoop.isTerminated()) {
+ log.error("服务关闭,不能重连");
+ return;
+ }
while (true) {
try {
connect();
diff --git a/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/ClientMessageHandler.java b/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/ClientMessageHandler.java
index db6b78e67cdf5cdf27e25dbeb30f688edcd07d48..80897a6acf996bf62706899cc308dcab635da7fc 100644
--- a/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/ClientMessageHandler.java
+++ b/framework-network-common/src/main/java/me/hekr/iotos/softgateway/network/common/client/ClientMessageHandler.java
@@ -8,8 +8,8 @@ import java.net.InetSocketAddress;
import lombok.extern.slf4j.Slf4j;
import me.hekr.iotos.softgateway.network.common.CloseReason;
import me.hekr.iotos.softgateway.network.common.InternalPacket;
-import me.hekr.iotos.softgateway.network.common.listener.MessageListener;
import me.hekr.iotos.softgateway.network.common.PacketContext;
+import me.hekr.iotos.softgateway.network.common.listener.MessageListener;
/** @author iotos */
@Sharable
@@ -35,6 +35,10 @@ public class ClientMessageHandler extends SimpleChannelInboundHandler packet) {
+ if (log.isDebugEnabled()) {
+ log.debug("收到消息:{}", packet);
+ }
+
// 如果不是同步,调用消息回调接口
if (!sync) {
messageListener.onMessage(PacketContext.wrap(packet.getAddress(), packet.getMessage()));
diff --git a/framework-network-http/pom.xml b/framework-network-http/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4c43d83c5d4a1c760880805fee139f8afaddd9c
--- /dev/null
+++ b/framework-network-http/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+ iotos-soft-gateway
+ me.hekr.iotos.softgateway
+ 3.2.1-SNAPSHOT
+
+ 4.0.0
+ framework-network-http
+
+
+
+ org.springframework.boot
+ spring-boot-parent
+ 2.2.12.RELEASE
+ pom
+ import
+
+
+
+
+
+
+ me.hekr.iotos.softgateway
+ framework-common-utils
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.squareup.okhttp3
+ logging-interceptor
+ 3.13.1
+
+
+
+
+ 8
+ 8
+
+
+
\ No newline at end of file
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpClient.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..862d81f53861fa37d3a444aa157e11e8b82db163
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpClient.java
@@ -0,0 +1,136 @@
+package me.hekr.iotos.softgateway.network.http;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import lombok.Data;
+import lombok.Setter;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import me.hekr.iotos.softgateway.common.utils.JsonUtil;
+import okhttp3.ConnectionPool;
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import okhttp3.logging.HttpLoggingInterceptor;
+import okhttp3.logging.HttpLoggingInterceptor.Level;
+
+/** @author du */
+@Data
+@Slf4j
+public class HttpClient {
+
+ private OkHttpClient okHttpClient;
+ private String baseUrl;
+ /** http response 结果校验,如果不通过则抛出异常 */
+ @Setter private HttpResponseChecker httpResponseChecker = HttpResponseChecker.DEFAULT;
+
+ private HttpClient() {}
+
+ @SneakyThrows
+ public static HttpClient newInstance(String baseUrl, int timeoutOfSecs, Level level) {
+ ConnectionPool connectionPool = new ConnectionPool(1, 30, TimeUnit.SECONDS);
+ HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
+ interceptor.setLevel(level);
+ OkHttpClient client =
+ new OkHttpClient()
+ .newBuilder()
+ // 读超时
+ .readTimeout(Duration.ofSeconds(timeoutOfSecs))
+ // 写超时
+ .writeTimeout(Duration.ofSeconds(timeoutOfSecs))
+ //
+ .callTimeout(Duration.ofSeconds(timeoutOfSecs))
+ // 连接池
+ .connectionPool(connectionPool)
+ // 连接超时
+ .connectTimeout(Duration.ofSeconds(timeoutOfSecs))
+ // 不重试
+ .retryOnConnectionFailure(false)
+ .addInterceptor(interceptor)
+ .build();
+ HttpClient httpClient = new HttpClient();
+ httpClient.okHttpClient = client;
+ httpClient.baseUrl = baseUrl;
+ return httpClient;
+ }
+
+ @SneakyThrows
+ public static HttpClient newInstance(String url) {
+ return newInstance(url, 3, Level.BASIC);
+ }
+
+ @SneakyThrows
+ public static HttpClient newInstance(String url, Level level) {
+ return newInstance(url, 3, level);
+ }
+
+ @SneakyThrows
+ public HttpResponse exec(HttpRequest request) {
+ HttpResponse httpResponse;
+ request.baseUrl = baseUrl;
+ try {
+ Response response = okHttpClient.newCall(request.getOkHttpRequest()).execute();
+ ResponseBody body = response.body();
+ byte[] bytes = body == null ? null : body.bytes();
+ httpResponse = new HttpResponse(response, bytes);
+ } catch (Exception e) {
+ throw new HttpException(request, e);
+ }
+
+ boolean success = httpResponseChecker.isSuccess(httpResponse);
+ if (!success) {
+ throw new HttpException(request, httpResponse, httpResponseChecker.desc());
+ }
+
+ return httpResponse;
+ }
+
+ /**
+ * 执行请求,并自动从 json 对象解析成对象
+ *
+ * @param request 请求
+ * @param clazz 映射的对象
+ * @param 参数类型
+ * @return 结果
+ */
+ @SneakyThrows
+ public T exec(HttpRequest request, Class clazz) {
+ return exec(request, response -> JsonUtil.fromBytes(response.bytes, clazz));
+ }
+
+ @SneakyThrows
+ public T exec(HttpRequest request, ResponseParser parser) {
+ HttpResponse response = exec(request);
+ return parser.parse(response);
+ }
+
+ /**
+ * @param request 请求
+ * @param parser response解析
+ * @param curPage 初始化当前页码
+ * @param pageSize 初始化每页大小
+ * @param response
+ * @param response 中的元素
+ * @return 元素列表
+ */
+ public , T> List exec(
+ HttpRequestPageable request,
+ PageableResponseParser parser,
+ int curPage,
+ int pageSize) {
+ List resultList = new ArrayList<>();
+ boolean hasMore = true;
+ int page = curPage;
+ while (hasMore) {
+ HttpResponse resp = exec(request.buildRequest(page, pageSize));
+ HttpPageResponse parse = parser.parse(resp);
+ resultList.addAll(parse.getItems());
+ hasMore = request.hasMore(parse.getResult());
+ page++;
+ }
+
+ return resultList;
+ }
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpException.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpException.java
new file mode 100644
index 0000000000000000000000000000000000000000..fff0806508eb0e65de1cf2e0cd4269a73794556d
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpException.java
@@ -0,0 +1,36 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/**
+ * http 异常
+ *
+ * @author IoTOS
+ */
+public class HttpException extends RuntimeException {
+
+ public HttpException(HttpRequest request, Throwable t) {}
+
+ public HttpException(String message) {
+ super(message);
+ }
+
+ public HttpException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public HttpException(Throwable cause) {
+ super(cause);
+ }
+
+ public HttpException(
+ String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public HttpException(HttpRequest request, HttpResponse response, Throwable throwable) {
+ super("request:" + request + ", response:" + response, throwable);
+ }
+
+ public HttpException(HttpRequest request, HttpResponse response, String desc) {
+ super(desc + ", request:" + request + ", response:" + response);
+ }
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpExceptionHandler.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..544796e99e21c7cf0abb967ae2dd6d8f4b5e6d88
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpExceptionHandler.java
@@ -0,0 +1,33 @@
+package me.hekr.iotos.softgateway.network.http;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 异常处理器
+ *
+ * @author IoTOS
+ */
+public interface HttpExceptionHandler {
+ Logger log = LoggerFactory.getLogger(HttpExceptionHandler.class);
+ /** 抛出异常 */
+ HttpExceptionHandler THROW_HANDLER =
+ (request, t) -> {
+ throw new HttpException(request, t);
+ };
+
+ /** 默认打印异常 */
+ HttpExceptionHandler LOG_HANDLER =
+ (request, t) -> {
+ log.error("request:" + request + ", error:" + t.getMessage(), t);
+ return new HttpResponse();
+ };
+ /**
+ * 异常发生的时候
+ *
+ * @param request 请求
+ * @param t 异常
+ * @return 自定义 response
+ */
+ HttpResponse onException(HttpRequest request, Throwable t);
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpMethod.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpMethod.java
new file mode 100644
index 0000000000000000000000000000000000000000..c99a57a7f48cafe2504c779976b550225505837f
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpMethod.java
@@ -0,0 +1,14 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/** @author iotos */
+public enum HttpMethod {
+ OPTIONS,
+ GET,
+ POST,
+ HEAD,
+ PUT,
+ PATCH,
+ DELETE,
+ TRACE,
+ CONNECT
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpPageRequest.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpPageRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fe46d9dc2181046bc9183ed3e3f38d19bce6f7d
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpPageRequest.java
@@ -0,0 +1,12 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/** @author iotos */
+public abstract class HttpPageRequest extends HttpRequest {
+ private Builder builder;
+
+ public HttpPageRequest(Builder builder) {
+ super(builder);
+ }
+
+ public abstract HttpPageRequest build();
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpPageResponse.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpPageResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..01831edee6fbe58fe96bca5ae9d13b4c4a8d7cd7
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpPageResponse.java
@@ -0,0 +1,31 @@
+package me.hekr.iotos.softgateway.network.http;
+
+import java.util.Collection;
+import java.util.Collections;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 分页请求结果
+ *
+ * @author iotos
+ */
+public class HttpPageResponse, T> {
+
+ /** response 整体结果 */
+ @Setter @Getter private R result;
+
+ public HttpPageResponse() {}
+
+ public HttpPageResponse(R r) {
+ this.result = r;
+ }
+
+ public static , T> HttpPageResponse wrap(R r) {
+ return new HttpPageResponse<>(r);
+ }
+
+ public Collection getItems() {
+ return result == null ? Collections.emptyList() : result.getItems();
+ }
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpRequest.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c5d8088717a22862986d63cb29813587b5386f4
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpRequest.java
@@ -0,0 +1,113 @@
+package me.hekr.iotos.softgateway.network.http;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import okhttp3.Headers;
+import okhttp3.HttpUrl;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import org.springframework.http.MediaType;
+
+/** @author iotos */
+public class HttpRequest {
+ protected Request request;
+ String baseUrl;
+ private Builder requestBuilder;
+
+ public HttpRequest(Builder builder) {
+ this.requestBuilder = builder;
+ }
+
+ public HttpRequest(Request request) {
+ this.request = request;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Request getOkHttpRequest() {
+ HttpUrl httpUrl = HttpUrl.parse(requestBuilder.path);
+ // 为 null,非完整的 url,拼接 baseUrl
+ if (httpUrl == null) {
+ httpUrl = HttpUrl.parse(baseUrl + requestBuilder.path);
+ Objects.requireNonNull(httpUrl, "需要填写baseUrl 或者 request 的 path 需要填写完整的 url 地址");
+ }
+ HttpUrl.Builder httpUrlBuilder = httpUrl.newBuilder();
+ requestBuilder.queryParams.forEach(
+ (k, v) -> httpUrlBuilder.addQueryParameter(k, String.valueOf(v)));
+
+ return requestBuilder.okHttpRequestBuilder.url(httpUrlBuilder.build()).build();
+ }
+
+ @Override
+ public String toString() {
+ return "HttpRequest{" + "request=" + getOkHttpRequest() + '}';
+ }
+
+ public static class Builder {
+ private final Map queryParams = new HashMap<>(10);
+ private final Headers.Builder headerBuilder = new Headers.Builder();
+ Request.Builder okHttpRequestBuilder;
+ private byte[] body;
+ private HttpMethod method = HttpMethod.GET;
+ private MediaType mediaType = MediaType.APPLICATION_JSON;
+ private String path = "";
+
+ public HttpRequest build() {
+ okHttpRequestBuilder = new Request.Builder();
+ handleHeaders();
+ handleMethodAndBody();
+ return new HttpRequest(this);
+ }
+
+ private void handleUrl() {
+ HttpUrl.Builder httpUrlBuilder = HttpUrl.get(path).newBuilder();
+ queryParams.forEach((k, v) -> httpUrlBuilder.addQueryParameter(k, String.valueOf(v)));
+ okHttpRequestBuilder.url(httpUrlBuilder.build());
+ }
+
+ private void handleMethodAndBody() {
+ RequestBody requestBody = null;
+ if (okhttp3.internal.http.HttpMethod.requiresRequestBody(method.name())) {
+ requestBody = RequestBody.create(okhttp3.MediaType.parse(mediaType.toString()), body);
+ }
+ okHttpRequestBuilder.method(method.name(), requestBody);
+ }
+
+ private void handleHeaders() {
+ okHttpRequestBuilder.headers(headerBuilder.build());
+ }
+
+ public Builder addHeader(String name, String value) {
+ headerBuilder.add(name, value);
+ return this;
+ }
+
+ public Builder body(byte[] body) {
+ this.body = body;
+ return this;
+ }
+
+ public Builder addParam(String name, Object value) {
+ queryParams.put(name, value);
+ return this;
+ }
+
+ public Builder path(String path) {
+ this.path = path;
+ return this;
+ }
+
+ public Builder method(HttpMethod method) {
+ this.method = method;
+ return this;
+ }
+
+ public Builder mediaType(MediaType mediaType) {
+ this.mediaType = mediaType;
+ return this;
+ }
+ }
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpRequestPageable.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpRequestPageable.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7a17c3e98823a4d3e894f637a96de592a294c93
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpRequestPageable.java
@@ -0,0 +1,36 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/**
+ * 分页请求
+ *
+ * @author iotos
+ */
+public abstract class HttpRequestPageable {
+ int curPage = 0;
+ int pageSize = 10;
+
+ /** 默认分页 curPage=0; pageSize=10; */
+ public HttpRequestPageable() {}
+
+ public HttpRequestPageable(int curPage, int pageSize) {
+ this.curPage = curPage;
+ this.pageSize = pageSize;
+ }
+
+ /**
+ * 通过分页信息构造一个 httpRequest
+ *
+ * @param curPage 当前页码, 下次查询的页码,第一次传入是 初始化的页面,后面每次调用会+1
+ * @param pageSize 每页大小
+ * @return 构造的 HttpRequest
+ */
+ public abstract HttpRequest buildRequest(int curPage, int pageSize);
+
+ /**
+ * 是否还有更多元素
+ *
+ * @param resp 结果
+ * @return true 还有剩余分页数据;false 没有分页数据
+ */
+ public abstract boolean hasMore(R resp);
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpResponse.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd6533571fa9a201b0f1bc3f43c1c8d07edbacad
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpResponse.java
@@ -0,0 +1,24 @@
+package me.hekr.iotos.softgateway.network.http;
+
+import lombok.Getter;
+import okhttp3.Response;
+
+/** @author IoTOS */
+public class HttpResponse {
+ Response response;
+ @Getter byte[] bytes;
+ @Getter int statusCode;
+
+ public HttpResponse(Response response, byte[] bytes) {
+ this.response = response;
+ this.statusCode = response.code();
+ this.bytes = bytes;
+ }
+
+ public HttpResponse() {}
+
+ @Override
+ public String toString() {
+ return "HttpResponse{" + "response=" + response + '}';
+ }
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpResponseChecker.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpResponseChecker.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbb1777d1fe01bd7b8b38a6d1316a6e141b27c99
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/HttpResponseChecker.java
@@ -0,0 +1,40 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/**
+ * 是否成功校验
+ *
+ * @author iotos
+ */
+public interface HttpResponseChecker {
+
+ /** 默认实现, http status 200 <=code<300 */
+ HttpResponseChecker DEFAULT =
+ new HttpResponseChecker() {
+ @Override
+ public boolean isSuccess(HttpResponse response) {
+ return response.response.isSuccessful();
+ }
+
+ @Override
+ public String desc() {
+ return "status code 不是2xx";
+ }
+ };
+ /**
+ * 是否成功
+ *
+ * @param response response
+ * @return 成功 true,否则 false
+ */
+ boolean isSuccess(HttpResponse response);
+
+ /**
+ * 校验失败描述
+ *
+ * @return 描述
+ */
+ default String desc() {
+ return "response 校验失败";
+ }
+ ;
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/PageableResponse.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/PageableResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf3df7055640ed5a84f2d47e982f668319958410
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/PageableResponse.java
@@ -0,0 +1,14 @@
+package me.hekr.iotos.softgateway.network.http;
+
+import java.util.List;
+
+/** @author iotos */
+public interface PageableResponse {
+
+ /**
+ * 获取分页的元素列表
+ *
+ * @return 分页的元素列表
+ */
+ List getItems();
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/PageableResponseParser.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/PageableResponseParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba044adbc45db7e0a488c4ba2f69fb5df4c46fc8
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/PageableResponseParser.java
@@ -0,0 +1,12 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/** @author iotos */
+public interface PageableResponseParser, T> {
+ /**
+ * 解析 response
+ *
+ * @param response 请求结果
+ * @return 请求结果
+ */
+ HttpPageResponse parse(HttpResponse response);
+}
diff --git a/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/ResponseParser.java b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/ResponseParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..0feaa4d1e66582fbb691ca549d8b9f05263b1198
--- /dev/null
+++ b/framework-network-http/src/main/java/me/hekr/iotos/softgateway/network/http/ResponseParser.java
@@ -0,0 +1,13 @@
+package me.hekr.iotos.softgateway.network.http;
+
+/** @author iotos */
+public interface ResponseParser {
+
+ /**
+ * 从 response 解析成对象
+ *
+ * @param response response
+ * @return 解析结果
+ */
+ T parse(HttpResponse response);
+}
diff --git a/framework-network-mqtt/pom.xml b/framework-network-mqtt/pom.xml
index 00b9a6979a641dee81c0407f8248e5ccf5e1aba0..25abf8af7b05107417033ff340a709d928a4ef06 100644
--- a/framework-network-mqtt/pom.xml
+++ b/framework-network-mqtt/pom.xml
@@ -5,7 +5,7 @@
iotos-soft-gateway
me.hekr.iotos.softgateway
- 3.1.0
+ 3.2.1-SNAPSHOT
4.0.0
@@ -25,7 +25,7 @@
me.hekr.iotos.softgateway
framework-network-common
- 3.1.0
+ 3.2.1-SNAPSHOT
\ No newline at end of file
diff --git a/framework-network-tcp/pom.xml b/framework-network-tcp/pom.xml
index 53b25ca864a75fa5a52d061ccb47160f709e5d05..8d546fb0b0f3a2fe695d20e54dbf61e60b712b12 100644
--- a/framework-network-tcp/pom.xml
+++ b/framework-network-tcp/pom.xml
@@ -5,12 +5,11 @@
iotos-soft-gateway
me.hekr.iotos.softgateway
- 3.1.0
+ 3.2.1-SNAPSHOT
4.0.0
framework-network-tcp
- 3.1.0
8
diff --git a/framework-network-udp/pom.xml b/framework-network-udp/pom.xml
index 269d00993fdef9ab367f89c084e2f8dbcade4eab..fbe6af6c2f33612d1d5b6461eddc8a26bc3848af 100644
--- a/framework-network-udp/pom.xml
+++ b/framework-network-udp/pom.xml
@@ -5,12 +5,11 @@
iotos-soft-gateway
me.hekr.iotos.softgateway
- 3.1.0
+ 3.2.1-SNAPSHOT
4.0.0
framework-network-udp
- 3.1.0
8
diff --git a/pom.xml b/pom.xml
index f3c220967307823f3f1427e01d77627fae8211a5..75b996607345473760ecbf81177c4c7826d5a176 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,12 +12,13 @@
example
framework-common-utils
framework-network-mqtt
+ framework-network-http
me.hekr.iotos.softgateway
iotos-soft-gateway
- 3.1.0
+ 3.2.1-SNAPSHOT
${project.groupId}:${project.artifactId}
IoTOS 软网关
https://gitee.com/geekhekr/iotos-soft-gateway
@@ -29,7 +30,7 @@
UTF-8
UTF-8
UTF-8
- 3.1.0
+ 3.2.1-SNAPSHOT
@@ -50,7 +51,8 @@
scm:git:git://https://gitee.com/geekhekr/iotos-soft-gateway.git
- scm:git:ssh://gitee.com:geekhekr/iotos-soft-gateway.git
+ scm:git:ssh://gitee.com:geekhekr/iotos-soft-gateway.git
+
https://gitee.com/geekhekr/iotos-soft-gateway
@@ -61,6 +63,11 @@
netty-all
4.1.60.Final