commit
30aac270e8
139 changed files with 7552 additions and 0 deletions
@ -0,0 +1,34 @@ |
|||
HELP.md |
|||
target/ |
|||
!.mvn/wrapper/maven-wrapper.jar |
|||
!**/src/main/**/target/ |
|||
!**/src/test/**/target/ |
|||
|
|||
### STS ### |
|||
.apt_generated |
|||
.classpath |
|||
.factorypath |
|||
.project |
|||
.settings |
|||
.springBeans |
|||
.sts4-cache |
|||
|
|||
### IntelliJ IDEA ### |
|||
.idea |
|||
*.iws |
|||
*.iml |
|||
*.ipr |
|||
|
|||
### NetBeans ### |
|||
/nbproject/private/ |
|||
/nbbuild/ |
|||
/dist/ |
|||
/nbdist/ |
|||
/.nb-gradle/ |
|||
build/ |
|||
!**/src/main/**/build/ |
|||
!**/src/test/**/build/ |
|||
|
|||
### VS Code ### |
|||
.vscode/ |
|||
logs/ |
|||
@ -0,0 +1,118 @@ |
|||
/* |
|||
* Copyright 2007-present the original author or authors. |
|||
* |
|||
* 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 |
|||
* |
|||
* https://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. |
|||
*/ |
|||
|
|||
import java.net.*; |
|||
import java.io.*; |
|||
import java.nio.channels.*; |
|||
import java.util.Properties; |
|||
|
|||
public class MavenWrapperDownloader { |
|||
|
|||
private static final String WRAPPER_VERSION = "0.5.6"; |
|||
/** |
|||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. |
|||
*/ |
|||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" |
|||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; |
|||
|
|||
/** |
|||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to |
|||
* use instead of the default one. |
|||
*/ |
|||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH = |
|||
".mvn/wrapper/maven-wrapper.properties"; |
|||
|
|||
/** |
|||
* Path where the maven-wrapper.jar will be saved to. |
|||
*/ |
|||
private static final String MAVEN_WRAPPER_JAR_PATH = |
|||
".mvn/wrapper/maven-wrapper.jar"; |
|||
|
|||
/** |
|||
* Name of the property which should be used to override the default download url for the wrapper. |
|||
*/ |
|||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; |
|||
|
|||
public static void main(String args[]) { |
|||
System.out.println("- Downloader started"); |
|||
File baseDirectory = new File(args[0]); |
|||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); |
|||
|
|||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
|||
// wrapperUrl parameter.
|
|||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); |
|||
String url = DEFAULT_DOWNLOAD_URL; |
|||
if (mavenWrapperPropertyFile.exists()) { |
|||
FileInputStream mavenWrapperPropertyFileInputStream = null; |
|||
try { |
|||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); |
|||
Properties mavenWrapperProperties = new Properties(); |
|||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); |
|||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); |
|||
} catch (IOException e) { |
|||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); |
|||
} finally { |
|||
try { |
|||
if (mavenWrapperPropertyFileInputStream != null) { |
|||
mavenWrapperPropertyFileInputStream.close(); |
|||
} |
|||
} catch (IOException e) { |
|||
// Ignore ...
|
|||
} |
|||
} |
|||
} |
|||
System.out.println("- Downloading from: " + url); |
|||
|
|||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); |
|||
if (!outputFile.getParentFile().exists()) { |
|||
if (!outputFile.getParentFile().mkdirs()) { |
|||
System.out.println( |
|||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); |
|||
} |
|||
} |
|||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); |
|||
try { |
|||
downloadFileFromURL(url, outputFile); |
|||
System.out.println("Done"); |
|||
System.exit(0); |
|||
} catch (Throwable e) { |
|||
System.out.println("- Error downloading"); |
|||
e.printStackTrace(); |
|||
System.exit(1); |
|||
} |
|||
} |
|||
|
|||
private static void downloadFileFromURL(String urlString, File destination) throws Exception { |
|||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { |
|||
String username = System.getenv("MVNW_USERNAME"); |
|||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); |
|||
Authenticator.setDefault(new Authenticator() { |
|||
@Override |
|||
protected PasswordAuthentication getPasswordAuthentication() { |
|||
return new PasswordAuthentication(username, password); |
|||
} |
|||
}); |
|||
} |
|||
URL website = new URL(urlString); |
|||
ReadableByteChannel rbc; |
|||
rbc = Channels.newChannel(website.openStream()); |
|||
FileOutputStream fos = new FileOutputStream(destination); |
|||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); |
|||
fos.close(); |
|||
rbc.close(); |
|||
} |
|||
|
|||
} |
|||
Binary file not shown.
@ -0,0 +1,2 @@ |
|||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip |
|||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar |
|||
@ -0,0 +1,53 @@ |
|||
version: '1.0' |
|||
name: branch-pipeline |
|||
displayName: BranchPipeline |
|||
stages: |
|||
- stage: |
|||
name: compile |
|||
displayName: 编译 |
|||
steps: |
|||
- step: build@maven |
|||
name: build_maven |
|||
displayName: Maven 构建 |
|||
# 支持6、7、8、9、10、11六个版本 |
|||
jdkVersion: 8 |
|||
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本 |
|||
mavenVersion: 3.3.9 |
|||
# 构建命令 |
|||
commands: |
|||
- mvn -B clean package -Dmaven.test.skip=true |
|||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除 |
|||
artifacts: |
|||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址 |
|||
- name: BUILD_ARTIFACT |
|||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录 |
|||
path: |
|||
- ./target |
|||
- step: publish@general_artifacts |
|||
name: publish_general_artifacts |
|||
displayName: 上传制品 |
|||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT |
|||
dependArtifact: BUILD_ARTIFACT |
|||
# 上传到制品库时的制品命名,默认output |
|||
artifactName: output |
|||
dependsOn: build_maven |
|||
- stage: |
|||
name: release |
|||
displayName: 发布 |
|||
steps: |
|||
- step: publish@release_artifacts |
|||
name: publish_release_artifacts |
|||
displayName: '发布' |
|||
# 上游上传制品任务的产出 |
|||
dependArtifact: output |
|||
# 发布制品版本号 |
|||
version: '1.0.0.0' |
|||
# 是否开启版本号自增,默认开启 |
|||
autoIncrement: true |
|||
triggers: |
|||
push: |
|||
branches: |
|||
exclude: |
|||
- master |
|||
include: |
|||
- .* |
|||
@ -0,0 +1,51 @@ |
|||
version: '1.0' |
|||
name: master-pipeline |
|||
displayName: MasterPipeline |
|||
stages: |
|||
- stage: |
|||
name: compile |
|||
displayName: 编译 |
|||
steps: |
|||
- step: build@maven |
|||
name: build_maven |
|||
displayName: Maven 构建 |
|||
# 支持6、7、8、9、10、11六个版本 |
|||
jdkVersion: 8 |
|||
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本 |
|||
mavenVersion: 3.3.9 |
|||
# 构建命令 |
|||
commands: |
|||
- mvn -B clean package -Dmaven.test.skip=true |
|||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除 |
|||
artifacts: |
|||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址 |
|||
- name: BUILD_ARTIFACT |
|||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录 |
|||
path: |
|||
- ./target |
|||
- step: publish@general_artifacts |
|||
name: publish_general_artifacts |
|||
displayName: 上传制品 |
|||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT |
|||
dependArtifact: BUILD_ARTIFACT |
|||
# 上传到制品库时的制品命名,默认output |
|||
artifactName: output |
|||
dependsOn: build_maven |
|||
- stage: |
|||
name: release |
|||
displayName: 发布 |
|||
steps: |
|||
- step: publish@release_artifacts |
|||
name: publish_release_artifacts |
|||
displayName: '发布' |
|||
# 上游上传制品任务的产出 |
|||
dependArtifact: output |
|||
# 发布制品版本号 |
|||
version: '1.0.0.0' |
|||
# 是否开启版本号自增,默认开启 |
|||
autoIncrement: true |
|||
triggers: |
|||
push: |
|||
branches: |
|||
include: |
|||
- master |
|||
@ -0,0 +1,40 @@ |
|||
version: '1.0' |
|||
name: pr-pipeline |
|||
displayName: PRPipeline |
|||
stages: |
|||
- stage: |
|||
name: compile |
|||
displayName: 编译 |
|||
steps: |
|||
- step: build@maven |
|||
name: build_maven |
|||
displayName: Maven 构建 |
|||
# 支持6、7、8、9、10、11六个版本 |
|||
jdkVersion: 8 |
|||
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本 |
|||
mavenVersion: 3.3.9 |
|||
# 构建命令 |
|||
commands: |
|||
- mvn -B clean package -Dmaven.test.skip=true |
|||
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除 |
|||
artifacts: |
|||
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址 |
|||
- name: BUILD_ARTIFACT |
|||
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录 |
|||
path: |
|||
- ./target |
|||
- step: publish@general_artifacts |
|||
name: publish_general_artifacts |
|||
displayName: 上传制品 |
|||
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT |
|||
dependArtifact: BUILD_ARTIFACT |
|||
# 构建产物制品库,默认default,系统默认创建 |
|||
artifactRepository: default |
|||
# 上传到制品库时的制品命名,默认output |
|||
artifactName: output |
|||
dependsOn: build_maven |
|||
triggers: |
|||
pr: |
|||
branches: |
|||
include: |
|||
- master |
|||
@ -0,0 +1,15 @@ |
|||
FROM registry.ap-northeast-1.aliyuncs.com/southwave/jdk17-template:latest |
|||
WORKDIR /app |
|||
COPY target/data-center-receiver.jar app.jar |
|||
EXPOSE 8200 |
|||
|
|||
# 使用UseCGroupMemoryLimitForHeap |
|||
|
|||
# ENV JAVA_OPTS="-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log" |
|||
|
|||
# 使用shell方式的ENTRYPOINT来确保环境变量被展开 |
|||
ENTRYPOINT java $JAVA_OPTS -jar app.jar -Djavax.net.debug=ssl --spring-profiles=$env |
|||
|
|||
|
|||
|
|||
|
|||
@ -0,0 +1,68 @@ |
|||
# 介绍 |
|||
组件用于订阅客户端数据。 |
|||
组件运行在8201端口 |
|||
数据库为data_center |
|||
|
|||
# 功能 |
|||
1. 订阅MQTT数据,并转发至本地8200端口的TECHSOR_dataCenter_sender服务处理 |
|||
|
|||
# 初始化 |
|||
启动组件后,调用以下接口开启所有mqtt订阅: |
|||
GET localhost:8200/v1/mqtt/startAll |
|||
|
|||
|
|||
|
|||
# 开发测试环境信息 |
|||
|
|||
Redis 信息 |
|||
公网地址: r-uf63x4g5p6ir5xao87pd.redis.rds.aliyuncs.com |
|||
内网地址: r-uf63x4g5p6ir5xao87.redis.rds.aliyuncs.com |
|||
端口号:6379 |
|||
密码:B2BGn4gK4htgkEwP |
|||
|
|||
|
|||
mysql信息 |
|||
地址:rm-bp11k2zm2fr7864428o.mysql.rds.aliyuncs.com |
|||
端口号:3306 |
|||
用户名:zhc |
|||
密码:Youqu48bnb1 |
|||
|
|||
Docker镜像仓库 |
|||
sender推送地址及方法: |
|||
$ docker login --username=4099*****@qq.com registry.cn-shanghai.aliyuncs.com$ docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_sender:[镜像版本号]$ docker push registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_sender:[镜像版本号] |
|||
|
|||
receiver推送地址及方法: |
|||
$ docker login --username=4099*****@qq.com registry.cn-shanghai.aliyuncs.com$ docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_receiver:[镜像版本号]$ docker push registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_receiver:[镜像版本号] |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
# 服务器1 |
|||
47.122.21.64 |
|||
root |
|||
证书:southwave_datacenter_test.pem |
|||
|
|||
# 服务器2 |
|||
47.122.2.42 |
|||
root |
|||
证书:southwave_datacenter_test.pem |
|||
|
|||
|
|||
### docker 环境配置 |
|||
#### 环境启动问题 |
|||
aws上应该可以设置环境变量 `env` |
|||
|
|||
`env`=dev |
|||
或者 |
|||
`env`=stg |
|||
或者 |
|||
`env`=prd |
|||
|
|||
#### sender地址 |
|||
|
|||
aws 上设置环境变量 'sendUrl' |
|||
|
|||
`sendUrl`=http://localhost:8021 |
|||
|
|||
|
|||
@ -0,0 +1,27 @@ |
|||
-----BEGIN RSA PRIVATE KEY----- |
|||
MIIEpAIBAAKCAQEAoXT+WI0CFw06NjKINFhz5y9xs9CeQYHN0+G24fIePPEBPRhW |
|||
Faxg36GuFuYKxk59W+Ey8w5Stz8R1wckbU//uaio/P7QhNbl+OpVIKbU93SVW8x6 |
|||
VH8roTSf+uYh6k6qO5ejAjqiicuEj8dZ8fQWyYSB4X/mLrXg5k5dxKyjhv5nM8RO |
|||
vvFHy/uvcdFOAeBbYrq9pHOkSP3BLU+wjutBDmxEdM9YLJk9qOM9bulxr1+QMXNY |
|||
4pjpWDlqfM1BpZZDhKzvUqLVjO+QwQ2E8mUgoK2PVY1umC5X8Jlcfy83A77+pKzl |
|||
ZKYpLgfLHj7rV5I12uoBx4mvLO1jw6XrNlIb9QIDAQABAoIBAGe+pDxEBwbG4hO3 |
|||
LpvsBjWT38y6DSZsgNRX4cqXZ+Siu7gFLjNo+ypXWmSuVlgMUTK7pqBVIMNMjGsN |
|||
1NNEpz4l6Mf/9/6Tk1v5Ps/nQ0rqJ5q/7g7jVCaWiQGP5FUJTQtTqVOiV5SRKFG2 |
|||
t83nmMjOEyLRqxdymNuDmW7pu33ebtDZxwm+QeN3nz6TwAbV7Geas5NC1UJLR0+C |
|||
nLQh0M9QELv7fKUPiznr6wE9CxB+1fx9es6HJxYK6Q4W+4mjd8CVXXMPDiQhTVEt |
|||
jnibk3UfxBQB7fkYP8PUukGq+Z4BgCszoAW0J8gFwiC8YMuzzQw3k83vPCiZZ+JQ |
|||
u0hgUPUCgYEA1lQi4mhKNtYMfbVtKEURajvUy5pZw4rzIyo+6XFjE25c3Q/nt3ot |
|||
d+vgh6dNCfRll95CB2RKOUoelj3nDeX+aM+QEwwQghLAtAdcRcIhG3DfIYBOJmiw |
|||
ugjbk5AW1bc38eQsjtRD7aZMyJjjr2bI7D2D5/MrjqdMZ6sxYdFRmpMCgYEAwNlB |
|||
h/Da5kY/z9qcXSnysr78ffU5BLGcxN2At+aXYGKyoR2YQqSME0y1jC9h0w+a7nAx |
|||
jCtkz+ozhBkP7o0vRZ8eGbP/65CbPrsY8P9Kpvk7dr2IRMTUjMFihhptGQFrLP3a |
|||
g+T2T+gQWS0v5HqiSot6znHZL+jND9elwx8nnFcCgYEAuemhmOL9/TMPArwtQ5El |
|||
2hCsNTBeTNBqt0Yd7ED+wAwrYVY6mVzRtARXb1Qf71KgDWwtulu0Rp2Uip6Hnfaz |
|||
CBeD0gHVD/9USNVZpOkP7s2pv1WcdJS7N6QXU5jZNekIDjruq7ZUdgCa+iYk2jE+ |
|||
eC2kDb9RORzFmedVnpQDRSECgYBH26xTXyfxzhNQ/ABvpoXMnOWweYN5gEUOBgtE |
|||
eyPEwoIVDtYBXxbiyh6L0cv9vT7Zwex0cmbqIjZ37m7FUM5gft3UbgHaYNO4GDc+ |
|||
9aF3fj7uC8mO9ljM6fIwTgCA5MpuxVh69QHi3HHbCL9jv15hsH9eFYX8GB7w3EXj |
|||
4uP7mQKBgQCFG7l/s1VDsLn9VNpkoUBjZMMdrLCyCWVrTEdeYtZ5LIx3etZxgbah |
|||
/rvryIDgc/j7riQgEDnqYk19Ee/HVxK1duJO6d/ywDcSlnNMaChrS8khsMrbK6yI |
|||
geqH+9jaaPUVacfeVe0MCIGLxnMiUucIUIyp3VV2OuJ2xx68xqw1wA== |
|||
-----END RSA PRIVATE KEY----- |
|||
@ -0,0 +1,2 @@ |
|||
scp -i ./TECHSOR_OFFICIAL.pem ./target/TECHSOR_dataCenter_receiver-0.0.1-SNAPSHOT.jar root@8.209.255.206:~ |
|||
ssh -i ./TECHSOR_OFFICIAL.pem root@8.209.255.206 |
|||
@ -0,0 +1,20 @@ |
|||
version: '3.8' |
|||
# docker pull adoptopenjdk/openjdk8:ppc64le-debian-jdk8u212-b03 |
|||
services: |
|||
app: |
|||
build: . |
|||
|
|||
ports: |
|||
- "8200:8200" |
|||
environment: |
|||
JAVA_OPTS: "-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log" |
|||
AGENT_PATH: "-agentpath:/app/liberror-detector-agent.so=packageName=org/springframework/integration,=filePath=./gcclogs/errorlog.log" # Replace this with your actual agent options if necessary |
|||
env: "dev" # Replace this with your actual spring profile if necessary |
|||
volumes: |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/data-center-receiver.jar:/app/app.jar |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/liberror-detector-agent.so:/app/liberror-detector-agent.so |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/app/gc.log:/app/gc.log # Make sure this path is correct for your gc logs |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/:/app/ |
|||
entrypoint: java $AGENT_PATH $JAVA_OPTS -jar /app/app.jar -Djavax.net.debug=ssl --spring-profiles=$env |
|||
|
|||
|
|||
@ -0,0 +1,310 @@ |
|||
#!/bin/sh |
|||
# ---------------------------------------------------------------------------- |
|||
# Licensed to the Apache Software Foundation (ASF) under one |
|||
# or more contributor license agreements. See the NOTICE file |
|||
# distributed with this work for additional information |
|||
# regarding copyright ownership. The ASF licenses this file |
|||
# to you 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 |
|||
# |
|||
# https://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. |
|||
# ---------------------------------------------------------------------------- |
|||
|
|||
# ---------------------------------------------------------------------------- |
|||
# Maven Start Up Batch script |
|||
# |
|||
# Required ENV vars: |
|||
# ------------------ |
|||
# JAVA_HOME - location of a JDK home dir |
|||
# |
|||
# Optional ENV vars |
|||
# ----------------- |
|||
# M2_HOME - location of maven2's installed home dir |
|||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven |
|||
# e.g. to debug Maven itself, use |
|||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
|||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
|||
# ---------------------------------------------------------------------------- |
|||
|
|||
if [ -z "$MAVEN_SKIP_RC" ] ; then |
|||
|
|||
if [ -f /etc/mavenrc ] ; then |
|||
. /etc/mavenrc |
|||
fi |
|||
|
|||
if [ -f "$HOME/.mavenrc" ] ; then |
|||
. "$HOME/.mavenrc" |
|||
fi |
|||
|
|||
fi |
|||
|
|||
# OS specific support. $var _must_ be set to either true or false. |
|||
cygwin=false; |
|||
darwin=false; |
|||
mingw=false |
|||
case "`uname`" in |
|||
CYGWIN*) cygwin=true ;; |
|||
MINGW*) mingw=true;; |
|||
Darwin*) darwin=true |
|||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home |
|||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html |
|||
if [ -z "$JAVA_HOME" ]; then |
|||
if [ -x "/usr/libexec/java_home" ]; then |
|||
export JAVA_HOME="`/usr/libexec/java_home`" |
|||
else |
|||
export JAVA_HOME="/Library/Java/Home" |
|||
fi |
|||
fi |
|||
;; |
|||
esac |
|||
|
|||
if [ -z "$JAVA_HOME" ] ; then |
|||
if [ -r /etc/gentoo-release ] ; then |
|||
JAVA_HOME=`java-config --jre-home` |
|||
fi |
|||
fi |
|||
|
|||
if [ -z "$M2_HOME" ] ; then |
|||
## resolve links - $0 may be a link to maven's home |
|||
PRG="$0" |
|||
|
|||
# need this for relative symlinks |
|||
while [ -h "$PRG" ] ; do |
|||
ls=`ls -ld "$PRG"` |
|||
link=`expr "$ls" : '.*-> \(.*\)$'` |
|||
if expr "$link" : '/.*' > /dev/null; then |
|||
PRG="$link" |
|||
else |
|||
PRG="`dirname "$PRG"`/$link" |
|||
fi |
|||
done |
|||
|
|||
saveddir=`pwd` |
|||
|
|||
M2_HOME=`dirname "$PRG"`/.. |
|||
|
|||
# make it fully qualified |
|||
M2_HOME=`cd "$M2_HOME" && pwd` |
|||
|
|||
cd "$saveddir" |
|||
# echo Using m2 at $M2_HOME |
|||
fi |
|||
|
|||
# For Cygwin, ensure paths are in UNIX format before anything is touched |
|||
if $cygwin ; then |
|||
[ -n "$M2_HOME" ] && |
|||
M2_HOME=`cygpath --unix "$M2_HOME"` |
|||
[ -n "$JAVA_HOME" ] && |
|||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"` |
|||
[ -n "$CLASSPATH" ] && |
|||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"` |
|||
fi |
|||
|
|||
# For Mingw, ensure paths are in UNIX format before anything is touched |
|||
if $mingw ; then |
|||
[ -n "$M2_HOME" ] && |
|||
M2_HOME="`(cd "$M2_HOME"; pwd)`" |
|||
[ -n "$JAVA_HOME" ] && |
|||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" |
|||
fi |
|||
|
|||
if [ -z "$JAVA_HOME" ]; then |
|||
javaExecutable="`which javac`" |
|||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then |
|||
# readlink(1) is not available as standard on Solaris 10. |
|||
readLink=`which readlink` |
|||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then |
|||
if $darwin ; then |
|||
javaHome="`dirname \"$javaExecutable\"`" |
|||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" |
|||
else |
|||
javaExecutable="`readlink -f \"$javaExecutable\"`" |
|||
fi |
|||
javaHome="`dirname \"$javaExecutable\"`" |
|||
javaHome=`expr "$javaHome" : '\(.*\)/bin'` |
|||
JAVA_HOME="$javaHome" |
|||
export JAVA_HOME |
|||
fi |
|||
fi |
|||
fi |
|||
|
|||
if [ -z "$JAVACMD" ] ; then |
|||
if [ -n "$JAVA_HOME" ] ; then |
|||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
|||
# IBM's JDK on AIX uses strange locations for the executables |
|||
JAVACMD="$JAVA_HOME/jre/sh/java" |
|||
else |
|||
JAVACMD="$JAVA_HOME/bin/java" |
|||
fi |
|||
else |
|||
JAVACMD="`which java`" |
|||
fi |
|||
fi |
|||
|
|||
if [ ! -x "$JAVACMD" ] ; then |
|||
echo "Error: JAVA_HOME is not defined correctly." >&2 |
|||
echo " We cannot execute $JAVACMD" >&2 |
|||
exit 1 |
|||
fi |
|||
|
|||
if [ -z "$JAVA_HOME" ] ; then |
|||
echo "Warning: JAVA_HOME environment variable is not set." |
|||
fi |
|||
|
|||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher |
|||
|
|||
# traverses directory structure from process work directory to filesystem root |
|||
# first directory with .mvn subdirectory is considered project base directory |
|||
find_maven_basedir() { |
|||
|
|||
if [ -z "$1" ] |
|||
then |
|||
echo "Path not specified to find_maven_basedir" |
|||
return 1 |
|||
fi |
|||
|
|||
basedir="$1" |
|||
wdir="$1" |
|||
while [ "$wdir" != '/' ] ; do |
|||
if [ -d "$wdir"/.mvn ] ; then |
|||
basedir=$wdir |
|||
break |
|||
fi |
|||
# workaround for JBEAP-8937 (on Solaris 10/Sparc) |
|||
if [ -d "${wdir}" ]; then |
|||
wdir=`cd "$wdir/.."; pwd` |
|||
fi |
|||
# end of workaround |
|||
done |
|||
echo "${basedir}" |
|||
} |
|||
|
|||
# concatenates all lines of a file |
|||
concat_lines() { |
|||
if [ -f "$1" ]; then |
|||
echo "$(tr -s '\n' ' ' < "$1")" |
|||
fi |
|||
} |
|||
|
|||
BASE_DIR=`find_maven_basedir "$(pwd)"` |
|||
if [ -z "$BASE_DIR" ]; then |
|||
exit 1; |
|||
fi |
|||
|
|||
########################################################################################## |
|||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
|||
# This allows using the maven wrapper in projects that prohibit checking in binary data. |
|||
########################################################################################## |
|||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo "Found .mvn/wrapper/maven-wrapper.jar" |
|||
fi |
|||
else |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." |
|||
fi |
|||
if [ -n "$MVNW_REPOURL" ]; then |
|||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
|||
else |
|||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
|||
fi |
|||
while IFS="=" read key value; do |
|||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;; |
|||
esac |
|||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo "Downloading from: $jarUrl" |
|||
fi |
|||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" |
|||
if $cygwin; then |
|||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` |
|||
fi |
|||
|
|||
if command -v wget > /dev/null; then |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo "Found wget ... using wget" |
|||
fi |
|||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then |
|||
wget "$jarUrl" -O "$wrapperJarPath" |
|||
else |
|||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" |
|||
fi |
|||
elif command -v curl > /dev/null; then |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo "Found curl ... using curl" |
|||
fi |
|||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then |
|||
curl -o "$wrapperJarPath" "$jarUrl" -f |
|||
else |
|||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f |
|||
fi |
|||
|
|||
else |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo "Falling back to using Java to download" |
|||
fi |
|||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" |
|||
# For Cygwin, switch paths to Windows format before running javac |
|||
if $cygwin; then |
|||
javaClass=`cygpath --path --windows "$javaClass"` |
|||
fi |
|||
if [ -e "$javaClass" ]; then |
|||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo " - Compiling MavenWrapperDownloader.java ..." |
|||
fi |
|||
# Compiling the Java class |
|||
("$JAVA_HOME/bin/javac" "$javaClass") |
|||
fi |
|||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then |
|||
# Running the downloader |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo " - Running MavenWrapperDownloader.java ..." |
|||
fi |
|||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") |
|||
fi |
|||
fi |
|||
fi |
|||
fi |
|||
########################################################################################## |
|||
# End of extension |
|||
########################################################################################## |
|||
|
|||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} |
|||
if [ "$MVNW_VERBOSE" = true ]; then |
|||
echo $MAVEN_PROJECTBASEDIR |
|||
fi |
|||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" |
|||
|
|||
# For Cygwin, switch paths to Windows format before running java |
|||
if $cygwin; then |
|||
[ -n "$M2_HOME" ] && |
|||
M2_HOME=`cygpath --path --windows "$M2_HOME"` |
|||
[ -n "$JAVA_HOME" ] && |
|||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` |
|||
[ -n "$CLASSPATH" ] && |
|||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"` |
|||
[ -n "$MAVEN_PROJECTBASEDIR" ] && |
|||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` |
|||
fi |
|||
|
|||
# Provide a "standardized" way to retrieve the CLI args that will |
|||
# work with both Windows and non-Windows executions. |
|||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" |
|||
export MAVEN_CMD_LINE_ARGS |
|||
|
|||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
|||
|
|||
exec "$JAVACMD" \ |
|||
$MAVEN_OPTS \ |
|||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ |
|||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ |
|||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" |
|||
@ -0,0 +1,182 @@ |
|||
@REM ---------------------------------------------------------------------------- |
|||
@REM Licensed to the Apache Software Foundation (ASF) under one |
|||
@REM or more contributor license agreements. See the NOTICE file |
|||
@REM distributed with this work for additional information |
|||
@REM regarding copyright ownership. The ASF licenses this file |
|||
@REM to you under the Apache License, Version 2.0 (the |
|||
@REM "License"); you may not use this file except in compliance |
|||
@REM with the License. You may obtain a copy of the License at |
|||
@REM |
|||
@REM https://www.apache.org/licenses/LICENSE-2.0 |
|||
@REM |
|||
@REM Unless required by applicable law or agreed to in writing, |
|||
@REM software distributed under the License is distributed on an |
|||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
|||
@REM KIND, either express or implied. See the License for the |
|||
@REM specific language governing permissions and limitations |
|||
@REM under the License. |
|||
@REM ---------------------------------------------------------------------------- |
|||
|
|||
@REM ---------------------------------------------------------------------------- |
|||
@REM Maven Start Up Batch script |
|||
@REM |
|||
@REM Required ENV vars: |
|||
@REM JAVA_HOME - location of a JDK home dir |
|||
@REM |
|||
@REM Optional ENV vars |
|||
@REM M2_HOME - location of maven2's installed home dir |
|||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands |
|||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending |
|||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven |
|||
@REM e.g. to debug Maven itself, use |
|||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 |
|||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files |
|||
@REM ---------------------------------------------------------------------------- |
|||
|
|||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' |
|||
@echo off |
|||
@REM set title of command window |
|||
title %0 |
|||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' |
|||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% |
|||
|
|||
@REM set %HOME% to equivalent of $HOME |
|||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") |
|||
|
|||
@REM Execute a user defined script before this one |
|||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre |
|||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending |
|||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" |
|||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" |
|||
:skipRcPre |
|||
|
|||
@setlocal |
|||
|
|||
set ERROR_CODE=0 |
|||
|
|||
@REM To isolate internal variables from possible post scripts, we use another setlocal |
|||
@setlocal |
|||
|
|||
@REM ==== START VALIDATION ==== |
|||
if not "%JAVA_HOME%" == "" goto OkJHome |
|||
|
|||
echo. |
|||
echo Error: JAVA_HOME not found in your environment. >&2 |
|||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
|||
echo location of your Java installation. >&2 |
|||
echo. |
|||
goto error |
|||
|
|||
:OkJHome |
|||
if exist "%JAVA_HOME%\bin\java.exe" goto init |
|||
|
|||
echo. |
|||
echo Error: JAVA_HOME is set to an invalid directory. >&2 |
|||
echo JAVA_HOME = "%JAVA_HOME%" >&2 |
|||
echo Please set the JAVA_HOME variable in your environment to match the >&2 |
|||
echo location of your Java installation. >&2 |
|||
echo. |
|||
goto error |
|||
|
|||
@REM ==== END VALIDATION ==== |
|||
|
|||
:init |
|||
|
|||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". |
|||
@REM Fallback to current working directory if not found. |
|||
|
|||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% |
|||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir |
|||
|
|||
set EXEC_DIR=%CD% |
|||
set WDIR=%EXEC_DIR% |
|||
:findBaseDir |
|||
IF EXIST "%WDIR%"\.mvn goto baseDirFound |
|||
cd .. |
|||
IF "%WDIR%"=="%CD%" goto baseDirNotFound |
|||
set WDIR=%CD% |
|||
goto findBaseDir |
|||
|
|||
:baseDirFound |
|||
set MAVEN_PROJECTBASEDIR=%WDIR% |
|||
cd "%EXEC_DIR%" |
|||
goto endDetectBaseDir |
|||
|
|||
:baseDirNotFound |
|||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR% |
|||
cd "%EXEC_DIR%" |
|||
|
|||
:endDetectBaseDir |
|||
|
|||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig |
|||
|
|||
@setlocal EnableExtensions EnableDelayedExpansion |
|||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a |
|||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% |
|||
|
|||
:endReadAdditionalConfig |
|||
|
|||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" |
|||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" |
|||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain |
|||
|
|||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
|||
|
|||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( |
|||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B |
|||
) |
|||
|
|||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central |
|||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data. |
|||
if exist %WRAPPER_JAR% ( |
|||
if "%MVNW_VERBOSE%" == "true" ( |
|||
echo Found %WRAPPER_JAR% |
|||
) |
|||
) else ( |
|||
if not "%MVNW_REPOURL%" == "" ( |
|||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" |
|||
) |
|||
if "%MVNW_VERBOSE%" == "true" ( |
|||
echo Couldn't find %WRAPPER_JAR%, downloading it ... |
|||
echo Downloading from: %DOWNLOAD_URL% |
|||
) |
|||
|
|||
powershell -Command "&{"^ |
|||
"$webclient = new-object System.Net.WebClient;"^ |
|||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ |
|||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ |
|||
"}"^ |
|||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ |
|||
"}" |
|||
if "%MVNW_VERBOSE%" == "true" ( |
|||
echo Finished downloading %WRAPPER_JAR% |
|||
) |
|||
) |
|||
@REM End of extension |
|||
|
|||
@REM Provide a "standardized" way to retrieve the CLI args that will |
|||
@REM work with both Windows and non-Windows executions. |
|||
set MAVEN_CMD_LINE_ARGS=%* |
|||
|
|||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* |
|||
if ERRORLEVEL 1 goto error |
|||
goto end |
|||
|
|||
:error |
|||
set ERROR_CODE=1 |
|||
|
|||
:end |
|||
@endlocal & set ERROR_CODE=%ERROR_CODE% |
|||
|
|||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost |
|||
@REM check for post script, once with legacy .bat ending and once with .cmd ending |
|||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" |
|||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" |
|||
:skipRcPost |
|||
|
|||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' |
|||
if "%MAVEN_BATCH_PAUSE%" == "on" pause |
|||
|
|||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% |
|||
|
|||
exit /B %ERROR_CODE% |
|||
@ -0,0 +1,648 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<parent> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-parent</artifactId> |
|||
<version>3.2.12</version> |
|||
<relativePath/> <!-- lookup parent from repository --> |
|||
</parent> |
|||
<groupId>com.techsor</groupId> |
|||
<artifactId>data.center.receiver</artifactId> |
|||
<version>0.0.1-SNAPSHOT</version> |
|||
<name>TECHSOR_dataCenter_receiver</name> |
|||
<properties> |
|||
<java.version>17</java.version> |
|||
<aws.ecr.registry>381659385655.dkr.ecr.ap-northeast-1.amazonaws.com</aws.ecr.registry> |
|||
<aws.ecr.registryTest>923770123186.dkr.ecr.ap-northeast-1.amazonaws.com</aws.ecr.registryTest> |
|||
<aws.ecr.repository>tokyo-build-receiver</aws.ecr.repository> |
|||
<netty.version>4.2.2.Final</netty.version> |
|||
</properties> |
|||
<dependencyManagement> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>software.amazon.awssdk</groupId> |
|||
<artifactId>bom</artifactId> |
|||
<version>2.20.113</version> |
|||
<type>pom</type> |
|||
<scope>import</scope> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-buffer</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-base</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-compression</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-dns</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-haproxy</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-http</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-http2</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-http3</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-memcache</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-mqtt</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-redis</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-smtp</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-socks</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-stomp</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-xml</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-protobuf</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-marshalling</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 其他核心模块 --> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-common</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-handler</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-handler-proxy</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-handler-ssl-ocsp</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- resolver & transport --> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-resolver</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-resolver-dns</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-resolver-dns-classes-macos</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-classes-epoll</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-classes-kqueue</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-classes-io_uring</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-unix-common</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- platform-specific native modules --> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-epoll</artifactId> |
|||
<classifier>linux-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-epoll</artifactId> |
|||
<classifier>linux-aarch_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-epoll</artifactId> |
|||
<classifier>linux-riscv64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-io_uring</artifactId> |
|||
<classifier>linux-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-io_uring</artifactId> |
|||
<classifier>linux-aarch_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-io_uring</artifactId> |
|||
<classifier>linux-riscv64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-kqueue</artifactId> |
|||
<classifier>osx-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-native-kqueue</artifactId> |
|||
<classifier>osx-aarch_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-resolver-dns-native-macos</artifactId> |
|||
<classifier>osx-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-resolver-dns-native-macos</artifactId> |
|||
<classifier>osx-aarch_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-native-quic</artifactId> |
|||
<classifier>linux-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-native-quic</artifactId> |
|||
<classifier>linux-aarch_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-native-quic</artifactId> |
|||
<classifier>osx-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-native-quic</artifactId> |
|||
<classifier>osx-aarch_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-native-quic</artifactId> |
|||
<classifier>windows-x86_64</classifier> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 特殊模块 --> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-rxtx</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-sctp</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-transport-udt</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-codec-classes-quic</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
</dependencies> |
|||
</dependencyManagement> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-jdbc</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-web</artifactId> |
|||
<exclusions> |
|||
<exclusion> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-logging</artifactId> |
|||
</exclusion> |
|||
<exclusion> |
|||
<groupId>org.apache.tomcat.embed</groupId> |
|||
<artifactId>tomcat-embed-core</artifactId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-core --> |
|||
<dependency> |
|||
<groupId>org.apache.tomcat.embed</groupId> |
|||
<artifactId>tomcat-embed-core</artifactId> |
|||
<version>10.1.42</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-configuration-processor</artifactId> |
|||
<optional>true</optional> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-integration</artifactId> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-mqtt --> |
|||
<!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-mqtt --> |
|||
<dependency> |
|||
<groupId>org.springframework.integration</groupId> |
|||
<artifactId>spring-integration-mqtt</artifactId> |
|||
<version>5.5.1</version> |
|||
</dependency> |
|||
|
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-redis</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-integration</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.integration</groupId> |
|||
<artifactId>spring-integration-redis</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-actuator</artifactId> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-test</artifactId> |
|||
<scope>test</scope> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>software.amazon.awssdk</groupId> |
|||
<artifactId>s3</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>commons-io</groupId> |
|||
<artifactId>commons-io</artifactId> |
|||
<version>2.19.0</version> |
|||
</dependency> |
|||
<!-- MYSQL --> |
|||
<dependency> |
|||
<groupId>com.mysql</groupId> |
|||
<artifactId>mysql-connector-j</artifactId> |
|||
<version>9.3.0</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.projectlombok</groupId> |
|||
<artifactId>lombok</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/io.joynr.java.messaging.mqtt/paho-mqtt-client --> |
|||
<dependency> |
|||
<groupId>io.joynr.java.messaging.mqtt</groupId> |
|||
<artifactId>paho-mqtt-client</artifactId> |
|||
<version>1.14.2</version> |
|||
</dependency> |
|||
<!-- JSON等格式的转义和反转义 --> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-text</artifactId> |
|||
<version>1.13.1</version> |
|||
</dependency> |
|||
|
|||
<!-- <dependency> |
|||
<groupId>net.sf.json-lib</groupId> |
|||
<artifactId>json-lib</artifactId> |
|||
<version>2.4</version> |
|||
<classifier>jdk15</classifier> |
|||
</dependency>--> |
|||
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> |
|||
<dependency> |
|||
<groupId>com.google.code.gson</groupId> |
|||
<artifactId>gson</artifactId> |
|||
<version>2.13.1</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-all</artifactId> |
|||
<version>${netty.version}</version> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk18on --> |
|||
<dependency> |
|||
<groupId>org.bouncycastle</groupId> |
|||
<artifactId>bcpkix-jdk18on</artifactId> |
|||
<version>1.81</version> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> |
|||
<dependency> |
|||
<groupId>com.squareup.okhttp3</groupId> |
|||
<artifactId>okhttp</artifactId> |
|||
<version>4.12.0</version> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/junit/junit --> |
|||
<dependency> |
|||
<groupId>junit</groupId> |
|||
<artifactId>junit</artifactId> |
|||
<version>4.13.2</version> |
|||
<scope>test</scope> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.github.houbb</groupId> |
|||
<artifactId>data-factory-core</artifactId> |
|||
<version>1.2.0</version> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/com.github.noconnor/junitperf --> |
|||
<dependency> |
|||
<groupId>com.github.noconnor</groupId> |
|||
<artifactId>junitperf</artifactId> |
|||
<version>1.22.1</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-pool2</artifactId> |
|||
<version>2.11.1</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-all</artifactId> |
|||
<version>5.8.38</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.github.derjust</groupId> |
|||
<artifactId>spring-data-dynamodb</artifactId> |
|||
<version>5.1.0</version> |
|||
<exclusions> |
|||
<exclusion> |
|||
<groupId>com.amazonaws</groupId> |
|||
<artifactId>aws-java-sdk-dynamodb</artifactId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-dynamodb --> |
|||
<dependency> |
|||
<groupId>com.amazonaws</groupId> |
|||
<artifactId>aws-java-sdk-dynamodb</artifactId> |
|||
<version>1.12.786</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-data-jpa</artifactId> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.jayway.jsonpath</groupId> |
|||
<artifactId>json-path</artifactId> |
|||
<version>2.9.0</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.slf4j</groupId> |
|||
<artifactId>jul-to-slf4j</artifactId> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 --> |
|||
<dependency> |
|||
<groupId>com.alibaba.fastjson2</groupId> |
|||
<artifactId>fastjson2</artifactId> |
|||
<version>2.0.46</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.apache.kafka</groupId> |
|||
<artifactId>kafka-clients</artifactId> |
|||
<version>4.0.0</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml --> |
|||
<dependency> |
|||
<groupId>org.yaml</groupId> |
|||
<artifactId>snakeyaml</artifactId> |
|||
<version>2.4</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/net.minidev/json-smart --> |
|||
<dependency> |
|||
<groupId>net.minidev</groupId> |
|||
<artifactId>json-smart</artifactId> |
|||
<version>2.5.2</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> |
|||
<dependency> |
|||
<groupId>org.springframework</groupId> |
|||
<artifactId>spring-context</artifactId> |
|||
<version>6.1.21</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support --> |
|||
<dependency> |
|||
<groupId>org.springframework</groupId> |
|||
<artifactId>spring-context-support</artifactId> |
|||
<version>6.1.21</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> |
|||
<dependency> |
|||
<groupId>ch.qos.logback</groupId> |
|||
<artifactId>logback-classic</artifactId> |
|||
<version>1.5.18</version> |
|||
<scope>compile</scope> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>ch.qos.logback</groupId> |
|||
<artifactId>logback-core</artifactId> |
|||
<version>1.5.18</version> |
|||
<scope>compile</scope> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>com.google.guava</groupId> |
|||
<artifactId>guava</artifactId> |
|||
<version>33.4.8-jre</version> |
|||
</dependency> |
|||
|
|||
</dependencies> |
|||
|
|||
<build> |
|||
<finalName>data-center-receiver</finalName> |
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-maven-plugin</artifactId> |
|||
</plugin> |
|||
<!-- https://mvnrepository.com/artifact/pl.project13.maven/git-commit-id-plugin --> |
|||
<plugin> |
|||
<groupId>pl.project13.maven</groupId> |
|||
<artifactId>git-commit-id-plugin</artifactId> |
|||
<version>4.9.10</version> |
|||
<executions> |
|||
<execution> |
|||
<goals> |
|||
<goal>revision</goal> |
|||
</goals> |
|||
</execution> |
|||
</executions> |
|||
<configuration> |
|||
<verbose>true</verbose> |
|||
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat> |
|||
<generateGitPropertiesFile>true</generateGitPropertiesFile> |
|||
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename> |
|||
</configuration> |
|||
</plugin> |
|||
|
|||
<!--<!–正式环境–>--> |
|||
<!-- <plugin>--> |
|||
<!-- <groupId>io.fabric8</groupId>--> |
|||
<!-- <artifactId>docker-maven-plugin</artifactId>--> |
|||
<!-- <version>0.38.1</version>--> |
|||
<!-- <configuration>--> |
|||
<!-- <authConfig>--> |
|||
<!-- <username>AKIAVRXFMB43XVQ3GXAL</username>--> |
|||
<!-- <password>G0FaGcizm8FlgLxZsL+8xBwfPSzQF71294nrtE2y</password>--> |
|||
<!-- </authConfig>--> |
|||
<!-- <images>--> |
|||
<!-- <image>--> |
|||
<!-- <name>${aws.ecr.registry}/${aws.ecr.repository}:latest</name>--> |
|||
<!-- <registry>${aws.ecr.registry}</registry>--> |
|||
<!-- <build>--> |
|||
<!-- <dockerFile>${project.basedir}/Dockerfile</dockerFile>--> |
|||
<!-- </build>--> |
|||
<!-- </image>--> |
|||
<!-- </images>--> |
|||
<!-- </configuration>--> |
|||
<!-- </plugin>--> |
|||
|
|||
<!-- 测试环境--> |
|||
<plugin> |
|||
<groupId>io.fabric8</groupId> |
|||
<artifactId>docker-maven-plugin</artifactId> |
|||
<version>0.38.1</version> |
|||
<configuration> |
|||
<authConfig> |
|||
<username>AKIA5OFH5OOZPCXZIRUQ</username> |
|||
<password>TMIN27+OxamT1FmBQSVKfUIWpOVldhxQx2Stxwix</password> |
|||
</authConfig> |
|||
<images> |
|||
<image> |
|||
<name>${aws.ecr.registryTest}/${aws.ecr.repository}:latest</name> |
|||
<registry>${aws.ecr.registry}</registry> |
|||
<build> |
|||
<dockerFile>${project.basedir}/Dockerfile</dockerFile> |
|||
</build> |
|||
</image> |
|||
</images> |
|||
</configuration> |
|||
</plugin> |
|||
|
|||
</plugins> |
|||
|
|||
<resources> |
|||
<resource> |
|||
<directory>src/main/java</directory> |
|||
<includes> |
|||
<include>**/*.xml</include> |
|||
</includes> |
|||
</resource> |
|||
|
|||
<resource> |
|||
<directory>src/main/resources</directory> |
|||
<includes> |
|||
<include>**/*</include> |
|||
</includes> |
|||
</resource> |
|||
</resources> |
|||
</build> |
|||
|
|||
|
|||
</project> |
|||
@ -0,0 +1,15 @@ |
|||
# 二期说明 |
|||
|
|||
## 激活或者冷冻数据来源配置表 |
|||
aws lamdba 通过脚本 |
|||
调用receiver的接口 |
|||
` |
|||
/notification/receive |
|||
` |
|||
传入参数state,和List<Long> 类型的id,用于决定哪些数据来源的数据源激活还是冷冻; |
|||
|
|||
## 数据来源配置表生效 |
|||
|
|||
接上,会根据配置来实现对应数据源是MQTT接入还是RESTFUL方式接收数据。 |
|||
|
|||
|
|||
@ -0,0 +1,3 @@ |
|||
git pull |
|||
mvn clean |
|||
mvn package -DskipTests=true docker:build |
|||
@ -0,0 +1,15 @@ |
|||
FROM openjdk:8-jre |
|||
WORKDIR /app |
|||
COPY ../../../target/data-center-receiver.jar app.jar |
|||
EXPOSE 8200 |
|||
|
|||
# 使用UseCGroupMemoryLimitForHeap |
|||
|
|||
ENV JAVA_OPTS="-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log" |
|||
|
|||
# 使用shell方式的ENTRYPOINT来确保环境变量被展开 |
|||
ENTRYPOINT java $JAVA_OPTS -jar app.jar -Djavax.net.debug=ssl --spring-profiles=$env |
|||
|
|||
|
|||
|
|||
|
|||
@ -0,0 +1,17 @@ |
|||
version: '3.8' |
|||
|
|||
services: |
|||
app: |
|||
build: . |
|||
|
|||
ports: |
|||
- "8200:8200" |
|||
environment: |
|||
JAVA_OPTS: "-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log" |
|||
AGENT_PATH: "-agentpath:/app/liberror-detector-agent.so=packageName=org.eclipse.paho.client.mqttv3,=filePath=./gclogs/errorlog.log" # Replace this with your actual agent options if necessary |
|||
env: "dev" # Replace this with your actual spring profile if necessary |
|||
volumes: |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/data-center-receiver.jar:/app/app.jar |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/liberror-detector-agent.so:/app/liberror-detector-agent.so |
|||
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/app/gc.log:/app/gc.log # Make sure this path is correct for your gc logs |
|||
entrypoint: java $AGENT_PATH $JAVA_OPTS -jar /app/app.jar -Djavax.net.debug=ssl --spring-profiles=$env |
|||
@ -0,0 +1,37 @@ |
|||
package com.techsor.datacenter.receiver; |
|||
|
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.slf4j.bridge.SLF4JBridgeHandler; |
|||
import org.springframework.boot.SpringApplication; |
|||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; |
|||
import org.springframework.integration.annotation.IntegrationComponentScan; |
|||
import org.springframework.integration.config.EnableIntegration; |
|||
import org.springframework.scheduling.annotation.EnableScheduling; |
|||
|
|||
import jakarta.annotation.PostConstruct; |
|||
|
|||
@EnableScheduling |
|||
@IntegrationComponentScan |
|||
@EnableIntegration |
|||
@SpringBootApplication(scanBasePackages = {"com.techsor.*"},exclude = { HibernateJpaAutoConfiguration.class}) |
|||
public class TechsorDataCenterReceiverApplication { |
|||
private static final Logger logger = LoggerFactory.getLogger(TechsorDataCenterReceiverApplication.class); |
|||
|
|||
public static void main(String[] args) { |
|||
logger.info("application started success!!"); |
|||
SpringApplication.run(TechsorDataCenterReceiverApplication.class, args); |
|||
logger.info("application started success!!"); |
|||
} |
|||
@PostConstruct |
|||
public void init() { |
|||
// Remove existing handlers attached to the j.u.l root logger
|
|||
SLF4JBridgeHandler.removeHandlersForRootLogger(); |
|||
|
|||
// Bridge/join j.u.l. to SLF4J
|
|||
SLF4JBridgeHandler.install(); |
|||
} |
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,60 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
|
|||
import com.techsor.datacenter.receiver.config.DeltaClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import com.techsor.datacenter.receiver.utils.SslUtil; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
import org.eclipse.paho.client.mqttv3.MqttClient; |
|||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
|||
import org.eclipse.paho.client.mqttv3.MqttException; |
|||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.InitializingBean; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.concurrent.ScheduledExecutorService; |
|||
|
|||
@Component("deltaClientMQTT") |
|||
public class DeltaClientMQTTS { |
|||
private static final Logger logger = LoggerFactory.getLogger(DeltaClientMQTTS.class); |
|||
// public String TOPIC = "Publish_Topic";
|
|||
//// public String HOST = "ssl://8.209.255.206:8883";
|
|||
// public String HOST = "ssl://127.0.0.1:8883";
|
|||
public String randomKey; //a random
|
|||
|
|||
@Resource(name = "client") |
|||
private MqttClient client; |
|||
@Resource |
|||
private MqttConnectOptions options; |
|||
|
|||
@Autowired |
|||
private DeltaClientConfig deltaClientConfig; |
|||
|
|||
@Resource |
|||
private DeltaPushCallback deltaPushCallback; |
|||
public void reconnect(MqttClient mqttClient) throws MqttException { |
|||
mqttClient.reconnect(); |
|||
} |
|||
|
|||
|
|||
|
|||
public void start() throws Exception { |
|||
|
|||
|
|||
client.setCallback(deltaPushCallback); |
|||
|
|||
client.connect(options); |
|||
//subscribe
|
|||
int[] Qos = {1}; |
|||
String[] topic1 = {this |
|||
.deltaClientConfig.getTOPIC()}; |
|||
client.subscribe(topic1, Qos); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,120 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.config.DataCenterEnvConfig; |
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.constants.UrlConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryService; |
|||
|
|||
import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil; |
|||
import com.techsor.datacenter.receiver.utils.SpringUtils; |
|||
import lombok.SneakyThrows; |
|||
import org.eclipse.paho.client.mqttv3.*; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.InitializingBean; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
/** |
|||
* 发布消息的回调类 |
|||
* |
|||
* 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。 |
|||
* 每个客户机标识都需要一个回调实例。在此示例中,构造函数传递客户机标识以另存为实例数据。 |
|||
* 在回调中,将它用来标识已经启动了该回调的哪个实例。 |
|||
* 必须在回调类中实现三个方法: |
|||
* |
|||
* public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。 |
|||
* |
|||
* public void connectionLost(Throwable cause)在断开连接时调用。 |
|||
* |
|||
* public void deliveryComplete(MqttDeliveryToken token)) |
|||
* 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。 |
|||
* 由 MqttClient.connect 激活此回调。 |
|||
* |
|||
*/ |
|||
@Component |
|||
public class DeltaPushCallback implements MqttCallback, MqttCallbackExtended{ |
|||
|
|||
|
|||
@Resource |
|||
private MqttPublisherEntity mqttPublisherEntity; |
|||
|
|||
@Resource |
|||
private MqttClient client; |
|||
|
|||
@Resource |
|||
private MqttHistoryService mqttHistoryService; |
|||
@Resource |
|||
private DefaultHttpRequestUtil defaultHttpRequestUtil; |
|||
@Resource |
|||
private DataCenterEnvConfig dataCenterEnvConfig; |
|||
|
|||
@Resource |
|||
MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
private static final Logger logger = LoggerFactory.getLogger(DeltaPushCallback.class); |
|||
|
|||
|
|||
@SneakyThrows |
|||
public void connectionLost(Throwable cause) { |
|||
// 连接丢失后,一般在这里面进行重连,由于设置了自动重连,断开连接后会自动重连,然后进入connectComplete中
|
|||
logger.error("Connection Lost,Trying to reconnect... ClientId: "+this.client.getClientId()); |
|||
Boolean isConnected = client.isConnected(); |
|||
logger.warn("client connect status:"+isConnected); |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 连接成功会进入到这里 |
|||
* @param reconnect |
|||
* @param serverURI |
|||
*/ |
|||
@SneakyThrows |
|||
@Override |
|||
public void connectComplete(boolean reconnect, String serverURI) { |
|||
// 可以做订阅主题
|
|||
logger.info("Connect success"); |
|||
Boolean isConnected = client.isConnected(); |
|||
logger.warn("client connect status:"+isConnected); |
|||
if (isConnected){ |
|||
logger.info("Subscribe to :"+mqttPublisherEntity.getTopic()); |
|||
client.subscribe(mqttPublisherEntity.getTopic(),0); |
|||
} |
|||
} |
|||
|
|||
public void deliveryComplete(IMqttDeliveryToken token) { |
|||
logger.debug("deliveryComplete---------" + token.isComplete()); |
|||
} |
|||
|
|||
public void messageArrived(String topic, MqttMessage message) throws Exception { |
|||
BaseTransDataEntity mqttHistoryEntity = new BaseTransDataEntity(); |
|||
mqttHistoryEntity.setContent(new String(message.getPayload())); |
|||
mqttHistoryEntity.setTs(System.currentTimeMillis()+""); |
|||
mqttHistoryEntity.setCompany(CompanyConstants.DELTA); |
|||
mqttHistoryService.insertHistory(mqttHistoryEntity); |
|||
|
|||
this.mqttHistoryDynamoDBService.save(mqttHistoryEntity); |
|||
|
|||
try { |
|||
forwardMessage(mqttHistoryEntity); |
|||
}catch (Exception e){ |
|||
logger.warn("Not correct data"); |
|||
} |
|||
} |
|||
|
|||
//转发收到的数据到 数据转发平台
|
|||
private void forwardMessage(BaseTransDataEntity mqttHistoryEntity){ |
|||
//只转发终端数据
|
|||
Gson gson = new Gson(); |
|||
String jsonParams = gson.toJson(mqttHistoryEntity); |
|||
logger.info("Send Data To: {},{}", this.dataCenterEnvConfig.getReceiveUrl(),jsonParams); |
|||
this.defaultHttpRequestUtil.postJson(this.dataCenterEnvConfig.getReceiveUrl(),jsonParams); |
|||
|
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import org.eclipse.paho.client.mqttv3.MqttClient; |
|||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
|||
import org.eclipse.paho.client.mqttv3.MqttException; |
|||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
|
|||
public class ITAClientMQTT { |
|||
private static final Logger logger = LoggerFactory.getLogger(ITAClientMQTT.class); |
|||
public String TOPIC = "#"; |
|||
public String HOST = ""; |
|||
|
|||
public String randomKey; //a random
|
|||
private String clientID; |
|||
private MqttClient client; |
|||
private MqttConnectOptions options; |
|||
private String userName = ""; |
|||
private String passWord = ""; |
|||
|
|||
private MqttPublisherEntity publisherEntity; |
|||
|
|||
|
|||
|
|||
public ITAClientMQTT(MqttPublisherEntity publisherEntity, String randomKey){ |
|||
this.publisherEntity = publisherEntity; |
|||
this.HOST = publisherEntity.getHost(); |
|||
this.userName = publisherEntity.getUsername(); |
|||
this.passWord = publisherEntity.getPassword(); |
|||
this.TOPIC = publisherEntity.getTopic(); |
|||
this.randomKey = randomKey; |
|||
this.clientID = this.userName+":"+this.passWord+randomKey; |
|||
|
|||
} |
|||
|
|||
public void reconnect(MqttClient mqttClient) throws MqttException { |
|||
mqttClient.reconnect(); |
|||
} |
|||
|
|||
public void start() throws MqttException { |
|||
logger.info("重新连接成功,Connect to MQTT: {} Client ID: {}",this.HOST,clientID); |
|||
logger.info("Username: {}",userName); |
|||
client = new MqttClient(HOST, clientID, new MemoryPersistence()); |
|||
options = new MqttConnectOptions(); |
|||
options.setCleanSession(false); |
|||
options.setUserName(userName); |
|||
options.setPassword(passWord.toCharArray()); |
|||
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1); |
|||
// Set Timeout
|
|||
options.setConnectionTimeout(20); |
|||
// Set mqtt-heartbeat interval
|
|||
options.setKeepAliveInterval(10); |
|||
options.setAutomaticReconnect(true); |
|||
client.setCallback(new ITAPushCallback(publisherEntity,randomKey,client)); |
|||
|
|||
client.connect(options); |
|||
//subscribe
|
|||
int[] Qos = {0}; |
|||
String[] topic1 = {TOPIC}; |
|||
client.subscribe(topic1, Qos); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,121 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import cn.hutool.json.JSONUtil; |
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.config.DataCenterEnvConfig; |
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.constants.UrlConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryService; |
|||
import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil; |
|||
import com.techsor.datacenter.receiver.utils.SpringUtils; |
|||
import lombok.SneakyThrows; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.eclipse.paho.client.mqttv3.*; |
|||
|
|||
/** |
|||
* 发布消息的回调类 |
|||
* <p> |
|||
* 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。 |
|||
* 每个客户机标识都需要一个回调实例。在此示例中,构造函数传递客户机标识以另存为实例数据。 |
|||
* 在回调中,将它用来标识已经启动了该回调的哪个实例。 |
|||
* 必须在回调类中实现三个方法: |
|||
* <p> |
|||
* public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。 |
|||
* <p> |
|||
* public void connectionLost(Throwable cause)在断开连接时调用。 |
|||
* <p> |
|||
* public void deliveryComplete(MqttDeliveryToken token)) |
|||
* 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。 |
|||
* 由 MqttClient.connect 激活此回调。 |
|||
*/ |
|||
@Slf4j |
|||
public class ITAPushCallback implements MqttCallback, MqttCallbackExtended { |
|||
private DataCenterEnvConfig dataCenterEnvConfig; |
|||
private String randomKey; |
|||
private MqttPublisherEntity mqttPublisherEntity; |
|||
private MqttClient client; |
|||
|
|||
private MqttHistoryService mqttHistoryService; |
|||
|
|||
private DefaultHttpRequestUtil defaultHttpRequestUtil; |
|||
|
|||
|
|||
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
|
|||
public ITAPushCallback(MqttPublisherEntity mqttPublisherEntity, String randomKey, MqttClient client) { |
|||
this.randomKey = randomKey; |
|||
this.mqttPublisherEntity = mqttPublisherEntity; |
|||
this.client = client; |
|||
this.mqttHistoryService = SpringUtils.getBean("mqttHistoryService", MqttHistoryService.class); |
|||
this.defaultHttpRequestUtil = SpringUtils.getBean("defaultHttpRequestUtil", DefaultHttpRequestUtil.class); |
|||
this.dataCenterEnvConfig = SpringUtils.getBean("dataCenterEnvConfig", DataCenterEnvConfig.class); |
|||
this.mqttHistoryDynamoDBService=SpringUtils.getBean("mqttHistoryDynamoDBService",MqttHistoryDynamoDBService.class); |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public void connectionLost(Throwable cause) { |
|||
// 连接丢失后,一般在这里面进行重连,由于设置了自动重连,断开连接后会自动重连,然后进入connectComplete中
|
|||
log.error("Connection Lost,Trying to reconnect... ClientId: {}", this.client.getClientId()); |
|||
Boolean isConnected = client.isConnected(); |
|||
log.warn("client connect status: {}", isConnected); |
|||
} |
|||
|
|||
/** |
|||
* 连接成功会进入到这里 |
|||
* |
|||
* @param reconnect |
|||
* @param serverURI |
|||
*/ |
|||
@SneakyThrows |
|||
@Override |
|||
public void connectComplete(boolean reconnect, String serverURI) { |
|||
// 可以做订阅主题
|
|||
log.info("Connect success"); |
|||
Boolean isConnected = client.isConnected(); |
|||
log.warn("client connect status: {}", isConnected); |
|||
if (isConnected) { |
|||
log.info("Subscribe to :{}", mqttPublisherEntity.getTopic()); |
|||
client.subscribe(mqttPublisherEntity.getTopic(), 0); |
|||
} |
|||
} |
|||
|
|||
public void deliveryComplete(IMqttDeliveryToken token) { |
|||
log.info("deliveryComplete--------- {}", token.isComplete()); |
|||
} |
|||
|
|||
public void messageArrived(String topic, MqttMessage message) throws Exception { |
|||
log.info("message arrived {}", JSONUtil.toJsonStr(message)); |
|||
BaseTransDataEntity mqttHistoryEntity = new BaseTransDataEntity(); |
|||
mqttHistoryEntity.setContent(new String(message.getPayload())); |
|||
mqttHistoryEntity.setTs(System.currentTimeMillis() + ""); |
|||
mqttHistoryEntity.setCompany(CompanyConstants.ZIFISENSE); |
|||
|
|||
mqttHistoryService.insertHistory(mqttHistoryEntity); |
|||
//保存到dynamodb中
|
|||
this.mqttHistoryDynamoDBService.save(mqttHistoryEntity); |
|||
try { |
|||
forwardMessage(mqttHistoryEntity); |
|||
} catch (Exception e) { |
|||
log.error("Not correct data:{}", e.getMessage(), e); |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
//转发收到的数据到 数据转发平台
|
|||
private void forwardMessage(BaseTransDataEntity mqttHistoryEntity) { |
|||
//只转发终端数据
|
|||
if (mqttHistoryEntity.getContent().contains("msUid")) { |
|||
Gson gson = new Gson(); |
|||
String jsonParams = gson.toJson(mqttHistoryEntity); |
|||
log.info("Send Data To: {}", UrlConstants.RECEIVER_URL); |
|||
log.info("Send Data : {}", jsonParams); |
|||
this.defaultHttpRequestUtil.postJson(this.dataCenterEnvConfig.getReceiveUrl(), jsonParams); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.JsonResponse; |
|||
import com.techsor.datacenter.receiver.entity.metcom.MetcomEntity; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.RestfulService; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@RestController |
|||
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT}) |
|||
public class MetComClient { |
|||
private static final Logger logger = LoggerFactory.getLogger(MetComClient.class); |
|||
|
|||
@Resource |
|||
private RestfulService historyDAO; |
|||
|
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
@Resource |
|||
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
|
|||
//MetCom 3D室内定位数据转发接口
|
|||
@PutMapping(value = "api/v2/to_dbm/metcom/user/location/{userId}") |
|||
public JsonResponse nittan(@PathVariable("userId") String userId, @RequestBody String rawJson) throws Exception { |
|||
//合并uuid及其他参数
|
|||
MetcomEntity metcomEntity = new Gson().fromJson(rawJson,MetcomEntity.class); |
|||
metcomEntity.setUuid(userId); |
|||
rawJson = new Gson().toJson(metcomEntity); |
|||
//记录数据转发历史
|
|||
historyDAO.insertHistory(rawJson, CompanyConstants.METCOM); |
|||
|
|||
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity(); |
|||
baseTransDataEntity.setCompany(CompanyConstants.METCOM); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis())); |
|||
this.mqttHistoryDynamoDBService.save(baseTransDataEntity); |
|||
//转发数据
|
|||
this.dataTransService.transferData(userId,CompanyConstants.METCOM,rawJson); |
|||
|
|||
return JsonResponse.buildSuccess(""); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.JsonResponse; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.RestfulService; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@RestController |
|||
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST}) |
|||
public class NBIClient { |
|||
|
|||
@Resource |
|||
private RestfulService oviPhoneDAO; |
|||
|
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
|
|||
@Resource |
|||
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
//nbi数据转发测试接口,直接转发数据
|
|||
@RequestMapping(value = "api/v1/nbi/raw", method = RequestMethod.POST) |
|||
public JsonResponse ReceiveRawData(@RequestBody String rawJson) { |
|||
oviPhoneDAO.insertHistory(rawJson,CompanyConstants.NBI); |
|||
|
|||
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity(); |
|||
baseTransDataEntity.setCompany(CompanyConstants.NBI); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis())); |
|||
this.mqttHistoryDynamoDBService.save(baseTransDataEntity); |
|||
|
|||
this.dataTransService.transferData("",CompanyConstants.NBI,rawJson); |
|||
return JsonResponse.buildSuccess(rawJson); |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.JsonResponse; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.RestfulService; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@RestController |
|||
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST}) |
|||
public class NittanClient { |
|||
|
|||
@Resource |
|||
private RestfulService historyDAO; |
|||
|
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
|
|||
@Resource |
|||
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
|
|||
//nittan数据转发接口
|
|||
@RequestMapping(value = "api/v1/to_dbm/nittan", method = RequestMethod.POST) |
|||
public JsonResponse nittan(@RequestBody String rawJson) throws Exception { |
|||
//记录数据转发历史
|
|||
historyDAO.insertHistory(rawJson, CompanyConstants.NITTAN); |
|||
|
|||
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity(); |
|||
baseTransDataEntity.setCompany(CompanyConstants.NITTAN); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis())); |
|||
this.mqttHistoryDynamoDBService.save(baseTransDataEntity); |
|||
|
|||
this.dataTransService.transferData("",CompanyConstants.NITTAN,rawJson); |
|||
return JsonResponse.buildSuccess(""); |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.JsonResponse; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.RestfulService; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@RestController |
|||
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST}) |
|||
public class OCRClient { |
|||
private static final Logger logger = LoggerFactory.getLogger(OCRClient.class); |
|||
|
|||
@Resource |
|||
private RestfulService historyDAO; |
|||
|
|||
@Resource |
|||
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
|
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
/** |
|||
* OCR 数据接口 |
|||
* @param rawJson |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
@RequestMapping(value = "api/v1/to_dbm/ocr", method = RequestMethod.POST) |
|||
public JsonResponse nittan(@RequestBody String rawJson) throws Exception { |
|||
//记录数据转发历史
|
|||
historyDAO.insertHistory(rawJson, CompanyConstants.OCR); |
|||
|
|||
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity(); |
|||
baseTransDataEntity.setCompany(CompanyConstants.OCR); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis())); |
|||
this.mqttHistoryDynamoDBService.save(baseTransDataEntity); |
|||
|
|||
this.dataTransService.transferData("",CompanyConstants.OCR,rawJson); |
|||
|
|||
return JsonResponse.buildSuccess(""); |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
package com.techsor.datacenter.receiver.clients; |
|||
|
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.JsonResponse; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; |
|||
import com.techsor.datacenter.receiver.service.RestfulService; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@RestController |
|||
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST}) |
|||
public class OVIPhoneClient { |
|||
|
|||
@Resource |
|||
private RestfulService oviPhoneDAO; |
|||
|
|||
@Resource |
|||
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; |
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
//nittan数据转发测试接口,直接转发数据
|
|||
@RequestMapping(value = "api/v1/oviphone/raw", method = RequestMethod.POST) |
|||
public JsonResponse ReceiveRawData(@RequestBody String rawJson) { |
|||
oviPhoneDAO.insertHistory(rawJson,CompanyConstants.OVIPHONE); |
|||
|
|||
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity(); |
|||
baseTransDataEntity.setCompany(CompanyConstants.OVIPHONE); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis())); |
|||
this.mqttHistoryDynamoDBService.save(baseTransDataEntity); |
|||
|
|||
this.dataTransService.transferData("",CompanyConstants.OVIPHONE,rawJson); |
|||
return JsonResponse.buildSuccess(rawJson); |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
|
|||
import java.io.*; |
|||
|
|||
import jakarta.servlet.ReadListener; |
|||
import jakarta.servlet.ServletInputStream; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletRequestWrapper; |
|||
|
|||
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper { |
|||
|
|||
byte[] cachedBody; |
|||
|
|||
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException { |
|||
super(request); |
|||
InputStream requestInputStream = request.getInputStream(); |
|||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
|||
byte[] buffer = new byte[1024]; |
|||
int len; |
|||
while ((len = requestInputStream.read(buffer)) != -1) { |
|||
byteArrayOutputStream.write(buffer, 0, len); |
|||
} |
|||
this.cachedBody = byteArrayOutputStream.toByteArray(); |
|||
} |
|||
|
|||
@Override |
|||
public ServletInputStream getInputStream() throws IOException { |
|||
return new CachedBodyServletInputStream(this.cachedBody); |
|||
} |
|||
|
|||
private static class CachedBodyServletInputStream extends ServletInputStream { |
|||
|
|||
private ByteArrayInputStream byteArrayInputStream; |
|||
|
|||
public CachedBodyServletInputStream(byte[] data) { |
|||
this.byteArrayInputStream = new ByteArrayInputStream(data); |
|||
} |
|||
|
|||
@Override |
|||
public boolean isFinished() { |
|||
return byteArrayInputStream.available() == 0; |
|||
} |
|||
|
|||
@Override |
|||
public boolean isReady() { |
|||
return true; |
|||
} |
|||
|
|||
@Override |
|||
public void setReadListener(ReadListener readListener) { |
|||
throw new UnsupportedOperationException(); |
|||
} |
|||
|
|||
@Override |
|||
public int read() throws IOException { |
|||
return byteArrayInputStream.read(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
|
|||
import lombok.Data; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
/** |
|||
* 系统配置 |
|||
* */ |
|||
|
|||
@Configuration |
|||
public class DataCenterEnvConfig { |
|||
|
|||
|
|||
private String receiveUrl; |
|||
|
|||
@Value("${data.center.receive.address}") |
|||
private String apiAddress; |
|||
|
|||
@Value("${data.center.receive.api:#{'/v1/main_receiver'}}") |
|||
private String apiUrl; |
|||
|
|||
@Value("${data.center.process.api:#{'/v1/generic/process'}}") |
|||
private String processApiUrl; |
|||
|
|||
@Value("${data.center.ioserver_process.api:#{'/v1/generic/ioserver_process'}}") |
|||
private String processIoserverUrl; |
|||
|
|||
@Value("${data.center.ioserver_process.api:#{'/v1/generic/st150_process'}}") |
|||
private String processGW150Url; |
|||
|
|||
@Value("${data.center.zaiot_process.api:#{'/v1/generic/zaiot_process'}}") |
|||
private String zaiotProcessApiUrl; |
|||
|
|||
|
|||
public String getReceiveUrl() { |
|||
return apiAddress+apiUrl; |
|||
} |
|||
|
|||
public void setReceiveUrl(String receiveUrl) { |
|||
this.receiveUrl = receiveUrl; |
|||
} |
|||
|
|||
public String getApiAddress() { |
|||
return apiAddress; |
|||
} |
|||
|
|||
public void setApiAddress(String apiAddress) { |
|||
this.apiAddress = apiAddress; |
|||
} |
|||
|
|||
public String getApiUrl() { |
|||
return apiUrl; |
|||
} |
|||
|
|||
public void setApiUrl(String apiUrl) { |
|||
this.apiUrl = apiUrl; |
|||
} |
|||
|
|||
public String getProcessApiUrl() { |
|||
return apiAddress+processApiUrl; |
|||
} |
|||
|
|||
public void setProcessApiUrl(String processApiUrl) { |
|||
this.processApiUrl = processApiUrl; |
|||
} |
|||
|
|||
public String getProcessIoserverUrl() { |
|||
return apiAddress+processIoserverUrl; |
|||
} |
|||
|
|||
public void setProcessIoserverUrl(String processIoserverUrl) { |
|||
this.processIoserverUrl = processIoserverUrl; |
|||
} |
|||
|
|||
public String getZaiotProcessApiUrl() { |
|||
return apiAddress+zaiotProcessApiUrl; |
|||
} |
|||
|
|||
public void setZaiotProcessApiUrl(String zaiotProcessApiUrl) { |
|||
this.zaiotProcessApiUrl = zaiotProcessApiUrl; |
|||
} |
|||
|
|||
public String getProcessGW150Url() { |
|||
return processGW150Url; |
|||
} |
|||
|
|||
public void setProcessGW150Url(String processGW150Url) { |
|||
this.processGW150Url = processGW150Url; |
|||
} |
|||
|
|||
public String getGW150ProcessUrl() { |
|||
return apiAddress+this.processGW150Url; |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import com.techsor.datacenter.receiver.utils.SslUtil; |
|||
import lombok.Data; |
|||
import org.eclipse.paho.client.mqttv3.MqttClient; |
|||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
|||
import org.eclipse.paho.client.mqttv3.MqttException; |
|||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
import java.util.Random; |
|||
|
|||
@Configuration |
|||
@Data |
|||
public class DeltaClientConfig { |
|||
private static final Logger logger = LoggerFactory.getLogger(DeltaClientConfig.class); |
|||
@Value("${delta.topic:Publish_Topic}") |
|||
private String TOPIC; |
|||
// public String HOST = "ssl://8.209.255.206:8883";
|
|||
@Value("${delta.host:ssl://127.0.0.1:8883}") |
|||
private String HOST = "ssl://127.0.0.1:8883"; |
|||
@Value("${delta.userName:techsor}") |
|||
private String userName = "techsor"; |
|||
@Value("${delta.usepassWordrName:techsorAsd123456}") |
|||
private String passWord = "techsorAsd123456"; |
|||
@Value("${delta.enableSSL:false}") |
|||
private boolean enableSSL; |
|||
|
|||
@Bean |
|||
public MqttPublisherEntity deltaMqttPublisherEntity(){ |
|||
MqttPublisherEntity publisherEntity = new MqttPublisherEntity(); |
|||
publisherEntity.setHost(this.HOST); |
|||
publisherEntity.setUsername(this.userName); |
|||
publisherEntity.setPassword(this.passWord); |
|||
publisherEntity.setTopic(this.TOPIC); |
|||
return publisherEntity; |
|||
} |
|||
@Bean |
|||
public MqttConnectOptions options() throws Exception { |
|||
|
|||
MqttConnectOptions options = new MqttConnectOptions(); |
|||
options.setCleanSession(false); |
|||
options.setUserName(userName); |
|||
options.setPassword(passWord.toCharArray()); |
|||
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1); |
|||
options.setHttpsHostnameVerificationEnabled(false); |
|||
//Set ssl
|
|||
if(enableSSL){ |
|||
options.setSocketFactory(SslUtil.getSocketFactory("/ssl/ca.pem", "/ssl/client.pem", "/ssl/client.key", "")); |
|||
} |
|||
// Set Timeout
|
|||
options.setConnectionTimeout(0); |
|||
// Set mqtt-heartbeat interval
|
|||
options.setKeepAliveInterval(60); |
|||
options.setAutomaticReconnect(true); |
|||
return options; |
|||
} |
|||
|
|||
@Bean |
|||
public String clientID(){ |
|||
String clientID = this.userName+":"+this.passWord+getRandoms(); |
|||
return clientID; |
|||
} |
|||
@Bean |
|||
public MqttClient client(String clientID) throws MqttException { |
|||
logger.info("Connect to MQTTs:"+this.HOST+" Client ID:"+clientID); |
|||
logger.info("Username:"+userName); |
|||
MqttClient client = new MqttClient(HOST, clientID, new MemoryPersistence()); |
|||
return client; |
|||
|
|||
} |
|||
|
|||
|
|||
public int getRandoms(){ |
|||
// 创建一个Random对象
|
|||
Random random = new Random(); |
|||
|
|||
// 生成一个范围在100到999之间的随机数(包括100,但不包括1000)
|
|||
int randomNumber = random.nextInt(900) + 100; |
|||
return randomNumber; |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
//package com.techsor.datacenter.receiver.config;
|
|||
//
|
|||
//
|
|||
//import com.amazonaws.auth.AWSCredentials;
|
|||
//import com.amazonaws.auth.AWSCredentialsProvider;
|
|||
//import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
|||
//import com.amazonaws.auth.BasicAWSCredentials;
|
|||
//import com.amazonaws.regions.Regions;
|
|||
//import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
|
|||
//import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
|
|||
//import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
|
|||
//import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
|
|||
//import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
|
|||
//import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
|
|||
//import org.socialsignin.spring.data.dynamodb.repository.config.DynamoDBMapperConfigFactory;
|
|||
//import org.springframework.beans.factory.annotation.Value;
|
|||
//import org.springframework.context.annotation.Bean;
|
|||
//import org.springframework.context.annotation.Configuration;
|
|||
//
|
|||
////@Configuration
|
|||
////public class DynamoDBConfig {
|
|||
////
|
|||
//// @Value("${amazon.aws.accesskey}")
|
|||
//// private String amazonAWSAccessKey;
|
|||
////
|
|||
//// @Value("${amazon.aws.secretkey}")
|
|||
//// private String amazonAWSSecretKey;
|
|||
////
|
|||
//// public AWSCredentialsProvider amazonAWSCredentialsProvider() {
|
|||
//// return new AWSStaticCredentialsProvider(amazonAWSCredentials());
|
|||
//// }
|
|||
////
|
|||
//// @Bean
|
|||
//// public AWSCredentials amazonAWSCredentials() {
|
|||
//// return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
|
|||
//// }
|
|||
//// @Value("${amazon.dynamodb.tableName:mqtt_history}")
|
|||
//// private String dynamoDBTableName ;
|
|||
////
|
|||
//// @Bean
|
|||
//// public DynamoDBMapperConfig.TableNameOverride tableNameOverrider() {
|
|||
//// return DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(this.dynamoDBTableName);
|
|||
//// }
|
|||
////
|
|||
//// @Bean
|
|||
//// public DynamoDBMapperConfig dynamoCustomDBMapperConfig(DynamoDBMapperConfig.TableNameOverride tableNameOverrider) {
|
|||
//// DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
|
|||
//// builder.withTableNameOverride(tableNameOverrider);
|
|||
//// return builder.build();
|
|||
////
|
|||
//// }
|
|||
////
|
|||
//// @Bean
|
|||
//// public DynamoDBMapper dynamoCustomDBMapper(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig dynamoCustomDBMapperConfig) {
|
|||
//// return new DynamoDBMapper(amazonDynamoDB, dynamoCustomDBMapperConfig);
|
|||
//// }
|
|||
////
|
|||
//// @Bean
|
|||
//// public AmazonDynamoDB amazonDynamoDB() {
|
|||
//// return AmazonDynamoDBClientBuilder.standard().withCredentials(amazonAWSCredentialsProvider())
|
|||
//// .withRegion(Regions.AP_NORTHEAST_1).build();
|
|||
//// }
|
|||
////
|
|||
//// @Bean
|
|||
//// public DynamoDBMappingContext dynamoDBMappingContext() {
|
|||
//// return new DynamoDBMappingContext();
|
|||
//// }
|
|||
////
|
|||
//// @Bean
|
|||
//// public DynamoDBTemplate dynamoDBTemplate(AmazonDynamoDB amazonDynamoDB, DynamoDBMapper dynamoCustomDBMapper ,DynamoDBMapperConfig dynamoCustomDBMapperConfig) {
|
|||
////
|
|||
//// return new DynamoDBTemplate(amazonDynamoDB, dynamoCustomDBMapper,dynamoCustomDBMapperConfig);
|
|||
//// }
|
|||
//
|
|||
//
|
|||
//}
|
|||
@ -0,0 +1,16 @@ |
|||
//package com.techsor.datacenter.receiver.config;
|
|||
//
|
|||
//import org.springframework.context.annotation.Bean;
|
|||
//import org.springframework.context.annotation.Configuration;
|
|||
//import org.springframework.jdbc.core.JdbcTemplate;
|
|||
//
|
|||
//import javax.sql.DataSource;
|
|||
//
|
|||
//@Configuration
|
|||
//public class JdbcTemplateConfig {
|
|||
//
|
|||
// @Bean
|
|||
// public JdbcTemplate jdbcTemplate(DataSource dataSource){
|
|||
// return new JdbcTemplate(dataSource);
|
|||
// }
|
|||
//}
|
|||
@ -0,0 +1,87 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.jayway.jsonpath.JsonPath; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import com.techsor.datacenter.receiver.service.GlobalStateService; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.filter.GenericFilterBean; |
|||
|
|||
import jakarta.servlet.FilterChain; |
|||
import jakarta.servlet.ServletException; |
|||
import jakarta.servlet.ServletRequest; |
|||
import jakarta.servlet.ServletResponse; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import java.io.BufferedReader; |
|||
import java.io.IOException; |
|||
import java.io.InputStream; |
|||
import java.io.InputStreamReader; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Component |
|||
public class MyFilter extends GenericFilterBean { |
|||
@Autowired |
|||
private GlobalStateService globalStateService; |
|||
|
|||
@Override |
|||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
|||
throws IOException, ServletException { |
|||
|
|||
HttpServletRequest httpServletRequest=(HttpServletRequest)request; |
|||
|
|||
HttpServletResponse httpServletResponse=(HttpServletResponse)response; |
|||
String uri=httpServletRequest.getRequestURI(); |
|||
|
|||
if (this.globalStateService.checkUrlExist(uri)) { |
|||
|
|||
|
|||
StringBuilder stringBuilder = new StringBuilder(); |
|||
// 使用包装器包装原始的 HttpServletRequest
|
|||
CachedBodyHttpServletRequest wrappedRequest = new CachedBodyHttpServletRequest(httpServletRequest); |
|||
// 获取请求体
|
|||
String body = new String(wrappedRequest.cachedBody, StandardCharsets.UTF_8); |
|||
body=StringUtils.replaceAll(body, "\n", ""); |
|||
body=StringUtils.replaceAll(body, "\t", ""); |
|||
body=StringUtils.replaceAll(body, "\\s+", ""); |
|||
DatasourceConfigEntity dataSrcEntity = this.globalStateService.getDatasourceConfig(uri); |
|||
if(StringUtils.isEmpty(dataSrcEntity.getDeviceIdPosition())){ |
|||
httpServletResponse.setStatus(200); |
|||
Map<String,String> errorMap=new HashMap<>(); |
|||
errorMap.put("code","-1"); |
|||
errorMap.put("msg","deviceId position id null"); |
|||
Gson gson=new Gson(); |
|||
httpServletResponse.setContentType("application/json;charset=UTF-8"); |
|||
httpServletResponse.getWriter().write(gson.toJson(errorMap)); |
|||
httpServletResponse.getWriter().flush(); |
|||
return; |
|||
} |
|||
Gson currentGson=new Gson(); |
|||
Map resultMao=currentGson.fromJson(body, Map.class); |
|||
String resultBody=currentGson.toJson(resultMao); |
|||
String deviceId= JsonPath.read(resultBody,dataSrcEntity.getDeviceIdPosition()); |
|||
if(StringUtils.isEmpty(deviceId)){ |
|||
httpServletResponse.setStatus(200); |
|||
Map<String,String> errorMap=new HashMap<>(); |
|||
httpServletResponse.setContentType("application/json;charset=UTF-8"); |
|||
errorMap.put("code","-1"); |
|||
errorMap.put("msg","deviceId is null"); |
|||
Gson gson=new Gson(); |
|||
httpServletResponse.getWriter().write(gson.toJson(errorMap)); |
|||
httpServletResponse.getWriter().flush(); |
|||
return; |
|||
} |
|||
String contextPath=httpServletRequest.getContextPath(); |
|||
wrappedRequest.getRequestDispatcher(contextPath+"/api/generic/process?MyDeviceId="+deviceId).forward(wrappedRequest, response); |
|||
|
|||
}else{ |
|||
chain.doFilter(request, response); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; |
|||
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; |
|||
import com.techsor.datacenter.receiver.listener.RedisNotificationMessageSubscriber; |
|||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
|||
import com.fasterxml.jackson.annotation.JsonAutoDetect; |
|||
import com.fasterxml.jackson.annotation.JsonTypeInfo; |
|||
import com.fasterxml.jackson.annotation.PropertyAccessor; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.data.redis.connection.RedisConnectionFactory; |
|||
import org.springframework.data.redis.connection.RedisPassword; |
|||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration; |
|||
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; |
|||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; |
|||
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.data.redis.listener.PatternTopic; |
|||
import org.springframework.data.redis.listener.RedisMessageListenerContainer; |
|||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; |
|||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; |
|||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; |
|||
import org.springframework.data.redis.serializer.RedisSerializer; |
|||
import org.springframework.data.redis.serializer.StringRedisSerializer; |
|||
import org.springframework.integration.redis.util.RedisLockRegistry; |
|||
|
|||
import java.time.Duration; |
|||
|
|||
@Configuration |
|||
public class RedisConfig { |
|||
@Value("${spring.redis.database}") |
|||
private int database; |
|||
|
|||
@Value("${spring.redis.host}") |
|||
private String host; |
|||
|
|||
@Value("${spring.redis.password}") |
|||
private String password; |
|||
|
|||
@Value("${spring.redis.port}") |
|||
private int port; |
|||
|
|||
@Value("${spring.redis.timeout}") |
|||
private long timeout; |
|||
|
|||
@Value("${spring.redis.lettuce.shutdown-timeout}") |
|||
private long shutDownTimeout; |
|||
|
|||
@Value("${spring.redis.lettuce.pool.max-idle}") |
|||
private int maxIdle; |
|||
|
|||
@Value("${spring.redis.lettuce.pool.min-idle}") |
|||
private int minIdle; |
|||
|
|||
@Value("${spring.redis.lettuce.pool.max-active}") |
|||
private int maxActive; |
|||
|
|||
@Value("${spring.redis.lettuce.pool.max-wait}") |
|||
private long maxWait; |
|||
|
|||
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); |
|||
|
|||
@Bean |
|||
public LettuceConnectionFactory lettuceConnectionFactory() { |
|||
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig(); |
|||
genericObjectPoolConfig.setMaxIdle(maxIdle); |
|||
genericObjectPoolConfig.setMinIdle(minIdle); |
|||
genericObjectPoolConfig.setMaxTotal(maxActive); |
|||
genericObjectPoolConfig.setMaxWaitMillis(maxWait); |
|||
genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(100); |
|||
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); |
|||
redisStandaloneConfiguration.setDatabase(database); |
|||
redisStandaloneConfiguration.setHostName(host); |
|||
redisStandaloneConfiguration.setPort(port); |
|||
redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); |
|||
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder() |
|||
.commandTimeout(Duration.ofMillis(timeout)) |
|||
.shutdownTimeout(Duration.ofMillis(shutDownTimeout)) |
|||
.poolConfig(genericObjectPoolConfig) |
|||
.build(); |
|||
|
|||
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig); |
|||
|
|||
return factory; |
|||
} |
|||
|
|||
@Bean |
|||
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { |
|||
RedisTemplate<String, Object> template = new RedisTemplate<>(); |
|||
template.setConnectionFactory(lettuceConnectionFactory); |
|||
//使用Jackson2JsonRedisSerializer替换默认的JdkSerializationRedisSerializer来序列化和反序列化redis的value值
|
|||
ObjectMapper mapper = new ObjectMapper(); |
|||
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); |
|||
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, |
|||
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); |
|||
jackson2JsonRedisSerializer.setObjectMapper(mapper); |
|||
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); |
|||
//key采用String的序列化方式
|
|||
template.setKeySerializer(stringRedisSerializer); |
|||
// hash的key也采用String的序列化方式
|
|||
template.setHashKeySerializer(stringRedisSerializer); |
|||
// value序列化方式采用jackson
|
|||
template.setValueSerializer(jackson2JsonRedisSerializer); |
|||
// hash的value序列化方式采用jackson
|
|||
template.setHashValueSerializer(jackson2JsonRedisSerializer); |
|||
template.afterPropertiesSet(); |
|||
return template; |
|||
} |
|||
|
|||
@Value("${redis.lock.expire}") |
|||
private Integer lockAttempTimeout ; |
|||
|
|||
@Bean |
|||
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory){ |
|||
return new RedisLockRegistry(redisConnectionFactory, "redis-receiver-lock",lockAttempTimeout); |
|||
} |
|||
|
|||
|
|||
@Bean |
|||
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, |
|||
MessageListenerAdapter listenerAdapter) { |
|||
RedisMessageListenerContainer container = new RedisMessageListenerContainer(); |
|||
container.setConnectionFactory(connectionFactory); |
|||
container.addMessageListener(listenerAdapter, new PatternTopic("notificationReceiver")); |
|||
return container; |
|||
} |
|||
|
|||
@Bean |
|||
MessageListenerAdapter listenerAdapter(RedisNotificationMessageSubscriber subscriber) { |
|||
return new MessageListenerAdapter(subscriber); |
|||
} |
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,65 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
|
|||
import okhttp3.ConnectionPool; |
|||
import okhttp3.OkHttpClient; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.http.client.ClientHttpRequestFactory; |
|||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; |
|||
import org.springframework.web.client.RestTemplate; |
|||
|
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
/*** |
|||
* 使用okhttp connectionFactory |
|||
* **/ |
|||
@Configuration |
|||
public class RestTemplateConfig { |
|||
|
|||
|
|||
@Value("${ok.http.connect-timeout}") |
|||
private Integer connectTimeout; |
|||
|
|||
@Value("${ok.http.read-timeout}") |
|||
private Integer readTimeout; |
|||
|
|||
@Value("${ok.http.write-timeout}") |
|||
private Integer writeTimeout; |
|||
|
|||
@Value("${ok.http.max-idle-connections}") |
|||
private Integer maxIdleConnections; |
|||
|
|||
@Value("${ok.http.keep-alive-duration}") |
|||
private Long keepAliveDuration; |
|||
|
|||
|
|||
/** |
|||
* 声明 RestTemplate |
|||
*/ |
|||
@Bean |
|||
public RestTemplate httpRestTemplate() { |
|||
ClientHttpRequestFactory factory = httpRequestFactory(); |
|||
RestTemplate restTemplate = new RestTemplate(factory); |
|||
return restTemplate; |
|||
} |
|||
|
|||
public ClientHttpRequestFactory httpRequestFactory() { |
|||
return new OkHttp3ClientHttpRequestFactory(okHttpConfigClient()); |
|||
} |
|||
|
|||
public OkHttpClient okHttpConfigClient(){ |
|||
return new OkHttpClient().newBuilder() |
|||
.connectionPool(pool()) |
|||
.connectTimeout(connectTimeout, TimeUnit.SECONDS) |
|||
.readTimeout(readTimeout, TimeUnit.SECONDS) |
|||
.writeTimeout(writeTimeout, TimeUnit.SECONDS) |
|||
.hostnameVerifier((hostname, session) -> true) |
|||
.build(); |
|||
} |
|||
|
|||
public ConnectionPool pool() { |
|||
return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
package com.techsor.datacenter.receiver.config; |
|||
|
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.scheduling.TaskScheduler; |
|||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
|||
import org.springframework.core.task.TaskExecutor; |
|||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; |
|||
|
|||
import java.util.concurrent.Executor; |
|||
import java.util.concurrent.ThreadPoolExecutor; |
|||
|
|||
@Configuration |
|||
public class TaskExecutorConfig { |
|||
|
|||
@Bean("threadPoolTaskExecutor") |
|||
public TaskExecutor threadPoolTaskExecutor() { |
|||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
|||
executor.setCorePoolSize(4); |
|||
executor.setMaxPoolSize(10); |
|||
executor.setThreadNamePrefix("my_executor_thread"); |
|||
executor.initialize(); |
|||
return executor; |
|||
} |
|||
|
|||
@Bean("taskScheduler") |
|||
public TaskScheduler taskScheduler(){ |
|||
ThreadPoolTaskScheduler threadPoolTaskScheduler |
|||
= new ThreadPoolTaskScheduler(); |
|||
threadPoolTaskScheduler.setPoolSize(5); |
|||
threadPoolTaskScheduler.setThreadNamePrefix( |
|||
"ThreadPoolTaskScheduler"); |
|||
return threadPoolTaskScheduler; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
@Bean("postSenderThreadTaskExecutor") |
|||
public Executor postSenderThreadTaskExecutor() { |
|||
int cpuCores = Runtime.getRuntime().availableProcessors(); |
|||
int poolSize = cpuCores * 2; // 假设I/O密集型,可根据实际情况调整
|
|||
|
|||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); |
|||
executor.setCorePoolSize(poolSize); |
|||
executor.setMaxPoolSize(poolSize * 2); // 可以根据需要进一步调整
|
|||
executor.setQueueCapacity(100); // 可以根据需要进一步调整
|
|||
executor.setThreadNamePrefix("Async-"); |
|||
executor.setKeepAliveSeconds(60); // 如果需要,可以设置keep-alive时间
|
|||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 设置拒绝策略
|
|||
executor.initialize(); |
|||
return executor; |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,186 @@ |
|||
package com.techsor.datacenter.receiver.config.datasource; |
|||
|
|||
|
|||
import com.zaxxer.hikari.HikariDataSource; |
|||
|
|||
import jakarta.persistence.EntityManagerFactory; |
|||
|
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.annotation.Qualifier; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.jdbc.DataSourceBuilder; |
|||
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.context.annotation.Primary; |
|||
import org.springframework.jdbc.core.JdbcTemplate; |
|||
import org.springframework.orm.jpa.JpaTransactionManager; |
|||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; |
|||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; |
|||
import org.springframework.transaction.PlatformTransactionManager; |
|||
|
|||
import javax.sql.DataSource; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Configuration |
|||
public class DataSourceAdminConfig { |
|||
private static final Logger logger= LoggerFactory.getLogger(DataSourceAdminConfig.class); |
|||
|
|||
@Value("${spring.datasource.admin.name}") |
|||
private String name; |
|||
|
|||
@Value("${spring.datasource.admin.url}") |
|||
private String url; |
|||
|
|||
@Value("${spring.datasource.admin.username}") |
|||
private String username; |
|||
|
|||
@Value("${spring.datasource.admin.password}") |
|||
private String password; |
|||
|
|||
@Value("${spring.datasource.admin.driverClassName}") |
|||
private String driverClassName; |
|||
|
|||
|
|||
|
|||
@Value("${spring.datasource.admin.hikari.schema}") |
|||
private String schema; |
|||
|
|||
@Value("${spring.datasource.admin.hikari.minimum-idle}") |
|||
private Integer mininumIdle; |
|||
|
|||
@Value("${spring.datasource.admin.hikari.maximum-pool-size}") |
|||
private Integer maximuPoolSize; |
|||
|
|||
@Value("${spring.datasource.admin.hikari.connection-timeout}") |
|||
private Integer connectionTimeout; |
|||
|
|||
@Value("${dynamic.jdbc.url}") |
|||
private String dynamicJdbcUrl; |
|||
|
|||
/** |
|||
* Retrieve the admin data source. |
|||
*/ |
|||
@Primary |
|||
@Bean |
|||
public DataSource adminDatasource() { |
|||
HikariDataSource adminDatasource = DataSourceBuilder.create() |
|||
.url(url) |
|||
.username(username) |
|||
.password(password).driverClassName(driverClassName) |
|||
.type(HikariDataSource.class) |
|||
.build(); |
|||
adminDatasource.setSchema(schema); |
|||
adminDatasource.setMinimumIdle(mininumIdle); |
|||
adminDatasource.setMaximumPoolSize(maximuPoolSize); |
|||
adminDatasource.setConnectionTimeout(connectionTimeout); |
|||
return adminDatasource; |
|||
} |
|||
|
|||
|
|||
@Bean |
|||
public DataSource thirdDatasource() { |
|||
String dbUrl=String.format(dynamicJdbcUrl,"data_center_aeon_admin"); |
|||
HikariDataSource adminDatasource = DataSourceBuilder.create() |
|||
.url(dbUrl) |
|||
.username(username) |
|||
.password(password).driverClassName(driverClassName) |
|||
.type(HikariDataSource.class) |
|||
.build(); |
|||
adminDatasource.setSchema("data_center_aeon_admin"); |
|||
adminDatasource.setMinimumIdle(mininumIdle); |
|||
adminDatasource.setMaximumPoolSize(maximuPoolSize); |
|||
adminDatasource.setConnectionTimeout(connectionTimeout); |
|||
return adminDatasource; |
|||
} |
|||
|
|||
/** |
|||
* Construct a JdbcTemplate for accessing the dynamic data source. |
|||
*/ |
|||
@Bean |
|||
public JdbcTemplate jdbcTemplate(@Qualifier("adminDatasource") DataSource adminDatasource) { |
|||
return new JdbcTemplate(adminDatasource); |
|||
} |
|||
|
|||
|
|||
|
|||
@Bean |
|||
public DataSource dynamicDataSource(JdbcTemplate jdbcTemplate,@Qualifier("adminDatasource") DataSource adminDatasource,@Qualifier("thirdDatasource") DataSource thirdDatasource) { |
|||
DynamicRouteDataSource dynamicDataSource = new DynamicRouteDataSource(); |
|||
Map<Object, Object> targetDataSources = new HashMap<>(); |
|||
|
|||
String sql=" SELECT " + |
|||
" bcom.id,bcom.parent_id, " + |
|||
" bcom.company_name companyName " + |
|||
" FROM " + |
|||
" data_center_aeon_admin.basic_company bcom " + |
|||
" WHERE (bcom.parent_id=1 or bcom.parent_id=-1) and bcom.flag!=1"; |
|||
|
|||
jdbcTemplate.query(sql,rs->{ |
|||
HikariDataSource dataSource1 = new HikariDataSource(); |
|||
String dbName="data_center_aeon_"+rs.getInt("id"); |
|||
String dbUrl=String.format(dynamicJdbcUrl,dbName); |
|||
dataSource1.setJdbcUrl(dbUrl); |
|||
dataSource1.setUsername(username); |
|||
dataSource1.setPassword(password); |
|||
dataSource1.setDriverClassName(driverClassName); |
|||
dataSource1.setSchema(dbName); |
|||
dataSource1.setMinimumIdle(mininumIdle); |
|||
dataSource1.setMaximumPoolSize(maximuPoolSize); |
|||
dataSource1.setConnectionTimeout(connectionTimeout); |
|||
if (rs.getInt("parent_id")==1 || rs.getInt("parent_id")==-1){ |
|||
targetDataSources.put("dataSourceForCompany_"+rs.getInt("id"), dataSource1); |
|||
logger.info("Put dataSourceForCompany_"+rs.getInt("id")+" -- URL:"+dbUrl); |
|||
}else{ |
|||
|
|||
} |
|||
}); |
|||
targetDataSources.put("dataSourceForCompany_0", thirdDatasource); |
|||
|
|||
dynamicDataSource.setTargetDataSources(targetDataSources); |
|||
dynamicDataSource.setDefaultTargetDataSource(adminDatasource); // 设置默认数据源
|
|||
return dynamicDataSource; |
|||
} |
|||
|
|||
|
|||
@Bean |
|||
public JdbcTemplate dynamicJdbcTemplate(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) { |
|||
return new JdbcTemplate(dynamicDataSource); |
|||
} |
|||
|
|||
|
|||
|
|||
// 新增这个Bean,让Spring容器有EntityManagerFactoryBuilder可用
|
|||
@Bean |
|||
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() { |
|||
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); |
|||
// 如果你有特别的jpa配置,可以设置下面这行:
|
|||
// vendorAdapter.setGenerateDdl(true);
|
|||
// vendorAdapter.setShowSql(true);
|
|||
|
|||
return new EntityManagerFactoryBuilder(vendorAdapter, new HashMap<>(), null); |
|||
} |
|||
|
|||
@Primary |
|||
@Bean(name = {"adminEntityManagerFactory", "entityManagerFactory"}) |
|||
public LocalContainerEntityManagerFactoryBean adminEntityManagerFactory( |
|||
EntityManagerFactoryBuilder builder, |
|||
@Qualifier("adminDatasource") DataSource adminDatasource) { |
|||
return builder |
|||
.dataSource(adminDatasource) |
|||
.packages("com.techsor.datacenter.receiver.entity") |
|||
.persistenceUnit("adminPU") |
|||
.build(); |
|||
} |
|||
|
|||
@Primary |
|||
@Bean(name = "adminTransactionManager") |
|||
public PlatformTransactionManager adminTransactionManager( |
|||
@Qualifier("adminEntityManagerFactory") EntityManagerFactory adminEntityManagerFactory) { |
|||
return new JpaTransactionManager(adminEntityManagerFactory); |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.techsor.datacenter.receiver.config.datasource; |
|||
|
|||
public class DataSourceContextHolder { |
|||
|
|||
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); |
|||
|
|||
public static void setCurrentDataSourceKey(String dataSourceKey) { |
|||
contextHolder.set(dataSourceKey); |
|||
} |
|||
|
|||
public static String getCurrentDataSourceKey() { |
|||
return contextHolder.get(); |
|||
} |
|||
|
|||
public static void clearCurrentDataSourceKey() { |
|||
contextHolder.remove(); |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
package com.techsor.datacenter.receiver.config.datasource; |
|||
|
|||
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; |
|||
|
|||
|
|||
public class DynamicRouteDataSource extends AbstractRoutingDataSource { |
|||
|
|||
@Override |
|||
protected Object determineCurrentLookupKey() { |
|||
// Retrieve the key of the data source to be used by the current thread.
|
|||
return DataSourceContextHolder.getCurrentDataSourceKey(); |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka; |
|||
|
|||
import com.techsor.datacenter.receiver.config.kafka.ZiFiClient; |
|||
import com.techsor.datacenter.receiver.config.kafka.imp.ClientFactory; |
|||
import com.techsor.datacenter.receiver.config.kafka.imp.ClientType; |
|||
public class Main { |
|||
public static void main(String[] args) { |
|||
|
|||
String host; |
|||
String apiKey; |
|||
String apiSecret; |
|||
String companyCode; |
|||
|
|||
//hostname,连接的服务器地址,实际使用需要修改\com\zifisense\zetag\mq\api\RegionEnum.java里面的连接地址
|
|||
host = "https://zetagintl.zifisense.com:9093"; |
|||
//apiKey,现在支持一个企业有多ApiKey;在V1版本为企业编码
|
|||
apiKey = "7c5554faf5744135b310a81a13bb487e"; |
|||
// apiKey对应的apiSecret;在v1版本中,相当于企业秘钥
|
|||
apiSecret = "691b57705c644b6ab080a89de7949f27"; |
|||
//企业编号
|
|||
companyCode = "00ebe81f74b34ce38b41266993487f3c"; |
|||
|
|||
//建立客户端
|
|||
ZiFiClient c = ClientFactory.createClient(ClientType.KAFKA, host, apiKey, apiSecret, companyCode); |
|||
//订阅topic
|
|||
c.subscribe(); |
|||
/* 在v1版本中还需指定topic,该方式已被弃用 |
|||
// 描述需要获取哪些数据
|
|||
String topic= "zetag-heartbeat-all"; |
|||
c.subscribe(topic); |
|||
*/ |
|||
while (true) { |
|||
//循环处理收到的数据
|
|||
c.poll().forEach(message->{ |
|||
System.out.printf("id = %s, value = %s%n", message.getMessageId(), message.getBody()); |
|||
}); |
|||
//commit之后才能继续消费下一批次数据
|
|||
c.commit(); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka; |
|||
|
|||
public enum RegionEnum { |
|||
|
|||
CN("zetagos.zifisense.com:9093"); |
|||
|
|||
RegionEnum(String url) { |
|||
this.url = url; |
|||
} |
|||
|
|||
private String url; |
|||
|
|||
public String getUrl() { |
|||
return url; |
|||
} |
|||
|
|||
public void setUrl(String url) { |
|||
this.url = url; |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka; |
|||
|
|||
import com.techsor.datacenter.receiver.config.kafka.RegionEnum; |
|||
import com.techsor.datacenter.receiver.config.kafka.model.Message; |
|||
|
|||
import java.util.Collection; |
|||
|
|||
public abstract class ZiFiClient { |
|||
|
|||
public abstract void init(com.techsor.datacenter.receiver.config.kafka.RegionEnum region, String apiKey, String apiSecret, String companyCode); |
|||
|
|||
public abstract void init(RegionEnum region, String apiKey, String apiSecret, String companyCode, String certPath); |
|||
|
|||
public abstract void init(String host, String apiKey, String apiSecret, String companyCode); |
|||
|
|||
public abstract void init(String host, String apiKey, String apiSecret, String companyCode, String certPath); |
|||
|
|||
public abstract void subscribe(String topic); |
|||
|
|||
public abstract void subscribe(); |
|||
|
|||
public abstract Collection<Message> poll(); |
|||
|
|||
public abstract void commit(); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka.imp; |
|||
|
|||
import com.techsor.datacenter.receiver.config.kafka.RegionEnum; |
|||
import com.techsor.datacenter.receiver.config.kafka.ZiFiClient; |
|||
import com.techsor.datacenter.receiver.config.kafka.imp.ClientType; |
|||
|
|||
public class ClientFactory { |
|||
|
|||
private static Object loadImplement(String className) |
|||
{ |
|||
try { |
|||
ClassLoader cl = ClientFactory.class.getClassLoader(); |
|||
Class<?> implClass; |
|||
implClass = Class.forName(className, true, cl); |
|||
return implClass.newInstance(); |
|||
} catch (ClassNotFoundException e) { |
|||
throw new RuntimeException("Cannot load class " + className, e); |
|||
} catch (InstantiationException e) { |
|||
throw new RuntimeException("Cannot instantiate class " + className, e); |
|||
} catch (IllegalAccessException e) { |
|||
throw new RuntimeException("Cannot access class " + className, e); |
|||
} catch (SecurityException e) { |
|||
throw new RuntimeException("Cannot access class " + className, e); |
|||
} |
|||
} |
|||
|
|||
public static ZiFiClient createClient(com.techsor.datacenter.receiver.config.kafka.imp.ClientType type, RegionEnum region, String apiKey, String apiSecret, String companyCode){ |
|||
ZiFiClient client = (ZiFiClient)loadImplement(type.getName()); |
|||
client.init(region, apiKey, apiSecret, companyCode); |
|||
return client; |
|||
} |
|||
|
|||
public static ZiFiClient createClient(com.techsor.datacenter.receiver.config.kafka.imp.ClientType type, String host, String apiKey, String apiSecret, String companyCode){ |
|||
ZiFiClient client = (ZiFiClient)loadImplement(type.getName()); |
|||
client.init(host, apiKey, apiSecret, companyCode); |
|||
return client; |
|||
} |
|||
|
|||
public static ZiFiClient createClient(ClientType type, RegionEnum region, String apiKey, String apiSecret, String companyCode, String certPath){ |
|||
ZiFiClient client = (ZiFiClient)loadImplement(type.getName()); |
|||
client.init(region, apiKey, apiSecret, companyCode, certPath); |
|||
return client; |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka.imp; |
|||
|
|||
public enum ClientType { |
|||
|
|||
KAFKA("com.techsor.datacenter.receiver.config.kafka.imp.KafkaZiFiClient"); |
|||
|
|||
ClientType(String name) { |
|||
this.name = name; |
|||
} |
|||
|
|||
private String name; |
|||
|
|||
public String getName() { |
|||
return name; |
|||
} |
|||
|
|||
public void setName(String name) { |
|||
this.name = name; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka.imp; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
import org.apache.kafka.clients.consumer.ConsumerRecord; |
|||
|
|||
import com.techsor.datacenter.receiver.config.kafka.model.Message; |
|||
|
|||
public class KafkaMessage extends Message { |
|||
|
|||
private static final String TOPIC_NAME = "topicName"; |
|||
private static final String PARTITION = "partition"; |
|||
private static final String TIME = "time"; |
|||
|
|||
public KafkaMessage(ConsumerRecord<String, String> record) { |
|||
setBody(record.value()); |
|||
setMessageId(String.valueOf(record.offset())); |
|||
Map<String,String> head = new HashMap<>(); |
|||
head.put(TOPIC_NAME, record.topic()); |
|||
head.put(PARTITION, String.valueOf(record.partition())); |
|||
head.put(TIME, String.valueOf(record.timestamp())); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,138 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka.imp; |
|||
|
|||
import com.techsor.datacenter.receiver.config.kafka.RegionEnum; |
|||
import com.techsor.datacenter.receiver.config.kafka.ZiFiClient; |
|||
import com.techsor.datacenter.receiver.config.kafka.model.Message; |
|||
import org.apache.kafka.clients.consumer.ConsumerConfig; |
|||
import org.apache.kafka.clients.consumer.ConsumerRecord; |
|||
import org.apache.kafka.clients.consumer.ConsumerRecords; |
|||
import org.apache.kafka.clients.consumer.KafkaConsumer; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
|
|||
import java.io.File; |
|||
import java.io.FileOutputStream; |
|||
import java.io.InputStream; |
|||
import java.nio.file.Files; |
|||
import java.time.Duration; |
|||
import java.util.ArrayList; |
|||
import java.util.Collection; |
|||
import java.util.Properties; |
|||
import java.util.regex.Pattern; |
|||
|
|||
public class KafkaZiFiClient extends ZiFiClient { |
|||
|
|||
private static final Logger logger = LoggerFactory.getLogger(KafkaZiFiClient.class); |
|||
|
|||
private KafkaConsumer<String, String> consumer; |
|||
private static final Pattern TOPIC_PATTERN_V2 = Pattern.compile(".*-v2"); |
|||
|
|||
private KafkaConsumer<String, String> createConsumer(String url, String apiKey, String apiSecret, String certPath) { |
|||
Properties props = new Properties(); |
|||
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, url); |
|||
props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, apiKey); |
|||
props.setProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); |
|||
props.setProperty(ConsumerConfig.METADATA_MAX_AGE_CONFIG, "60000"); |
|||
props.setProperty(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, "300000"); |
|||
props.setProperty(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "20000"); |
|||
props.setProperty("security.protocol", "SASL_SSL"); |
|||
props.setProperty("ssl.truststore.location", certPath); |
|||
props.setProperty("ssl.truststore.password", "zifisense"); |
|||
props.setProperty("sasl.mechanism", "PLAIN"); |
|||
props.setProperty("sasl.jaas.config", "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" + apiKey + "\" password=\"" + apiSecret + "\";"); |
|||
props.setProperty("ssl.endpoint.identification.algorithm", ""); |
|||
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); |
|||
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer"); |
|||
return new KafkaConsumer<>(props); |
|||
} |
|||
|
|||
@Override |
|||
public void init(RegionEnum region, String apiKey, String apiSecret, String companyCode) { |
|||
this.init(region, apiKey, apiSecret, companyCode, getFilePath()); |
|||
} |
|||
|
|||
@Override |
|||
public void init(String host, String apiKey, String apiSecret, String companyCode) { |
|||
this.init(host, apiKey, apiSecret, companyCode, getFilePath()); |
|||
} |
|||
|
|||
@Override |
|||
public void init(String host, String apiKey, String apiSecret, String companyCode, String certPath) { |
|||
this.consumer = createConsumer(host, apiKey, apiSecret, certPath); |
|||
} |
|||
|
|||
@Override |
|||
public void init(RegionEnum region, String apiKey, String apiSecret, String companyCode, String certPath) { |
|||
this.consumer = createConsumer(region.getUrl(), apiKey, apiSecret, certPath); |
|||
} |
|||
|
|||
public String getFilePath() { |
|||
// String path = KafkaZiFiClient.class.getClassLoader().getResource("certificate/client.truststore.jks").getPath();
|
|||
// if (path.startsWith("/")) {
|
|||
// return path.substring(1);
|
|||
// } else if (path.startsWith("file:/")) {
|
|||
// return path.substring(6);
|
|||
// } else {
|
|||
// return path;
|
|||
// }
|
|||
try { |
|||
// 获取 JAR 内的证书文件流
|
|||
InputStream inputStream = KafkaZiFiClient.class.getClassLoader().getResourceAsStream("certificate/client.truststore.jks"); |
|||
if (inputStream == null) { |
|||
throw new RuntimeException("Certificate file not found!"); |
|||
} |
|||
|
|||
// 创建临时文件
|
|||
File tempFile = Files.createTempFile("client.truststore", ".jks").toFile(); |
|||
tempFile.deleteOnExit(); // JVM 退出时自动删除
|
|||
|
|||
// 将证书文件流写入临时文件
|
|||
try (FileOutputStream outputStream = new FileOutputStream(tempFile)) { |
|||
byte[] buffer = new byte[1024]; // 缓冲区
|
|||
int bytesRead; |
|||
while ((bytesRead = inputStream.read(buffer)) != -1) { |
|||
outputStream.write(buffer, 0, bytesRead); |
|||
} |
|||
} |
|||
|
|||
// 返回临时文件的绝对路径
|
|||
logger.info("truststore path:{}", tempFile.getAbsolutePath()); |
|||
return tempFile.getAbsolutePath(); |
|||
|
|||
} catch (Exception e) { |
|||
throw new RuntimeException("Failed to extract certificate file", e); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 订阅KAFKA v1版本接口数据,v1版本接口需要使用topic来区分 |
|||
* |
|||
* @deprecated 该方法订阅不到V2版本的接口,若要订阅v2版本接口请使用 {@link #subscribe()}。 |
|||
*/ |
|||
@Deprecated |
|||
@Override |
|||
public void subscribe(String topic) { |
|||
consumer.subscribe(Pattern.compile(".*-v1-" + topic)); |
|||
} |
|||
|
|||
@Override |
|||
public void subscribe() { |
|||
consumer.subscribe(TOPIC_PATTERN_V2); |
|||
} |
|||
|
|||
@Override |
|||
public Collection<Message> poll() { |
|||
Collection<Message> messages = new ArrayList<Message>(); |
|||
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100)); |
|||
for (ConsumerRecord<String, String> record : records) { |
|||
messages.add(new KafkaMessage(record)); |
|||
} |
|||
return messages; |
|||
} |
|||
|
|||
@Override |
|||
public void commit() { |
|||
consumer.commitSync(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
package com.techsor.datacenter.receiver.config.kafka.model; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public class Message { |
|||
|
|||
private String body; |
|||
|
|||
private Map<String,String> headers; |
|||
|
|||
private String messageId; |
|||
|
|||
|
|||
public String getMessageId() { |
|||
return messageId; |
|||
} |
|||
|
|||
public void setMessageId(String messageId) { |
|||
this.messageId = messageId; |
|||
} |
|||
|
|||
public String getBody() { |
|||
return body; |
|||
} |
|||
|
|||
public void setBody(String body) { |
|||
this.body = body; |
|||
} |
|||
|
|||
public Map<String, String> getHeaders() { |
|||
return headers; |
|||
} |
|||
|
|||
public void setHeaders(Map<String, String> headers) { |
|||
this.headers = headers; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
package com.techsor.datacenter.receiver.constants; |
|||
|
|||
public class CodeConstants { |
|||
|
|||
public static int CODE_SUCCESS=200; |
|||
public static int CODE_SERVER_ERROR=500; |
|||
public static int CODE_WRONG_VERIFYCODE=601; |
|||
public static int CODE_USER_NOT_REGISTERED=602; |
|||
|
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
package com.techsor.datacenter.receiver.constants; |
|||
|
|||
public class CompanyConstants { |
|||
public final static String ZIFISENSE="zifisense"; |
|||
public final static String NBI="nbi"; |
|||
public final static String OVIPHONE="oviphone"; |
|||
public final static String NITTAN="nittan"; |
|||
public final static String OCR="ocr"; |
|||
public final static String DELTA="delta"; |
|||
public final static String METCOM="metcom"; |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.techsor.datacenter.receiver.constants; |
|||
|
|||
public class MsgConstants { |
|||
|
|||
public static String MSG_SERVER_ERROR="服务器问题,请联系管理员"; |
|||
public static String MSG_WRONG_VERIFYCODE="验证码错误"; |
|||
public static String MSG_USER_NOT_REGISTERED="用户未注册,请注册"; |
|||
|
|||
|
|||
public static String REDIS_COMMAND_NOTIFICATION_TYPE="notification"; |
|||
|
|||
|
|||
public static String REIDS_COMMAND_SWITCH_TYPE="switch"; |
|||
|
|||
public static final String SWITCH_STATUS_PREFIX="switch:stats:status"; |
|||
|
|||
|
|||
public static final String REDIS_COMMAND_STAT_EVENT="startStat"; |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
package com.techsor.datacenter.receiver.constants; |
|||
|
|||
|
|||
|
|||
public class UrlConstants { |
|||
public static String RECEIVER_URL="http://localhost:8201/v1/main_receiver"; |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
package com.techsor.datacenter.receiver.controller; |
|||
|
|||
import com.alibaba.fastjson2.JSON; |
|||
import org.springframework.core.io.ClassPathResource; |
|||
import org.springframework.core.io.Resource; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import java.io.IOException; |
|||
import java.lang.management.ManagementFactory; |
|||
import java.lang.management.RuntimeMXBean; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
import java.util.Properties; |
|||
|
|||
@RestController |
|||
public class HealthController { |
|||
@GetMapping("/healthcheck") |
|||
public String healhealthcheck(){ |
|||
return "ok"; |
|||
} |
|||
|
|||
|
|||
@GetMapping("/health") |
|||
public String health(){ |
|||
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); |
|||
long startTime = runtimeMXBean.getStartTime(); |
|||
Map<String,String> resultMap=new HashMap<>(); |
|||
resultMap.put("status","UP"); |
|||
resultMap.put("startUpDate",String.valueOf(startTime)); |
|||
return JSON.toJSONString(resultMap); |
|||
} |
|||
|
|||
|
|||
@GetMapping("/version") |
|||
public String getVersion() throws IOException { |
|||
Properties properties = new Properties(); |
|||
Resource currentResource = new ClassPathResource("git.properties"); |
|||
properties.load(currentResource.getInputStream()); |
|||
String version=properties.getProperty("git.commit.id.abbrev"); |
|||
return version; |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
package com.techsor.datacenter.receiver.controller; |
|||
|
|||
|
|||
import com.google.common.collect.Maps; |
|||
import com.techsor.datacenter.receiver.service.IDataReceiveService; |
|||
import org.apache.commons.collections.MapUtils; |
|||
import org.springframework.core.task.TaskExecutor; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
|
|||
/** |
|||
* 通知接收,用于触发接收本地MQTTSink的数据 |
|||
* **/ |
|||
@RequestMapping("/notification") |
|||
@RestController |
|||
public class NotificationSinkController { |
|||
|
|||
|
|||
@Resource |
|||
private IDataReceiveService dataReceiveService; |
|||
|
|||
|
|||
@Resource(name="threadPoolTaskExecutor") |
|||
private TaskExecutor threadPoolTaskExecutor; |
|||
/** |
|||
* 给lambda提供接收通知接口,用于触发数据来源监听 |
|||
* */ |
|||
@PostMapping("/receive") |
|||
public Object receiveNotification(@RequestParam(name="state") String state, |
|||
@RequestBody List<Long> params){ |
|||
|
|||
this.threadPoolTaskExecutor.execute(() -> dataReceiveService.receiveCurrentDataSrc(state,params)); |
|||
|
|||
|
|||
Map resultMap=Maps.newHashMap(); |
|||
resultMap.put("result",state); |
|||
return resultMap; |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
package com.techsor.datacenter.receiver.controller; |
|||
|
|||
|
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@RequestMapping("/api/generic") |
|||
@RestController |
|||
public class ReceiverController { |
|||
|
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
|
|||
|
|||
//TODO
|
|||
@PostMapping("/process") |
|||
public Object process(@RequestParam("MyDeviceId")String deviceId,@RequestBody(required = false) Object params){ |
|||
//TODO
|
|||
Gson gson=new Gson(); |
|||
String json=gson.toJson(params); |
|||
this.dataTransService.transferData(deviceId,json); |
|||
Map<String,String> resultMap=new HashMap<>(); |
|||
resultMap.put("code","0"); |
|||
resultMap.put("msg","success"); |
|||
return resultMap; |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey; |
|||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; |
|||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; |
|||
import lombok.Data; |
|||
|
|||
import java.util.UUID; |
|||
|
|||
|
|||
@Data |
|||
public class BaseTransDataEntity { |
|||
|
|||
@DynamoDBHashKey |
|||
@DynamoDBAutoGeneratedKey() |
|||
private UUID hashId; |
|||
|
|||
private Integer id; |
|||
private String content; |
|||
private String ts; |
|||
private String company; //zifisense:纵行, nbi:农博, oviphone:oviphone
|
|||
|
|||
private String dateKey; //日期,格式:yyyy-MM-dd
|
|||
|
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class CommonTransDataEntity { |
|||
|
|||
private Integer id; |
|||
private String content; |
|||
private String ts; |
|||
private String dataSrcCode; //数据源编码
|
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
public class JsonResponse { |
|||
private int code; |
|||
private Object data; |
|||
private String msg; |
|||
|
|||
public JsonResponse() { |
|||
} |
|||
|
|||
public JsonResponse(int code, Object data) { |
|||
this.code = code; |
|||
this.data = data; |
|||
} |
|||
|
|||
public JsonResponse(int code, Object data, String msg) { |
|||
this.code = code; |
|||
this.data = data; |
|||
this.msg = msg; |
|||
} |
|||
|
|||
public static JsonResponse buildSuccess(Object data) { |
|||
return new JsonResponse(200, data); |
|||
} |
|||
|
|||
public static JsonResponse buildError(String msg) { |
|||
return new JsonResponse(400, "", msg); |
|||
} |
|||
|
|||
public static JsonResponse buildError(int code, String msg) { |
|||
return new JsonResponse(code, "", msg); |
|||
} |
|||
|
|||
public int getCode() { |
|||
return code; |
|||
} |
|||
|
|||
public void setCode(int code) { |
|||
this.code = code; |
|||
} |
|||
|
|||
public Object getData() { |
|||
return data; |
|||
} |
|||
|
|||
public void setData(Object data) { |
|||
this.data = data; |
|||
} |
|||
|
|||
public String getMsg() { |
|||
return msg; |
|||
} |
|||
|
|||
public void setMsg(String msg) { |
|||
this.msg = msg; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class KafkaClientConfig { |
|||
|
|||
private String host; |
|||
|
|||
private String apiKey; |
|||
|
|||
private String apiSecret; |
|||
|
|||
private String companyCode; |
|||
|
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
public class KafkaZetaMessage { |
|||
private Payload payload; |
|||
private Source source; |
|||
|
|||
@lombok.Data |
|||
public static class Payload { |
|||
private Data data; |
|||
private String identify; |
|||
} |
|||
|
|||
@lombok.Data |
|||
public static class Data { |
|||
private long upTime; |
|||
private long apTime; |
|||
private String parsedData; // JSON string, can be parsed into ParsedData object
|
|||
private String apUid; |
|||
private String rawData; |
|||
private String msUid; |
|||
} |
|||
|
|||
@lombok.Data |
|||
public static class Source { |
|||
private long createTime; |
|||
private long pushTime; |
|||
private String topicName; |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,37 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class MqttClientConfig { |
|||
|
|||
private String url; |
|||
|
|||
private String clientId; |
|||
|
|||
private String username; |
|||
|
|||
private String password; |
|||
|
|||
private String topic; |
|||
|
|||
private boolean sslState; |
|||
|
|||
private Integer connectionTimeout; |
|||
|
|||
|
|||
private String description; |
|||
|
|||
//1
|
|||
private String caPath; |
|||
|
|||
//2
|
|||
private String clientCrtPath; |
|||
|
|||
//3
|
|||
private String clientKeyPath; |
|||
|
|||
private Integer Qos; |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import lombok.Data; |
|||
import org.springframework.context.annotation.Bean; |
|||
|
|||
@Data |
|||
public class MqttPublisherEntity { |
|||
private Integer id; |
|||
private String host; |
|||
private String username; |
|||
private String password; |
|||
private String topic; |
|||
private String description; |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class MqttStartStatusEntity { |
|||
private String HOST; |
|||
private String status; |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class ResponseEntity { |
|||
private int code; |
|||
private String msg; |
|||
private List<Object> data; |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.techsor.datacenter.receiver.entity.common; |
|||
|
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class ZAIotTransDataEntity { |
|||
|
|||
private String content; |
|||
private String ts; |
|||
private String deviceId; |
|||
private String identify; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package com.techsor.datacenter.receiver.entity.company; |
|||
|
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* create table basic_company |
|||
* ( |
|||
* id bigint auto_increment |
|||
* primary key, |
|||
* parent_id bigint null comment '父企业ID', |
|||
* company_name varchar(500) charset utf8mb4 null, |
|||
* flag int default 0 null comment '0-正常,1-删除', |
|||
* create_time bigint null, |
|||
* creator_id bigint null, |
|||
* modify_time bigint null, |
|||
* modifier_id bigint null |
|||
* ); |
|||
* |
|||
* **/ |
|||
@Data |
|||
public class CompanyEntity { |
|||
|
|||
private Long id; |
|||
|
|||
private Long parentId; |
|||
|
|||
private String companyName; |
|||
|
|||
private Integer flag; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
package com.techsor.datacenter.receiver.entity.datasource; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* create table data_src_config |
|||
* ( |
|||
* id bigint auto_increment |
|||
* primary key, |
|||
* code varchar(100) null comment '数据来源识别代码', |
|||
* api_key varchar(100) null comment 'api_key', |
|||
* name varchar(100) null comment '数据来源名称', |
|||
* method_type varchar(2) null comment '来源方式(0:MQTT;1:RESTFULL)', |
|||
* params varchar(1000) null comment '链接参数', |
|||
* state varchar(2) null comment '状态;(0:激活;1:冻结;)', |
|||
* created_by bigint null, |
|||
* created_timestamp timestamp null, |
|||
* updated_by bigint null, |
|||
* updated_timestamp timestamp null, |
|||
* company_id bigint not null |
|||
* ) |
|||
* comment '数据来源配置表'; |
|||
* */ |
|||
|
|||
@Data |
|||
public class DatasourceConfigEntity { |
|||
|
|||
private Long id; |
|||
|
|||
private String code; |
|||
|
|||
private String apiKey; |
|||
|
|||
private String name; |
|||
|
|||
private String methodType; |
|||
|
|||
private String params; |
|||
|
|||
private String state; |
|||
|
|||
private Long companyId; |
|||
|
|||
private String deviceIdPosition; |
|||
|
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
package com.techsor.datacenter.receiver.entity.datasource; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class RestfulParams { |
|||
|
|||
private String url; |
|||
|
|||
|
|||
private Object params; |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
package com.techsor.datacenter.receiver.entity.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
/**** |
|||
* 开关,commandType为类型 |
|||
* commandType=='notification',则是通知处理mqtt相关信息 |
|||
* commandType=='switch',则是通知处理redis开关,则value为on,off |
|||
* ***/ |
|||
@Data |
|||
public class RedisCommandReceiverDTO { |
|||
|
|||
|
|||
private String commandType; |
|||
|
|||
private String value; |
|||
|
|||
private String state; |
|||
|
|||
private List<Long> params; |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
package com.techsor.datacenter.receiver.entity.metcom; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
//{
|
|||
// “measured” : [計測時刻 (unix timestamp)],
|
|||
// “spaceId” : “[DBM空間コード]”,
|
|||
// “latitude” : [緯度(deg)],
|
|||
// “longitude” : [経度(deg)],
|
|||
// “floor” : [階数],
|
|||
// “hae” : [楕円体高(m)],
|
|||
// “hat” : [地上高(m)]
|
|||
//}
|
|||
public class MetcomEntity { |
|||
private String uuid; |
|||
private Long measured; |
|||
private String spaceId; |
|||
private double latitude; |
|||
private double longitude; |
|||
private int floor; |
|||
private float hae; |
|||
private float hat; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
package com.techsor.datacenter.receiver.entity.nittan; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class AuthEntity{ |
|||
private String subscription_id; |
|||
private String signature; |
|||
private String code; |
|||
private String version; |
|||
private Integer timestamp; |
|||
|
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
package com.techsor.datacenter.receiver.entity.nittan; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class DeviceInfoEntity{ |
|||
private String device_name; |
|||
private String device_class; |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
package com.techsor.datacenter.receiver.entity.nittan; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class FacilityInfoEntity{ |
|||
private String facility_id; |
|||
private String facility_maker; |
|||
private String facility_mode; |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
package com.techsor.datacenter.receiver.entity.nittan; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class LocationInfoEntity{ |
|||
private String location_address; |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
package com.techsor.datacenter.receiver.entity.nittan; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class NittanEntity { |
|||
private AuthEntity auth; |
|||
private String cmd; |
|||
private FacilityInfoEntity facility_info; |
|||
private List<NoticeInfoEntity> notice_info; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -0,0 +1,12 @@ |
|||
package com.techsor.datacenter.receiver.entity.nittan; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class NoticeInfoEntity { |
|||
private String notice_type; |
|||
private String notice_level; |
|||
private String notice_status; |
|||
private LocationInfoEntity location_info; |
|||
private DeviceInfoEntity device_info; |
|||
} |
|||
@ -0,0 +1,113 @@ |
|||
package com.techsor.datacenter.receiver.listener; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.config.datasource.DataSourceContextHolder; |
|||
import com.techsor.datacenter.receiver.entity.common.KafkaClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.company.CompanyEntity; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import com.techsor.datacenter.receiver.service.GlobalStateService; |
|||
import com.techsor.datacenter.receiver.service.IDataSourceConfigService; |
|||
import com.techsor.datacenter.receiver.service.IMQTTService; |
|||
import com.techsor.datacenter.receiver.service.ZetaKafkaService; |
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.context.event.ApplicationStartedEvent; |
|||
import org.springframework.context.ApplicationListener; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class DataSourceConfigListener implements ApplicationListener<ApplicationStartedEvent> { |
|||
private static final Logger logger= LoggerFactory.getLogger(DataSourceConfigListener.class); |
|||
@Resource |
|||
private GlobalStateService globalStateService; |
|||
@Resource |
|||
private IMQTTService mqttService; |
|||
@Resource |
|||
private IDataSourceConfigService dataSourceConfigService; |
|||
@Resource |
|||
private ZetaKafkaService zetaKafkaService; |
|||
|
|||
@Value("${base.companyId}") |
|||
private Integer baseComanyId; |
|||
|
|||
/** |
|||
* 应用程序启动事件监听器。此方法在应用程序启动完成后被自动调用,用于根据数据库中的数据源配置来启动或停止数据接收客户端。 |
|||
* |
|||
* @param event 应用程序启动事件。 |
|||
*/ |
|||
@Override |
|||
public void onApplicationEvent(ApplicationStartedEvent event) { |
|||
if (!(event instanceof ApplicationStartedEvent)){ |
|||
return; |
|||
} |
|||
|
|||
// Clearing data source to use the default one.
|
|||
DataSourceContextHolder.clearCurrentDataSourceKey(); |
|||
|
|||
|
|||
//Get companyId and parentId
|
|||
List<CompanyEntity> companyEntityList=this.dataSourceConfigService.getRelatedTopCompany(baseComanyId.toString()); |
|||
List<Long> companyIdList = new ArrayList<>(); |
|||
for (CompanyEntity companyItem : companyEntityList){ |
|||
companyIdList.add(companyItem.getId()); |
|||
if (companyItem.getParentId()!=-1){ |
|||
companyIdList.add(companyItem.getParentId()); |
|||
} |
|||
} |
|||
|
|||
DataSourceContextHolder.clearCurrentDataSourceKey(); |
|||
|
|||
companyIdList.forEach(iter-> { |
|||
logger.info("Not Error, debug Log:dataSourceForCompany" + iter); |
|||
DataSourceContextHolder.setCurrentDataSourceKey("dataSourceForCompany_" + iter); |
|||
List<DatasourceConfigEntity> resultList = this.dataSourceConfigService.getDataSourceConfigWithState(); |
|||
logger.info("All datasource:"+new Gson().toJson(resultList)); |
|||
for (int i = 0; i < resultList.size(); i++) { |
|||
DatasourceConfigEntity item = resultList.get(i); |
|||
// 检查数据源的状态,如果状态为"0",表示需要启动该数据源。
|
|||
if (StringUtils.equals("0", item.getState())) { |
|||
//判断类型,MQTT
|
|||
if (StringUtils.equals("0", item.getMethodType())) { |
|||
//mqtt
|
|||
Gson gson = new Gson(); |
|||
MqttClientConfig mqttClientConfig = gson.fromJson(item.getParams(), MqttClientConfig.class); |
|||
this.mqttService.addMQTTConsumerClient(iter,item.getId(), mqttClientConfig, item); |
|||
} else if (StringUtils.equals("1",item.getMethodType())) { |
|||
// 对于HTTP类型,将数据源配置添加到全局状态服务中管理。
|
|||
this.globalStateService.addDatasourceConfig(item); |
|||
} else if (StringUtils.equals("2",item.getMethodType())) { |
|||
//kafka
|
|||
Gson gson=new Gson(); |
|||
KafkaClientConfig kafkaClientConfig = gson.fromJson(item.getParams(), KafkaClientConfig.class); |
|||
this.zetaKafkaService.addKafkaClient(iter, item.getId(), kafkaClientConfig, item); |
|||
} |
|||
} else { |
|||
|
|||
if (StringUtils.equals("0", item.getMethodType())) { |
|||
//mqtt
|
|||
this.mqttService.removeMQTTConsumerClient(item.getId()); |
|||
} else { |
|||
this.globalStateService.removeDatasourceConfig(item); |
|||
} |
|||
|
|||
} |
|||
} |
|||
DataSourceContextHolder.clearCurrentDataSourceKey(); |
|||
}); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
package com.techsor.datacenter.receiver.listener; |
|||
|
|||
import com.techsor.datacenter.receiver.clients.DeltaClientMQTTS; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.boot.context.event.ApplicationStartedEvent; |
|||
import org.springframework.context.ApplicationListener; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@Component |
|||
public class DeltaMQTTListener implements ApplicationListener<ApplicationStartedEvent> { |
|||
private static final Logger logger= LoggerFactory.getLogger(MqttPublisherListener.class); |
|||
|
|||
@Resource |
|||
private DeltaClientMQTTS deltaClientMQTT; |
|||
@Override |
|||
public void onApplicationEvent(ApplicationStartedEvent event) { |
|||
if (!(event instanceof ApplicationStartedEvent)){ |
|||
return; |
|||
} |
|||
|
|||
try { |
|||
deltaClientMQTT.start(); |
|||
} catch (Exception e) { |
|||
logger.error("DeltaClientMQTTS runtime exception",e); |
|||
// throw new RuntimeException(e);
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
package com.techsor.datacenter.receiver.listener; |
|||
|
|||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; |
|||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; |
|||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression; |
|||
import com.amazonaws.services.dynamodbv2.model.AttributeValue; |
|||
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; |
|||
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; |
|||
import com.amazonaws.services.dynamodbv2.model.QueryRequest; |
|||
import com.amazonaws.services.dynamodbv2.util.TableUtils; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.context.event.ApplicationStartedEvent; |
|||
import org.springframework.context.ApplicationListener; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.HashMap; |
|||
|
|||
//@Component
|
|||
public class DynamoDBListener implements ApplicationListener<ApplicationStartedEvent> { |
|||
private static final Logger logger= LoggerFactory.getLogger(DynamoDBListener.class); |
|||
|
|||
@Resource |
|||
AmazonDynamoDB amazonDynamoDB; |
|||
|
|||
@Resource |
|||
DynamoDBMapper dynamoDBMapper; |
|||
@Value("${amazon.dynamodb.tableName:mqtt_history}") |
|||
private String dynamoDBTableName; |
|||
|
|||
|
|||
/*** |
|||
* 生成创建表的请求。这里使用DynamoDBMapper的generateCreateTableRequest方法 |
|||
* 为BaseTransDataEntity类生成创建表的请求,同时指定读写吞吐量。 |
|||
* 等待表变为活动状态。这是为了确保表已经完全创建并可以使用。 |
|||
* */ |
|||
@Override |
|||
public void onApplicationEvent(ApplicationStartedEvent event) { |
|||
if (!(event instanceof ApplicationStartedEvent)){ |
|||
return; |
|||
} |
|||
logger.info("DynamoDBListner started successfully!!!"); |
|||
// 生成创建表的请求。这里使用DynamoDBMapper的generateCreateTableRequest方法
|
|||
// 为BaseTransDataEntity类生成创建表的请求,同时指定读写吞吐量。
|
|||
CreateTableRequest ctr = dynamoDBMapper.generateCreateTableRequest(BaseTransDataEntity.class) |
|||
.withProvisionedThroughput(new ProvisionedThroughput(1L, 1L)); |
|||
ctr.setTableName(dynamoDBTableName); |
|||
TableUtils.createTableIfNotExists(amazonDynamoDB, ctr); |
|||
try { |
|||
// 等待表变为活动状态。这是为了确保表已经完全创建并可以使用。
|
|||
TableUtils.waitUntilActive(amazonDynamoDB, ctr.getTableName()); |
|||
} catch (InterruptedException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
logger.info("DynamoDBListener createTableIfNotExists successfully!!!"); |
|||
|
|||
logger.info("DynamoDBListener save successfully!!!"); |
|||
} |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
package com.techsor.datacenter.receiver.listener; |
|||
|
|||
import com.techsor.datacenter.receiver.clients.ITAClientMQTT; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttStartStatusEntity; |
|||
import com.techsor.datacenter.receiver.service.MqttPublisherService; |
|||
import org.eclipse.paho.client.mqttv3.MqttException; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.boot.context.event.ApplicationStartedEvent; |
|||
import org.springframework.context.ApplicationListener; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.List; |
|||
import java.util.Random; |
|||
|
|||
//@Component
|
|||
public class MqttPublisherListener implements ApplicationListener<ApplicationStartedEvent> { |
|||
|
|||
private static final Logger logger=LoggerFactory.getLogger(MqttPublisherListener.class); |
|||
|
|||
@Resource |
|||
private MqttPublisherService mqttPublisherService; |
|||
|
|||
|
|||
@Override |
|||
public void onApplicationEvent(ApplicationStartedEvent event) { |
|||
if (!(event instanceof ApplicationStartedEvent)){ |
|||
return; |
|||
} |
|||
|
|||
List publisherList = mqttPublisherService.getList(); |
|||
|
|||
for (int i=0;i<publisherList.size();i++){ |
|||
ITAClientMQTT clientMQTT = new ITAClientMQTT((MqttPublisherEntity) publisherList.get(i),getRandoms()+""); |
|||
MqttStartStatusEntity statusItem = new MqttStartStatusEntity(); |
|||
statusItem.setHOST(((MqttPublisherEntity) publisherList.get(i)).getHost()); |
|||
try { |
|||
clientMQTT.start(); |
|||
statusItem.setStatus("Success"); |
|||
}catch (MqttException e) { |
|||
logger.error("Failed,please check log. {}",e); |
|||
statusItem.setStatus("Failed,please check log."); |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
public int getRandoms(){ |
|||
// 创建一个Random对象
|
|||
Random random = new Random(); |
|||
|
|||
// 生成一个范围在100到999之间的随机数(包括100,但不包括1000)
|
|||
int randomNumber = random.nextInt(900) + 100; |
|||
return randomNumber; |
|||
} |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
package com.techsor.datacenter.receiver.listener; |
|||
|
|||
import com.alibaba.fastjson2.JSON; |
|||
import com.google.gson.Gson; |
|||
import com.google.gson.GsonBuilder; |
|||
import com.techsor.datacenter.receiver.constants.MsgConstants; |
|||
import com.techsor.datacenter.receiver.entity.dto.RedisCommandReceiverDTO; |
|||
import com.techsor.datacenter.receiver.service.GlobalSwitchStatusComponent; |
|||
import com.techsor.datacenter.receiver.service.GuavaRedisCache; |
|||
import com.techsor.datacenter.receiver.service.IDataReceiveService; |
|||
import com.techsor.datacenter.receiver.utils.JsonUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.apache.commons.text.StringEscapeUtils; |
|||
import org.springframework.core.task.TaskExecutor; |
|||
import org.springframework.data.redis.connection.Message; |
|||
import org.springframework.data.redis.connection.MessageListener; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.Objects; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class RedisNotificationMessageSubscriber implements MessageListener { |
|||
@Resource |
|||
private IDataReceiveService dataReceiveService; |
|||
|
|||
@Resource |
|||
private GlobalSwitchStatusComponent globalSwitchStatusComponent; |
|||
@Resource(name="threadPoolTaskExecutor") |
|||
private TaskExecutor threadPoolTaskExecutor; |
|||
|
|||
@Resource |
|||
private GuavaRedisCache guavaRedisCache; |
|||
@Override |
|||
public void onMessage(Message message, byte[] pattern) { |
|||
String commandMessage = new String(message.getBody()); |
|||
if (StringUtils.isEmpty(commandMessage)){ |
|||
log.warn("Empty message received."); |
|||
return; |
|||
} |
|||
log.info("Message received: {}" , commandMessage); |
|||
commandMessage = commandMessage.substring(1, commandMessage.length() - 1); |
|||
commandMessage=StringEscapeUtils.unescapeJson(commandMessage); |
|||
RedisCommandReceiverDTO redisCommandReceiverDTO=JSON.parseObject(commandMessage, RedisCommandReceiverDTO.class); |
|||
|
|||
if (redisCommandReceiverDTO==null){ |
|||
log.warn("Failed to parse message: {}",commandMessage); |
|||
return; |
|||
} |
|||
|
|||
if (StringUtils.equals(redisCommandReceiverDTO.getCommandType(), MsgConstants.REDIS_COMMAND_NOTIFICATION_TYPE)){ |
|||
this.threadPoolTaskExecutor.execute(() -> dataReceiveService.receiveCurrentDataSrc(redisCommandReceiverDTO.getState(),redisCommandReceiverDTO.getParams())); |
|||
}else{ |
|||
//redis统计事件,每隔5分钟会被触发
|
|||
log.warn("redisCommandReceiverDTO.getCommandType():"+redisCommandReceiverDTO.getCommandType()); |
|||
log.warn("MsgConstants.REDIS_COMMAND_STAT_EVENT:"+MsgConstants.REDIS_COMMAND_STAT_EVENT); |
|||
if (StringUtils.equalsIgnoreCase(redisCommandReceiverDTO.getCommandType(), MsgConstants.REDIS_COMMAND_STAT_EVENT)) { |
|||
this.guavaRedisCache.syncToRedis(); |
|||
}else{ |
|||
if (StringUtils.equals(redisCommandReceiverDTO.getCommandType(), MsgConstants.REIDS_COMMAND_SWITCH_TYPE)){ |
|||
String value=redisCommandReceiverDTO.getValue(); |
|||
this.globalSwitchStatusComponent.updateSwitchStatus(Objects.equals(value, "on")); |
|||
}else{ |
|||
log.warn("Unknown command type: {}",redisCommandReceiverDTO.getCommandType()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package com.techsor.datacenter.receiver.listener; |
|||
|
|||
import com.techsor.datacenter.receiver.constants.MsgConstants; |
|||
import com.techsor.datacenter.receiver.service.GlobalSwitchStatusComponent; |
|||
import org.springframework.boot.context.event.ApplicationStartedEvent; |
|||
import org.springframework.context.ApplicationListener; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.Objects; |
|||
|
|||
@Component |
|||
public class RedisStatsSwitchListener implements ApplicationListener<ApplicationStartedEvent> { |
|||
|
|||
@Resource |
|||
private RedisTemplate<String,Object> redisTemplate; |
|||
|
|||
@Resource |
|||
private GlobalSwitchStatusComponent globalSwitchStatusComponent; |
|||
@Override |
|||
public void onApplicationEvent(ApplicationStartedEvent event) { |
|||
if (!(event instanceof ApplicationStartedEvent)){ |
|||
return; |
|||
} |
|||
|
|||
Object switchStatus = redisTemplate.opsForValue().get(MsgConstants.SWITCH_STATUS_PREFIX); |
|||
|
|||
if (Objects.nonNull(switchStatus)){ |
|||
this.globalSwitchStatusComponent.updateSwitchStatus(Boolean.parseBoolean(String.valueOf(switchStatus))); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.google.gson.JsonObject; |
|||
import com.google.gson.JsonParser; |
|||
import com.techsor.datacenter.receiver.config.DataCenterEnvConfig; |
|||
import com.techsor.datacenter.receiver.constants.CompanyConstants; |
|||
import com.techsor.datacenter.receiver.constants.UrlConstants; |
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.CommonTransDataEntity; |
|||
import com.techsor.datacenter.receiver.entity.common.ZAIotTransDataEntity; |
|||
import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil; |
|||
import com.techsor.datacenter.receiver.utils.MyHTTPResponse; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.Objects; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class DataTransService { |
|||
|
|||
private static final Logger logger= LoggerFactory.getLogger(DataTransService.class); |
|||
@Resource |
|||
private DefaultHttpRequestUtil defaultHttpRequestUtil; |
|||
|
|||
@Autowired |
|||
private RedisTemplate redisTemplate; |
|||
|
|||
@Resource |
|||
private DataCenterEnvConfig dataCenterEnvConfig; |
|||
|
|||
public void transferData(String userId,String companyName,String rawJson){ |
|||
logger.warn("Start Process:{},",rawJson); |
|||
BaseTransDataEntity baseTransDataEntity = new BaseTransDataEntity(); |
|||
baseTransDataEntity.setCompany(companyName); |
|||
baseTransDataEntity.setTs(System.currentTimeMillis()+""); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
Gson gson = new Gson(); |
|||
String jsonParams = gson.toJson(baseTransDataEntity); |
|||
if(StringUtils.isEmpty(userId)){ |
|||
logger.debug("Send Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getReceiveUrl()); |
|||
}else{ |
|||
logger.debug("Send Data :{} by:{},To: {}", jsonParams,userId,dataCenterEnvConfig.getReceiveUrl()); |
|||
} |
|||
|
|||
this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getReceiveUrl(),jsonParams); |
|||
} |
|||
|
|||
@Resource |
|||
private DuplicateDataProcessor duplicateDataProcessor; |
|||
|
|||
public MyHTTPResponse transferData(String srcCode,String rawJson){ |
|||
String redisKey = Objects.toString(srcCode, "") + Objects.toString(rawJson, ""); |
|||
boolean redisResp = redisTemplate.opsForValue().setIfAbsent(redisKey, System.currentTimeMillis(), 60, TimeUnit.SECONDS); |
|||
|
|||
MyHTTPResponse response=new MyHTTPResponse<>(); |
|||
if (redisResp) { |
|||
CommonTransDataEntity baseTransDataEntity = new CommonTransDataEntity(); |
|||
baseTransDataEntity.setDataSrcCode(srcCode); |
|||
baseTransDataEntity.setTs(System.currentTimeMillis()+""); |
|||
baseTransDataEntity.setContent(rawJson); |
|||
Gson gson = new Gson(); |
|||
String jsonParams = gson.toJson(baseTransDataEntity); |
|||
|
|||
try{ |
|||
if (rawJson.contains("PNs") && rawJson.contains("Objs")){ |
|||
//单独处理IoServer数据
|
|||
logger.debug("CustomSend Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getProcessIoserverUrl()); |
|||
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getProcessIoserverUrl(), jsonParams); |
|||
}else if (isGW150(rawJson)){ |
|||
//单独处理ST-150网关数据
|
|||
logger.debug("CustomSend Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getProcessIoserverUrl()); |
|||
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getGW150ProcessUrl(), jsonParams); |
|||
}else{ |
|||
logger.debug("CustomSend Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getProcessApiUrl()); |
|||
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getProcessApiUrl(), jsonParams); |
|||
} |
|||
}catch (Exception e){ |
|||
response.setCode(500); |
|||
log.error("transferData error:{}",rawJson,e); |
|||
} |
|||
logger.debug("transferData response:{}",new Gson().toJson(response)); |
|||
} |
|||
return response; |
|||
} |
|||
|
|||
public MyHTTPResponse transferDataZaiot(String deviceId, String rawJson, String identify) { |
|||
String redisKey = Objects.toString(deviceId, "") + Objects.toString(rawJson, ""); |
|||
boolean redisResp = redisTemplate.opsForValue().setIfAbsent(redisKey, System.currentTimeMillis(), 60, TimeUnit.SECONDS); |
|||
|
|||
if (redisResp) { |
|||
MyHTTPResponse response=new MyHTTPResponse<>(); |
|||
ZAIotTransDataEntity zAIotTransDataEntity = new ZAIotTransDataEntity(); |
|||
zAIotTransDataEntity.setDeviceId(deviceId); |
|||
zAIotTransDataEntity.setTs(System.currentTimeMillis()+""); |
|||
zAIotTransDataEntity.setContent(rawJson); |
|||
zAIotTransDataEntity.setIdentify(identify); |
|||
|
|||
Gson gson = new Gson(); |
|||
String zaiotProcessJsonParams = gson.toJson(zAIotTransDataEntity); |
|||
logger.debug("zaiot_process Data :{} ,To: {}", zaiotProcessJsonParams, dataCenterEnvConfig.getZaiotProcessApiUrl()); |
|||
try{ |
|||
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getZaiotProcessApiUrl(), zaiotProcessJsonParams); |
|||
}catch (Exception e){ |
|||
response.setCode(500); |
|||
logger.error("zaiot_process error:{}",zaiotProcessJsonParams,e); |
|||
} |
|||
return response; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
/** |
|||
* 检查JSON字符串是否包含特定的字段,用于判断是否符合GW150数据格式 |
|||
* |
|||
* @param jsonStr 待检查的JSON字符串 |
|||
* @return 如果JSON字符串同时包含字段"d"和"ts",则返回true,否则返回false |
|||
*/ |
|||
private Boolean isGW150(String jsonStr){ |
|||
// 解析JSON字符串为JsonObject,以便进行字段检查
|
|||
JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject(); |
|||
|
|||
// 检查JSON对象中是否包含字段"d"
|
|||
boolean hasD = json.has("d"); |
|||
// 检查JSON对象中是否包含字段"ts"
|
|||
boolean hasTs = json.has("ts"); |
|||
|
|||
// 如果同时存在字段"d"和"ts",则认为是GW150数据格式,返回true,否则返回false
|
|||
return hasD && hasTs; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,84 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
|
|||
import cn.hutool.crypto.digest.DigestAlgorithm; |
|||
import cn.hutool.crypto.digest.DigestUtil; |
|||
import com.techsor.datacenter.receiver.utils.RedisUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.integration.redis.util.RedisLockRegistry; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.concurrent.TimeUnit; |
|||
import java.util.concurrent.locks.Lock; |
|||
|
|||
/** |
|||
* 处理数据去重的类,使用Redis分布式锁来确保数据的唯一性。 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class DuplicateDataProcessor { |
|||
|
|||
private final static Logger myLogger = LoggerFactory.getLogger(DuplicateDataProcessor.class); |
|||
|
|||
@Resource |
|||
private RedisLockRegistry redisLockRegistry; |
|||
|
|||
@Resource |
|||
private RedisUtils redisUtils; |
|||
|
|||
/** |
|||
* 移除重复数据。 |
|||
* |
|||
* @param content 需要去重的数据内容。 |
|||
* @return 布尔值,表示是否成功去除重复数据(true表示数据是唯一的,false表示数据重复)。 |
|||
*/ |
|||
public boolean removeDuplicateData(String content) { |
|||
//获取lockKeyName
|
|||
String lockKeyName= DigestUtil.digester(DigestAlgorithm.SHA1).digestHex(content); |
|||
//此处排除并发下为空的情况
|
|||
if (StringUtils.isEmpty(lockKeyName)){ |
|||
return false; |
|||
} |
|||
//定义返回结果
|
|||
boolean result=false; |
|||
//获取分布式锁,进行去重
|
|||
|
|||
Lock lock=this.redisLockRegistry.obtain("receiver_"+lockKeyName); |
|||
try{ |
|||
if (lock.tryLock(10, TimeUnit.SECONDS)){ |
|||
log.debug("get lock success"); |
|||
//有数据
|
|||
if (this.redisUtils.hasKey("receiver_"+lockKeyName)){ |
|||
|
|||
result=false; |
|||
}else{ |
|||
//没有数据,则写入redis
|
|||
result=true; |
|||
this.redisUtils.add("receiver_"+lockKeyName,content,3600L,TimeUnit.SECONDS); |
|||
log.debug("add data to redis success,lockKeyName:{},content:{}",lockKeyName,content); |
|||
} |
|||
}else{ |
|||
log.debug("get lock failed {}",content); |
|||
return false; |
|||
} |
|||
}catch (InterruptedException e){ |
|||
// myLogger.error("an exception caught here :{}",e.getMessage(),e);
|
|||
result=false; |
|||
}finally { |
|||
try{ |
|||
lock.unlock(); |
|||
}catch (Exception e){ |
|||
// myLogger.error("an exception caught here :{}",e.getMessage(),e);
|
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import com.techsor.datacenter.receiver.entity.datasource.RestfulParams; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.Map; |
|||
import java.util.concurrent.ConcurrentHashMap; |
|||
|
|||
@Service |
|||
public class GlobalStateService { |
|||
|
|||
private Map<String, DatasourceConfigEntity> datasourceConfigMap = new ConcurrentHashMap<>(); |
|||
|
|||
public void addDatasourceConfig(DatasourceConfigEntity datasourceConfigEntity) { |
|||
String params= datasourceConfigEntity.getParams(); |
|||
Gson gson = new Gson(); |
|||
RestfulParams restfulParams=gson.fromJson(params, RestfulParams.class); |
|||
datasourceConfigMap.put(restfulParams.getUrl(), datasourceConfigEntity); |
|||
} |
|||
|
|||
|
|||
public DatasourceConfigEntity getDatasourceConfig(String url){ |
|||
return this.datasourceConfigMap.get(url); |
|||
} |
|||
public boolean checkUrlExist(String url){ |
|||
return this.datasourceConfigMap.containsKey(url); |
|||
} |
|||
|
|||
public void removeDatasourceConfig(DatasourceConfigEntity datasourceConfigEntity) { |
|||
String params= datasourceConfigEntity.getParams(); |
|||
Gson gson = new Gson(); |
|||
RestfulParams restfulParams=gson.fromJson(params, RestfulParams.class); |
|||
datasourceConfigMap.remove(restfulParams.getUrl()); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.PostConstruct; |
|||
|
|||
import java.util.concurrent.atomic.AtomicBoolean; |
|||
|
|||
@Component |
|||
public class GlobalSwitchStatusComponent { |
|||
|
|||
private AtomicBoolean switchStatus; |
|||
|
|||
@PostConstruct |
|||
public void init(){ |
|||
this.switchStatus=new AtomicBoolean(false); |
|||
} |
|||
|
|||
|
|||
public void updateSwitchStatus(boolean switchStatus){ |
|||
this.switchStatus=new AtomicBoolean(switchStatus); |
|||
} |
|||
|
|||
public boolean getSwitchStatus(){ |
|||
return this.switchStatus.get(); |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.alibaba.fastjson2.JSON; |
|||
import com.google.common.cache.CacheBuilder; |
|||
import com.google.common.cache.CacheLoader; |
|||
import com.google.common.cache.LoadingCache; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.slf4j.MDC; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.scheduling.annotation.Scheduled; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.PostConstruct; |
|||
import java.time.Duration; |
|||
import java.time.LocalDate; |
|||
import java.time.ZoneId; |
|||
import java.time.ZonedDateTime; |
|||
import java.time.format.DateTimeFormatter; |
|||
import java.util.Objects; |
|||
import java.util.UUID; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
import static com.google.common.cache.CacheBuilder.newBuilder; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
public class GuavaRedisCache { |
|||
|
|||
private final LoadingCache<String, Integer> cache; |
|||
private final RedisTemplate<String, Object> redisTemplate; |
|||
|
|||
|
|||
private final GlobalSwitchStatusComponent globalSwitchStatusComponent; |
|||
@Autowired |
|||
public GuavaRedisCache(RedisTemplate<String, Object> redisTemplate, GlobalSwitchStatusComponent globalSwitchStatusComponent ) { |
|||
this.redisTemplate = redisTemplate; |
|||
this.globalSwitchStatusComponent = globalSwitchStatusComponent; |
|||
this.cache = CacheBuilder.newBuilder() |
|||
.maximumSize(10000) |
|||
.expireAfterWrite(7, TimeUnit.MINUTES) |
|||
.concurrencyLevel(1000) |
|||
.build(new CacheLoader<String,Integer>() { |
|||
@Override |
|||
public Integer load(String s) throws Exception { |
|||
return 0; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void incrementDailyDeviceIdCount(String deviceId) { |
|||
String key = getKeyForToday(); |
|||
cache.put(key + ":" + deviceId, cache.getUnchecked(key + ":" + deviceId) + 1); |
|||
} |
|||
|
|||
public String getKeyForToday() { |
|||
LocalDate today = LocalDate.now(); |
|||
// 设置日本时区
|
|||
ZoneId japanZone = ZoneId.of("Asia/Tokyo"); |
|||
|
|||
// 获取日本时区的当前日期和时间
|
|||
ZonedDateTime nowInJapan = ZonedDateTime.now(japanZone); |
|||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
|||
LocalDate yesterdayInJapan = nowInJapan.toLocalDate(); |
|||
return "receiver:device:counts:" + formatter.format(yesterdayInJapan); |
|||
} |
|||
|
|||
//由guava同步到redis
|
|||
public void syncToRedis() { |
|||
String requestId =UUID.randomUUID().toString(); |
|||
MDC.put("requestId", requestId); |
|||
log.info("Syncing cache to Redis=============================>"); |
|||
log.info("Current Cache Size Data {}", cache.size()); |
|||
log.info("Current Cache Value :{}", JSON.toJSON(cache.asMap())); |
|||
cache.asMap().forEach((key, value) -> { |
|||
String[] parts = key.split(":"); |
|||
String redisKey = parts[0] + ":" + parts[1] + ":" + parts[2] + ":" + parts[3]; |
|||
String deviceId = parts[4]; |
|||
redisTemplate.opsForHash().increment(redisKey, deviceId, value); |
|||
redisTemplate.expire(redisKey, Duration.ofDays(2)); // 设置键2天后过期
|
|||
}); |
|||
log.info("Syncing cache to Redis done"); |
|||
this.cache.invalidateAll(); |
|||
MDC.clear(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface IDataReceiveService { |
|||
|
|||
|
|||
/**** |
|||
* 本方法用于接收aws lambda触发的通知,用于触发数据来源监听或者停止监听 |
|||
* */ |
|||
public void receiveCurrentDataSrc(String state, List<Long> params); |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
|
|||
import com.techsor.datacenter.receiver.entity.company.CompanyEntity; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface IDataSourceConfigService { |
|||
|
|||
|
|||
public List<DatasourceConfigEntity> getDataSourceConfig(List<Long> datasourceIds) ; |
|||
|
|||
|
|||
public List<DatasourceConfigEntity> getDataSourceConfigWithState() ; |
|||
|
|||
public List<CompanyEntity> getRelatedTopCompany(String baseCompanyId); |
|||
|
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
|
|||
public interface IMQTTService { |
|||
|
|||
//增加MQTT客户端
|
|||
void addMQTTConsumerClient(Long companyId,Long id, MqttClientConfig config, DatasourceConfigEntity datasourceConfigEntity); |
|||
|
|||
//根据ID去除MQTT客户端
|
|||
public void removeMQTTConsumerClient(Long id); |
|||
} |
|||
|
|||
@ -0,0 +1,98 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.io.FileUtils; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; |
|||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; |
|||
import software.amazon.awssdk.core.sync.RequestBody; |
|||
import software.amazon.awssdk.regions.Region; |
|||
import software.amazon.awssdk.services.s3.S3Client; |
|||
import software.amazon.awssdk.services.s3.model.GetObjectRequest; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.io.OutputStream; |
|||
import java.nio.file.Path; |
|||
import java.nio.file.Paths; |
|||
|
|||
/** |
|||
* 用于处理与MQTT证书相关的服务,包括从AWS S3下载证书文件。 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class MQTTCrtService { |
|||
|
|||
|
|||
@Value("${amazon.aws.accesskey}") |
|||
private String awsAccessKeyId; |
|||
|
|||
@Value("${amazon.aws.secretkey}") |
|||
private String awsAccessSecret; |
|||
|
|||
@Value("${amazon.aws.bucket}") |
|||
private String awsBucketAdress; |
|||
|
|||
|
|||
|
|||
|
|||
public static final String CERT_FILE_PATH="tokyobuilding-certs/"; |
|||
|
|||
/** |
|||
* 从AWS S3下载指定路径的文件到本地系统。 |
|||
* |
|||
* @param filePath S3中文件的路径。 |
|||
* @return 下载文件的本地路径。 |
|||
*/ |
|||
public String getFilePath(String filePath) { |
|||
if (StringUtils.isEmpty(filePath)) { |
|||
return ""; |
|||
} |
|||
String bucket = awsBucketAdress; |
|||
|
|||
// 创建获取对象的请求
|
|||
GetObjectRequest getObjectRequest = GetObjectRequest.builder() |
|||
.bucket(bucket) |
|||
.key(CERT_FILE_PATH + filePath) |
|||
.build(); |
|||
String tmpDir = System.getProperty("java.io.tmpdir"); |
|||
// 下载文件到本地路径
|
|||
Region region = Region.AP_NORTHEAST_1; |
|||
|
|||
S3Client s3 = S3Client |
|||
.builder().region(region) |
|||
.credentialsProvider(StaticCredentialsProvider |
|||
.create(AwsBasicCredentials.create(awsAccessKeyId, awsAccessSecret))) |
|||
.build(); |
|||
|
|||
String localPath = tmpDir + File.separator + "certs" + File.separator + System.currentTimeMillis() + File.separator + filePath; |
|||
|
|||
s3.getObject(getObjectRequest, (response, inputStream) -> { |
|||
if (response.sdkHttpResponse().isSuccessful()) { |
|||
// Handle the response here
|
|||
Path path = Paths.get(localPath); |
|||
if (path.getParent() != null) { |
|||
FileUtils.forceMkdir(path.getParent().toFile()); |
|||
} |
|||
|
|||
try (OutputStream outputStream = FileUtils.openOutputStream(path.toFile())) { |
|||
byte[] bytes = new byte[1024]; |
|||
int len; |
|||
while ((len = inputStream.read(bytes)) != -1) { |
|||
outputStream.write(bytes, 0, len); |
|||
} |
|||
} catch (IOException e) { |
|||
log.error("下载文件失败", e); |
|||
} |
|||
} else { |
|||
throw new RuntimeException("Failed to get object from AWS S3"); |
|||
} |
|||
return null; |
|||
}); |
|||
|
|||
return localPath; |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import com.techsor.datacenter.receiver.utils.DateUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
|
|||
import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.Objects; |
|||
|
|||
//@Component
|
|||
//@Repository
|
|||
//@EnableScan
|
|||
//public interface MqttHistoryDynamoDBService extends DynamoDBCrudRepository<BaseTransDataEntity, UUID> {
|
|||
//
|
|||
//}
|
|||
@Slf4j |
|||
@Component |
|||
public class MqttHistoryDynamoDBService { |
|||
|
|||
//@Resource
|
|||
private DynamoDBTemplate dynamoDBTemplate; |
|||
|
|||
@Resource |
|||
private DuplicateDataProcessor duplicateDataProcessor; |
|||
public void save(BaseTransDataEntity baseTransDataEntity) { |
|||
// if (Objects.isNull(baseTransDataEntity)){
|
|||
// return;
|
|||
// }
|
|||
//
|
|||
// boolean flag=this.duplicateDataProcessor.removeDuplicateData(baseTransDataEntity.getContent());
|
|||
// log.debug("save data to dynamoDB flag:{},{}",baseTransDataEntity.getContent(),flag);
|
|||
// if (!flag){
|
|||
// return;
|
|||
// }
|
|||
// baseTransDataEntity.setDateKey(DateUtils.getCurrentDate());
|
|||
// this.dynamoDBTemplate.save(baseTransDataEntity);
|
|||
// log.debug("save data to dynamoDB success");
|
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.jdbc.core.JdbcTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@Service("mqttHistoryService") |
|||
public class MqttHistoryService { |
|||
private static final Logger logger = LoggerFactory.getLogger(MqttHistoryService.class); |
|||
|
|||
@Resource |
|||
private JdbcTemplate jdbcTemplate; |
|||
|
|||
public void insertHistory(BaseTransDataEntity mqttHistoryEntity){ |
|||
logger.info("insertHistory is disabled now "); |
|||
//编写sql语句
|
|||
String sql = "insert into mqtt_history(content,ts) values(\'"+mqttHistoryEntity.getContent()+"\',\'"+mqttHistoryEntity.getTs()+"\')"; |
|||
logger.info("Execute SQL: {}",sql); |
|||
//调用他的update方法
|
|||
Integer result = jdbcTemplate.update(sql); |
|||
if (result==1){ |
|||
logger.info("Save succeed."); |
|||
}else{ |
|||
logger.warn("Save failed, content:"+mqttHistoryEntity.getContent()); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.jdbc.core.JdbcTemplate; |
|||
import org.springframework.jdbc.core.RowMapper; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.sql.ResultSet; |
|||
import java.sql.SQLException; |
|||
import java.util.List; |
|||
|
|||
@Service |
|||
public class MqttPublisherService { |
|||
|
|||
@Resource |
|||
private JdbcTemplate jdbcTemplate ; |
|||
|
|||
public List<MqttPublisherEntity> getList(){ |
|||
String sql = "SELECT * FROM mqtt_publisher"; |
|||
List<MqttPublisherEntity> dataList = (List<MqttPublisherEntity>) jdbcTemplate.query(sql, new RowMapper<MqttPublisherEntity>(){ |
|||
@Override |
|||
public MqttPublisherEntity mapRow(ResultSet rs, int rowNum) throws SQLException { |
|||
MqttPublisherEntity dataItem = new MqttPublisherEntity(); |
|||
dataItem.setId(rs.getInt("id")); |
|||
dataItem.setHost(rs.getString("host")); |
|||
dataItem.setUsername(rs.getString("username")); |
|||
dataItem.setPassword(rs.getString("password")); |
|||
dataItem.setTopic(rs.getString("topic")); |
|||
dataItem.setDescription(rs.getString("description")); |
|||
return dataItem; |
|||
} |
|||
}); |
|||
|
|||
return dataList; |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import org.apache.commons.text.StringEscapeUtils; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.jdbc.core.JdbcTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
|
|||
@Service |
|||
public class RestfulService { |
|||
|
|||
@Resource |
|||
private JdbcTemplate jdbcTemplate; |
|||
private static final Logger logger = LoggerFactory.getLogger(RestfulService.class); |
|||
|
|||
|
|||
public void insertHistory(String content,String company) { |
|||
|
|||
content = StringEscapeUtils.escapeJson(content); |
|||
String sql = "insert into restful_history (content,company,ts) values (\""+content+"\",\""+company+"\",\""+System.currentTimeMillis()/1000+"\")"; |
|||
logger.debug("insertHistory : "+sql); |
|||
logger.debug("From : "+company); |
|||
|
|||
jdbcTemplate.execute(sql); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.techsor.datacenter.receiver.service; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.common.KafkaClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
@Service |
|||
public interface ZetaKafkaService { |
|||
|
|||
|
|||
void addKafkaClient(Long companyId, Long configId, KafkaClientConfig config, DatasourceConfigEntity datasourceConfigEntity); |
|||
|
|||
public void removeKafkaClient(Long companyId,Long configId); |
|||
|
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
package com.techsor.datacenter.receiver.service.impl; |
|||
|
|||
import com.google.gson.Gson; |
|||
import com.techsor.datacenter.receiver.config.datasource.DataSourceContextHolder; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import com.techsor.datacenter.receiver.service.GlobalStateService; |
|||
import com.techsor.datacenter.receiver.service.IDataReceiveService; |
|||
import com.techsor.datacenter.receiver.service.IDataSourceConfigService; |
|||
import com.techsor.datacenter.receiver.service.IMQTTService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 数据接收服务实现,用于管理数据源的接收状态。 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class DataReceiveServiceImpl implements IDataReceiveService { |
|||
|
|||
|
|||
@Resource |
|||
private IDataSourceConfigService dataSourceConfigService; |
|||
|
|||
@Resource |
|||
private GlobalStateService globalStateService; |
|||
@Resource |
|||
private IMQTTService mqttService; |
|||
|
|||
@Value("${base.companyId}") |
|||
private Long baseComanyId; |
|||
|
|||
|
|||
/** |
|||
* 根据提供的状态和数据源ID列表,启动或停止相应的数据接收客户端。 |
|||
* |
|||
* @param state 数据源的期望状态,"0"表示启动,其他值表示停止。 |
|||
* @param params 数据源ID的列表,用于指定哪些数据源需要被处理。 |
|||
*/ |
|||
@Override |
|||
public void receiveCurrentDataSrc(String state, List<Long> params) { |
|||
DataSourceContextHolder.setCurrentDataSourceKey("dataSourceForCompany_" + baseComanyId); |
|||
List<DatasourceConfigEntity> resultList = this.dataSourceConfigService.getDataSourceConfig(params); |
|||
|
|||
for (int i = 0; i < resultList.size(); i++) { |
|||
DatasourceConfigEntity item = resultList.get(i); |
|||
if (StringUtils.equals("0",state)){ |
|||
//判断类型,MQTT
|
|||
if (StringUtils.equals("0",item.getMethodType())) { |
|||
//mqtt
|
|||
Gson gson=new Gson(); |
|||
MqttClientConfig mqttClientConfig=gson.fromJson(item.getParams(), MqttClientConfig.class); |
|||
this.mqttService.addMQTTConsumerClient(baseComanyId,item.getId(),mqttClientConfig,item); |
|||
}else{ |
|||
//http
|
|||
this.globalStateService.addDatasourceConfig(item); |
|||
} |
|||
}else{ |
|||
|
|||
if (StringUtils.equals("0",item.getMethodType())) { |
|||
//mqtt
|
|||
this.mqttService.removeMQTTConsumerClient(item.getId()); |
|||
}else{ |
|||
this.globalStateService.removeDatasourceConfig(item); |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,115 @@ |
|||
package com.techsor.datacenter.receiver.service.impl; |
|||
|
|||
import com.techsor.datacenter.receiver.entity.company.CompanyEntity; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import com.techsor.datacenter.receiver.service.IDataSourceConfigService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.collections.CollectionUtils; |
|||
import org.springframework.jdbc.core.JdbcTemplate; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
|
|||
@Slf4j |
|||
@Service |
|||
public class DataSourceConfigServiceImpl implements IDataSourceConfigService { |
|||
|
|||
|
|||
@Resource |
|||
private JdbcTemplate jdbcTemplate; |
|||
@Resource |
|||
private JdbcTemplate dynamicJdbcTemplate; |
|||
|
|||
|
|||
/** |
|||
* create table data_src_config |
|||
* ( |
|||
* id bigint auto_increment |
|||
* primary key, |
|||
* code varchar(100) null comment '数据来源识别代码', |
|||
* api_key varchar(100) null comment 'api_key', |
|||
* name varchar(100) null comment '数据来源名称', |
|||
* method_type varchar(2) null comment '来源方式(0:MQTT;1:RESTFULL)', |
|||
* params varchar(1000) null comment '链接参数', |
|||
* state varchar(2) null comment '状态;(0:激活;1:冻结;)', |
|||
* created_by bigint null, |
|||
* created_timestamp timestamp null, |
|||
* updated_by bigint null, |
|||
* updated_timestamp timestamp null, |
|||
* company_id bigint not null |
|||
* ) |
|||
* comment '数据来源配置表'; |
|||
* */ |
|||
@Override |
|||
public List<DatasourceConfigEntity> getDataSourceConfig(List<Long> datasourceIds) { |
|||
|
|||
if (CollectionUtils.isEmpty(datasourceIds)){ |
|||
return new ArrayList<>(); |
|||
} |
|||
//查询激活后的数据源配置
|
|||
String sql="select * from data_src_config where id in (%s) "; |
|||
|
|||
StringBuffer sb=new StringBuffer(); |
|||
datasourceIds.stream().forEach(iter->{ |
|||
sb.append(iter).append(","); |
|||
}); |
|||
sb.deleteCharAt(sb.length()-1); |
|||
sql=String.format(sql,sb.toString()); |
|||
|
|||
List<DatasourceConfigEntity> resultList = this.dynamicJdbcTemplate.query(sql, |
|||
(rs, rowNum) -> { |
|||
DatasourceConfigEntity item = new DatasourceConfigEntity(); |
|||
item.setId(rs.getLong("id")); |
|||
item.setCode(rs.getString("code")); |
|||
item.setApiKey(rs.getString("api_key")); |
|||
item.setName(rs.getString("name")); |
|||
item.setMethodType(rs.getString("method_type")); |
|||
item.setParams(rs.getString("params")); |
|||
item.setState(rs.getString("state")); |
|||
item.setDeviceIdPosition(rs.getString("device_id_position")); |
|||
return item; |
|||
}); |
|||
|
|||
return resultList; |
|||
} |
|||
|
|||
@Override |
|||
public List<DatasourceConfigEntity> getDataSourceConfigWithState() { |
|||
|
|||
//查询激活后的数据源配置
|
|||
String sql="select * from data_src_config where state='0' and flag=0 "; |
|||
|
|||
List<DatasourceConfigEntity> resultList = this.dynamicJdbcTemplate.query(sql, |
|||
(rs, rowNum) -> { |
|||
DatasourceConfigEntity item = new DatasourceConfigEntity(); |
|||
item.setId(rs.getLong("id")); |
|||
item.setCode(rs.getString("code")); |
|||
item.setApiKey(rs.getString("api_key")); |
|||
item.setName(rs.getString("name")); |
|||
item.setMethodType(rs.getString("method_type")); |
|||
item.setParams(rs.getString("params")); |
|||
item.setState(rs.getString("state")); |
|||
item.setDeviceIdPosition(rs.getString("device_id_position")); |
|||
return item; |
|||
}); |
|||
|
|||
return resultList; |
|||
} |
|||
|
|||
@Override |
|||
public List<CompanyEntity> getRelatedTopCompany(String baseCompanyId) { |
|||
String sql="SELECT bcom.id,bcom.parent_id FROM data_center_aeon_admin.basic_company bcom WHERE bcom.id="+baseCompanyId+" and bcom.flag!=1"; |
|||
List<CompanyEntity> dataList = this.jdbcTemplate.query(sql, (rs, rowNum) -> { |
|||
CompanyEntity item = new CompanyEntity(); |
|||
item.setId(rs.getLong("id")); |
|||
item.setParentId(rs.getLong("parent_id")); |
|||
return item; |
|||
}); |
|||
return dataList; |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,465 @@ |
|||
package com.techsor.datacenter.receiver.service.impl; |
|||
|
|||
import com.alibaba.fastjson2.JSON; |
|||
import com.google.gson.Gson; |
|||
import com.google.gson.JsonArray; |
|||
import com.google.gson.JsonElement; |
|||
import com.jayway.jsonpath.JsonPath; |
|||
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig; |
|||
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity; |
|||
import com.techsor.datacenter.receiver.service.DataTransService; |
|||
import com.techsor.datacenter.receiver.service.GuavaRedisCache; |
|||
import com.techsor.datacenter.receiver.service.IMQTTService; |
|||
import com.techsor.datacenter.receiver.service.MQTTCrtService; |
|||
import com.techsor.datacenter.receiver.utils.JsonUtils; |
|||
import com.techsor.datacenter.receiver.utils.MyHTTPResponse; |
|||
import com.techsor.datacenter.receiver.utils.RandomUtils; |
|||
import com.techsor.datacenter.receiver.utils.SslUtil; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.apache.commons.lang3.tuple.Pair; |
|||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; |
|||
import org.springframework.integration.mqtt.core.MqttPahoClientFactory; |
|||
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; |
|||
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; |
|||
import org.springframework.messaging.Message; |
|||
import org.springframework.messaging.support.AbstractMessageChannel; |
|||
import org.springframework.scheduling.TaskScheduler; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import jakarta.annotation.Resource; |
|||
import javax.net.ssl.SSLContext; |
|||
import javax.net.ssl.SSLSocketFactory; |
|||
import javax.net.ssl.TrustManager; |
|||
import javax.net.ssl.X509TrustManager; |
|||
import java.security.SecureRandom; |
|||
import java.security.cert.X509Certificate; |
|||
import java.time.Duration; |
|||
import java.time.LocalDate; |
|||
import java.time.ZoneId; |
|||
import java.time.ZonedDateTime; |
|||
import java.time.format.DateTimeFormatter; |
|||
import java.util.*; |
|||
import java.util.concurrent.*; |
|||
|
|||
/** |
|||
* MQTT服务实现类,用于管理MQTT消费者客户端的添加和移除,以及处理MQTT消息。 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class MQTTServiceImpl implements IMQTTService { |
|||
|
|||
|
|||
private MqttConsumerCache consumerCache = new MqttConsumerCache(2000); // Max 1000 consumers in cache
|
|||
|
|||
@Resource |
|||
private DataTransService dataTransService; |
|||
|
|||
@Value("${mqtt.keepAliveInterval}") |
|||
private Integer keepAliveInterval; |
|||
|
|||
@Resource |
|||
MQTTCrtService mqttCrtService; |
|||
@Resource |
|||
private TaskScheduler taskScheduler; |
|||
|
|||
@Resource |
|||
private RedisTemplate<String, Object> redisTemplate; |
|||
|
|||
@Resource |
|||
private Executor postSenderThreadTaskExecutor; |
|||
|
|||
@Resource |
|||
private GuavaRedisCache guavaRedisCache; |
|||
/** |
|||
* 根据提供的MQTT客户端配置创建MQTT客户端工厂实例。 |
|||
* |
|||
* @param config MQTT客户端配置对象。 |
|||
* @return 创建的MQTT客户端工厂实例。 |
|||
* @throws Exception 如果创建过程中发生错误,则抛出异常。 |
|||
*/ |
|||
private MqttPahoClientFactory mqttClientFactory(MqttClientConfig config) throws Exception { |
|||
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); |
|||
MqttConnectOptions options = new MqttConnectOptions(); |
|||
options.setServerURIs(new String[]{config.getUrl()}); |
|||
options.setUserName(config.getUsername()); |
|||
options.setPassword(config.getPassword().toCharArray()); |
|||
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1); |
|||
|
|||
if(config.isSslState()){ |
|||
String caCrtFile=config.getCaPath(); |
|||
String crtFile=config.getClientCrtPath(); |
|||
String keyFile=config.getClientKeyPath(); |
|||
|
|||
String localCaCrtFilePath=this.mqttCrtService.getFilePath(caCrtFile); |
|||
String localCrtFile=this.mqttCrtService.getFilePath(crtFile); |
|||
String localKeyFile=this.mqttCrtService.getFilePath(keyFile); |
|||
options.setSocketFactory(SslUtil.getSocketFactory(localCaCrtFilePath, localCrtFile, localKeyFile, "")); |
|||
options.setHttpsHostnameVerificationEnabled(false); |
|||
} |
|||
if (Objects.nonNull(config.getConnectionTimeout())) { |
|||
if (config.getConnectionTimeout() > 0){ |
|||
options.setConnectionTimeout(config.getConnectionTimeout()); |
|||
}else { |
|||
options.setConnectionTimeout(1000); |
|||
} |
|||
} |
|||
// Set mqtt-heartbeat interval
|
|||
options.setKeepAliveInterval(this.keepAliveInterval); |
|||
options.setAutomaticReconnect(true); |
|||
factory.setConnectionOptions(options); |
|||
return factory; |
|||
} |
|||
|
|||
/** |
|||
* 添加一个MQTT消费者客户端到消费者缓存中,并启动它。 |
|||
* |
|||
* @param id 消费者客户端的唯一标识。 |
|||
* @param config MQTT客户端配置。 |
|||
* @param datasourceConfigEntity 数据源配置实体。 |
|||
*/ |
|||
@Override |
|||
public void addMQTTConsumerClient(Long companyId,Long id, MqttClientConfig config, DatasourceConfigEntity datasourceConfigEntity) { |
|||
if (!consumerCache.containsKey(String.valueOf(id))) { |
|||
MqttConsumer consumer = null; |
|||
try { |
|||
if (Objects.isNull(config)){ |
|||
return; |
|||
} |
|||
consumer = new MqttConsumer(config, mqttClientFactory(config),this.dataTransService, |
|||
this.taskScheduler,datasourceConfigEntity,this.postSenderThreadTaskExecutor, |
|||
this.redisTemplate, |
|||
this.guavaRedisCache |
|||
); |
|||
} catch (Exception e) { |
|||
// throw new RuntimeException(e);
|
|||
log.error("addMQTTConsumerClient error:{}",e.getMessage()); |
|||
return; |
|||
} |
|||
consumerCache.put(String.valueOf(id), consumer); |
|||
consumer.start(); |
|||
} |
|||
} |
|||
/** |
|||
* 从消费者缓存中移除指定的MQTT消费者客户端,并停止它。 |
|||
* |
|||
* @param id 要移除的消费者客户端的唯一标识。 |
|||
*/ |
|||
@Override |
|||
public void removeMQTTConsumerClient(Long id) { |
|||
String key=String.valueOf(id); |
|||
if (this.consumerCache.containsKey(key)){ |
|||
this.consumerCache.get(key).stop(); |
|||
this.consumerCache.remove(key); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* MQTT消费者类,负责接收MQTT消息并进行处理。 |
|||
*/ |
|||
@Slf4j |
|||
class MqttConsumer { |
|||
private MqttPahoMessageDrivenChannelAdapter adapter; |
|||
private MqttClientConfig config; |
|||
|
|||
|
|||
private DatasourceConfigEntity datasourceConfigEntity; |
|||
|
|||
private Executor postSenderThreadTaskExecutor; |
|||
|
|||
|
|||
private DataTransService dataTransService; |
|||
|
|||
// 使用ConcurrentLinkedQueue代替List来存储需要重试的请求
|
|||
private final ConcurrentLinkedQueue<Pair<String, String>> retryRequests = new ConcurrentLinkedQueue<>(); |
|||
private final ScheduledExecutorService scheduleRetryTaskExecutor = Executors.newScheduledThreadPool(1); |
|||
private static final int MAX_RETRY_ATTEMPTS = 5; |
|||
private final Map<Pair<String, String>, Integer> retryAttempts = new ConcurrentHashMap<>(); |
|||
|
|||
private RedisTemplate<String, Object> redisTemplate; |
|||
|
|||
|
|||
private GuavaRedisCache guavaRedisCache; |
|||
/** |
|||
* 构造一个新的MQTT消费者实例。 |
|||
* 此构造函数初始化MQTT消费者,并设置消息处理逻辑。 |
|||
* |
|||
* @param config MQTT客户端配置,包含连接信息和客户端特定配置。 |
|||
* @param clientFactory 用于创建MQTT客户端的工厂,根据提供的配置生成连接选项。 |
|||
* @param dataTransService 用于数据传输的服务,处理接收到的MQTT消息。 |
|||
* @param taskScheduler 任务调度器,用于调度异步任务,例如消息重传。 |
|||
* @param datasourceConfigEntity 数据源配置实体,包含数据处理规则和目标信息。 |
|||
* @param postSenderThreadTaskExecutor 用于执行后台任务的执行器,如发送消息到目的地。 |
|||
*/ |
|||
public MqttConsumer(MqttClientConfig config, MqttPahoClientFactory clientFactory, |
|||
DataTransService dataTransService, |
|||
TaskScheduler taskScheduler, |
|||
DatasourceConfigEntity datasourceConfigEntity, |
|||
Executor postSenderThreadTaskExecutor, |
|||
RedisTemplate<String, Object> redisTemplate, |
|||
GuavaRedisCache guavaRedisCache |
|||
) { |
|||
this.config = config; |
|||
if (StringUtils.isBlank(config.getClientId())) { |
|||
config.setClientId(UUID.randomUUID().toString()); |
|||
} |
|||
String clientId = config.getClientId()+ RandomUtils.unique3DigitGenerator()+UUID.randomUUID().toString(); |
|||
String topics=config.getTopic(); |
|||
if (StringUtils.contains(topics,",")){ |
|||
String[] topicArrays=topics.split(","); |
|||
this.adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, clientFactory, topicArrays); |
|||
}else{ |
|||
this.adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, clientFactory, config.getTopic()); |
|||
} |
|||
|
|||
adapter.setCompletionTimeout(5000); |
|||
adapter.setRecoveryInterval(5000); |
|||
adapter.setConverter(new DefaultPahoMessageConverter()); |
|||
if (!Objects.nonNull(config.getQos())){ |
|||
adapter.setQos(1); |
|||
}else{ |
|||
adapter.setQos(config.getQos()); |
|||
} |
|||
this.dataTransService = dataTransService; |
|||
this.datasourceConfigEntity=datasourceConfigEntity; |
|||
this.postSenderThreadTaskExecutor=postSenderThreadTaskExecutor; |
|||
adapter.setTaskScheduler(taskScheduler); |
|||
final DataTransService finalDataTransService=dataTransService; |
|||
this.redisTemplate=redisTemplate; |
|||
this.guavaRedisCache=guavaRedisCache; |
|||
adapter.setOutputChannel(new AbstractMessageChannel() { |
|||
@Override |
|||
protected boolean sendInternal(Message<?> message, long timeout) { |
|||
// 在这里处理接收到的消息
|
|||
log.debug("Received Message:{}", message.getPayload()); |
|||
if (message.getPayload() == null) { |
|||
return true; |
|||
} |
|||
// 根据配置的设备ID位置,从消息中提取设备ID
|
|||
String deviceIdPosition = datasourceConfigEntity.getDeviceIdPosition(); |
|||
|
|||
//此处做如下操作
|
|||
if (StringUtils.isEmpty(deviceIdPosition)) { |
|||
log.warn("deviceIdPosition is null:==>{}", datasourceConfigEntity); |
|||
return true; |
|||
} |
|||
String[] deviceIdPositionArrays; |
|||
if (JsonUtils.isJsonArray(deviceIdPosition)){ |
|||
deviceIdPositionArrays= JSON.parseArray(deviceIdPosition,String.class).toArray(new String[0]); |
|||
}else { |
|||
deviceIdPositionArrays=new String[]{deviceIdPosition}; |
|||
} |
|||
//解析出多个设备ID
|
|||
|
|||
Gson gson = new Gson(); |
|||
String payloadStr = message.getPayload() instanceof String |
|||
? (String) message.getPayload() |
|||
: gson.toJson(message.getPayload()); |
|||
|
|||
String trimData = StringUtils.trim(payloadStr); |
|||
if (!JsonUtils.isJson(trimData)) { |
|||
log.warn("data is not json:==>{}", datasourceConfigEntity, trimData); |
|||
return true; |
|||
} |
|||
if (JsonUtils.isJsonArray(trimData)) { |
|||
|
|||
postSenderThreadTaskExecutor.execute(() -> { |
|||
JsonArray resultJsonArrays = gson.fromJson(trimData, JsonArray.class); |
|||
for (JsonElement element : resultJsonArrays) { |
|||
String currentJsonValue = gson.toJson(element); |
|||
//获取最终设备ID位置信息
|
|||
String finalDevicePosition=extractDevicePosition(currentJsonValue,deviceIdPositionArrays); |
|||
String deviceId = JsonPath.read(currentJsonValue, finalDevicePosition); |
|||
|
|||
if (StringUtils.isEmpty(deviceId)) { |
|||
log.warn("deviceId is null:==>{}", datasourceConfigEntity); |
|||
continue; |
|||
} |
|||
//计数
|
|||
guavaRedisCache.incrementDailyDeviceIdCount(deviceId); |
|||
MyHTTPResponse response=finalDataTransService.transferData(deviceId, currentJsonValue); |
|||
if (response.getCode()!=200){ |
|||
log.error("transferData error:{}",currentJsonValue); |
|||
synchronized (retryRequests){ |
|||
retryRequests.add(Pair.of(deviceId,currentJsonValue)); |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
} else { |
|||
if(StringUtils.isEmpty(trimData)){ |
|||
return true; |
|||
} |
|||
if (!JsonUtils.isJson(trimData)) { |
|||
return true; |
|||
} |
|||
String deviceId = JsonPath.read(trimData, deviceIdPosition); |
|||
if (StringUtils.isEmpty(deviceId)) { |
|||
log.warn("deviceId is null:==>{}", datasourceConfigEntity); |
|||
return true; |
|||
} |
|||
guavaRedisCache.incrementDailyDeviceIdCount(deviceId); |
|||
MyHTTPResponse response=finalDataTransService.transferData(deviceId, trimData); |
|||
if (response.getCode()!=200){ |
|||
log.error("transferData error:{}",trimData); |
|||
synchronized (retryRequests){ |
|||
retryRequests.add(Pair.of(deviceId,trimData)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
}); |
|||
// 定时任务改为只处理队列的头部请求,避免一次处理整个队列
|
|||
scheduleRetryTaskExecutor.scheduleWithFixedDelay(() -> { |
|||
if (!retryRequests.isEmpty()) { |
|||
Pair<String, String> request = retryRequests.poll(); // 获取并移除此队列的头部
|
|||
if (request != null) { |
|||
retryFailedMessage(request); |
|||
} |
|||
} |
|||
}, 0, 5, TimeUnit.SECONDS); |
|||
} |
|||
|
|||
|
|||
private void retryFailedMessage(Pair<String, String> request) { |
|||
Integer attempts = retryAttempts.getOrDefault(request, 0); |
|||
if (attempts >= MAX_RETRY_ATTEMPTS) { |
|||
log.error("Reached max retry attempts, discarding it."); |
|||
retryAttempts.remove(request); |
|||
} else { |
|||
try { |
|||
sendAndRetry(request); |
|||
} catch (Exception e) { |
|||
log.error("Error retrying, request: {}", request, e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
private void sendAndRetry(Pair<String, String> request) { |
|||
MyHTTPResponse response = dataTransService.transferData(request.getLeft(), request.getRight()); |
|||
if (response.getCode() != 200) { |
|||
log.error("Transfer data failed, retrying... Request: {}", request); |
|||
log.error("Response: {}", new Gson().toJson(response)); |
|||
Integer attempts = retryAttempts.compute(request, (k, v) -> (v == null) ? 1 : v + 1); |
|||
if (attempts < MAX_RETRY_ATTEMPTS) { |
|||
retryRequests.offer(request); // 重新加入队列末尾
|
|||
} else { |
|||
log.error("Reached max retry attempts, discarding request: {}", request); |
|||
retryAttempts.remove(request); |
|||
} |
|||
} else { |
|||
log.info("Data transferred successfully on retry. Request: {}", request); |
|||
retryAttempts.remove(request); |
|||
} |
|||
} |
|||
|
|||
private String extractDevicePosition(String rootCurrentJsonValue,String[] deviceIdPositionArrays){ |
|||
String result=""; |
|||
for (int i = 0; i < deviceIdPositionArrays.length; i++) { |
|||
try{ |
|||
Object value=JsonPath.read(rootCurrentJsonValue,deviceIdPositionArrays[i]); |
|||
if (!Objects.isNull(value)){ |
|||
result = deviceIdPositionArrays[i]; |
|||
break; |
|||
} |
|||
}catch (Exception e){ |
|||
|
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
public MqttClientConfig getConfig() { |
|||
return this.config; |
|||
} |
|||
|
|||
public String getKeyForToday() { |
|||
LocalDate today = LocalDate.now(); |
|||
// 设置日本时区
|
|||
ZoneId japanZone = ZoneId.of("Asia/Tokyo"); |
|||
|
|||
// 获取日本时区的当前日期和时间
|
|||
ZonedDateTime nowInJapan = ZonedDateTime.now(japanZone); |
|||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
|||
// 计算昨天的日期
|
|||
LocalDate yesterdayInJapan = nowInJapan.toLocalDate(); |
|||
return "receiver:device:counts:" + formatter.format(yesterdayInJapan); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 启动MQTT消费者客户端,开始接收和处理消息。 |
|||
*/ |
|||
public void start() { |
|||
this.adapter.start(); |
|||
log.info("MqttConsumer start success:{}", this.config); |
|||
} |
|||
/** |
|||
* 停止MQTT消费者客户端,停止接收和处理消息。 |
|||
*/ |
|||
public void stop() { |
|||
log.info("MqttConsumer stop success:{}", this.config); |
|||
safeDisconnectMqttClient(); |
|||
} |
|||
private void safeDisconnectMqttClient() { |
|||
final int maxRetries = 3; // 最大重试次数
|
|||
int retryCount = 0; |
|||
|
|||
while (true) { |
|||
try { |
|||
if (this.adapter != null && this.adapter.isRunning()) { |
|||
this.adapter.stop(); // 尝试停止适配器
|
|||
this.adapter.destroy(); // 销毁适配器
|
|||
log.info("MQTT 客户端成功断开!!!!!!!!"); |
|||
break; // 成功后退出循环
|
|||
} |
|||
} catch (Exception e) { |
|||
log.info("尝试断开 MQTT 客户端时发生错误: " + e.getMessage()); |
|||
retryCount++; |
|||
if (retryCount >= maxRetries) { |
|||
log.info("尝试断开 MQTT 客户端失败达到最大次数,停止重试。"); |
|||
break; // 达到最大重试次数,退出循环
|
|||
} |
|||
try { |
|||
Thread.sleep(2000); // 等待2秒后重试
|
|||
} catch (InterruptedException ie) { |
|||
Thread.currentThread().interrupt(); // 保持良好的中断实践
|
|||
log.info("重试等待被中断。"); |
|||
break; |
|||
} |
|||
log.info("重试断开 MQTT 客户端。.............................."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
/** |
|||
* MQTT消费者缓存类,用于缓存和管理MQTT消费者客户端实例。 |
|||
* 当缓存达到最大容量时,最老的消费者客户端将被自动移除并停止。 |
|||
*/ |
|||
class MqttConsumerCache extends LinkedHashMap<String, MqttConsumer> { |
|||
private final int maxSize; |
|||
|
|||
public MqttConsumerCache(int maxSize) { |
|||
super(maxSize + 1, 1.0f, true); |
|||
this.maxSize = maxSize; |
|||
} |
|||
|
|||
@Override |
|||
protected boolean removeEldestEntry(Map.Entry<String, MqttConsumer> eldest) { |
|||
boolean shouldRemove = size() > maxSize; |
|||
|
|||
if (shouldRemove) { |
|||
MqttConsumer consumer = eldest.getValue(); |
|||
consumer.stop(); |
|||
} |
|||
|
|||
return shouldRemove; |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue