新疆后端项目
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/java
|
||||
{
|
||||
"name": "Java",
|
||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||
"image": "mcr.microsoft.com/devcontainers/java:1-8-bullseye",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/java:1": {
|
||||
"version": "none",
|
||||
"installMaven": "true",
|
||||
"installGradle": "false"
|
||||
}
|
||||
},
|
||||
"runArgs": [
|
||||
"--network",
|
||||
"dev",
|
||||
"-v",
|
||||
"dev-maven-repo:/home/vscode/.m2"
|
||||
],
|
||||
"containerEnv": {
|
||||
"NACOS_SERVER_ADDR": "nacos:8848",
|
||||
"NACOS_USERNAME": "cqyt",
|
||||
"NACOS_PASSWORD": "Aa123456",
|
||||
"NACOS_NAMESPACE": "2639a2d4-7b64-4408-98c9-b97e0bdf4c1f"
|
||||
},
|
||||
remoteEnv: {
|
||||
"PROFILE_NAME": "dev",
|
||||
"NACOS_GROUP": "dev"
|
||||
},
|
||||
"build": {
|
||||
"options": [
|
||||
"-t", "cqyt-platform-dev-image"
|
||||
]
|
||||
},
|
||||
|
||||
"customizations": {
|
||||
"jetbrains": {
|
||||
"backend": "IntelliJ"
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
*.js linguist-language=Java
|
||||
*.css linguist-language=Java
|
||||
*.html linguist-language=Java
|
||||
*.vue linguist-language=Java
|
||||
*.sql linguist-language=Java
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
## ide
|
||||
**/.idea
|
||||
*.iml
|
||||
rebel.xml
|
||||
uploadFile
|
||||
|
||||
## backend
|
||||
**/target
|
||||
**/logs
|
||||
|
||||
## front
|
||||
**/*.lock
|
||||
|
||||
## Fast Request Plugin
|
||||
**/.fastRequest
|
||||
**/test
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM eclipse-temurin:8-jdk
|
||||
#添加时区环境变量
|
||||
ENV TZ Asia/Shanghai
|
||||
#修改apt使用国内源
|
||||
RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
|
||||
&& sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
|
||||
#为镜像设置时区和字体包
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y fonts-dejavu \
|
||||
&& cp /usr/share/zoneinfo/${TZ} /etc/localtime \
|
||||
&& echo ${TZ} > /etc/timezone
|
||||
#将打包好的jar包封装进镜像
|
||||
ARG JAR_NAME=health-evaluate
|
||||
COPY ${JAR_NAME}.jar app.jar
|
||||
#镜像运行命令
|
||||
ENTRYPOINT [ "java", "-jar", "/app.jar" ]
|
||||
#ENV LOG4J_CONTEXT_SELECTOR org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
|
||||
EXPOSE 10001
|
||||
Vendored
+273
@@ -0,0 +1,273 @@
|
||||
def FeiShu(status, serviceName){
|
||||
def jobNameParts = JOB_NAME.tokenize('/') as String[]
|
||||
def folderName = jobNameParts[0]
|
||||
String statusText = ""
|
||||
if (status == 1) {
|
||||
statusText = "<font color=\\\"green\\\">成功<font>"
|
||||
} else if (status == 2) {
|
||||
statusText = "<font color=\\\"yellow\\\">不稳定<font>"
|
||||
} else {
|
||||
statusText = "<font color=\\\"red\\\">失败<font>"
|
||||
}
|
||||
env.COMMIT_SHORT_HASH = "${sh(script:'git log --pretty=format:\"%h\" --no-merges|head -1', returnStdout: true)}".trim()
|
||||
env.COMMIT_MESSAGE = "${sh(script:'git log --pretty=format:\"%s\" --no-merges|head -1', returnStdout: true)}".trim()
|
||||
env.COMMIT_AUTHOR = "${sh(script:'git log --pretty=format:\"%cn\" --no-merges|head -1', returnStdout: true)}".trim()
|
||||
sh """
|
||||
curl --location --request POST 'https://open.feishu.cn/open-apis/bot/v2/hook/1babaf75-a3e4-4bf0-b236-ee9112b5f68f' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"msg_type": "interactive",
|
||||
"card": {
|
||||
"config": {
|
||||
"update_multi": true,
|
||||
"enable_forward": true
|
||||
},
|
||||
"header": {
|
||||
"template": "blue",
|
||||
"title": {
|
||||
"content": "项目 四合一后端 构建报告",
|
||||
"tag": "plain_text"
|
||||
}
|
||||
},
|
||||
"card_link": {
|
||||
"url": "${JENKINS_URL}/blue/organizations/jenkins/${folderName}/detail/${BRANCH_NAME}/${BUILD_NUMBER}/pipeline",
|
||||
"pc_url": "",
|
||||
"android_url": "",
|
||||
"ios_url": ""
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"tag": "markdown",
|
||||
"content": "**构建分支**:${BRANCH_NAME}\\n**构建编号**:${BUILD_NUMBER}\\n**提交成员**:${COMMIT_AUTHOR}\\n**提交信息**:${COMMIT_MESSAGE}\\n**构建服务**:${serviceName}\\n**构建状态**:${statusText}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
"""
|
||||
}
|
||||
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
triggers {
|
||||
pollSCM('*/5 * * * *')
|
||||
}
|
||||
|
||||
environment {
|
||||
PROJECT_NAME = 'cqyt_system'
|
||||
}
|
||||
|
||||
stages{
|
||||
|
||||
stage("Update All Check") {
|
||||
|
||||
when {
|
||||
anyOf {
|
||||
branch "develop"
|
||||
branch "test"
|
||||
branch "master"
|
||||
}
|
||||
}
|
||||
|
||||
agent {
|
||||
docker {
|
||||
image "ubuntu:22.04"
|
||||
args "-v hash_storage:/hash"
|
||||
}
|
||||
}
|
||||
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/jeecg-boot-base-core") {
|
||||
sh '''#!/bin/bash -xe
|
||||
cp -r /hash/${PROJECT_NAME}/env ./
|
||||
buildFIle="./isBuild"
|
||||
sumPath="/hash/${PROJECT_NAME}/jeecg-boot-base-core"
|
||||
sumFile="${sumPath}/${BRANCH_NAME}"
|
||||
checksum=$(find . -type f -exec md5sum {} + | LC_ALL=C sort | md5sum)
|
||||
checksum=${checksum:0:32}
|
||||
if [[ ! -d ${sumPath} ]]
|
||||
then
|
||||
mkdir -p ${sumPath}
|
||||
fi
|
||||
if [[ ! -f ${sumFile} ]]
|
||||
then
|
||||
echo ${checksum} > ${sumFile}
|
||||
echo "TRUE" > ${buildFIle}
|
||||
else
|
||||
if [[ "${checksum}" = "$(cat ${sumFile})" ]]
|
||||
then
|
||||
echo "FALSE" > ${buildFIle}
|
||||
else
|
||||
echo ${checksum} > ${sumFile}
|
||||
echo "TRUE" > ${buildFIle}
|
||||
fi
|
||||
fi
|
||||
'''
|
||||
script {
|
||||
env.IS_BUILD = readFile('./isBuild').trim()
|
||||
env.NACOS_SERVER_ADDR = readFile("./env/NACOS_SERVER_ADDR").trim()
|
||||
env.NACOS_USERNAME = readFile("./env/NACOS_USERNAME").trim()
|
||||
env.NACOS_PASSWORD = readFile("./env/NACOS_PASSWORD").trim()
|
||||
env.NACOS_NAMESPACE = readFile("./env/NACOS_NAMESPACE").trim()
|
||||
if ( env.BRANCH_NAME == 'master' ) {
|
||||
env.NETWORK_NAME = 'stage'
|
||||
} else
|
||||
if ( env.BRANCH_NAME == 'test' ) {
|
||||
env.NETWORK_NAME = 'test'
|
||||
} else {
|
||||
env.NETWORK_NAME = 'dev'
|
||||
}
|
||||
env.PROFILE_NAME = env.NETWORK_NAME
|
||||
env.NACOS_GROUP = env.NETWORK_NAME
|
||||
}
|
||||
sh "rm -f ./isBuild"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stage("Microservice CI") {
|
||||
|
||||
when {
|
||||
anyOf {
|
||||
branch "develop"
|
||||
branch "test"
|
||||
branch "master"
|
||||
}
|
||||
}
|
||||
|
||||
matrix {
|
||||
|
||||
axes {
|
||||
|
||||
axis {
|
||||
name 'SERVICE_NAME'
|
||||
values 'jeecg-system', 'health-im', 'health-medical', 'health-emergency', 'health-consultation'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
stage("Diff Check") {
|
||||
agent {
|
||||
docker {
|
||||
image "ubuntu:22.04"
|
||||
args "-v hash_storage:/hash"
|
||||
}
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/${SERVICE_NAME}") {
|
||||
sh '''#!/bin/bash -xe
|
||||
buildFIle="./isBuild"
|
||||
if [[ "${IS_BUILD}" = "TRUE" ]]
|
||||
then
|
||||
echo "TRUE" > ${buildFIle}
|
||||
exit 0
|
||||
fi
|
||||
sumPath="/hash/${PROJECT_NAME}/${SERVICE_NAME}"
|
||||
sumFile="${sumPath}/${BRANCH_NAME}"
|
||||
checksum=$(find . -type f -exec md5sum {} + | LC_ALL=C sort | md5sum)
|
||||
checksum=${checksum:0:32}
|
||||
if [[ ! -d ${sumPath} ]]
|
||||
then
|
||||
mkdir -p ${sumPath}
|
||||
fi
|
||||
if [[ ! -f ${sumFile} ]]
|
||||
then
|
||||
echo ${checksum} > ${sumFile}
|
||||
echo "TRUE" > ${buildFIle}
|
||||
else
|
||||
if [[ "${checksum}" = "$(cat ${sumFile})" ]]
|
||||
then
|
||||
echo "FALSE" > ${buildFIle}
|
||||
else
|
||||
echo ${checksum} > ${sumFile}
|
||||
echo "TRUE" > ${buildFIle}
|
||||
fi
|
||||
fi
|
||||
'''
|
||||
script {
|
||||
env."${SERVICE_NAME}_IS_BUILD" = readFile('./isBuild').trim()
|
||||
}
|
||||
sh "rm -f ./isBuild"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Maven Package") {
|
||||
when {
|
||||
environment name: "${SERVICE_NAME}_IS_BUILD", value: "TRUE"
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image "maven:3-eclipse-temurin-8"
|
||||
args "-v maven-repo:/root/.m2 -v maven-conf:/usr/share/maven/conf"
|
||||
}
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}") {
|
||||
echo "Package ${SERVICE_NAME}"
|
||||
sh "mvn -pl health-system-boms,${SERVICE_NAME}/${SERVICE_NAME}-start -e -B -U -am clean install"
|
||||
}
|
||||
dir("${env.WORKSPACE}/${SERVICE_NAME}/${SERVICE_NAME}-start/target") {
|
||||
echo "Copy ${SERVICE_NAME} JAR"
|
||||
stash(name: "${SERVICE_NAME}_jar", includes: "${SERVICE_NAME}-start.jar")
|
||||
}
|
||||
dir("${env.WORKSPACE}") {
|
||||
echo "Clean Build"
|
||||
sh "mvn clean"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Docker Build & Run") {
|
||||
when {
|
||||
environment name: "${SERVICE_NAME}_IS_BUILD", value: "TRUE"
|
||||
}
|
||||
agent any
|
||||
environment {
|
||||
REGISTER_HOST = "registry.cn-shanghai.aliyuncs.com"
|
||||
REGISTER_REPO = "yg7709"
|
||||
IMAGE_NAME = "${PROJECT_NAME}_${SERVICE_NAME}"
|
||||
IMAGE_TAG_LATEST = "${BRANCH_NAME}-latest"
|
||||
IMAGE_TAG_COMMIT = "${BRANCH_NAME}-${GIT_COMMIT}"
|
||||
}
|
||||
steps {
|
||||
dir("${env.WORKSPACE}/.jenkins") {
|
||||
unstash("${SERVICE_NAME}_jar")
|
||||
echo "Docker Build ${SERVICE_NAME}"
|
||||
sh "docker compose -f docker-compose.build.yaml build"
|
||||
echo "Docker Push ${SERVICE_NAME}"
|
||||
sh "docker push ${REGISTER_HOST}/${REGISTER_REPO}/${IMAGE_NAME}:${IMAGE_TAG_LATEST}"
|
||||
sh "docker push ${REGISTER_HOST}/${REGISTER_REPO}/${IMAGE_NAME}:${IMAGE_TAG_COMMIT}"
|
||||
echo "Docker Deploy ${SERVICE_NAME}"
|
||||
sh "docker compose -p ${PROJECT_NAME}_${PROFILE_NAME} up -d ${SERVICE_NAME}"
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
FeiShu(1,SERVICE_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
post {
|
||||
unstable {
|
||||
FeiShu(2,SERVICE_NAME)
|
||||
}
|
||||
failure {
|
||||
FeiShu(3,SERVICE_NAME)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
ms-service:
|
||||
build:
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- "${IMAGE_NAME}:${IMAGE_TAG_LATEST}"
|
||||
- "${IMAGE_NAME}:${IMAGE_TAG_COMMIT}"
|
||||
- "${REGISTER_HOST}/${REGISTER_REPO}/${IMAGE_NAME}:${IMAGE_TAG_LATEST}"
|
||||
- "${REGISTER_HOST}/${REGISTER_REPO}/${IMAGE_NAME}:${IMAGE_TAG_COMMIT}"
|
||||
args:
|
||||
JAR_NAME: ${SERVICE_NAME}-start
|
||||
@@ -0,0 +1,102 @@
|
||||
#版本
|
||||
version: '3.9'
|
||||
|
||||
x-template:
|
||||
service: &service_tmp
|
||||
environment:
|
||||
- NACOS_SERVER_ADDR=${NACOS_SERVER_ADDR}
|
||||
- NACOS_USERNAME=${NACOS_USERNAME}
|
||||
- NACOS_PASSWORD=${NACOS_PASSWORD}
|
||||
- NACOS_NAMESPACE=${NACOS_NAMESPACE}
|
||||
- NACOS_GROUP=${NACOS_GROUP}
|
||||
- PROFILE_NAME=${PROFILE_NAME}
|
||||
restart: always
|
||||
tty: true
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '4'
|
||||
memory: 4G
|
||||
reservations:
|
||||
cpus: '1'
|
||||
memory: 512M
|
||||
extra_hosts:
|
||||
- "yg.dt.io:192.168.1.5"
|
||||
|
||||
#服务配置
|
||||
services:
|
||||
|
||||
jeecg-system:
|
||||
<<: *service_tmp
|
||||
container_name: system-${PROFILE_NAME}
|
||||
hostname: system-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_jeecg-system:${IMAGE_TAG_LATEST}
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-f", "http://localhost:7001/actuator/health" ]
|
||||
interval: 2m
|
||||
timeout: 2s
|
||||
retries: 5
|
||||
start_period: 5m
|
||||
|
||||
health-consultation:
|
||||
<<: *service_tmp
|
||||
container_name: consultation-${PROFILE_NAME}
|
||||
hostname: consultation-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-consultation:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-emergency:
|
||||
<<: *service_tmp
|
||||
container_name: emergency-${PROFILE_NAME}
|
||||
hostname: emergency-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-emergency:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-im:
|
||||
<<: *service_tmp
|
||||
container_name: im-${PROFILE_NAME}
|
||||
hostname: im-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-im:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-medical:
|
||||
<<: *service_tmp
|
||||
container_name: medical-${PROFILE_NAME}
|
||||
hostname: medical-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-medical:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-medical-gi:
|
||||
<<: *service_tmp
|
||||
container_name: medical-gi-${PROFILE_NAME}
|
||||
hostname: medical-gi-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-medical-gi:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-archives:
|
||||
<<: *service_tmp
|
||||
container_name: archives-${PROFILE_NAME}
|
||||
hostname: archives-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-archives:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-watch:
|
||||
<<: *service_tmp
|
||||
container_name: watch-${PROFILE_NAME}
|
||||
hostname: watch-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-watch:${IMAGE_TAG_LATEST}
|
||||
|
||||
health-intervene:
|
||||
<<: *service_tmp
|
||||
container_name: intervene-${PROFILE_NAME}
|
||||
hostname: intervene-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_health-intervene:${IMAGE_TAG_LATEST}
|
||||
depends_on:
|
||||
jeecg-system:
|
||||
condition: service_healthy
|
||||
|
||||
medical-center:
|
||||
<<: *service_tmp
|
||||
container_name: medical-center-${PROFILE_NAME}
|
||||
hostname: medical-center-${PROFILE_NAME}
|
||||
image: ${REGISTER_HOST}/${REGISTER_REPO}/${PROJECT_NAME}_medical-center:${IMAGE_TAG_LATEST}
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: ${NETWORK_NAME}
|
||||
external: true
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2019 <a href="http://www.jeecg.com">Jeecg Boot</a> All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
|
||||
|
||||
开源协议补充
|
||||
JeecgBoot 是由 北京敲敲云科技有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
|
||||
|
||||
1.允许基于本平台软件开展业务系统开发。
|
||||
2.不得基于该平台软件的基础,修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售,或与JeecgBoot参与同类软件产品市场的竞争。
|
||||
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
|
||||
解释权归:http://www.jeecg.com
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
FROM mysql:8.0.19
|
||||
|
||||
MAINTAINER jeecgos@163.com
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
COPY ./tables_nacos.sql /docker-entrypoint-initdb.d
|
||||
|
||||
COPY ./jeecgboot-mysql-5.7.sql /docker-entrypoint-initdb.d
|
||||
|
||||
COPY ./tables_xxl_job.sql /docker-entrypoint-initdb.d
|
||||
@@ -0,0 +1,146 @@
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
loginUsername: admin
|
||||
loginPassword: 123456
|
||||
allow:
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
dynamic:
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
maxActive: 20
|
||||
maxWait: 60000
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
poolPreparedStatements: true
|
||||
maxPoolPreparedStatementPerConnectionSize: 20
|
||||
filters: stat,wall,slf4j
|
||||
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
|
||||
datasource:
|
||||
master:
|
||||
url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: root
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
redis:
|
||||
database: 0
|
||||
host: jeecg-boot-redis
|
||||
password:
|
||||
port: 6379
|
||||
rabbitmq:
|
||||
host: jeecg-boot-rabbitmq
|
||||
username: guest
|
||||
password: guest
|
||||
port: 5672
|
||||
publisher-confirms: true
|
||||
publisher-returns: true
|
||||
virtual-host: /
|
||||
listener:
|
||||
simple:
|
||||
acknowledge-mode: manual
|
||||
concurrency: 1
|
||||
max-concurrency: 1
|
||||
retry:
|
||||
enabled: true
|
||||
minidao:
|
||||
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
|
||||
jeecg:
|
||||
signatureSecret: dd05f1c54d63749eda95f9fa6d49v442a
|
||||
signUrls: /sys/dict/getDictItems/*,/sys/dict/loadDict/*,/sys/dict/loadDictOrderByValue/*,/sys/dict/loadDictItem/*,/sys/dict/loadTreeData,/sys/api/queryTableDictItemsByCode,/sys/api/queryFilterTableDictInfo,/sys/api/queryTableDictByKeys,/sys/api/translateDictFromTable,/sys/api/translateDictFromTableByKeys
|
||||
uploadType: local
|
||||
domainUrl:
|
||||
pc: http://localhost:3100
|
||||
app: http://localhost:8051
|
||||
path:
|
||||
upload: /opt/upFiles
|
||||
webapp: /opt/webapp
|
||||
shiro:
|
||||
excludeUrls: /test/jeecgDemo/demo3,/test/jeecgDemo/redisDemo/**,/category/**,/visual/**,/map/**,/jmreport/bigscreen2/**
|
||||
oss:
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
accessKey: ??
|
||||
secretKey: ??
|
||||
bucketName: jeecgdev
|
||||
staticDomain: ??
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
cluster-nodes: jeecg-boot-es:9200
|
||||
check-enabled: false
|
||||
file-view-domain: 127.0.0.1:8012
|
||||
minio:
|
||||
minio_url: http://minio.jeecg.com
|
||||
minio_name: ??
|
||||
minio_pass: ??
|
||||
bucketName: otatest
|
||||
jmreport:
|
||||
mode: dev
|
||||
is_verify_token: false
|
||||
verify_methods: remove,delete,save,add,update
|
||||
wps:
|
||||
domain: https://wwo.wps.cn/office/
|
||||
appid: ??
|
||||
appsecret: ??
|
||||
xxljob:
|
||||
enabled: false
|
||||
adminAddresses: http://jeecg-boot-xxljob:9080/xxl-job-admin
|
||||
appname: ${spring.application.name}
|
||||
accessToken: ''
|
||||
logPath: logs/jeecg/job/jobhandler/
|
||||
logRetentionDays: 30
|
||||
redisson:
|
||||
address: jeecg-boot-redis:6379
|
||||
password:
|
||||
type: STANDALONE
|
||||
enabled: true
|
||||
logging:
|
||||
level:
|
||||
org.jeecg.modules.system.mapper: info
|
||||
cas:
|
||||
prefixUrl: http://localhost:8888/cas
|
||||
knife4j:
|
||||
production: false
|
||||
basic:
|
||||
enable: false
|
||||
username: jeecg
|
||||
password: jeecg1314
|
||||
justauth:
|
||||
enabled: true
|
||||
type:
|
||||
GITHUB:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/github/callback
|
||||
WECHAT_ENTERPRISE:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/wechat_enterprise/callback
|
||||
agent-id: ??
|
||||
DINGTALK:
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
redirect-uri: http://sso.test.com:8080/jeecg-boot/thirdLogin/dingtalk/callback
|
||||
cache:
|
||||
type: default
|
||||
prefix: 'demo::'
|
||||
timeout: 1h
|
||||
third-app:
|
||||
enabled: false
|
||||
type:
|
||||
WECHAT_ENTERPRISE:
|
||||
enabled: false
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
agent-id: ??
|
||||
DINGTALK:
|
||||
enabled: false
|
||||
client-id: ??
|
||||
client-secret: ??
|
||||
agent-id: ??
|
||||
@@ -0,0 +1,13 @@
|
||||
jeecg:
|
||||
route:
|
||||
config:
|
||||
#type:database nacos yml
|
||||
data-type: database
|
||||
group: DEFAULT_GROUP
|
||||
data-id: jeecg-gateway-router
|
||||
spring:
|
||||
redis:
|
||||
database: 0
|
||||
host: jeecg-boot-redis
|
||||
port: 6379
|
||||
password:
|
||||
@@ -0,0 +1,65 @@
|
||||
[
|
||||
{
|
||||
"id": "jeecg-system",
|
||||
"order": 0,
|
||||
"predicates": [
|
||||
{
|
||||
"name": "Path",
|
||||
"args": {
|
||||
"_genkey_0": "/sys/**",
|
||||
"_genkey_1": "/jmreport/**",
|
||||
"_genkey_3": "/online/**",
|
||||
"_genkey_4": "/generic/**"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [],
|
||||
"uri": "lb://jeecg-system"
|
||||
},
|
||||
{
|
||||
"id": "jeecg-demo",
|
||||
"order": 1,
|
||||
"predicates": [
|
||||
{
|
||||
"name": "Path",
|
||||
"args": {
|
||||
"_genkey_0": "/mock/**",
|
||||
"_genkey_1": "/test/**",
|
||||
"_genkey_2": "/bigscreen/template1/**",
|
||||
"_genkey_3": "/bigscreen/template2/**"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [],
|
||||
"uri": "lb://jeecg-demo"
|
||||
},
|
||||
{
|
||||
"id": "jeecg-system-websocket",
|
||||
"order": 2,
|
||||
"predicates": [
|
||||
{
|
||||
"name": "Path",
|
||||
"args": {
|
||||
"_genkey_0": "/websocket/**",
|
||||
"_genkey_1": "/newsWebsocket/**"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [],
|
||||
"uri": "lb:ws://jeecg-system"
|
||||
},
|
||||
{
|
||||
"id": "jeecg-demo-websocket",
|
||||
"order": 3,
|
||||
"predicates": [
|
||||
{
|
||||
"name": "Path",
|
||||
"args": {
|
||||
"_genkey_0": "/vxeSocket/**"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [],
|
||||
"uri": "lb:ws://jeecg-demo"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,100 @@
|
||||
server:
|
||||
tomcat:
|
||||
max-swallow-size: -1
|
||||
error:
|
||||
include-exception: true
|
||||
include-stacktrace: ALWAYS
|
||||
include-message: ALWAYS
|
||||
compression:
|
||||
enabled: true
|
||||
min-response-size: 1024
|
||||
mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*
|
||||
management:
|
||||
health:
|
||||
mail:
|
||||
enabled: false
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: "*"
|
||||
health:
|
||||
sensitive: true
|
||||
endpoint:
|
||||
health:
|
||||
show-details: ALWAYS
|
||||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
mail:
|
||||
host: smtp.163.com
|
||||
username: jeecgos@163.com
|
||||
password: ??
|
||||
properties:
|
||||
mail:
|
||||
smtp:
|
||||
auth: true
|
||||
starttls:
|
||||
enable: true
|
||||
required: true
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
initialize-schema: embedded
|
||||
auto-startup: false
|
||||
startup-delay: 1s
|
||||
overwrite-existing-jobs: true
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: MyScheduler
|
||||
instanceId: AUTO
|
||||
jobStore:
|
||||
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: true
|
||||
misfireThreshold: 12000
|
||||
clusterCheckinInterval: 15000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 10
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
aop:
|
||||
proxy-target-class: true
|
||||
activiti:
|
||||
check-process-definitions: false
|
||||
async-executor-activate: false
|
||||
job-executor-activate: false
|
||||
jpa:
|
||||
open-in-view: false
|
||||
freemarker:
|
||||
suffix: .ftl
|
||||
content-type: text/html
|
||||
charset: UTF-8
|
||||
cache: false
|
||||
prefer-file-system-access: false
|
||||
template-loader-path:
|
||||
- classpath:/templates
|
||||
mvc:
|
||||
static-path-pattern: /**
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
resource:
|
||||
static-locations: classpath:/static/,classpath:/public/
|
||||
autoconfigure:
|
||||
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath*:org/jeecg/modules/**/xml/*Mapper.xml
|
||||
global-config:
|
||||
banner: false
|
||||
db-config:
|
||||
id-type: ASSIGN_ID
|
||||
table-underline: true
|
||||
configuration:
|
||||
call-setters-on-nulls: true
|
||||
@@ -0,0 +1,59 @@
|
||||
spring:
|
||||
shardingsphere:
|
||||
datasource:
|
||||
names: ds0,ds1
|
||||
ds0:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
username: root
|
||||
password: root
|
||||
ds1:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot2?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
username: root
|
||||
password: root
|
||||
props:
|
||||
sql-show: true
|
||||
rules:
|
||||
replica-query:
|
||||
load-balancers:
|
||||
round-robin:
|
||||
type: ROUND_ROBIN
|
||||
props:
|
||||
default: 0
|
||||
data-sources:
|
||||
prds:
|
||||
primary-data-source-name: ds0
|
||||
replica-data-source-names: ds1
|
||||
load-balancer-name: round_robin
|
||||
sharding:
|
||||
binding-tables:
|
||||
- sys_log
|
||||
key-generators:
|
||||
snowflake:
|
||||
type: SNOWFLAKE
|
||||
props:
|
||||
worker-id: 123
|
||||
sharding-algorithms:
|
||||
table-classbased:
|
||||
props:
|
||||
strategy: standard
|
||||
algorithmClassName: org.jeecg.modules.test.sharding.algorithm.StandardModTableShardAlgorithm
|
||||
type: CLASS_BASED
|
||||
database-inline:
|
||||
type: INLINE
|
||||
props:
|
||||
algorithm-expression: ds$->{operate_type % 2}
|
||||
tables:
|
||||
sys_log:
|
||||
actual-data-nodes: ds$->{0..1}.sys_log$->{0..1}
|
||||
database-strategy:
|
||||
standard:
|
||||
sharding-column: operate_type
|
||||
sharding-algorithm-name: database-inline
|
||||
table-strategy:
|
||||
standard:
|
||||
sharding-algorithm-name: table-classbased
|
||||
sharding-column: log_type
|
||||
@@ -0,0 +1,33 @@
|
||||
spring:
|
||||
shardingsphere:
|
||||
datasource:
|
||||
names: ds0
|
||||
ds0:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://jeecg-boot-mysql:3306/jeecg-boot?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: root
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
props:
|
||||
sql-show: true
|
||||
rules:
|
||||
sharding:
|
||||
binding-tables: sys_log
|
||||
key-generators:
|
||||
snowflake:
|
||||
type: SNOWFLAKE
|
||||
props:
|
||||
worker-id: 123
|
||||
sharding-algorithms:
|
||||
table-classbased:
|
||||
props:
|
||||
strategy: standard
|
||||
algorithmClassName: org.jeecg.modules.test.sharding.algorithm.StandardModTableShardAlgorithm
|
||||
type: CLASS_BASED
|
||||
tables:
|
||||
sys_log:
|
||||
actual-data-nodes: ds0.sys_log$->{0..1}
|
||||
table-strategy:
|
||||
standard:
|
||||
sharding-algorithm-name: table-classbased
|
||||
sharding-column: log_type
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>functional-modules</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>data-center-api</artifactId>
|
||||
<version>2.0.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.retry</groupId>
|
||||
<artifactId>spring-retry</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-base-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package com.renkang.datacenter.api;
|
||||
|
||||
import com.renkang.datacenter.bean.*;
|
||||
import com.renkang.datacenter.config.ImcCenterConstants;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Retryable(maxAttempts = 2, listeners = "restRetryListener")
|
||||
public interface DataCenterExecutor {
|
||||
|
||||
Result<Object> addDevice(WatchDevice device);
|
||||
|
||||
Result<Object> addDeviceBatch(WatchDeviceBatch devices);
|
||||
|
||||
Result<Object> removeDevice(WatchNo watchNo);
|
||||
|
||||
Result<Object> setSwitchStatus(WatchDeviceSwitch watchDeviceSwitch);
|
||||
|
||||
Result<Object> setSwitchStatusAll(DeviceSwitch deviceSwitch);
|
||||
|
||||
Result<Object> cmdNotice(Notice notice);
|
||||
|
||||
Result<Object> cmdNoticeMulti(Notice notice);
|
||||
|
||||
Result<Object> watchDataList(WatchDataList watchDataList);
|
||||
|
||||
Result<Object> increaseWatchDataCount(IncreaseWatchDataCount dataCount);
|
||||
|
||||
Result<Object> increaseWatchDataList(IncreaseWatchDataList dataList);
|
||||
|
||||
Result<Object> watchSdcItemData(WatchSdcItemData sdcItemData);
|
||||
|
||||
Result<Object> deviceInfoAll(WatchNo watchNo);
|
||||
|
||||
Result<Object> getRate(WatchNo watchNo);
|
||||
|
||||
Result<Object> getPeriod(WatchNo watchNo);
|
||||
|
||||
Result<Object> getWarnSwitch(WatchNo watchNo);
|
||||
|
||||
Result<Object> saveRate(Rate rate);
|
||||
|
||||
Result<Object> savePeriod(Period period);
|
||||
|
||||
Result<Object> saveWarnSwitch(WarnSwitch warnSwitch);
|
||||
|
||||
Result<Object> cmdDataPush(String watchNo);
|
||||
|
||||
Result<Object> cmdUpdatePeriod(String watchNo);
|
||||
|
||||
Result<Object> cmdUpdateTask(String watchNo);
|
||||
|
||||
Result<Object> cmdUpdateSwitch(String watchNo);
|
||||
|
||||
@Retryable(maxAttempts = 2, listeners = ImcCenterConstants.IMC_LISTENER)
|
||||
Result<Object> getImageMessage(ImcPeIdVo imcPeIdVo);
|
||||
|
||||
/**
|
||||
* 通过peId获取影像基本信息
|
||||
* @param imcPeIdVo
|
||||
* @return
|
||||
*/
|
||||
@Retryable(maxAttempts = 2, listeners = ImcCenterConstants.IMC_LISTENER)
|
||||
Result<Object> getImageItems(ImcPeIdVo imcPeIdVo);
|
||||
|
||||
String downloadAsString(String filepath);
|
||||
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
package com.renkang.datacenter.api;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.datacenter.bean.*;
|
||||
import com.renkang.datacenter.config.DataCenterConstants;
|
||||
import com.renkang.datacenter.config.DataCenterProperties;
|
||||
import com.renkang.datacenter.config.MethodApi;
|
||||
import com.renkang.datacenter.util.RemoteUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class DefaultDataCenterExecutor implements DataCenterExecutor {
|
||||
|
||||
private DataCenterProperties properties;
|
||||
|
||||
|
||||
@Autowired
|
||||
public void setProperties(DataCenterProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> addDevice(WatchDevice device) {
|
||||
return RemoteUtils.post(MethodApi.ADD_DEVICE,device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> addDeviceBatch(WatchDeviceBatch devices) {
|
||||
return RemoteUtils.post(MethodApi.ADD_DEVICE_BATCH,devices);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> removeDevice(WatchNo watchNo) {
|
||||
return RemoteUtils.post(MethodApi.REMOVE_DEVICE, objectToMap(watchNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> setSwitchStatus(WatchDeviceSwitch watchDeviceSwitch) {
|
||||
return RemoteUtils.post(MethodApi.SET_SWITCH_STATUS, watchDeviceSwitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> setSwitchStatusAll(DeviceSwitch deviceSwitch) {
|
||||
return RemoteUtils.post(MethodApi.SET_SWITCH_STATUS_ALL, deviceSwitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> cmdNotice(Notice notice) {
|
||||
return RemoteUtils.post(MethodApi.CMD_NOTICE, objectToMap(notice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> cmdNoticeMulti(Notice notice) {
|
||||
return RemoteUtils.post(MethodApi.CMD_NOTICE_MULTI, objectToMap(notice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> watchDataList(WatchDataList watchDataList) {
|
||||
return RemoteUtils.get(MethodApi.WATCH_DATA_LIST, objectToMap(watchDataList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> increaseWatchDataCount(IncreaseWatchDataCount dataCount) {
|
||||
if (Objects.isNull(dataCount.getPageSize()) || dataCount.getPageSize() == 0) {
|
||||
dataCount.setPageSize(properties.getPageSize());
|
||||
}
|
||||
return RemoteUtils.get(MethodApi.INCREASE_WATCH_DATA_PAGE_COUNT, objectToMap(dataCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> increaseWatchDataList(IncreaseWatchDataList dataList) {
|
||||
if (Objects.isNull(dataList.getPageSize()) || dataList.getPageSize() == 0) {
|
||||
dataList.setPageSize(properties.getPageSize());
|
||||
}
|
||||
return RemoteUtils.get(MethodApi.INCREASE_WATCH_DATA_PAGE_LIST, objectToMap(dataList));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> watchSdcItemData(WatchSdcItemData sdcItemData) {
|
||||
return RemoteUtils.get(MethodApi.WATCH_SDC_ITEM_DATA, objectToMap(sdcItemData));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> deviceInfoAll(WatchNo watchNo) {
|
||||
return RemoteUtils.get(MethodApi.DEVICE_INFO_ALL, objectToMap(watchNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> getRate(WatchNo watchNo) {
|
||||
return RemoteUtils.get(MethodApi.GET_RATE, objectToMap(watchNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> getPeriod(WatchNo watchNo) {
|
||||
return RemoteUtils.get(MethodApi.GET_PERIOD, objectToMap(watchNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> getWarnSwitch(WatchNo watchNo) {
|
||||
return RemoteUtils.get(MethodApi.GET_WARN_SWITCH, objectToMap(watchNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> saveRate(Rate rate) {
|
||||
return RemoteUtils.post(MethodApi.SAVE_RATE, rate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> savePeriod(Period period) {
|
||||
return RemoteUtils.post(MethodApi.SAVE_PERIOD, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> saveWarnSwitch(WarnSwitch warnSwitch) {
|
||||
return RemoteUtils.post(MethodApi.SAVE_WARN_SWITCH, warnSwitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> cmdDataPush(String watchNo) {
|
||||
MqttTask task = new MqttTask();
|
||||
task.setWatchNo(watchNo);
|
||||
task.setTaskName(DataCenterConstants.MQTT_CMD_DATA_PUSH);
|
||||
return cmdDataPush(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> cmdUpdatePeriod(String watchNo) {
|
||||
MqttTask task = new MqttTask();
|
||||
task.setWatchNo(watchNo);
|
||||
task.setTaskName(DataCenterConstants.MQTT_CMD_UPDATE_PERIOD);
|
||||
return cmdDataPush(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> cmdUpdateTask(String watchNo) {
|
||||
MqttTask task = new MqttTask();
|
||||
task.setWatchNo(watchNo);
|
||||
task.setTaskName(DataCenterConstants.MQTT_CMD_UPDATE_TASK);
|
||||
return cmdDataPush(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> cmdUpdateSwitch(String watchNo) {
|
||||
MqttTask task = new MqttTask();
|
||||
task.setWatchNo(watchNo);
|
||||
task.setTaskName(DataCenterConstants.MQTT_CMD_UPDATE_SWITCH);
|
||||
return cmdDataPush(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Object> getImageMessage(ImcPeIdVo imcPeIdVo) {
|
||||
return RemoteUtils.post(MethodApi.GET_IMAGE_MESSAGE, imcPeIdVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过peId获取影像基本信息
|
||||
*
|
||||
* @param imcPeIdVo
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Result<Object> getImageItems(ImcPeIdVo imcPeIdVo) {
|
||||
return RemoteUtils.post(MethodApi.GET_IMAGE_ITEMS, imcPeIdVo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String downloadAsString(String filepath) {
|
||||
return RemoteUtils.downloadAsString(filepath);
|
||||
}
|
||||
|
||||
private Result<Object> cmdDataPush(MqttTask task) {
|
||||
return RemoteUtils.post(MethodApi.CMD_DATA_PUSH, objectToMap(task));
|
||||
}
|
||||
|
||||
private Map<String,Object> objectToMap(Object source) {
|
||||
return (JSONObject) JSON.toJSON(source);
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataCommon extends WatchDataBase {
|
||||
|
||||
private String wdType;
|
||||
|
||||
private Double dataValue;
|
||||
|
||||
private String timeStamp;
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataEcg extends WatchDataBase {
|
||||
|
||||
|
||||
private Long ecgStartTime;
|
||||
|
||||
private Long ecgEndTime;
|
||||
|
||||
@JSONField(format = "yyyy-MM-dd")
|
||||
private Date dataDate;
|
||||
|
||||
private Integer ecgArrhyType;
|
||||
|
||||
private String ecgArrhyTypeDict;
|
||||
|
||||
private Integer ecgUserSymptom;
|
||||
|
||||
private String ecgUserSymptomDict;
|
||||
|
||||
private Integer ecgArrhyAvgRate;
|
||||
|
||||
private Integer ecgDataPointsCount;
|
||||
|
||||
private String ecgDataPoints;
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataExercise extends WatchDataBase {
|
||||
|
||||
/**
|
||||
* 中高强度运动时间(分钟)
|
||||
*/
|
||||
private Integer strengthTimes;
|
||||
/**
|
||||
* 总活动时长(小时)
|
||||
*/
|
||||
private Integer totalTime;
|
||||
/**
|
||||
* 数据日期
|
||||
*/
|
||||
private String dataDate;
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataGps extends WatchDataBase {
|
||||
|
||||
private Double lon;
|
||||
|
||||
private Double lat;
|
||||
|
||||
private String address;
|
||||
|
||||
private String timeStamp;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataHeartRate extends WatchDataBase {
|
||||
|
||||
private Double dataValue;
|
||||
|
||||
private Double silenceValue;
|
||||
|
||||
private String timeStamp;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataSdc extends WatchDataBase {
|
||||
|
||||
private String sdcDate;
|
||||
|
||||
private Long dataValue;
|
||||
|
||||
private String wdType;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataSleep extends WatchDataBase {
|
||||
|
||||
private String startTimeStamp;
|
||||
|
||||
private String endTimeStamp;
|
||||
|
||||
private String sleepType;
|
||||
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataSleepNew extends WatchDataBase {
|
||||
|
||||
private String sleepFlag;
|
||||
|
||||
@JSONField(alternateNames = "DataDate")
|
||||
private String dataDate;
|
||||
|
||||
private Integer errCode;
|
||||
|
||||
private List<Error> errCodeArr;
|
||||
|
||||
private List<Day> statusInDayArr;
|
||||
|
||||
private List<Minute> statusInMinuteArr;
|
||||
|
||||
@Data
|
||||
public static class Error implements Serializable {
|
||||
|
||||
private Integer errCode;
|
||||
|
||||
private String startTime;
|
||||
|
||||
private String endTime;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Day implements Serializable {
|
||||
/**
|
||||
* 睡梦时长(分钟)
|
||||
*/
|
||||
private Integer deepSleepPartCnt;
|
||||
/**
|
||||
* 入睡时间点
|
||||
*/
|
||||
private String fallAsleepTime;
|
||||
/**
|
||||
* 上床时间
|
||||
*/
|
||||
private String goBedTime;
|
||||
/**
|
||||
* 睡眠效率百分比
|
||||
*/
|
||||
private Integer sleepEfficiency;
|
||||
/**
|
||||
* 睡眠潜伏期
|
||||
*/
|
||||
private Long sleepLatency;
|
||||
/**
|
||||
* 睡眠得分
|
||||
*/
|
||||
private Integer sleepScore;
|
||||
/**
|
||||
* 原始睡眠得分
|
||||
*/
|
||||
@JSONField(alternateNames = "sleepScoreOrign")
|
||||
private Integer sleepScoreOrigin;
|
||||
/**
|
||||
* 鼾声(每小时次数)
|
||||
*/
|
||||
private Integer snoreFreq;
|
||||
/**
|
||||
* 当天的时间戳
|
||||
*/
|
||||
private String startTime;
|
||||
/**
|
||||
* 数据有效性
|
||||
*/
|
||||
private Double validData;
|
||||
/**
|
||||
* 醒来时间
|
||||
*/
|
||||
private String wakeUpTime;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Minute implements Serializable {
|
||||
/**
|
||||
* 睡眠状态
|
||||
*/
|
||||
private String status;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private String startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private String endTime;
|
||||
}
|
||||
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataSteps extends WatchDataBase {
|
||||
|
||||
/**
|
||||
* 数据日期
|
||||
*/
|
||||
@JSONField(format = "yyyy-MM-dd")
|
||||
private Date stepDate;
|
||||
|
||||
private Integer stepCount;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataStress extends WatchDataBase {
|
||||
|
||||
private Double dataValue;
|
||||
|
||||
private String startTimeStamp;
|
||||
|
||||
private String endTimeStamp;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataTemperature extends WatchDataBase {
|
||||
|
||||
private Double skinTempera;
|
||||
|
||||
private Double dataValue;
|
||||
|
||||
private String timeStamp;
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataTrace extends WatchDataBase {
|
||||
|
||||
private String recordId;
|
||||
/**
|
||||
* 海拔
|
||||
*/
|
||||
private Double altitude;
|
||||
/**
|
||||
* 纬度
|
||||
*/
|
||||
private Double latitude;
|
||||
/**
|
||||
* 经度
|
||||
*/
|
||||
private Double longitude;
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private String utcTime;
|
||||
/**
|
||||
* 数据是否合法
|
||||
*/
|
||||
private String valid;
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class DataWorkout extends WatchDataBase {
|
||||
|
||||
private String workoutType;
|
||||
|
||||
private Double calorie;
|
||||
|
||||
private Double distance;
|
||||
|
||||
private String startTimeStamp;
|
||||
|
||||
private String endTimeStamp;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class DeviceSwitch implements Serializable {
|
||||
|
||||
private String wdType;
|
||||
|
||||
private String switchFlag;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ImcPeIdVo {
|
||||
|
||||
private String peId;
|
||||
|
||||
private String hospitalId;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class IncreaseWatchDataCount implements Serializable {
|
||||
|
||||
private String wdType;
|
||||
|
||||
private String id;
|
||||
|
||||
private Integer pageSize;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class IncreaseWatchDataList extends IncreaseWatchDataCount implements Serializable {
|
||||
|
||||
private Integer pageNo;
|
||||
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class Login implements Serializable {
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class MqttTask implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
private String taskName;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class Notice implements Serializable {
|
||||
|
||||
private String noticeTitle;
|
||||
|
||||
private String notice;
|
||||
|
||||
private String watchNo;
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class Period implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
private String wdType;
|
||||
|
||||
private Double warnMin;
|
||||
|
||||
private Double warnMax;
|
||||
|
||||
private Integer period;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class Rate implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
private String wdType;
|
||||
|
||||
private Integer taskRate;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class WarnSwitch implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
private String wdType;
|
||||
|
||||
private String switchFlag;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@Data
|
||||
public class WatchDataBase implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private String watchNo;
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class WatchDataList implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
private String queryDate;
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/13
|
||||
*/
|
||||
@Data
|
||||
public class WatchDataResult implements Serializable {
|
||||
|
||||
private String maxId;
|
||||
|
||||
@JSONField(alternateNames = "commonVoList")
|
||||
private List<DataCommon> commonList;
|
||||
|
||||
@JSONField(alternateNames = "heartRateVoList")
|
||||
private List<DataHeartRate> heartRateList;
|
||||
|
||||
@JSONField(alternateNames = "gpsVoList")
|
||||
private List<DataGps> gpsList;
|
||||
|
||||
@JSONField(alternateNames = "sleepVoList")
|
||||
private List<DataSleep> sleepList;
|
||||
|
||||
@JSONField(alternateNames = "sdcVoList")
|
||||
private List<DataSdc> sdcList;
|
||||
|
||||
@JSONField(alternateNames = "tempVoList")
|
||||
private List<DataTemperature> tempList;
|
||||
|
||||
@JSONField(alternateNames = "workoutVoList")
|
||||
private List<DataWorkout> workoutList;
|
||||
|
||||
@JSONField(alternateNames = "stressVoList")
|
||||
private List<DataStress> stressList;
|
||||
|
||||
@JSONField(alternateNames = "exerciseVoList")
|
||||
private List<DataExercise> exerciseList;
|
||||
|
||||
@JSONField(alternateNames = "traceVoList")
|
||||
private List<DataTrace> traceList;
|
||||
|
||||
@JSONField(alternateNames = "sleepNewVoList")
|
||||
private List<DataSleepNew> sleepNewList;
|
||||
|
||||
@JSONField(alternateNames = "ecgVoList")
|
||||
private List<DataEcg> ecgList;
|
||||
|
||||
@JSONField(alternateNames = "stepVoList")
|
||||
private List<DataSteps> stepList;
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class WatchDevice implements Serializable {
|
||||
|
||||
/**
|
||||
* 手表SN编码
|
||||
*/
|
||||
private String watchNo;
|
||||
/**
|
||||
* IMEI编码
|
||||
*/
|
||||
private String imeiNo;
|
||||
/**
|
||||
* EID编码
|
||||
*/
|
||||
private String eid;
|
||||
private String watchModel;
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class WatchDeviceBatch implements Serializable {
|
||||
|
||||
private List<WatchDevice> deviceVoList;
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class WatchDeviceSwitch extends DeviceSwitch implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class WatchNo implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
public static WatchNo of(String watchNo) {
|
||||
WatchNo instance = new WatchNo();
|
||||
instance.setWatchNo(watchNo);
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.datacenter.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/5
|
||||
*/
|
||||
@Data
|
||||
public class WatchSdcItemData implements Serializable {
|
||||
|
||||
private String watchNo;
|
||||
|
||||
private String wdType;
|
||||
|
||||
private String queryDate;
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
public interface DataCenterConstants {
|
||||
|
||||
//通知更新阈值及频率
|
||||
String MQTT_CMD_UPDATE_PERIOD = "updatePeriod";
|
||||
//通知更新定时任务
|
||||
String MQTT_CMD_UPDATE_TASK = "updateTask";
|
||||
//通知更新开关
|
||||
String MQTT_CMD_UPDATE_SWITCH = "updateSwitch";
|
||||
//通知手表上传数据
|
||||
String MQTT_CMD_DATA_PUSH = "dataPush";
|
||||
|
||||
String REDIS_TOKEN_KEY = "DC_TOKEN";
|
||||
|
||||
String HEADER_TOKEN_KEY = "X-Access-Token";
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("datacenter")
|
||||
@Data
|
||||
public class DataCenterProperties {
|
||||
|
||||
private String url = "";
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String publicKey;
|
||||
|
||||
private Long timeout = 3000L;
|
||||
|
||||
private Integer pageSize = 500;
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
public interface ImcCenterConstants {
|
||||
|
||||
String IMC_LISTENER = "RestRetryImcListener";
|
||||
String REDIS_TOKEN_KEY = "IMC_TOKEN";
|
||||
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
@Getter
|
||||
public enum MethodApi {
|
||||
/**
|
||||
* 获取令牌
|
||||
*/
|
||||
GET_TOKEN("sys/getToken"),
|
||||
/**
|
||||
* 添加设备
|
||||
*/
|
||||
ADD_DEVICE("watch/api/addDevice"),
|
||||
/**
|
||||
* 批量添加设备
|
||||
*/
|
||||
ADD_DEVICE_BATCH("watch/api/batchAddDevice"),
|
||||
/**
|
||||
* 删除设备
|
||||
*/
|
||||
REMOVE_DEVICE("watch/api/removeDevice?watchNo={watchNo}"),
|
||||
/**
|
||||
* 设备开关设置
|
||||
*/
|
||||
SET_SWITCH_STATUS("watch/api/setSwitchStatus"),
|
||||
/**
|
||||
* 设备开关全部设置
|
||||
*/
|
||||
SET_SWITCH_STATUS_ALL("watch/api/setAllSwitchStatus"),
|
||||
/**
|
||||
* 通知消息
|
||||
*/
|
||||
CMD_NOTICE("watch/mqtt/cmdNotice?watchNo={watchNo}¬iceTitle={noticeTitle}¬ice={notice}"),
|
||||
/**
|
||||
* 通知消息
|
||||
*/
|
||||
CMD_NOTICE_MULTI("watch/mqtt/cmdNoticeMulti?watchNo={watchNo}¬iceTitle={noticeTitle}¬ice={notice}"),
|
||||
/**
|
||||
* 推送数据通知
|
||||
*/
|
||||
CMD_DATA_PUSH("watch/mqtt/cmdDataPush?watchNo={watchNo}&taskName={taskName}"),
|
||||
/**
|
||||
* 全量数据获取
|
||||
*/
|
||||
WATCH_DATA_LIST("watch/api/getWatchDataList/{queryDate}?watchNo={watchNo}"),
|
||||
/**
|
||||
* 增量数据获取(页数)
|
||||
*/
|
||||
INCREASE_WATCH_DATA_PAGE_COUNT("watch/api/getIncreWatchDataPageCount/{wdType}/{id}/{pageSize}"),
|
||||
/**
|
||||
* 增量数据获取(数据)
|
||||
*/
|
||||
INCREASE_WATCH_DATA_PAGE_LIST("watch/api/getIncreWatchDataPageList/{wdType}/{id}/{pageNo}/{pageSize}"),
|
||||
/**
|
||||
* SDC详细数据获取
|
||||
*/
|
||||
WATCH_SDC_ITEM_DATA("watch/api/getWatchSdcItemData/{watchNo}/{queryDate}/{wdType}"),
|
||||
/**
|
||||
* 设备列表查询
|
||||
*/
|
||||
DEVICE_INFO_ALL("watch/api/getAllDeviceInfo?watchNo={watchNo}"),
|
||||
/**
|
||||
* 查询上传频率设置
|
||||
*/
|
||||
GET_RATE("watch/api/getRateByWatchNo?watchNo={watchNo}"),
|
||||
/**
|
||||
* 设置上传频率
|
||||
*/
|
||||
SAVE_RATE("watch/api/saveRateByNoAndWdType"),
|
||||
/**
|
||||
* 查询阈值设置
|
||||
*/
|
||||
GET_PERIOD("watch/api/getPeriodByWatchNo?watchNo={watchNo}"),
|
||||
/**
|
||||
* 设置阈值
|
||||
*/
|
||||
SAVE_PERIOD("watch/api/savePeriodByNoAndWdType"),
|
||||
/**
|
||||
* 查询报警开关设置
|
||||
*/
|
||||
GET_WARN_SWITCH("watch/api/getWarnListByWatchNo?watchNo={watchNo}"),
|
||||
/**
|
||||
* 设置报警开关
|
||||
*/
|
||||
SAVE_WARN_SWITCH("watch/api/saveWarnByNoAndWdType"),
|
||||
|
||||
// =======================影像中心============================
|
||||
/**
|
||||
* 查询影像人员信息
|
||||
*/
|
||||
GET_IMAGE_MESSAGE("imc/file/getImageMsg"),
|
||||
/**
|
||||
* 通过peId获取影像基本信息
|
||||
*/
|
||||
GET_IMAGE_ITEMS("imc/file/getImageItems"),
|
||||
;
|
||||
|
||||
private final String url;
|
||||
|
||||
MethodApi(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
@Configuration
|
||||
@EnableRetry
|
||||
public class RestConfig {
|
||||
|
||||
private final DataCenterProperties properties;
|
||||
|
||||
public RestConfig(DataCenterProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplate dataCenterTemplate() {
|
||||
return new RestTemplateBuilder()
|
||||
.setConnectTimeout(Duration.of(properties.getTimeout(), ChronoUnit.MILLIS))
|
||||
.additionalMessageConverters(
|
||||
new StringHttpMessageConverter(StandardCharsets.UTF_8),
|
||||
new MappingJackson2HttpMessageConverter()
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.datacenter.bean.Login;
|
||||
import com.renkang.datacenter.util.RemoteUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.util.RSAEncryptUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.RetryListener;
|
||||
import org.springframework.retry.interceptor.MethodInvocationRetryCallback;
|
||||
import org.springframework.retry.listener.MethodInvocationRetryListenerSupport;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
@Component(ImcCenterConstants.IMC_LISTENER)
|
||||
@Slf4j
|
||||
public class RestRetryImcListener extends MethodInvocationRetryListenerSupport implements RetryListener {
|
||||
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
private DataCenterProperties properties;
|
||||
|
||||
@Autowired
|
||||
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setProperties(DataCenterProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <T, E extends Throwable> boolean doOpen(RetryContext context, MethodInvocationRetryCallback<T, E> callback) {
|
||||
String token = "";
|
||||
try{
|
||||
token = (String) redisTemplate.opsForValue().get(ImcCenterConstants.REDIS_TOKEN_KEY);
|
||||
if (!StringUtils.hasLength(token)) {
|
||||
token = refreshToken();
|
||||
}
|
||||
}catch (Exception e){
|
||||
token = refreshToken();
|
||||
}
|
||||
RemoteUtils.TOKEN_CACHE.set(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, E extends Throwable> void doClose(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
|
||||
RemoteUtils.TOKEN_CACHE.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, E extends Throwable> void doOnError(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
|
||||
String methodName = callback.getInvocation().getMethod().getName();
|
||||
log.error("执行方法[{}]出错,刷新令牌后重试,当前重试次数:{}",methodName, context.getRetryCount(),throwable);
|
||||
String token = refreshToken();
|
||||
RemoteUtils.TOKEN_CACHE.set(token);
|
||||
}
|
||||
|
||||
private String refreshToken() {
|
||||
|
||||
Login body = new Login();
|
||||
body.setUsername(properties.getUsername());
|
||||
body.setPassword(RSAEncryptUtils.encrypt1(properties.getPassword(),properties.getPublicKey()));
|
||||
Result<Object> result = RemoteUtils.post(MethodApi.GET_TOKEN, body);
|
||||
if (!result.isSuccess()) {
|
||||
log.info("刷新数据中心令牌失败:{}",result.getMessage());
|
||||
return null;
|
||||
}
|
||||
JSONObject data = (JSONObject) JSON.toJSON(result.getResult());
|
||||
String token = data.getString("token");
|
||||
redisTemplate.opsForValue().set(ImcCenterConstants.REDIS_TOKEN_KEY,token, Duration.ofDays(1));
|
||||
log.info("刷新影像中心令牌成功:{}", token);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.renkang.datacenter.config;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.datacenter.bean.Login;
|
||||
import com.renkang.datacenter.util.RemoteUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.util.RSAEncryptUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.RetryListener;
|
||||
import org.springframework.retry.interceptor.MethodInvocationRetryCallback;
|
||||
import org.springframework.retry.listener.MethodInvocationRetryListenerSupport;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RestRetryListener extends MethodInvocationRetryListenerSupport implements RetryListener {
|
||||
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
private DataCenterProperties properties;
|
||||
|
||||
@Autowired
|
||||
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setProperties(DataCenterProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <T, E extends Throwable> boolean doOpen(RetryContext context, MethodInvocationRetryCallback<T, E> callback) {
|
||||
String token = "";
|
||||
try{
|
||||
token = (String) redisTemplate.opsForValue().get(DataCenterConstants.REDIS_TOKEN_KEY);
|
||||
if (!StringUtils.hasLength(token)) {
|
||||
token = refreshToken();
|
||||
}
|
||||
}catch (Exception e){
|
||||
token = refreshToken();
|
||||
}
|
||||
RemoteUtils.TOKEN_CACHE.set(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, E extends Throwable> void doClose(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
|
||||
RemoteUtils.TOKEN_CACHE.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, E extends Throwable> void doOnError(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
|
||||
String methodName = callback.getInvocation().getMethod().getName();
|
||||
log.error("执行方法[{}]出错,刷新令牌后重试,当前重试次数:{}",methodName, context.getRetryCount(),throwable);
|
||||
String token = refreshToken();
|
||||
RemoteUtils.TOKEN_CACHE.set(token);
|
||||
}
|
||||
|
||||
private String refreshToken() {
|
||||
|
||||
Login body = new Login();
|
||||
body.setUsername(properties.getUsername());
|
||||
body.setPassword(RSAEncryptUtils.encrypt1(properties.getPassword(),properties.getPublicKey()));
|
||||
Result<Object> result = RemoteUtils.post(MethodApi.GET_TOKEN, body);
|
||||
if (!result.isSuccess()) {
|
||||
log.info("刷新数据中心令牌失败:{}",result.getMessage());
|
||||
return null;
|
||||
}
|
||||
JSONObject data = (JSONObject) JSON.toJSON(result.getResult());
|
||||
String token = data.getString("token");
|
||||
redisTemplate.opsForValue().set(DataCenterConstants.REDIS_TOKEN_KEY,token, Duration.ofDays(1));
|
||||
log.info("刷新数据中心令牌成功:{}", token);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.renkang.datacenter.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.datacenter.config.DataCenterConstants;
|
||||
import com.renkang.datacenter.config.DataCenterProperties;
|
||||
import com.renkang.datacenter.config.MethodApi;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2023/11/3
|
||||
*/
|
||||
public class RemoteUtils {
|
||||
|
||||
public static final ThreadLocal<String> TOKEN_CACHE = new ThreadLocal<>();
|
||||
|
||||
private static RestTemplate restTemplate;
|
||||
|
||||
private static DataCenterProperties properties;
|
||||
|
||||
public static RestTemplate getRestTemplate() {
|
||||
if (Objects.isNull(restTemplate)) {
|
||||
restTemplate = SpringContextUtils.getBean("dataCenterTemplate", RestTemplate.class);
|
||||
}
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
public static DataCenterProperties getProperties() {
|
||||
if (Objects.isNull(properties)) {
|
||||
properties = SpringContextUtils.getBean(DataCenterProperties.class);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static Result<Object> get(MethodApi api, Map<String, Object> params) {
|
||||
return exchange(api, HttpMethod.GET, null, params);
|
||||
}
|
||||
|
||||
public static String downloadAsString(String filepath) {
|
||||
return getRestTemplate().getForObject(urlHandlerForFileDown(filepath), String.class);
|
||||
}
|
||||
|
||||
public static Result<Object> get(MethodApi api) {
|
||||
return exchange(api, HttpMethod.GET, null, null);
|
||||
}
|
||||
|
||||
public static Result<Object> post(MethodApi api, Object body) {
|
||||
return exchange(api, HttpMethod.POST, body, null);
|
||||
}
|
||||
|
||||
public static Result<Object> post(MethodApi api, Object body, Map<String, Object> params) {
|
||||
return exchange(api, HttpMethod.POST, body, params);
|
||||
}
|
||||
|
||||
public static Result<Object> post(MethodApi api, Map<String, Object> params) {
|
||||
return exchange(api, HttpMethod.POST, null, params);
|
||||
}
|
||||
|
||||
private static Result<Object> exchange(MethodApi api, HttpMethod method, Object body, Map<String, Object> params) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
String token = TOKEN_CACHE.get();
|
||||
if (StringUtils.hasLength(token)) {
|
||||
headers.add(DataCenterConstants.HEADER_TOKEN_KEY, TOKEN_CACHE.get());
|
||||
}
|
||||
HttpEntity<?> entity = new HttpEntity<>(body, headers);
|
||||
if (CollectionUtils.isEmpty(params)) {
|
||||
return responseHandler(getRestTemplate().exchange(urlHandler(api), method, entity, String.class));
|
||||
} else {
|
||||
return responseHandler(getRestTemplate().exchange(urlHandler(api), method, entity, String.class, params));
|
||||
}
|
||||
}
|
||||
|
||||
private static String urlHandler(MethodApi api) {
|
||||
return urlHandler(api.getUrl());
|
||||
}
|
||||
|
||||
private static String urlHandler(String url) {
|
||||
String baseUrl = getProperties().getUrl();
|
||||
String path = url;
|
||||
if (!baseUrl.endsWith("/") && !path.startsWith("/")) {
|
||||
path = "/".concat(path);
|
||||
}
|
||||
return baseUrl + path;
|
||||
}
|
||||
|
||||
private static String urlHandlerForFileDown(String url) {
|
||||
String fileUrl = "file/down/".concat(url).replace("//", "/");
|
||||
return urlHandler(fileUrl);
|
||||
}
|
||||
|
||||
private static Result<Object> responseHandler(ResponseEntity<String> entity) {
|
||||
String body = entity.getBody();
|
||||
JSONObject responseJson = JSON.parseObject(body);
|
||||
String message = Optional.ofNullable(responseJson.getString("message")).orElse("");
|
||||
if (responseJson.getBoolean("success")) {
|
||||
return Result.OK(message, responseJson.get("result"));
|
||||
} else {
|
||||
return Result.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>functional-modules</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>font-resources</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>functional-modules</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>monitoring-sync</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<!-- 打包名称 -->
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>divide-package</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<start-class>com.renkang.sync.ApplicationMain</start-class>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.renkang.sync;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableJpaRepositories(includeFilters = @ComponentScan.Filter(classes = Repository.class))
|
||||
public class ApplicationMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ApplicationMain.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.renkang.sync.bean;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 接口返回数据格式
|
||||
*
|
||||
* @author scott
|
||||
* @email jeecgos@163.com
|
||||
* @date 2019年1月19日
|
||||
*/
|
||||
@Data
|
||||
public class Result<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 成功标志
|
||||
*/
|
||||
private boolean success = true;
|
||||
|
||||
/**
|
||||
* 返回处理消息
|
||||
*/
|
||||
private String message = "";
|
||||
|
||||
/**
|
||||
* 返回代码
|
||||
*/
|
||||
private Integer code = 0;
|
||||
|
||||
/**
|
||||
* 返回数据对象 data
|
||||
*/
|
||||
private T result;
|
||||
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private long timestamp = System.currentTimeMillis();
|
||||
@JsonIgnore
|
||||
private String onlTable;
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容VUE3版token失效不跳转登录页面
|
||||
*/
|
||||
public Result(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok() {
|
||||
Result<T> r = new Result<>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(200);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法是为了兼容升级所创建
|
||||
*/
|
||||
public static <T> Result<T> ok(String msg) {
|
||||
Result<T> r = new Result<>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(200);
|
||||
r.setMessage(msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(T data) {
|
||||
Result<T> r = new Result<>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(200);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> ok(String msg, T data) {
|
||||
Result<T> r = new Result<>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(200);
|
||||
r.setMessage(msg);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String msg, T data) {
|
||||
Result<T> r = new Result<>();
|
||||
r.setSuccess(false);
|
||||
r.setCode(500);
|
||||
r.setMessage(msg);
|
||||
r.setResult(data);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String msg) {
|
||||
return error(500, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(int code, String msg) {
|
||||
Result<T> r = new Result<>();
|
||||
r.setCode(code);
|
||||
r.setMessage(msg);
|
||||
r.setSuccess(false);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 无权限访问返回结果
|
||||
*/
|
||||
public static <T> Result<T> noAuth(String msg) {
|
||||
return error(401, msg);
|
||||
}
|
||||
|
||||
public Result<T> success(String message) {
|
||||
this.message = message;
|
||||
this.code = 200;
|
||||
this.success = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> error500(String message) {
|
||||
this.message = message;
|
||||
this.code = 500;
|
||||
this.success = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.renkang.sync.bean.lefu;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.renkang.sync.entity.RemoteWeightManufacturerLefu;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Data
|
||||
public class BatchRecord {
|
||||
|
||||
@NotBlank(message = "Missing parameter: sn")
|
||||
private String sn;
|
||||
|
||||
@NotBlank(message = "Missing parameter: type")
|
||||
private String type;
|
||||
|
||||
@NotBlank(message = "Missing parameter: mac")
|
||||
@Pattern(regexp = "([A-Fa-f0-9]{2}[:]){5}[A-Fa-f0-9]{2}", message = "MAC address does not meet the rules")
|
||||
private String mac;
|
||||
|
||||
@NotBlank(message = "Missing parameter: charge")
|
||||
private String charge;
|
||||
|
||||
private String firmwareVersion;
|
||||
|
||||
private String wifiVersion;
|
||||
|
||||
@Valid
|
||||
private List<RecordData> data;
|
||||
|
||||
private RemoteWeightManufacturerLefu toRemoteEntity(RecordData data) {
|
||||
RemoteWeightManufacturerLefu remoteWeightManufacturerLefu = new RemoteWeightManufacturerLefu();
|
||||
remoteWeightManufacturerLefu.setDeviceSn(sn);
|
||||
remoteWeightManufacturerLefu.setDeviceType(type);
|
||||
remoteWeightManufacturerLefu.setDeviceMac(mac);
|
||||
remoteWeightManufacturerLefu.setDeviceCharge(charge);
|
||||
remoteWeightManufacturerLefu.setFirmwareVersion(firmwareVersion);
|
||||
remoteWeightManufacturerLefu.setWifiVersion(wifiVersion);
|
||||
remoteWeightManufacturerLefu.setDeviceImpedance(data.getImpedance());
|
||||
remoteWeightManufacturerLefu.setDataTime(data.getDataTime());
|
||||
remoteWeightManufacturerLefu.setWeight(data.getWeightNum());
|
||||
remoteWeightManufacturerLefu.setHeartRate(data.getHeartRate());
|
||||
remoteWeightManufacturerLefu.setCreateTime(DateUtil.date());
|
||||
return remoteWeightManufacturerLefu;
|
||||
}
|
||||
|
||||
public List<RemoteWeightManufacturerLefu> toRemoteEntities() {
|
||||
return CollectionUtil.isEmpty(data) ? Collections.emptyList() : data.stream()
|
||||
.map(this::toRemoteEntity)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.renkang.sync.bean.lefu;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Data
|
||||
public class DeviceInfo {
|
||||
|
||||
private String sn;
|
||||
|
||||
private String mac;
|
||||
|
||||
private String firmwareVersion;
|
||||
|
||||
@JsonProperty("WifiVersion")
|
||||
private String wifiVersion;
|
||||
|
||||
private String hardwareVersion;
|
||||
|
||||
private String charge;
|
||||
|
||||
private String type;
|
||||
|
||||
private Integer timezone;
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.renkang.sync.bean.lefu;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
public class LefuResponse<T> implements Serializable {
|
||||
|
||||
private static final Integer CODE_OK = 0;
|
||||
private static final Integer CODE_FAIL = 1;
|
||||
private static final Integer CODE_SUCCESS = 200;
|
||||
|
||||
private Integer code;
|
||||
|
||||
private T data;
|
||||
/**
|
||||
* The firmware on the device has been successfully written; this parameter is for compatibility with existing devices.
|
||||
*/
|
||||
private Integer errorCode; // Registration success status, 0 for success, non-zero for failure
|
||||
/**
|
||||
* The firmware on the device has been successfully written; this parameter is for compatibility with existing devices.
|
||||
*/
|
||||
private String text; // Return message, which can explain the reason for success or the reason for failure
|
||||
|
||||
public LefuResponse() {
|
||||
setCode(CODE_SUCCESS);
|
||||
}
|
||||
|
||||
public static <T> LefuResponse<T> ok(String text) {
|
||||
LefuResponse<T> scaleR = new LefuResponse<>();
|
||||
scaleR.setErrorCode(CODE_OK);
|
||||
scaleR.setText(text);
|
||||
return scaleR;
|
||||
}
|
||||
|
||||
public static <T> LefuResponse<T> ok(String text, T data) {
|
||||
LefuResponse<T> scaleR = new LefuResponse<>();
|
||||
scaleR.setErrorCode(CODE_OK);
|
||||
scaleR.setText(text);
|
||||
scaleR.setData(data);
|
||||
return scaleR;
|
||||
}
|
||||
|
||||
public static <T> LefuResponse<T> fail(String text, T data) {
|
||||
LefuResponse<T> scaleR = new LefuResponse<>();
|
||||
scaleR.setErrorCode(CODE_FAIL);
|
||||
scaleR.setText(text);
|
||||
scaleR.setData(data);
|
||||
return scaleR;
|
||||
}
|
||||
|
||||
public static <T> LefuResponse<T> fail(String text) {
|
||||
LefuResponse<T> scaleR = new LefuResponse<>();
|
||||
scaleR.setErrorCode(CODE_FAIL);
|
||||
scaleR.setText(text);
|
||||
return scaleR;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Integer getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public void setErrorCode(Integer errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.renkang.sync.bean.lefu;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.renkang.sync.entity.RemoteWeightManufacturerLefu;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
public class Record extends RecordData {
|
||||
|
||||
@NotBlank(message = "Missing parameter: sn")
|
||||
private String sn;
|
||||
|
||||
@NotBlank(message = "Missing parameter: type")
|
||||
private String type;
|
||||
|
||||
@NotBlank(message = "Missing parameter: mac")
|
||||
@Pattern(regexp = "([A-Fa-f0-9]{2}[:]){5}[A-Fa-f0-9]{2}", message = "MAC address does not meet the rules")
|
||||
private String mac;
|
||||
|
||||
@NotBlank(message = "Missing parameter: charge")
|
||||
private String charge;
|
||||
|
||||
private String firmwareVersion;
|
||||
|
||||
private String wifiVersion;
|
||||
|
||||
public RemoteWeightManufacturerLefu toRemoteEntity() {
|
||||
RemoteWeightManufacturerLefu remoteWeightManufacturerLefu = new RemoteWeightManufacturerLefu();
|
||||
remoteWeightManufacturerLefu.setDeviceSn(sn);
|
||||
remoteWeightManufacturerLefu.setDeviceType(type);
|
||||
remoteWeightManufacturerLefu.setDeviceMac(mac);
|
||||
remoteWeightManufacturerLefu.setDeviceCharge(charge);
|
||||
remoteWeightManufacturerLefu.setFirmwareVersion(firmwareVersion);
|
||||
remoteWeightManufacturerLefu.setWifiVersion(wifiVersion);
|
||||
remoteWeightManufacturerLefu.setDeviceImpedance(getImpedance());
|
||||
remoteWeightManufacturerLefu.setDataTime(getDataTime());
|
||||
remoteWeightManufacturerLefu.setWeight(getWeightNum());
|
||||
remoteWeightManufacturerLefu.setHeartRate(getHeartRate());
|
||||
remoteWeightManufacturerLefu.setCreateTime(DateUtil.date());
|
||||
return remoteWeightManufacturerLefu;
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.renkang.sync.bean.lefu;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Data
|
||||
public class RecordData {
|
||||
|
||||
private String weight;
|
||||
|
||||
private String impedance;
|
||||
|
||||
@NotBlank(message = "Missing parameter: timestamp")
|
||||
private String timestamp;
|
||||
|
||||
private Integer heartRate;
|
||||
|
||||
public Date getDataTime() {
|
||||
return StrUtil.isNumeric(getTimestamp()) ? DateUtil.date(Long.parseLong(getTimestamp())) : null;
|
||||
}
|
||||
|
||||
public BigDecimal getWeightNum() {
|
||||
return NumberUtil.isNumber(getWeight()) ? new BigDecimal(getWeight()) : null;
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.renkang.sync.bean.lefu;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Data
|
||||
public class TimeInfo {
|
||||
|
||||
private Long now;
|
||||
|
||||
private Integer unit;
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.renkang.sync.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@ConfigurationProperties("lefu")
|
||||
@Data
|
||||
public class LefuProperties {
|
||||
|
||||
private Map<String, Service> sync = new HashMap<>();
|
||||
|
||||
@Data
|
||||
public static class Service {
|
||||
|
||||
private String baseUrl = "";
|
||||
|
||||
private String username = "";
|
||||
|
||||
private String password = "";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.renkang.sync.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({SyncProperties.class, LefuProperties.class})
|
||||
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery", name = "enabled", havingValue = "false", matchIfMissing = true)
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
public class SyncConfiguration {
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TaskScheduler schedulingTaskExecutor() {
|
||||
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
threadPoolTaskScheduler.setPoolSize(10);
|
||||
threadPoolTaskScheduler.setThreadNamePrefix("task-pool-");
|
||||
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
|
||||
return threadPoolTaskScheduler;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TaskExecutor taskExecutor() {
|
||||
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
threadPoolTaskScheduler.setPoolSize(10);
|
||||
threadPoolTaskScheduler.setThreadNamePrefix("async-pool-");
|
||||
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
|
||||
return threadPoolTaskScheduler;
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.renkang.sync.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@ConfigurationProperties("sync")
|
||||
@Data
|
||||
public class SyncProperties {
|
||||
|
||||
private Integer size = 100;
|
||||
|
||||
private String cron = "0 */30 * * * *";
|
||||
|
||||
private List<String> baseUrls = new ArrayList<>();
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.renkang.sync.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.renkang.sync.bean.lefu.*;
|
||||
import com.renkang.sync.entity.RemoteWeightManufacturerLefu;
|
||||
import com.renkang.sync.service.LefuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/lefu/wifi")
|
||||
public class LefuController {
|
||||
|
||||
@Autowired
|
||||
private LefuService lefuService;
|
||||
|
||||
@PostMapping("/register")
|
||||
public LefuResponse<TimeInfo> register(@Validated @RequestBody DeviceInfo deviceInfo) {
|
||||
return LefuResponse.ok("DeviceInfo success", getTimeInfo());
|
||||
}
|
||||
|
||||
private TimeInfo getTimeInfo() {
|
||||
TimeInfo timeInfo = new TimeInfo();
|
||||
timeInfo.setUnit(0);
|
||||
timeInfo.setNow(System.currentTimeMillis());
|
||||
return timeInfo;
|
||||
}
|
||||
|
||||
@GetMapping("/config")
|
||||
public LefuResponse<TimeInfo> config(@Validated @RequestBody DeviceInfo deviceInfo) {
|
||||
return LefuResponse.ok("Get config info success", getTimeInfo());
|
||||
}
|
||||
|
||||
@PostMapping("/record")
|
||||
public LefuResponse<Boolean> record(@Validated @RequestBody Record record) throws JsonProcessingException {
|
||||
RemoteWeightManufacturerLefu data = lefuService.record(record);
|
||||
lefuService.sync(Collections.singletonList(data));
|
||||
return LefuResponse.ok("success");
|
||||
}
|
||||
|
||||
@PostMapping("/batchRecord")
|
||||
public LefuResponse<Boolean> batchRecord(@Validated @RequestBody BatchRecord batchRecord) throws JsonProcessingException {
|
||||
List<RemoteWeightManufacturerLefu> data = lefuService.batchRecord(batchRecord);
|
||||
lefuService.sync(data);
|
||||
return LefuResponse.ok("success");
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public LefuResponse<Page<RemoteWeightManufacturerLefu>> list(@RequestParam Integer pageNo, @RequestParam Integer pageSize) {
|
||||
return LefuResponse.ok("", lefuService.list(pageNo, pageSize));
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.renkang.sync.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.renkang.sync.bean.Result;
|
||||
import com.renkang.sync.entity.IdAware;
|
||||
import com.renkang.sync.service.DataService;
|
||||
import com.renkang.sync.util.Constants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.renkang.sync.util.Constants.GET_MAX_ID;
|
||||
import static com.renkang.sync.util.Constants.SAVE_DATA;
|
||||
|
||||
/**
|
||||
* @Name SyncController
|
||||
* @Author YangYuanChen
|
||||
* @Data 2024/7/26下午4:22
|
||||
*/
|
||||
@RestController
|
||||
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery", name = "enabled", havingValue = "true")
|
||||
public class SyncController {
|
||||
|
||||
private DataService dataService;
|
||||
|
||||
@Autowired
|
||||
public void setDataService(DataService dataService) {
|
||||
this.dataService = dataService;
|
||||
}
|
||||
|
||||
@GetMapping(GET_MAX_ID)
|
||||
public Result<String> getAllDataId(@RequestParam int type) {
|
||||
BigInteger maxId = dataService.getMaxId(Constants.getClass(type));
|
||||
return Result.ok("", Objects.nonNull(maxId) ? maxId.toString() : "0");
|
||||
}
|
||||
|
||||
@PostMapping(SAVE_DATA)
|
||||
public Result<Void> saveData(@RequestParam int type, @RequestBody String json) throws JsonProcessingException {
|
||||
Class<? extends IdAware> clz = Constants.getClass(type);
|
||||
Objects.requireNonNull(clz, "No type match.");
|
||||
dataService.saveData(clz, json);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.renkang.sync.entity;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
public interface IdAware {
|
||||
|
||||
BigInteger getId();
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.renkang.sync.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Name IndoorEnvironmentData
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午2:02
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "indoor_environment_data")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
public class IndoorEnvironmentData implements IdAware, Serializable {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private BigInteger id;
|
||||
@Column(name = "meter_code")
|
||||
private String meterCode;
|
||||
@Column(name = "read_time")
|
||||
private Integer readTime;
|
||||
@Column(name = "insert_time")
|
||||
private Integer insertTime;
|
||||
@Column(name = "temperature")
|
||||
private BigDecimal temperature;
|
||||
@Column(name = "humidity")
|
||||
private BigDecimal humidity;
|
||||
@Column(name = "carbon_dioxide")
|
||||
private BigDecimal carbonDioxide;
|
||||
@Column(name = "pm25")
|
||||
private BigDecimal pm25;
|
||||
@Column(name = "pm10")
|
||||
private BigDecimal pm10;
|
||||
@Column(name = "hcho")
|
||||
private BigDecimal hcho;
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
|
||||
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
|
||||
if (thisEffectiveClass != oEffectiveClass) {
|
||||
return false;
|
||||
}
|
||||
IndoorEnvironmentData that = (IndoorEnvironmentData) o;
|
||||
return getId() != null && Objects.equals(getId(), that.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.renkang.sync.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Name OutdoorEnvironmentData
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午2:05
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "outdoor_environment_data")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
public class OutdoorEnvironmentData implements IdAware, Serializable {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private BigInteger id;
|
||||
@Column(name = "meter_code")
|
||||
private String meterCode;
|
||||
@Column(name = "read_time")
|
||||
private Integer readTime;
|
||||
@Column(name = "insert_time")
|
||||
private Integer insertTime;
|
||||
@Column(name = "temperature")
|
||||
private BigDecimal temperature;
|
||||
@Column(name = "humidity")
|
||||
private BigDecimal humidity;
|
||||
@Column(name = "pm25")
|
||||
private BigDecimal pm25;
|
||||
@Column(name = "pm10")
|
||||
private BigDecimal pm10;
|
||||
@Column(name = "illuminance")
|
||||
private BigDecimal illuminance;
|
||||
@Column(name = "wind_speed")
|
||||
private BigDecimal windSpeed;
|
||||
@Column(name = "wind_direction")
|
||||
private Integer windDirection;
|
||||
@Column(name = "rs_ra")
|
||||
private BigDecimal rsRa;
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
|
||||
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
|
||||
if (thisEffectiveClass != oEffectiveClass) {
|
||||
return false;
|
||||
}
|
||||
OutdoorEnvironmentData that = (OutdoorEnvironmentData) o;
|
||||
return getId() != null && Objects.equals(getId(), that.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.renkang.sync.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Name PollenData
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午1:46
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "pollen_data")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
public class PollenData implements IdAware, Serializable {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private BigInteger id;
|
||||
@Column(name = "meter_code")
|
||||
private String meterCode;
|
||||
@Column(name = "read_time")
|
||||
private Integer readTime;
|
||||
@Column(name = "insert_time")
|
||||
private Integer insertTime;
|
||||
@Column(name = "one")
|
||||
private Integer one;
|
||||
@Column(name = "two")
|
||||
private Integer two;
|
||||
@Column(name = "three")
|
||||
private Integer three;
|
||||
@Column(name = "four")
|
||||
private Integer four;
|
||||
@Column(name = "five")
|
||||
private Integer five;
|
||||
@Column(name = "six")
|
||||
private Integer six;
|
||||
@Column(name = "temperature")
|
||||
private BigDecimal temperature;
|
||||
@Column(name = "humidity")
|
||||
private BigDecimal humidity;
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
|
||||
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
|
||||
if (thisEffectiveClass != oEffectiveClass) {
|
||||
return false;
|
||||
}
|
||||
PollenData that = (PollenData) o;
|
||||
return getId() != null && Objects.equals(getId(), that.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.renkang.sync.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author admin
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "remote_weight_manufacturer_lefu")
|
||||
public class RemoteWeightManufacturerLefu {
|
||||
@Id
|
||||
@Size(max = 32)
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "snow_flake_generator")
|
||||
@GenericGenerator(name = "snow_flake_generator", strategy = "com.renkang.sync.util.SnowFlakeIdGenerator")
|
||||
@Column(name = "id", nullable = false, length = 32)
|
||||
private String id;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "device_sn", length = 32)
|
||||
private String deviceSn;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "device_type", length = 32)
|
||||
private String deviceType;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "device_mac", length = 32)
|
||||
private String deviceMac;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "device_charge", length = 32)
|
||||
private String deviceCharge;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "device_impedance", length = 32)
|
||||
private String deviceImpedance;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "wifi_version", length = 32)
|
||||
private String wifiVersion;
|
||||
|
||||
@Size(max = 32)
|
||||
@Column(name = "firmware_version", length = 32)
|
||||
private String firmwareVersion;
|
||||
|
||||
@Column(name = "data_time")
|
||||
private Date dataTime;
|
||||
|
||||
@Column(name = "weight", precision = 6, scale = 2)
|
||||
private BigDecimal weight;
|
||||
|
||||
@Column(name = "heart_rate")
|
||||
private Integer heartRate;
|
||||
|
||||
@Column(name = "create_time")
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.renkang.sync.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Name WaterQualityData
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午2:41
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "water_quality_data")
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@RequiredArgsConstructor
|
||||
public class WaterQualityData implements IdAware, Serializable {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
private BigInteger id;
|
||||
@Column(name = "meter_code")
|
||||
private String meterCode;
|
||||
@Column(name = "insert_time")
|
||||
private Integer insertTime;
|
||||
@Column(name = "read_time")
|
||||
private Integer readTime;
|
||||
@Column(name = "temperature")
|
||||
private BigDecimal temperature;
|
||||
@Column(name = "conductivity")
|
||||
private BigDecimal conductivity;
|
||||
@Column(name = "turbidity")
|
||||
private BigDecimal turbidity;
|
||||
@Column(name = "residual_chlorine")
|
||||
private BigDecimal residualChlorine;
|
||||
@Column(name = "ph")
|
||||
private BigDecimal ph;
|
||||
@Column(name = "salinity")
|
||||
private BigDecimal salinity;
|
||||
@Column(name = "resistivity")
|
||||
private BigDecimal resistivity;
|
||||
@Column(name = "tds")
|
||||
private BigDecimal tds;
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
|
||||
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
|
||||
if (thisEffectiveClass != oEffectiveClass) {
|
||||
return false;
|
||||
}
|
||||
WaterQualityData that = (WaterQualityData) o;
|
||||
return getId() != null && Objects.equals(getId(), that.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.renkang.sync.repository;
|
||||
|
||||
import com.renkang.sync.entity.IdAware;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
public interface BaseRepository<T extends IdAware> extends JpaRepository<T, BigInteger> {
|
||||
|
||||
/**
|
||||
* 根据起始ID查询分页数据
|
||||
*
|
||||
* @param id 起始ID
|
||||
* @param pageable 分页参数
|
||||
* @return 分页数据
|
||||
*/
|
||||
Page<T> findByIdGreaterThan(BigInteger id, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询所有数据并返回 ID 最大的 BigInteger
|
||||
*
|
||||
* @return 最大ID值
|
||||
*/
|
||||
BigInteger findMaxId();
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.renkang.sync.repository;
|
||||
|
||||
import com.renkang.sync.entity.IndoorEnvironmentData;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* @Name IndoorRepository
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午4:52
|
||||
*/
|
||||
@Repository
|
||||
public interface IndoorRepository extends BaseRepository<IndoorEnvironmentData> {
|
||||
|
||||
/**
|
||||
* 查询所有数据并返回 ID 最大的 BigInteger
|
||||
*
|
||||
* @return 最大ID值
|
||||
*/
|
||||
@Override
|
||||
@Query("SELECT MAX(id) FROM IndoorEnvironmentData")
|
||||
BigInteger findMaxId();
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.renkang.sync.repository;
|
||||
|
||||
import com.renkang.sync.entity.RemoteWeightManufacturerLefu;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Repository
|
||||
public interface LefuRepository extends JpaRepository<RemoteWeightManufacturerLefu, String> {
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.renkang.sync.repository;
|
||||
|
||||
import com.renkang.sync.entity.OutdoorEnvironmentData;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* @Name OutdoorRepository
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午4:57
|
||||
*/
|
||||
@Repository
|
||||
public interface OutdoorRepository extends BaseRepository<OutdoorEnvironmentData> {
|
||||
|
||||
/**
|
||||
* 查询所有数据并返回 ID 最大的 BigInteger
|
||||
*
|
||||
* @return 最大ID值
|
||||
*/
|
||||
@Override
|
||||
@Query("SELECT MAX(id) FROM OutdoorEnvironmentData")
|
||||
BigInteger findMaxId();
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.renkang.sync.repository;
|
||||
|
||||
import com.renkang.sync.entity.PollenData;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* @Name PollenRepository
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午4:58
|
||||
*/
|
||||
@Repository
|
||||
public interface PollenRepository extends BaseRepository<PollenData> {
|
||||
|
||||
/**
|
||||
* 查询所有数据并返回 ID 最大的 BigInteger
|
||||
*
|
||||
* @return 最大ID值
|
||||
*/
|
||||
@Override
|
||||
@Query("SELECT MAX(id) FROM PollenData")
|
||||
BigInteger findMaxId();
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.renkang.sync.repository;
|
||||
|
||||
import com.renkang.sync.entity.WaterQualityData;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* @Name WaterRepository
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/25下午4:59
|
||||
*/
|
||||
@Repository
|
||||
public interface WaterRepository extends BaseRepository<WaterQualityData> {
|
||||
|
||||
/**
|
||||
* 查询所有数据并返回 ID 最大的 BigInteger
|
||||
*
|
||||
* @return 最大ID值
|
||||
*/
|
||||
@Override
|
||||
@Query("SELECT MAX(id) FROM WaterQualityData")
|
||||
BigInteger findMaxId();
|
||||
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package com.renkang.sync.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.renkang.sync.entity.*;
|
||||
import com.renkang.sync.repository.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Name DataService
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/26下午3:41
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DataService {
|
||||
|
||||
private IndoorRepository indoorRepository;
|
||||
|
||||
private OutdoorRepository outdoorRepository;
|
||||
|
||||
private PollenRepository pollenRepository;
|
||||
|
||||
private WaterRepository waterRepository;
|
||||
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
public void setIndoorRepository(IndoorRepository indoorRepository) {
|
||||
this.indoorRepository = indoorRepository;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setOutdoorRepository(OutdoorRepository outdoorRepository) {
|
||||
this.outdoorRepository = outdoorRepository;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setPollenRepository(PollenRepository pollenRepository) {
|
||||
this.pollenRepository = pollenRepository;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setWaterRepository(WaterRepository waterRepository) {
|
||||
this.waterRepository = waterRepository;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends IdAware> Page<T> getPagedDate(Class<T> clz, BigInteger start, Pageable pageable) {
|
||||
if (clz.equals(IndoorEnvironmentData.class)) {
|
||||
return (Page<T>) indoorRepository.findByIdGreaterThan(start, pageable);
|
||||
} else if (clz.equals(OutdoorEnvironmentData.class)) {
|
||||
return (Page<T>) outdoorRepository.findByIdGreaterThan(start, pageable);
|
||||
} else if (clz.equals(PollenData.class)) {
|
||||
return (Page<T>) pollenRepository.findByIdGreaterThan(start, pageable);
|
||||
} else if (clz.equals(WaterQualityData.class)) {
|
||||
return (Page<T>) waterRepository.findByIdGreaterThan(start, pageable);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void saveData(Class<? extends IdAware> clz, String json) throws JsonProcessingException {
|
||||
if (clz.equals(IndoorEnvironmentData.class)) {
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, IndoorEnvironmentData.class);
|
||||
List<IndoorEnvironmentData> data = objectMapper.readValue(json, javaType);
|
||||
save(indoorRepository, data);
|
||||
} else if (clz.equals(OutdoorEnvironmentData.class)) {
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, OutdoorEnvironmentData.class);
|
||||
List<OutdoorEnvironmentData> data = objectMapper.readValue(json, javaType);
|
||||
save(outdoorRepository, data);
|
||||
} else if (clz.equals(PollenData.class)) {
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, PollenData.class);
|
||||
List<PollenData> data = objectMapper.readValue(json, javaType);
|
||||
save(pollenRepository, data);
|
||||
} else if (clz.equals(WaterQualityData.class)) {
|
||||
JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, WaterQualityData.class);
|
||||
List<WaterQualityData> data = objectMapper.readValue(json, javaType);
|
||||
save(waterRepository, data);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends IdAware> void save(BaseRepository<T> repository, List<T> data) {
|
||||
repository.saveAll(data);
|
||||
}
|
||||
|
||||
public BigInteger getMaxId(Class<?> clz) {
|
||||
BaseRepository<? extends IdAware> repository = getRepository(clz);
|
||||
Objects.requireNonNull(repository, "No repository match.");
|
||||
return repository.findMaxId();
|
||||
}
|
||||
|
||||
private BaseRepository<? extends IdAware> getRepository(Class<?> clz) {
|
||||
if (clz == null) {
|
||||
return null;
|
||||
}
|
||||
if (clz.equals(IndoorEnvironmentData.class)) {
|
||||
return indoorRepository;
|
||||
} else if (clz.equals(OutdoorEnvironmentData.class)) {
|
||||
return outdoorRepository;
|
||||
} else if (clz.equals(PollenData.class)) {
|
||||
return pollenRepository;
|
||||
} else if (clz.equals(WaterQualityData.class)) {
|
||||
return waterRepository;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
package com.renkang.sync.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
|
||||
import com.renkang.sync.bean.Result;
|
||||
import com.renkang.sync.bean.lefu.BatchRecord;
|
||||
import com.renkang.sync.bean.lefu.Record;
|
||||
import com.renkang.sync.config.LefuProperties;
|
||||
import com.renkang.sync.entity.RemoteWeightManufacturerLefu;
|
||||
import com.renkang.sync.repository.LefuRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class LefuService {
|
||||
|
||||
public static final String X_ACCESS_TOKEN = "X-Access-Token";
|
||||
public static String PUSH_DATA = "/remote/data/device/weighing/lefu/sync";
|
||||
public static String CHECK_TOKEN = "/sys/checkToken";
|
||||
public static String GET_TOKEN = "/sys/thirdLogin";
|
||||
private final Map<String, String> tokenMap = new ConcurrentHashMap<>();
|
||||
private final ObjectMapper objectMapper;
|
||||
private LefuRepository lefuRepository;
|
||||
private LefuProperties lefuProperties;
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
public LefuService() {
|
||||
objectMapper = new ObjectMapper();
|
||||
//处理bigDecimal
|
||||
objectMapper.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
|
||||
objectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
|
||||
//处理失败
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, false);
|
||||
//默认的处理日期时间格式
|
||||
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||
objectMapper.registerModule(javaTimeModule);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setRestTemplate(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setLefuProperties(LefuProperties lefuProperties) {
|
||||
this.lefuProperties = lefuProperties;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setLefuRepository(LefuRepository lefuRepository) {
|
||||
this.lefuRepository = lefuRepository;
|
||||
}
|
||||
|
||||
@Async
|
||||
public void sync(List<RemoteWeightManufacturerLefu> data) throws JsonProcessingException {
|
||||
Map<String, LefuProperties.Service> sync = lefuProperties.getSync();
|
||||
for (Map.Entry<String, LefuProperties.Service> entry : sync.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
LefuProperties.Service service = entry.getValue();
|
||||
String url = service.getBaseUrl() + PUSH_DATA;
|
||||
ResponseEntity<Result<Void>> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(objectMapper.writeValueAsString(data), getHeaders(name, service)),
|
||||
new ParameterizedTypeReference<Result<Void>>() {
|
||||
});
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)
|
||||
|| ObjectUtils.isEmpty(response.getBody())
|
||||
|| !response.getBody().isSuccess()) {
|
||||
throw new RuntimeException("Push Lefu Data Error remotely");
|
||||
}
|
||||
log.info("Push Lefu Success {} for {}", data.size(), name);
|
||||
}
|
||||
}
|
||||
|
||||
private HttpHeaders getHeaders(String name, LefuProperties.Service service) throws JsonProcessingException {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.add(X_ACCESS_TOKEN, getToken(name, service));
|
||||
return httpHeaders;
|
||||
}
|
||||
|
||||
private String getToken(String name, LefuProperties.Service service) throws JsonProcessingException {
|
||||
String token = tokenMap.get(name);
|
||||
if (StrUtil.isBlank(token)) {
|
||||
remoteToken(name, service);
|
||||
} else {
|
||||
if (!checkToken(token, service)) {
|
||||
remoteToken(name, service);
|
||||
}
|
||||
}
|
||||
return tokenMap.get(name);
|
||||
}
|
||||
|
||||
private void remoteToken(String name, LefuProperties.Service service) throws JsonProcessingException {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("username", service.getUsername());
|
||||
data.put("password", service.getPassword());
|
||||
String url = service.getBaseUrl() + GET_TOKEN;
|
||||
ResponseEntity<Result<Map<String, String>>> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(objectMapper.writeValueAsString(data)),
|
||||
new ParameterizedTypeReference<Result<Map<String, String>>>() {
|
||||
});
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)
|
||||
|| ObjectUtils.isEmpty(response.getBody())
|
||||
|| !response.getBody().isSuccess()) {
|
||||
throw new RuntimeException("Get Token Error remotely");
|
||||
}
|
||||
String token = response.getBody().getResult().get("token");
|
||||
tokenMap.put(name, token);
|
||||
}
|
||||
|
||||
private boolean checkToken(String token, LefuProperties.Service service) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.add(X_ACCESS_TOKEN, token);
|
||||
String url = service.getBaseUrl() + CHECK_TOKEN;
|
||||
ResponseEntity<Result<Void>> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(httpHeaders),
|
||||
new ParameterizedTypeReference<Result<Void>>() {
|
||||
});
|
||||
return response.getStatusCode().equals(HttpStatus.OK)
|
||||
&& !ObjectUtils.isEmpty(response.getBody())
|
||||
&& response.getBody().isSuccess();
|
||||
}
|
||||
|
||||
public RemoteWeightManufacturerLefu record(Record record) {
|
||||
return lefuRepository.save(record.toRemoteEntity());
|
||||
}
|
||||
|
||||
public List<RemoteWeightManufacturerLefu> batchRecord(BatchRecord batchRecord) {
|
||||
return lefuRepository.saveAll(batchRecord.toRemoteEntities());
|
||||
}
|
||||
|
||||
public Page<RemoteWeightManufacturerLefu> list(Integer pageNo, Integer pageSize) {
|
||||
Pageable pageable = PageRequest.of(pageNo, pageSize).withSort(Sort.by(Sort.Order.desc("createTime")));
|
||||
return lefuRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
package com.renkang.sync.task;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.renkang.sync.bean.Result;
|
||||
import com.renkang.sync.config.SyncProperties;
|
||||
import com.renkang.sync.entity.*;
|
||||
import com.renkang.sync.service.DataService;
|
||||
import com.renkang.sync.util.Constants;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.support.CronTrigger;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import static com.renkang.sync.util.Constants.*;
|
||||
|
||||
/**
|
||||
* @Name SyncTask
|
||||
* @Author YangYuanChen
|
||||
* @Data 20242024/7/29下午7:45
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(prefix = "spring.cloud.nacos.discovery", name = "enabled", havingValue = "false", matchIfMissing = true)
|
||||
public class SyncTask {
|
||||
|
||||
private static final int[] TYPES = new int[]{
|
||||
INDOOR,
|
||||
OUTDOOR,
|
||||
POLLEN,
|
||||
WATER
|
||||
};
|
||||
private DataService dataService;
|
||||
private SyncProperties syncProperties;
|
||||
private RestTemplate restTemplate;
|
||||
private TaskScheduler schedulingTaskExecutor;
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
public void setDataService(DataService dataService) {
|
||||
this.dataService = dataService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setSyncProperties(SyncProperties syncProperties) {
|
||||
this.syncProperties = syncProperties;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setRestTemplate(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setSchedulingTaskExecutor(TaskScheduler schedulingTaskExecutor) {
|
||||
this.schedulingTaskExecutor = schedulingTaskExecutor;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
String cron = syncProperties.getCron();
|
||||
CronTrigger trigger = new CronTrigger(cron);
|
||||
for (String baseUrl : syncProperties.getBaseUrls()) {
|
||||
log.info("Add schedule task for base: {}", baseUrl);
|
||||
schedulingTaskExecutor.schedule(() -> {
|
||||
try {
|
||||
run(baseUrl);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}, trigger);
|
||||
}
|
||||
}
|
||||
|
||||
private void run(String baseUrl) throws JsonProcessingException {
|
||||
for (int type : TYPES) {
|
||||
try {
|
||||
BigInteger remoteMaxId = getRemoteMaxId(baseUrl, type);
|
||||
BigInteger localMaxId = getLocalMaxId(type);
|
||||
log.info("MaxId for base {} is: {}", baseUrl, remoteMaxId);
|
||||
if (remoteMaxId.compareTo(localMaxId) >= 0) {
|
||||
log.info("remote base {} is up-to-date", baseUrl);
|
||||
continue;
|
||||
}
|
||||
pushData(baseUrl, remoteMaxId, type);
|
||||
} catch (Exception e) {
|
||||
log.error("Error has occurred for base {} and type {}", baseUrl, type, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BigInteger getRemoteMaxId(String baseUrl, int type) {
|
||||
String url = getUrl(baseUrl, type, GET_MAX_ID);
|
||||
ResponseEntity<Result<String>> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<Result<String>>() {
|
||||
});
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)
|
||||
|| ObjectUtils.isEmpty(response.getBody())
|
||||
|| !StringUtils.hasText(response.getBody().getResult())) {
|
||||
errorLog(response);
|
||||
throw new RuntimeException("Get maxId Error remotely");
|
||||
}
|
||||
return new BigInteger(response.getBody().getResult());
|
||||
}
|
||||
|
||||
private BigInteger getLocalMaxId(int type) {
|
||||
BigInteger maxId = dataService.getMaxId(Constants.getClass(type));
|
||||
if (ObjectUtils.isEmpty(maxId)) {
|
||||
throw new RuntimeException("Get maxId Error locally");
|
||||
}
|
||||
return maxId;
|
||||
}
|
||||
|
||||
private void pushData(String baseUrl, BigInteger start, int type) throws JsonProcessingException {
|
||||
Pageable pageable = pageableInstance();
|
||||
Page<?> pagedData;
|
||||
boolean first = true;
|
||||
do {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
pageable = pageable.next();
|
||||
}
|
||||
pagedData = getPagedData(start, type, pageable);
|
||||
if (pagedData.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
remotePush(baseUrl, pagedData.getContent(), type);
|
||||
} while (pagedData.hasNext());
|
||||
}
|
||||
|
||||
private Pageable pageableInstance() {
|
||||
Sort sort = Sort.by(Sort.Order.asc(ID_FIELD));
|
||||
return PageRequest.of(0, syncProperties.getSize(), sort);
|
||||
}
|
||||
|
||||
private <T extends IdAware> Page<T> getPagedData(BigInteger start, Class<T> clz, Pageable pageable) {
|
||||
return dataService.getPagedDate(clz, start, pageable);
|
||||
}
|
||||
|
||||
private Page<?> getPagedData(BigInteger start, int type, Pageable pageable) {
|
||||
if (type == INDOOR) {
|
||||
return getPagedData(start, IndoorEnvironmentData.class, pageable);
|
||||
} else if (type == OUTDOOR) {
|
||||
return getPagedData(start, OutdoorEnvironmentData.class, pageable);
|
||||
} else if (type == POLLEN) {
|
||||
return getPagedData(start, PollenData.class, pageable);
|
||||
} else if (type == WATER) {
|
||||
return getPagedData(start, WaterQualityData.class, pageable);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
private void remotePush(String baseUrl, List<?> data, int type) throws JsonProcessingException {
|
||||
String url = getUrl(baseUrl, type, SAVE_DATA);
|
||||
ResponseEntity<Result<Void>> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
new HttpEntity<>(objectMapper.writeValueAsString(data)),
|
||||
new ParameterizedTypeReference<Result<Void>>() {
|
||||
});
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)
|
||||
|| ObjectUtils.isEmpty(response.getBody())
|
||||
|| !response.getBody().isSuccess()) {
|
||||
errorLog(response);
|
||||
throw new RuntimeException("Push Data Error remotely");
|
||||
}
|
||||
log.info("Push Success {} for type {}", data.size(), type);
|
||||
}
|
||||
|
||||
private void errorLog(ResponseEntity<?> response) {
|
||||
log.error("MaxId HttpCode: {}", response.getStatusCodeValue());
|
||||
log.error("MaxId Response: {}", response.getBody());
|
||||
}
|
||||
|
||||
private String getUrl(String baseUrl, int type, String api) {
|
||||
return UriComponentsBuilder.fromHttpUrl(baseUrl + api)
|
||||
.queryParam(TYPE_PARAM, type)
|
||||
.encode()
|
||||
.toUriString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.renkang.sync.util;
|
||||
|
||||
import com.renkang.sync.entity.*;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
public interface Constants {
|
||||
|
||||
int INDOOR = 1;
|
||||
|
||||
int OUTDOOR = 2;
|
||||
|
||||
int POLLEN = 3;
|
||||
|
||||
int WATER = 4;
|
||||
|
||||
String TYPE_PARAM = "type";
|
||||
|
||||
String ID_FIELD = "id";
|
||||
|
||||
String GET_MAX_ID = "/maxId";
|
||||
String SAVE_DATA = "/saveData";
|
||||
|
||||
/**
|
||||
* 根据字典类型返回对应的类
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 实体类
|
||||
*/
|
||||
static Class<? extends IdAware> getClass(int type) {
|
||||
switch (type) {
|
||||
case INDOOR:
|
||||
return IndoorEnvironmentData.class;
|
||||
case OUTDOOR:
|
||||
return OutdoorEnvironmentData.class;
|
||||
case POLLEN:
|
||||
return PollenData.class;
|
||||
case WATER:
|
||||
return WaterQualityData.class;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.renkang.sync.util;
|
||||
|
||||
import cn.hutool.core.lang.Snowflake;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Slf4j
|
||||
public class SnowFlakeIdGenerator implements IdentifierGenerator {
|
||||
|
||||
private final Snowflake snowFlake;
|
||||
|
||||
private Class<?> type;
|
||||
|
||||
public SnowFlakeIdGenerator() {
|
||||
this.snowFlake = IdUtil.getSnowflake();
|
||||
}
|
||||
|
||||
public synchronized long snowflakeId() {
|
||||
return snowFlake.nextId();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Serializable generate(SharedSessionContractImplementor session, Object object)
|
||||
throws HibernateException {
|
||||
long id = snowflakeId();
|
||||
if (Long.class.isAssignableFrom(type)) {
|
||||
return id;
|
||||
} else if (String.class.isAssignableFrom(type)) {
|
||||
return Long.toString(id);
|
||||
} else if (byte[].class.isAssignableFrom(type)) {
|
||||
return Long.toUnsignedString(id).getBytes();
|
||||
} else {
|
||||
throw new HibernateException("Unanticipated return type [" + type.getName() + "] for ID conversion");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
|
||||
this.type = type.getReturnedClass();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
PROFILE_NAME=dev
|
||||
SERVER_PORT=27002
|
||||
NACOS_SERVER_ADDR=nacos.yg.dt.io:80
|
||||
NACOS_USERNAME=cqyt
|
||||
NACOS_PASSWORD=Aa123456
|
||||
NACOS_NAMESPACE=2639a2d4-7b64-4408-98c9-b97e0bdf4c1f
|
||||
NACOS_GROUP=dev
|
||||
NACOS_ENABLE=false
|
||||
@@ -0,0 +1,27 @@
|
||||
server:
|
||||
port: ${SERVER_PORT:27001}
|
||||
spring:
|
||||
application:
|
||||
name: env-sync
|
||||
config:
|
||||
import:
|
||||
- optional:nacos:${spring.application.name}-${PROFILE_NAME}.yaml
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: ${NACOS_SERVER_ADDR}
|
||||
username: ${NACOS_USERNAME:nacos}
|
||||
password: ${NACOS_PASSWORD:nacos}
|
||||
config:
|
||||
enabled: true
|
||||
namespace: ${NACOS_NAMESPACE:}
|
||||
group: ${NACOS_GROUP:DEFAULT_GROUP}
|
||||
server-addr: ${spring.cloud.nacos.server-addr}
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
discovery:
|
||||
enabled: ${NACOS_ENABLE:false}
|
||||
namespace: ${NACOS_NAMESPACE:}
|
||||
group: ${NACOS_GROUP:DEFAULT_GROUP}
|
||||
server-addr: ${spring.cloud.nacos.server-addr}
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user