diff --git a/disruptor_nmc/.gitignore b/disruptor_nmc/.gitignore new file mode 100644 index 0000000..072d452 --- /dev/null +++ b/disruptor_nmc/.gitignore @@ -0,0 +1,34 @@ +HELP.md +target/ +/target/× +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/disruptor_nmc/.mvn/wrapper/maven-wrapper.jar b/disruptor_nmc/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..cb28b0e Binary files /dev/null and b/disruptor_nmc/.mvn/wrapper/maven-wrapper.jar differ diff --git a/disruptor_nmc/.mvn/wrapper/maven-wrapper.properties b/disruptor_nmc/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..5f0536e --- /dev/null +++ b/disruptor_nmc/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/disruptor_nmc/mvnw b/disruptor_nmc/mvnw new file mode 100755 index 0000000..66df285 --- /dev/null +++ b/disruptor_nmc/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/disruptor_nmc/mvnw.cmd b/disruptor_nmc/mvnw.cmd new file mode 100644 index 0000000..95ba6f5 --- /dev/null +++ b/disruptor_nmc/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/disruptor_nmc/pom.xml b/disruptor_nmc/pom.xml new file mode 100644 index 0000000..83b3940 --- /dev/null +++ b/disruptor_nmc/pom.xml @@ -0,0 +1,185 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.3 + + + com.rehome + disruptor_nmc + war + 1.0.0 + disruptor_nmc + SpringBoot + Disruptor 实现特快高并发处理,支撑每秒 600 万订单无压力! + + 1.8 + 2020.0.3 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.4 + + + javax.validation + validation-api + 2.0.1.Final + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-test + test + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.0 + + + com.google.code.gson + gson + 2.8.2 + + + com.squareup.okhttp3 + okhttp + 3.6.0 + + + org.apache.commons + commons-lang3 + 3.9 + + + org.jetbrains + annotations + 19.0.0 + + + + org.projectlombok + lombok + 1.18.20 + true + + + + org.apache.logging.log4j + log4j-api + 2.17.1 + + + + org.apache.logging.log4j + log4j-core + 2.17.1 + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.6 + + + commons-io + commons-io + 2.4 + + + + mysql + mysql-connector-java + 8.0.26 + runtime + + + + com.oracle + ojdbc6 + 11.2.0.1.0 + + + + com.microsoft.sqlserver + mssql-jdbc + 11.2.0.jre8 + + + io.swagger + swagger-annotations + 1.5.20 + + + com.alibaba + fastjson + 1.2.47 + + + org.bouncycastle + bcprov-jdk15on + 1.60 + compile + + + org.bouncycastle + bcpkix-jdk15on + 1.60 + compile + + + commons-codec + commons-codec + 1.11 + compile + + + com.lmax + disruptor + 3.4.4 + + + com.liuhuiyu + spring-util + 2021.1.0 + + + com.liuhuiyu + util + 2022.1.0 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/DisruptorNmcApplication.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/DisruptorNmcApplication.java new file mode 100644 index 0000000..452a64a --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/DisruptorNmcApplication.java @@ -0,0 +1,86 @@ +package com.rehome.disruptor_nmc; + +import com.rehome.disruptor_nmc.service.DisruptorMqService; +import com.rehome.disruptor_nmc.service.TemperatureService; +import org.springframework.beans.BeansException; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.bind.annotation.RequestMapping; +import javax.annotation.Resource; +import java.util.Map; + +@EnableJpaAuditing +@EnableScheduling +@SpringBootApplication +public class DisruptorNmcApplication extends SpringBootServletInitializer implements CommandLineRunner, ApplicationContextAware { + + /** + * 获取Spring框架的上下文 + */ + private ApplicationContext applicationContext; + /** + 后台接口自动导入 + */ + @Resource + private DisruptorMqService disruptorMqService; + + public static void main(String[] args) { + SpringApplication.run(DisruptorNmcApplication.class, args); + } + + /** + * @date 2021-05-18 09:20 + * @description: 容器配置,springboot打war包布署必须添加这个配置 为了打包springboot项目 + * @Param: SpringApplicationBuilder + */ + @Override + protected SpringApplicationBuilder configure( + SpringApplicationBuilder builder) { + return builder.sources(DisruptorNmcApplication.class); + } + + + @Override + public void run(String... args) { + //在这里可以调用applicationContext了 + Map controllers = applicationContext.getBeansWithAnnotation(RequestMapping.class); + for (Map.Entry entry : controllers.entrySet()) { + System.out.println("------------------------"); + System.out.println(entry.getKey());//demo1Controller + } + try { + if (disruptorMqService != null) { + System.out.println("------------------------"); + System.out.println("DisruptorMqService is not empty"); + //guangzhuo server temperature mqtt +// MqttRSAClient client = new MqttRSAClient(); +// client.start(disruptorMqService); + + //hk aliyun temperature mqtt +// MqttHkRSAClient clientHk = new MqttHkRSAClient(); +// clientHk.start(disruptorMqService); + //hk aliyun app_push mqtt + MqttHkAppPushRSAClient clientAppPush = new MqttHkAppPushRSAClient(); + clientAppPush.start(disruptorMqService); + } else { + System.out.println("DisruptorMqService is empty"); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttHkAppPushRSAClient.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttHkAppPushRSAClient.java new file mode 100644 index 0000000..572675e --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttHkAppPushRSAClient.java @@ -0,0 +1,149 @@ +package com.rehome.disruptor_nmc; + + + +import com.rehome.disruptor_nmc.service.DisruptorMqService; +import com.rehome.disruptor_nmc.utils.MqttSSLSocketFactory; +import com.rehome.disruptor_nmc.utils.UUIDUtil; +import org.eclipse.paho.client.mqttv3.*; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import javax.net.ssl.SSLSocketFactory; +import java.io.InputStream; +import java.util.Timer; +import java.util.TimerTask; + + +public class MqttHkAppPushRSAClient { + /** + * 代理服务器ip地址 + */ + public static final String MQTT_BROKER_HOST = "ssl://47.242.184.139:8883"; + + /** + * 客户端唯一标识 + */ + public static String MQTT_CLIENT_ID = "AppServer_disruptor_nmc_server_03"; + + /** + *帐号 + */ + public static String USERNAME = "admin"; + /** + * 密码 + */ + public static String PASSWORD = "publish452131wW452131wW$"; + /** + * 订阅标识 + */ + public static String TOPIC_FILTER = "app_push"; + + private volatile static MqttClient mqttClient; + private static MqttConnectOptions options; + private static int qos = 2; + + //定时器 + private Timer timer; + + public MqttHkAppPushRSAClient(){ + try { + MQTT_CLIENT_ID = UUIDUtil.getUUID(); + // host为主机名,clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示, + // MemoryPersistence设置clientid的保存形式,默认为以内存保存 + mqttClient = new MqttClient(MQTT_BROKER_HOST, MQTT_CLIENT_ID, new MemoryPersistence()); + // 配置参数信息 + options = new MqttConnectOptions(); + // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录, + // 这里设置为true表示每次连接到服务器都以新的身份连接 + options.setCleanSession(false); + // 设置用户名 + options.setUserName(USERNAME); + // 设置密码 + options.setPassword(PASSWORD.toCharArray()); + // 设置超时时间 单位为秒 + options.setConnectionTimeout(10); + // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制 + options.setKeepAliveInterval(20); + //断线重连 + options.setAutomaticReconnect(true); + //mqtt服务器端单双向加密 + InputStream caCrtFile = this.getClass().getResourceAsStream("/sslHk/my_root_ca.crt"); + InputStream crtFile = this.getClass().getResourceAsStream("/sslHk/client.crt"); + InputStream keyFile = this.getClass().getResourceAsStream("/sslHk/client.key"); + String password = ""; + SSLSocketFactory socketFactory = MqttSSLSocketFactory.getTwoDirSocketFactory(caCrtFile,crtFile,keyFile,password); + options.setSocketFactory(socketFactory); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void start(DisruptorMqService disruptorMqService) { + try { + // 连接 + mqttClient.connect(options); + // 订阅 + mqttClient.subscribe(TOPIC_FILTER,qos); + // 设置回调 + mqttClient.setCallback(new MqttCallbackExtended(){ + + @Override + public void connectionLost(Throwable throwable) { + System.out.println("connectionLost"); + try { + mqttClient.reconnect(); + } catch (MqttException e) { + e.printStackTrace(); + } + } + + @Override + public void messageArrived(String s, MqttMessage mqttMessage) { + String strData = new String(mqttMessage.getPayload()); + System.out.println("topic:"+s); + System.out.println("Qos:"+mqttMessage.getQos()); + System.out.println("message RSA:"+strData); + //disruptorMqService.pushTemperatureToMq(strData,s); + } + + @Override + public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { + System.out.println("deliveryComplete---------"+ iMqttDeliveryToken.isComplete()); + } + + @Override + public void connectComplete(boolean b, String s) { + //连接成功后调用 + try { + mqttClient.subscribe(TOPIC_FILTER,qos);//具体订阅代码 + } catch (MqttException e) { + e.printStackTrace(); + } + } + }); + + timer = new Timer(); + timer.schedule(new TimerTask() { + public void run() { + System.out.println("-------设定要指定任务--------"); + try { + //判断拦截状态,这里注意一下,如果没有这个判断,是非常坑的 + if (!mqttClient.isConnected()) { + System.out.println("***** 没有连接到服务器 *****"); + System.out.println("***** client to connect *****"); + // 重新连接 + mqttClient.connect(options); + } + if (mqttClient.isConnected()) {//连接成功,跳出连接 + System.out.println("***** connect success *****"); + } + } catch (MqttException e1) { + e1.printStackTrace(); + } + } + }, 10000,10000); + // 设定指定的时间time,此处为10000毫秒 + } catch (Exception e) { + e.printStackTrace(); + } + } +} + diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttHkRSAClient.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttHkRSAClient.java new file mode 100644 index 0000000..1d7c6bc --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttHkRSAClient.java @@ -0,0 +1,147 @@ +package com.rehome.disruptor_nmc; + + +import com.rehome.disruptor_nmc.service.DisruptorMqService; +import com.rehome.disruptor_nmc.utils.MqttSSLSocketFactory; +import com.rehome.disruptor_nmc.utils.UUIDUtil; +import org.eclipse.paho.client.mqttv3.*; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import javax.net.ssl.SSLSocketFactory; +import java.io.InputStream; +import java.util.Timer; +import java.util.TimerTask; + + +public class MqttHkRSAClient { + /** + * 代理服务器ip地址 + */ + public static final String MQTT_BROKER_HOST = "ssl://47.242.184.139:8883"; + + /** + * 客户端唯一标识 + */ + public static String MQTT_CLIENT_ID = "AppServer_disruptor_nmc_server_02"; + + /** + *帐号 + */ + public static String USERNAME = "admin"; + /** + * 密码 + */ + public static String PASSWORD = "publish452131wW452131wW$"; + /** + * 订阅标识 + */ + public static String TOPIC_FILTER = "WifiSHT/+/SHT20"; + + private volatile static MqttClient mqttClient; + private static MqttConnectOptions options; + private static int qos = 2; + + //定时器 + private Timer timer; + + public MqttHkRSAClient(){ + try { + MQTT_CLIENT_ID = UUIDUtil.getUUID(); + // host为主机名,clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示, + // MemoryPersistence设置clientid的保存形式,默认为以内存保存 + mqttClient = new MqttClient(MQTT_BROKER_HOST, MQTT_CLIENT_ID, new MemoryPersistence()); + // 配置参数信息 + options = new MqttConnectOptions(); + // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录, + // 这里设置为true表示每次连接到服务器都以新的身份连接 + options.setCleanSession(false); + // 设置用户名 + options.setUserName(USERNAME); + // 设置密码 + options.setPassword(PASSWORD.toCharArray()); + // 设置超时时间 单位为秒 + options.setConnectionTimeout(10); + // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制 + options.setKeepAliveInterval(20); + //断线重连 + options.setAutomaticReconnect(true); + //mqtt服务器端单双向加密 + InputStream caCrtFile = this.getClass().getResourceAsStream("/sslHk/my_root_ca.crt"); + InputStream crtFile = this.getClass().getResourceAsStream("/sslHk/client.crt"); + InputStream keyFile = this.getClass().getResourceAsStream("/sslHk/client.key"); + String password = ""; + SSLSocketFactory socketFactory = MqttSSLSocketFactory.getTwoDirSocketFactory(caCrtFile,crtFile,keyFile,password); + options.setSocketFactory(socketFactory); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void start(DisruptorMqService disruptorMqService) { + try { + // 连接 + mqttClient.connect(options); + // 订阅 + mqttClient.subscribe(TOPIC_FILTER,qos); + // 设置回调 + mqttClient.setCallback(new MqttCallbackExtended(){ + + @Override + public void connectionLost(Throwable throwable) { + System.out.println("connectionLost"); + try { + mqttClient.reconnect(); + } catch (MqttException e) { + e.printStackTrace(); + } + } + + @Override + public void messageArrived(String s, MqttMessage mqttMessage) { + String strData = new String(mqttMessage.getPayload()); + System.out.println("topic:"+s); + System.out.println("Qos:"+mqttMessage.getQos()); + System.out.println("message RSA:"+strData); + disruptorMqService.pushTemperatureToMq(strData,s); + } + + @Override + public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { + System.out.println("deliveryComplete---------"+ iMqttDeliveryToken.isComplete()); + } + + @Override + public void connectComplete(boolean b, String s) { + //连接成功后调用 + try { + mqttClient.subscribe(TOPIC_FILTER,qos);//具体订阅代码 + } catch (MqttException e) { + e.printStackTrace(); + } + } + }); + + timer = new Timer(); + timer.schedule(new TimerTask() { + public void run() { + System.out.println("-------设定要指定任务--------"); + try { + //判断拦截状态,这里注意一下,如果没有这个判断,是非常坑的 + if (!mqttClient.isConnected()) { + System.out.println("***** 没有连接到服务器 *****"); + System.out.println("***** client to connect *****"); + // 重新连接 + mqttClient.connect(options); + } + if (mqttClient.isConnected()) {//连接成功,跳出连接 + System.out.println("***** connect success *****"); + } + } catch (MqttException e1) { + e1.printStackTrace(); + } + } + }, 10000,10000); + // 设定指定的时间time,此处为10000毫秒 + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttRSAClient.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttRSAClient.java new file mode 100644 index 0000000..d384fac --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/MqttRSAClient.java @@ -0,0 +1,148 @@ +package com.rehome.disruptor_nmc; + + +import com.rehome.disruptor_nmc.service.DisruptorMqService; +import com.rehome.disruptor_nmc.service.TemperatureService; +import com.rehome.disruptor_nmc.utils.MqttSSLSocketFactory; +import com.rehome.disruptor_nmc.utils.UUIDUtil; +import org.eclipse.paho.client.mqttv3.*; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import javax.net.ssl.SSLSocketFactory; +import java.io.InputStream; +import java.util.Timer; +import java.util.TimerTask; + + +public class MqttRSAClient { + /** + * 代理服务器ip地址 + */ + public static final String MQTT_BROKER_HOST = "ssl://119.91.158.116:8883"; + + /** + * 客户端唯一标识 + */ + public static String MQTT_CLIENT_ID = "AppServer_disruptor_nmc_server_01"; + + /** + *帐号 + */ + public static String USERNAME = "admin"; + /** + * 密码 + */ + public static String PASSWORD = "publish452131wW452131wW$"; + /** + * 订阅标识 + */ + public static String TOPIC_FILTER = "WifiSHT/+/SHT20"; + + private volatile static MqttClient mqttClient; + private static MqttConnectOptions options; + private static int qos = 2; + + //定时器 + private Timer timer; + + public MqttRSAClient(){ + try { + MQTT_CLIENT_ID = UUIDUtil.getUUID(); + // host为主机名,clientid即连接MQTT的客户端ID,一般以客户端唯一标识符表示, + // MemoryPersistence设置clientid的保存形式,默认为以内存保存 + mqttClient = new MqttClient(MQTT_BROKER_HOST, MQTT_CLIENT_ID, new MemoryPersistence()); + // 配置参数信息 + options = new MqttConnectOptions(); + // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录, + // 这里设置为true表示每次连接到服务器都以新的身份连接 + options.setCleanSession(false); + // 设置用户名 + options.setUserName(USERNAME); + // 设置密码 + options.setPassword(PASSWORD.toCharArray()); + // 设置超时时间 单位为秒 + options.setConnectionTimeout(10); + // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制 + options.setKeepAliveInterval(20); + //断线重连 + options.setAutomaticReconnect(true); + //mqtt服务器端单双向加密 + InputStream caCrtFile = this.getClass().getResourceAsStream("/ssl/my_root_ca.crt"); + InputStream crtFile = this.getClass().getResourceAsStream("/ssl/client.crt"); + InputStream keyFile = this.getClass().getResourceAsStream("/ssl/client.key"); + String password = ""; + SSLSocketFactory socketFactory = MqttSSLSocketFactory.getTwoDirSocketFactory(caCrtFile,crtFile,keyFile,password); + options.setSocketFactory(socketFactory); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void start(DisruptorMqService disruptorMqService) { + try { + // 连接 + mqttClient.connect(options); + // 订阅 + mqttClient.subscribe(TOPIC_FILTER,qos); + // 设置回调 + mqttClient.setCallback(new MqttCallbackExtended(){ + + @Override + public void connectionLost(Throwable throwable) { + System.out.println("connectionLost"); + try { + mqttClient.reconnect(); + } catch (MqttException e) { + e.printStackTrace(); + } + } + + @Override + public void messageArrived(String s, MqttMessage mqttMessage) { + String strData = new String(mqttMessage.getPayload()); + System.out.println("topic:"+s); + System.out.println("Qos:"+mqttMessage.getQos()); + System.out.println("message RSA:"+strData); + disruptorMqService.pushTemperatureToMq(strData,s); + } + + @Override + public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { + System.out.println("deliveryComplete---------"+ iMqttDeliveryToken.isComplete()); + } + + @Override + public void connectComplete(boolean b, String s) { + //连接成功后调用 + try { + mqttClient.subscribe(TOPIC_FILTER,qos);//具体订阅代码 + } catch (MqttException e) { + e.printStackTrace(); + } + } + }); + + timer = new Timer(); + timer.schedule(new TimerTask() { + public void run() { + System.out.println("-------设定要指定任务--------"); + try { + //判断拦截状态,这里注意一下,如果没有这个判断,是非常坑的 + if (!mqttClient.isConnected()) { + System.out.println("***** 没有连接到服务器 *****"); + System.out.println("***** client to connect *****"); + // 重新连接 + mqttClient.connect(options); + } + if (mqttClient.isConnected()) {//连接成功,跳出连接 + System.out.println("***** connect success *****"); + } + } catch (MqttException e1) { + e1.printStackTrace(); + } + } + }, 10000,10000); + // 设定指定的时间time,此处为10000毫秒 + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/RSAAndroid.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/RSAAndroid.java new file mode 100644 index 0000000..d1f41d8 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/RSAAndroid.java @@ -0,0 +1,527 @@ +package com.rehome.disruptor_nmc; + + +/** + * @ Author : huangwenfei + * @ Date : Created in 2021/8/11 10:44 下午 + * @ Version : $1.0.0.0 + * @ Description: + */ + +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; +import java.util.List; + + +public class RSAAndroid { + private static String TAG = "RSAAndroid"; + public static final String RSA = "RSA";// 非对称加密密钥算法 + //public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式 + public static final String ECB_PKCS1_PADDING = "RSA";//加密填充方式 RSA/None/PKCS1Padding + public static final int DEFAULT_KEY_SIZE = 2048;//秘钥默认长度 + public static final byte[] DEFAULT_SPLIT = "#PART#".getBytes(); // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密 + public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;// 当前秘钥支持加密的最大字节数 + public static String publicRsaKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmMLyJw1CAl25lnDgEeYZvOps+1pSi93Q39djEniGNo5uUKVEkqDIayTli2zreX10HqT2jTtDN9APtwuEhWazP/VgOXoWsztbtZtSwJGM6Eg0R9zDCbKyQt5Qhg3jkTrXrvrGn7j/ZP56VNWELv/i5dsRCTccr1MeIyxjOC2pojCOsrTN4HZzgBj+GEUKPRLcKOiPfOsoP7HgkAua82vTOIgWpqIp+1PIfcjjCqzOsSv5PQnGP75+flIXtz75OKo/9hX9zl5JHNcH3SC6nS8Czii9E292XIsBtKdQijvNMn+YcmKFo6mZOUXHdO506NoKkxRny5fbKiPf/oqTA7Zx5QIDAQAB"; + public static String privateRsaKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCYwvInDUICXbmWcOAR5hm86mz7WlKL3dDf12MSeIY2jm5QpUSSoMhrJOWLbOt5fXQepPaNO0M30A+3C4SFZrM/9WA5ehazO1u1m1LAkYzoSDRH3MMJsrJC3lCGDeOROteu+safuP9k/npU1YQu/+Ll2xEJNxyvUx4jLGM4LamiMI6ytM3gdnOAGP4YRQo9Etwo6I986yg/seCQC5rza9M4iBamoin7U8h9yOMKrM6xK/k9CcY/vn5+Uhe3Pvk4qj/2Ff3OXkkc1wfdILqdLwLOKL0Tb3ZciwG0p1CKO80yf5hyYoWjqZk5Rcd07nTo2gqTFGfLl9sqI9/+ipMDtnHlAgMBAAECggEATJd5yCC6lusdMRO5FOBUyUaUi9X2i1AU+RZKAynQySvSnbavUgExW58tRCHBUrGW9gJp59ft1N8J8hHhSO18NDY4H7laBlVdnwmYjRqtFo2VQO6sD4G8JRDION5f2iIxn/b2fYDI9H8vILfJRbNgtTSILyGlzTYUZzhLKxCh+8IsN96Nic8wa5COd1vZZmdhf2y8TG8clFWmozaScNSAATx7y+8XLVWjjWiIRZ6xQvx0uQPUParc9KihXXTKR2pA22yPIdz+U4MGD4kC0eczlcFKZ/dYv9e7OIGgnJfT0idSCu7nYb1pxJ1LxD9fS6IScNTF5dSe0OIL98e+XdyoAQKBgQDRep+5cW4iAKrEMH+djmcXAkoMiYtNVtnu0efLE8dP6vjYytQi368X9SdcASbfrQ31eEZmr/xQnlUF8oyHGkI38YS8dpAHzQcrkP3BljbbzB/3gJZaUdghGsDrK0xAJIzzmFKQpeKnGtr23vxUgaGrNsCYvQ0eQ7+5056KXS4r5QKBgQC6r8xtRSaje6L4WIydjWvYywsmRO0Of0aJLMDA/Wt2MWhHfh7ba9oI1cKGN80ap7xB2a9lQLgpv+C53wNtE5SpvjxsikAj96nUMMhGy9ojXrUith6HQhiINETz6Shnznd+AyrXP6KI/RpfA5nkDB5nrJxODwtYLP467IL7Cv7OAQKBgQCl4KxKdH/5fP28jYsAgJsxpSZt9xzQCU5Zxu396ZOSvUaApVyGoQpNtluMh3z48lhzYOKevgzW6gn5w69z7F8zXZT2iAxVoQ1kelP2z7RxKJrHqpNkwhqbXEwX7RlcUZUr8BqxYCqymJl7k+fMIzqaEalBSbLxnEReKi0I8/Bz4QKBgHK4b0ZCtVDHPEmimJ6E9l4dv/c/afF7swu+zaCK2ouiJvOwBCRQbYb6XPR/u/GCXASXUdpF4CX/vIhcDE3uN2/r8FO+zVWM7vbvF1OyF5WesG7pPW9e5ZZlkG3WvLa1wOZV6fCmMSo/ZwI2Q05JSDHrd43cXttLotrw1jiQ9C4BAoGBAKi4SOoOVQ5J5HQCDkBwPbG1AOLHFinzfoDl26GF/8Hy7fmmd1JiRTFldQp/A9VTAABz3sVYmMB92HSIaJhuDMoYJNI2Cf/cZifsv7vUL8cbLn+lPsKsebiuB0m0g4P2qLwLfegfNGEgA7lA5HIz3SELqbdp3iuqJeQl1fsJqD74"; + + + public static byte[] decryptBASE64(String key) throws Exception { + return Base64.decodeBase64(key); + } + + public static String encryptBASE64(byte[] key) throws Exception { + return Base64.encodeBase64String(key); + } + + /** + * 随机生成RSA密钥对 + * + * @param keyLength 密钥长度,范围:512~2048 + * 一般1024 + * @return + */ + public static KeyPair generateRSAKeyPair(int keyLength) { + try { + KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA); + kpg.initialize(keyLength); + return kpg.genKeyPair(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + } + + /** + * 用公钥对字符串进行加密 + * + * @param data 原文 + */ + public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { + // 得到公钥 + byte[] decoded = Base64.decodeBase64(publicKey); + RSAPublicKey keyPublic = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); + // 加密数据 + Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); + cp.init(Cipher.ENCRYPT_MODE, keyPublic); + return cp.doFinal(data); + } + + /** + * 私钥加密 + * + * @param data 待加密数据 + * @param privateKey 密钥 + * @return byte[] 加密数据 + */ + public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { + // 得到私钥 + byte[] decoded = Base64.decodeBase64(privateKey); + RSAPrivateKey keyPrivate = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + // 数据加密 + Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); + cipher.init(Cipher.ENCRYPT_MODE, keyPrivate); + return cipher.doFinal(data); + } + + /** + * 公钥解密 + * + * @param data 待解密数据 + * @param publicKey 密钥 + * @return byte[] 解密数据 + */ + public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { + // 得到公钥 + byte[] decoded = Base64.decodeBase64(publicKey); + RSAPublicKey keyPublic = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); + // 数据解密 + Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); + cipher.init(Cipher.DECRYPT_MODE, keyPublic); + return cipher.doFinal(data); + } + + /** + * 使用私钥进行解密 + */ + public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { + // 得到私钥 + byte[] decoded = Base64.decodeBase64(privateKey); + RSAPrivateKey keyPrivate = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + + // 解密数据 + Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); + cp.init(Cipher.DECRYPT_MODE, keyPrivate); + byte[] arr = cp.doFinal(encrypted); + return arr; + } + + /** + * 用公钥对字符串进行分段加密 + */ + public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception { + int dataLen = data.length; + if (dataLen <= DEFAULT_BUFFERSIZE) { + return encryptByPublicKey(data, publicKey); + } + List allBytes = new ArrayList(2048); + int bufIndex = 0; + int subDataLoop = 0; + byte[] buf = new byte[DEFAULT_BUFFERSIZE]; + for (int i = 0; i < dataLen; i++) { + buf[bufIndex] = data[i]; + if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { + subDataLoop++; + if (subDataLoop != 1) { + for (byte b : DEFAULT_SPLIT) { + allBytes.add(b); + } + } + byte[] encryptBytes = encryptByPublicKey(buf, publicKey); + for (byte b : encryptBytes) { + allBytes.add(b); + } + bufIndex = 0; + if (i == dataLen - 1) { + buf = null; + } else { + buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; + } + } + } + byte[] bytes = new byte[allBytes.size()]; + { + int i = 0; + for (Byte b : allBytes) { + bytes[i++] = b.byteValue(); + } + } + return bytes; + } + + + + /** + * 使用私钥分段加密 + * + * @param data 要加密的原始数据 + * @param privateKey 秘钥 + */ + public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception { + int dataLen = data.length; + if (dataLen <= DEFAULT_BUFFERSIZE) { + return encryptByPrivateKey(data, privateKey); + } + List allBytes = new ArrayList(2048); + int bufIndex = 0; + int subDataLoop = 0; + byte[] buf = new byte[DEFAULT_BUFFERSIZE]; + for (int i = 0; i < dataLen; i++) { + buf[bufIndex] = data[i]; + if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { + subDataLoop++; + if (subDataLoop != 1) { + for (byte b : DEFAULT_SPLIT) { + allBytes.add(b); + } + } + byte[] encryptBytes = encryptByPrivateKey(buf, privateKey); + for (byte b : encryptBytes) { + allBytes.add(b); + } + bufIndex = 0; + if (i == dataLen - 1) { + buf = null; + } else { + buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; + } + } + } + byte[] bytes = new byte[allBytes.size()]; + { + int i = 0; + for (Byte b : allBytes) { + bytes[i++] = b.byteValue(); + } + } + return bytes; + } + + /** + * 公钥分段解密 + * + * @param encrypted 待解密数据 + * @param publicKey 密钥 + */ + public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception { + int splitLen = DEFAULT_SPLIT.length; + if (splitLen <= 0) { + return decryptByPublicKey(encrypted, publicKey); + } + int dataLen = encrypted.length; + List allBytes = new ArrayList(1024); + int latestStartIndex = 0; + for (int i = 0; i < dataLen; i++) { + byte bt = encrypted[i]; + boolean isMatchSplit = false; + if (i == dataLen - 1) { + // 到data的最后了 + byte[] part = new byte[dataLen - latestStartIndex]; + System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); + byte[] decryptPart = decryptByPublicKey(part, publicKey); + for (byte b : decryptPart) { + allBytes.add(b); + } + latestStartIndex = i + splitLen; + i = latestStartIndex - 1; + } else if (bt == DEFAULT_SPLIT[0]) { + // 这个是以split[0]开头 + if (splitLen > 1) { + if (i + splitLen < dataLen) { + // 没有超出data的范围 + for (int j = 1; j < splitLen; j++) { + if (DEFAULT_SPLIT[j] != encrypted[i + j]) { + break; + } + if (j == splitLen - 1) { + // 验证到split的最后一位,都没有break,则表明已经确认是split段 + isMatchSplit = true; + } + } + } + } else { + // split只有一位,则已经匹配了 + isMatchSplit = true; + } + } + if (isMatchSplit) { + byte[] part = new byte[i - latestStartIndex]; + System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); + byte[] decryptPart = decryptByPublicKey(part, publicKey); + for (byte b : decryptPart) { + allBytes.add(b); + } + latestStartIndex = i + splitLen; + i = latestStartIndex - 1; + } + } + byte[] bytes = new byte[allBytes.size()]; + { + int i = 0; + for (Byte b : allBytes) { + bytes[i++] = b.byteValue(); + } + } + return bytes; + } + + /** + * 使用私钥分段解密 + */ + public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception { + int splitLen = DEFAULT_SPLIT.length; + if (splitLen <= 0) { + return decryptByPrivateKey(encrypted, privateKey); + } + int dataLen = encrypted.length; + List allBytes = new ArrayList(1024); + int latestStartIndex = 0; + for (int i = 0; i < dataLen; i++) { + byte bt = encrypted[i]; + boolean isMatchSplit = false; + if (i == dataLen - 1) { + // 到data的最后了 + byte[] part = new byte[dataLen - latestStartIndex]; + System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); + byte[] decryptPart = decryptByPrivateKey(part, privateKey); + for (byte b : decryptPart) { + allBytes.add(b); + } + latestStartIndex = i + splitLen; + i = latestStartIndex - 1; + } else if (bt == DEFAULT_SPLIT[0]) { + // 这个是以split[0]开头 + if (splitLen > 1) { + if (i + splitLen < dataLen) { + // 没有超出data的范围 + for (int j = 1; j < splitLen; j++) { + if (DEFAULT_SPLIT[j] != encrypted[i + j]) { + break; + } + if (j == splitLen - 1) { + // 验证到split的最后一位,都没有break,则表明已经确认是split段 + isMatchSplit = true; + } + } + } + } else { + // split只有一位,则已经匹配了 + isMatchSplit = true; + } + } + if (isMatchSplit) { + byte[] part = new byte[i - latestStartIndex]; + System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); + byte[] decryptPart = decryptByPrivateKey(part, privateKey); + for (byte b : decryptPart) { + allBytes.add(b); + } + latestStartIndex = i + splitLen; + i = latestStartIndex - 1; + } + } + byte[] bytes = new byte[allBytes.size()]; + { + int i = 0; + for (Byte b : allBytes) { + bytes[i++] = b.byteValue(); + } + } + return bytes; + } + + /** + * 用公钥对字符串进行分段加密 + */ + public static String encryptByPublicKeyForSpiltStr(String data, String publicKey) throws Exception { + byte[] encryptBytes = encryptByPublicKeyForSpilt(data.getBytes(StandardCharsets.UTF_8), publicKey.getBytes()); + return encryptBASE64(encryptBytes); + } + + /** + * 使用私钥分段加密 + * + * @param data 要加密的原始数据 + * @param privateKey 秘钥 + */ + public static String encryptByPrivateKeyForSpiltStr(String data, String privateKey) throws Exception { + byte[] encryptBytes = encryptByPrivateKeyForSpilt(data.getBytes(StandardCharsets.UTF_8), privateKey.getBytes()); + return encryptBASE64(encryptBytes); + } + + /** + * 公钥分段解密 + * + * @param encrypted 待解密数据 + * @param publicKey 密钥 + */ + public static String decryptByPublicKeyForSpiltStr(String encrypted, String publicKey) throws Exception { + byte[] decryptBytes = decryptByPublicKeyForSpilt(decryptBASE64(encrypted), publicKey.getBytes()); + return new String(decryptBytes,StandardCharsets.UTF_8); + } + + /** + * 使用私钥分段解密 + */ + public static String decryptByPrivateKeyForSpiltStr(String encrypted, String privateKey) throws Exception { + byte[] decryptBytes = decryptByPrivateKeyForSpilt(decryptBASE64(encrypted), privateKey.getBytes()); + return new String(decryptBytes,StandardCharsets.UTF_8); + } + + public static void testEncrypt1(String content) { + //生成秘钥对 + KeyPair keyPair = RSAAndroid.generateRSAKeyPair(RSAAndroid.DEFAULT_KEY_SIZE); + //公钥 + PublicKey publicKey = keyPair.getPublic(); + //私钥 + PrivateKey privateKey = keyPair.getPrivate(); + + long start; + long end; + byte[] encryptBytes = new byte[0]; + byte[] decryptBytes = new byte[0]; + String encryStr, decryStr; + + try { + + System.out.println("公钥:" + encryptBASE64(RSAAndroid.publicRsaKey.getBytes())); + //公钥加密 + start = System.currentTimeMillis(); + + encryptBytes = RSAAndroid.encryptByPublicKeyForSpilt(content.getBytes(StandardCharsets.UTF_8), RSAAndroid.publicRsaKey.getBytes()); + System.out.println("testEncrypt: 公钥加密 encryptBytes:" + encryptBytes); + + end = System.currentTimeMillis(); + System.out.println("公钥加密耗时 cost time---->" + (end - start)); + //encryStr = BASE64Encoder.encode(encryptBytes); + encryStr = encryptBASE64(encryptBytes); +// Log.e(TAG, "加密后json数据 --1-->" + encryStr); + System.out.println("加密后json数据长度 --1-->" + encryStr.length()); + System.out.println("testEncrypt: encryStr:" + encryStr); + //私钥解密 + System.out.println("私钥:" + encryptBASE64(RSAAndroid.privateRsaKey.getBytes())); + start = System.currentTimeMillis(); + decryptBytes = RSAAndroid.decryptByPrivateKeyForSpilt(decryptBASE64(encryStr), RSAAndroid.privateRsaKey.getBytes()); + decryStr = new String(decryptBytes); + System.out.println("testEncrypt: 私钥解密 decryStr:" + decryStr); + end = System.currentTimeMillis(); + System.out.println("私钥解密耗时 cost time---->" + (end - start)); + System.out.println("解密后json数据 --1-->" + decryStr); + } catch (Exception e) { + e.printStackTrace(); + } + } + public static void testEncrypt2(String content) { + //生成秘钥对 + KeyPair keyPair = RSAAndroid.generateRSAKeyPair(RSAAndroid.DEFAULT_KEY_SIZE); + //公钥 + PublicKey publicKey = keyPair.getPublic(); + //私钥 + PrivateKey privateKey = keyPair.getPrivate(); + + long start; + long end; + byte[] encryptBytes = new byte[0]; + byte[] decryptBytes = new byte[0]; + String encryStr, decryStr; + + try { + + //私钥加密 + start = System.currentTimeMillis(); + encryptBytes = RSAAndroid.encryptByPrivateKeyForSpilt(content.getBytes(StandardCharsets.UTF_8), RSAAndroid.privateRsaKey.getBytes()); + end = System.currentTimeMillis(); + System.out.println("私钥加密密耗时 cost time---->" + (end - start)); + encryStr = encryptBASE64(encryptBytes); + +// Log.e(TAG, "加密后json数据 --2-->" + encryStr); + System.out.println("加密后json数据长度 --2-->" + encryStr.length()); + System.out.println("testEncrypt: 私钥加密密 encryStr:" + encryStr); + //公钥解密 + start = System.currentTimeMillis(); + decryptBytes = RSAAndroid.decryptByPublicKeyForSpilt(decryptBASE64(encryStr), RSAAndroid.publicRsaKey.getBytes()); + + decryStr = new String(decryptBytes); + System.out.println("testEncrypt: 公钥解密 decryStr:" + decryStr); + end = System.currentTimeMillis(); + System.out.println("公钥解密耗时 cost time---->" + (end - start)); + System.out.println("解密后json数据 --2-->" + decryStr); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void testEncrypt3(String content) { + long start; + long end; + String encryStr, decryStr; + try { + //公钥加密 + System.out.println("公钥:" + RSAAndroid.publicRsaKey); + start = System.currentTimeMillis(); + encryStr = RSAAndroid.encryptByPublicKeyForSpiltStr(content, RSAAndroid.publicRsaKey); + end = System.currentTimeMillis(); + System.out.println("公钥加密耗时 cost time---->" + (end - start)); + System.out.println("加密后json数据长度 --1-->" + encryStr.length()); + System.out.println("testEncrypt: 公钥加密 encryStr:" + encryStr); + //私钥解密 + System.out.println("私钥:" + RSAAndroid.privateRsaKey); + start = System.currentTimeMillis(); + encryStr = "X6Ad0LpiBP7ze/cEgwGkYS53zG5ozY1Nrk2HzrrGlWqFZdyrmYihc1Fo3pjxxfOJi60zkZXguPt197vdtf2NHjtBCamvGt8DYhvfGUFP0YSod11GckQQaUslUkwPjQKTGJ46Kdy7Y2gMKK7EdEabEmTPl/XIT9fDFX/nMWgAutcQ15Gq5FRwWQH7sSVNF5bjrxxBs7Q/JwsCsU+xl0LraifUf+1O6NzCHc4ll7dmWq6EGORjaSVYka8ItuI4hhVWffcrOhY1vDqjFkY+Mzac9ppgk1nc5StMMNGyPC4OYsLkqZa5h8acK8YhSi7dpj58Lo/yJWqMmewiGDSskrcFXCNQQVJUI10H9WmD3b//98jW6cq3awLqmpoZmjuN3fm8vx1KPOCEZs2GlM7/wCEUMabV7O5EsTtRf+6pqHYTPzZfxt2lXEEJviktjguG1WI71nwg+1XyIx5tn818XiYvs0L02hi3sWpQkk/NJ4QaE3LziuCMrgDU/GcFzYLybU627yAPPPLjB9wVZGefwUdWjMtY5AzPMBa9eNjsMaHAGe2zbnopafuouwsjH+uEZd2rzT3Uacb7+pNjl94XiB/0Xhwl1n5bi6HbT3aY2jC6YbKqCp5XQaLCbuefaRVCLC6pOHmNX6NKni98/bYKQ6XfhDoA56gJAEVsAaj/a6vpzVIMsej5zDI="; + decryStr = RSAAndroid.decryptByPrivateKeyForSpiltStr(encryStr, RSAAndroid.privateRsaKey); + end = System.currentTimeMillis(); + System.out.println("私钥解密耗时 cost time---->" + (end - start)); + System.out.println("解密后json数据长度 --1-->" + decryStr.length()); + System.out.println("testEncrypt: 私钥解密 decryStr:" + decryStr); + } catch (Exception e) { + e.printStackTrace(); + } + } + public static void testEncrypt4(String content) { + long start; + long end; + String encryStr, decryStr; + try { + System.out.println("公钥:" + RSAAndroid.publicRsaKey); + //私钥加密 + start = System.currentTimeMillis(); + encryStr = RSAAndroid.encryptByPrivateKeyForSpiltStr(content, RSAAndroid.privateRsaKey); + end = System.currentTimeMillis(); + System.out.println("私钥加密密耗时 cost time---->" + (end - start)); + System.out.println("加密后json数据长度 --2-->" + encryStr.length()); + System.out.println("testEncrypt: 私钥加密 encryStr:" + encryStr); + //公钥解密 + System.out.println("私钥:" + RSAAndroid.privateRsaKey); + start = System.currentTimeMillis(); + decryStr = RSAAndroid.decryptByPublicKeyForSpiltStr(encryStr, RSAAndroid.publicRsaKey); + end = System.currentTimeMillis(); + System.out.println("公钥解密耗时 cost time---->" + (end - start)); + System.out.println("解密后json数据 --2-->" + decryStr); + System.out.println("testEncrypt: 公钥解密 decryStr:" + decryStr); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + RSAAndroid.testEncrypt3("8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。8月8日晚,东京国立竞技场的奥运圣火熄灭,场内电子屏上打出了“ARIGATO”(日语“谢谢”的罗马字)。57年前的那一夜,东京奥运会闭幕式大屏上留下的是“SAYONARA”(日语“再见”罗马字)。从告别到感谢,本届奥运会对日本而言,原本是一场赌上国运的体育盛事,而现实却朝着与理想相反的方向一路狂奔。"); + } +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcCityRepository.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcCityRepository.java new file mode 100644 index 0000000..f383e4e --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcCityRepository.java @@ -0,0 +1,16 @@ +package com.rehome.disruptor_nmc.dao; + + +import com.rehome.disruptor_nmc.entity.NmcCity; +import org.springframework.data.jpa.repository.JpaRepository; + + +/** + * 参数一 T :当前需要映射的实体 + * 参数二 ID :当前映射的实体中的OID的类型 + */ +public interface NmcCityRepository extends JpaRepository { + + //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写) + NmcCity findByCode(String code); +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcForecastWeatherRepository.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcForecastWeatherRepository.java new file mode 100644 index 0000000..868951c --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcForecastWeatherRepository.java @@ -0,0 +1,20 @@ +package com.rehome.disruptor_nmc.dao; + + + +import com.rehome.disruptor_nmc.entity.NmcForecastWeather; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + + +/** + * 参数一 T :当前需要映射的实体 + * 参数二 ID :当前映射的实体中的OID的类型 + */ +public interface NmcForecastWeatherRepository extends JpaRepository { + + //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写) + List findByWeatherDateOrderByIdDesc(String weatherDate); + +} + diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcNowWeatherRepository.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcNowWeatherRepository.java new file mode 100644 index 0000000..9925d84 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcNowWeatherRepository.java @@ -0,0 +1,19 @@ +package com.rehome.disruptor_nmc.dao; + + +import com.rehome.disruptor_nmc.entity.NmcNowWeather; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + + +/** + * 参数一 T :当前需要映射的实体 + * 参数二 ID :当前映射的实体中的OID的类型 + */ +public interface NmcNowWeatherRepository extends JpaRepository { + + //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写) + List findByCodeAndWeatherDateOrderByIdDesc(String code, String weatherDate); +} + diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcProvinceRepository.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcProvinceRepository.java new file mode 100644 index 0000000..29e4dd8 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/NmcProvinceRepository.java @@ -0,0 +1,16 @@ +package com.rehome.disruptor_nmc.dao; + + +import com.rehome.disruptor_nmc.entity.NmcProvince; +import org.springframework.data.jpa.repository.JpaRepository; + + +/** + * 参数一 T :当前需要映射的实体 + * 参数二 ID :当前映射的实体中的OID的类型 + */ +public interface NmcProvinceRepository extends JpaRepository { + + //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写) + NmcProvince findByCode(String code); +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/TemperatureRepository.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/TemperatureRepository.java new file mode 100644 index 0000000..f00ab6b --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dao/TemperatureRepository.java @@ -0,0 +1,19 @@ +package com.rehome.disruptor_nmc.dao; + + +import com.rehome.disruptor_nmc.entity.Temperature; +import org.springframework.data.jpa.repository.JpaRepository; + + +/** + * 参数一 T :当前需要映射的实体 + * 参数二 ID :当前映射的实体中的OID的类型 + * + */ +public interface TemperatureRepository extends JpaRepository { + + //方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写) + Temperature findByDataDate(String dataDate); + Temperature findByDataHour(String dataHour); + Temperature findByDataMinute(String dataMinute); +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dto/NmcBaseDto.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dto/NmcBaseDto.java new file mode 100644 index 0000000..bfc8323 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/dto/NmcBaseDto.java @@ -0,0 +1,48 @@ +package com.rehome.disruptor_nmc.dto; + + +import com.liuhuiyu.util.map.MapUtil; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.util.Map; + +/** + * @author HuangWenFei + * @version v1.0.0.0 + * Created DateTime 2022-05-01 16:22 + */ +@ApiModel(value = "NmcBaseDto", description = "接收数据") +public class NmcBaseDto { + @ApiModelProperty("API状态码,具体含义请参考状态码 0请求成功") + private int code; + @ApiModelProperty("当前API的最近更新时间") + private String msg; + + /** + * 根据 map 还原 NmcBaseDto + * + * @param map 映射map + * @return com.rehome.jpahefengweather.dto.NmcBaseDto + * @author HuangWenFei + * Created DateTime 2022-04-19 10:02 + */ + public static NmcBaseDto ofSelfMap(Map map) { + return MapUtil.fromMap(map, NmcBaseDto.class); + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcCity.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcCity.java new file mode 100644 index 0000000..c37e07b --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcCity.java @@ -0,0 +1,30 @@ +package com.rehome.disruptor_nmc.entity; + +import lombok.Data; +import org.hibernate.annotations.Proxy; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@EntityListeners(AuditingEntityListener.class) +@Proxy(lazy = false) +@Data +@Entity +public class NmcCity implements Serializable { + @Id + private String code; + + private String province; + + private String city; + + private String url; + + @Temporal(TemporalType.TIMESTAMP) + private Date createDate; + + @Temporal(TemporalType.TIMESTAMP) + private Date lastUpdateDate; +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcForecastWeather.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcForecastWeather.java new file mode 100644 index 0000000..3f6fc68 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcForecastWeather.java @@ -0,0 +1,35 @@ +package com.rehome.disruptor_nmc.entity; + + +import lombok.Data; +import org.hibernate.annotations.Proxy; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@EntityListeners(AuditingEntityListener.class) +@Proxy(lazy = false) +@Data +@Entity +public class NmcForecastWeather implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + //存放长文本 + @Lob + @Basic(fetch = FetchType.LAZY) + private String weather; + + private String weatherDate; + + private String code; + + @Temporal(TemporalType.TIMESTAMP) + private Date createDate; + + @Temporal(TemporalType.TIMESTAMP) + private Date lastUpdateDate; +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcNowWeather.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcNowWeather.java new file mode 100644 index 0000000..ee178cc --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcNowWeather.java @@ -0,0 +1,50 @@ +package com.rehome.disruptor_nmc.entity; + +import lombok.Data; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Proxy; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@EntityListeners(AuditingEntityListener.class) +@Proxy(lazy = false) +@Data +@Entity +@Table(indexes = {@Index(name = "idx_weatherDate", columnList = "weatherDate"), + @Index(name = "idx_code", columnList = "code"), + @Index(name = "idx_createDate", columnList = "createDate"), + @Index(name = "idx_lastUpdateDate", columnList = "lastUpdateDate"), + @Index(name = "idx_weather_date_code_nmc", columnList = "weatherDate"), + @Index(name = "idx_weather_date_code_nmc", columnList = "code")}) +//@GenericGenerator(name = "NmcNowWeather-uuid", strategy = "uuid") +public class NmcNowWeather implements Serializable { + public static final int COLUMN_ID_MAX_LENGTH = 32; + public static final int COLUMN_CNAME_MAX_LENGTH = 16; + +// @Id +// @GenericGenerator(name = "NmcNowWeather-uuid", strategy = "uuid") +// @GeneratedValue(generator = "NmcNowWeather-uuid") +// @Column(length = 32) + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + //存放长文本 + @Lob + @Basic(fetch = FetchType.LAZY) + private String weather; + + private String weatherDate; + + private String code; + + @Temporal(TemporalType.TIMESTAMP) + private Date createDate; + + @Temporal(TemporalType.TIMESTAMP) + private Date lastUpdateDate; +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcProvince.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcProvince.java new file mode 100644 index 0000000..b5e3218 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/NmcProvince.java @@ -0,0 +1,27 @@ +package com.rehome.disruptor_nmc.entity; + +import lombok.Data; +import org.hibernate.annotations.Proxy; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@EntityListeners(AuditingEntityListener.class) +@Proxy(lazy = false) +@Data +@Entity +public class NmcProvince implements Serializable { + @Id + private String code; + + private String name; + + private String url; + + @Temporal(TemporalType.TIMESTAMP) + private Date createDate; + + @Temporal(TemporalType.TIMESTAMP) + private Date lastUpdateDate; +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/Temperature.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/Temperature.java new file mode 100644 index 0000000..074235e --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/entity/Temperature.java @@ -0,0 +1,64 @@ +package com.rehome.disruptor_nmc.entity; + + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.annotations.Proxy; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@EntityListeners(AuditingEntityListener.class) +@Proxy(lazy = false) +@Data +@Entity +//普通索引,不指定索引名,表自动创建索引名 +//@Table(indexes = {@Index(columnList = "dataDate"),@Index(columnList = "locationDesc")}) +//普通索引,指定索引名,创建单个索引 +//在这个例子中,Temperature实体类通过@Table注解的indexes属性定义了一个名为idx_dataDate的索引,它覆盖了dataDate字段。这意味着在数据库层面,针对dataDate字段的查询将会利用这个索引,从而提高查询效率。 +//@Table(indexes = {@Index(name = "idx_dataDate", columnList = "dataDate")}) +//同时创建多个普通索引,注意每个索引名都不同 +//@Table(indexes = {@Index(name = "idx_dataDate", columnList = "dataDate"),@Index(name = "idx_locationDesc", columnList = "locationDesc")}) +//@Table(indexes = {@Index(name = "idx_dataDate", columnList = "dataDate"),@Index(name = "idx_locationDesc", columnList = "locationDesc"),@Index(name = "idx_dataHour", columnList = "dataHour"),@Index(name = "idx_dataMinute", columnList = "dataMinute")}) +//创建组合索引,注意每个索引名都相同 +//@Table(indexes = {@Index(name = "data_date_location_desc", columnList = "dataDate"),@Index(name = "data_date_location_desc", columnList = "locationDesc")}) +//同时创建普通索引和组合索引,注意普通索引每个索引名都不同,注意组合索引每个索引名都相同 +@Table(indexes = {@Index(name = "idx_dataDate", columnList = "dataDate"),@Index(name = "idx_locationDesc", columnList = "locationDesc"),@Index(name = "idx_dataHour", columnList = "dataHour"),@Index(name = "idx_dataMinute", columnList = "dataMinute"),@Index(name = "data_date_location_desc", columnList = "dataDate"),@Index(name = "data_date_location_desc", columnList = "locationDesc")}) +public class Temperature implements Serializable { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @ApiModelProperty(value = "主键") + private Long id; + + @ApiModelProperty(value = "温度") + private Double temperature; + + @ApiModelProperty(value = "湿度") + private Double humidity; + + @ApiModelProperty(value = "日期") + @Column(length=20) + private String dataDate; + + @ApiModelProperty(value = "时") + @Column(length=20) + private String dataHour; + + @ApiModelProperty(value = "分") + @Column(length=20) + private String dataMinute; + + @ApiModelProperty(value = "主题") + @Column(length=60) + private String topic; + + @ApiModelProperty(value = "位置描述") + @Column(length=80) + private String locationDesc; + + @ApiModelProperty(value = "时间") + @Temporal(TemporalType.TIMESTAMP) + private Date createDate; + +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/BeanManager.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/BeanManager.java new file mode 100644 index 0000000..f59c433 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/BeanManager.java @@ -0,0 +1,40 @@ +package com.rehome.disruptor_nmc.mq; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * 获取实例化对象 + */ +@Component +public class BeanManager implements ApplicationContextAware { + + + + private static ApplicationContext applicationContext = null; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + + + this.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + + return applicationContext; } + + public static Object getBean(String name) { + + + return applicationContext.getBean(name); + } + + public static T getBean(Class clazz) { + + + return applicationContext.getBean(clazz); + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/MQManager.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/MQManager.java new file mode 100644 index 0000000..737ecab --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/MQManager.java @@ -0,0 +1,45 @@ +package com.rehome.disruptor_nmc.mq; + +import com.lmax.disruptor.BlockingWaitStrategy; +import com.lmax.disruptor.RingBuffer; +import com.lmax.disruptor.dsl.Disruptor; +import com.lmax.disruptor.dsl.ProducerType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Configuration +public class MQManager { + + + @Bean("messageModel") + public RingBuffer messageModelRingBuffer() { + + + //定义用于事件处理的线程池, Disruptor通过java.util.concurrent.ExecutorSerivce提供的线程来触发consumer的事件处理 + ExecutorService executor = Executors.newFixedThreadPool(2); + + //指定事件工厂 + NmcWeatherEventFactory factory = new NmcWeatherEventFactory(); + + //指定ringbuffer字节大小,必须为2的N次方(能将求模运算转为位运算提高效率),否则将影响效率 + int bufferSize = 1024 * 256; + + //单线程模式,获取额外的性能 + Disruptor disruptor = new Disruptor<>(factory, bufferSize, executor, + ProducerType.SINGLE, new BlockingWaitStrategy()); + + //设置事件业务处理器---消费者 + disruptor.handleEventsWith(new NmcWeatherEventHandler()); + + // 启动disruptor线程 + disruptor.start(); + + //获取ringbuffer环,用于接取生产者生产的事件 + RingBuffer ringBuffer = disruptor.getRingBuffer(); + + return ringBuffer; + } +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/MessageModel.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/MessageModel.java new file mode 100644 index 0000000..23bc2b4 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/MessageModel.java @@ -0,0 +1,16 @@ +package com.rehome.disruptor_nmc.mq; + +import com.rehome.disruptor_nmc.entity.NmcNowWeather; +import lombok.Data; + +@Data +public class MessageModel { + private NmcNowWeather message; + + private String temperatureAndHumidityData; + + private String topic; + + private String type; + +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/NmcWeatherEventFactory.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/NmcWeatherEventFactory.java new file mode 100644 index 0000000..e5b9940 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/NmcWeatherEventFactory.java @@ -0,0 +1,10 @@ +package com.rehome.disruptor_nmc.mq; + +import com.lmax.disruptor.EventFactory; + +public class NmcWeatherEventFactory implements EventFactory { + @Override + public MessageModel newInstance() { + return new MessageModel(); + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/NmcWeatherEventHandler.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/NmcWeatherEventHandler.java new file mode 100644 index 0000000..8699e6d --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/mq/NmcWeatherEventHandler.java @@ -0,0 +1,38 @@ +package com.rehome.disruptor_nmc.mq; + +import com.liuhuiyu.spring_util.SpringUtil; +import com.lmax.disruptor.EventHandler; +import com.rehome.disruptor_nmc.service.NmcWeatherService; +import com.rehome.disruptor_nmc.service.TemperatureService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + + +@Slf4j +public class NmcWeatherEventHandler implements EventHandler { + + @Override + public void onEvent(MessageModel event, long sequence, boolean endOfBatch) { + + try { + //这里停止1000ms是为了确定消费消息是异步的 + log.info("消费者处理消息开始"); + if (event != null) { + log.info("消费者消费的信息是:{}", event); + if("mqttTemperature".equals(event.getType())){ + TemperatureService temperatureService = SpringUtil.getBean(TemperatureService.class); + temperatureService.saveTemperature(event.getTemperatureAndHumidityData(),event.getTopic()); + } + if("NmcWeather".equals(event.getType())){ + NmcWeatherService nmcWeatherService = SpringUtil.getBean(NmcWeatherService.class); + nmcWeatherService.saveNowWeather(event.getMessage()); + } + } + } catch (Exception e) { + log.info("消费者处理消息失败"); + } + log.info("消费者处理消息结束"); + } +} + +//http://www.nmc.cn/ \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/GlobalExceptionHandler.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/GlobalExceptionHandler.java new file mode 100644 index 0000000..4fd335f --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/GlobalExceptionHandler.java @@ -0,0 +1,70 @@ +package com.rehome.disruptor_nmc.response; + +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.Optional; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(BindException.class) + public Result handleValidationException(BindException ex) { + Result result = Result.failedByParamValidated(); + for (FieldError error : ex.getBindingResult().getFieldErrors()) { + System.out.println(error.getField()); + System.out.println(error.getDefaultMessage()); + String baseErrorStr = result.getMessage(); + if(error.getField()!=null){ + baseErrorStr=baseErrorStr+","+error.getField(); + result.setMessage(baseErrorStr); + } + if(error.getDefaultMessage()!=null){ + baseErrorStr=baseErrorStr+":"+error.getDefaultMessage(); + result.setMessage(baseErrorStr); + } + } + return result; + } +} + + +//@RestControllerAdvice +//public class GlobalExceptionHandler { +// @ExceptionHandler(BindException.class) +// public R handleValidationException(BindException ex) { +// R result = R.error(); +// for (FieldError error : ex.getBindingResult().getFieldErrors()) { +// result.data(error.getField(), error.getDefaultMessage()); +// } +// Optional firstError = result.getData().values().stream().findFirst(); +// return result.msg("请完善信息: "+firstError.orElse("表单内容") + +// (ex.getErrorCount()>1?" 等多项问题":"")); +// } +//} + +//参考:https://www.cnblogs.com/liuscraft/p/17366441.html + +// +// +//org.springframework.boot +//spring-boot-starter-validation +// +// + + +//@RestController +//@RequestMapping("/users") +//@Validated +//public class UserController { +// @PostMapping +// public String createUser(@RequestBody User user, BindingResult result) { +// if (result.hasErrors()) { +// // 处理错误信息 +// return "error"; +// } +// // 处理用户信息 +// return "success"; +// } +//} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/IResult.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/IResult.java new file mode 100644 index 0000000..ad95c47 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/IResult.java @@ -0,0 +1,7 @@ +package com.rehome.disruptor_nmc.response; + +//定义返回数据结构 +public interface IResult { + Integer getCode(); + String getMessage(); +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/ResponseAdvice.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/ResponseAdvice.java new file mode 100644 index 0000000..fe4314c --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/ResponseAdvice.java @@ -0,0 +1,30 @@ +package com.rehome.disruptor_nmc.response; + +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +//统一包装处理,扫描需要包装返回数据的包 +//如果引入了swagger或knife4j的文档生成组件,这里需要仅扫描自己项目的包,否则文档无法正常生成 +@RestControllerAdvice(basePackages = "com.rehome.disruptor_nmc.controller") +public class ResponseAdvice implements ResponseBodyAdvice { + @Override + public boolean supports(MethodParameter returnType, Class> converterType) { + // 如果不需要进行封装的,可以添加一些校验手段,比如添加标记排除的注解 + return true; + } + + + @Override + public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + // 提供一定的灵活度,如果body已经被包装了,就不进行包装 + if (body instanceof Result) { + return body; + } + return Result.success(body); + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/Result.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/Result.java new file mode 100644 index 0000000..da3ed4f --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/Result.java @@ -0,0 +1,68 @@ +package com.rehome.disruptor_nmc.response; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; + +//统一返回数据结构 +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Result { + private Integer code; + private String message; + private T data; + + public static Result success(T data) { + return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), data); + } + + public static Result success(String message, T data) { + return new Result<>(ResultEnum.SUCCESS.getCode(), message, data); + } + + public static Result failed() { + return new Result<>(ResultEnum.COMMON_FAILED.getCode(), ResultEnum.COMMON_FAILED.getMessage(), null); + } + + public static Result failedByParamValidated() { + return new Result<>(ResultEnum.REQUEST_PARAM_VALIDATED_FAILED.getCode(), ResultEnum.REQUEST_PARAM_VALIDATED_FAILED.getMessage(), null); + } + + public static Result failedByParamValidated(BindingResult bindingResult) { + Result result = new Result<>(ResultEnum.REQUEST_PARAM_VALIDATED_FAILED.getCode(), ResultEnum.REQUEST_PARAM_VALIDATED_FAILED.getMessage(), null); + // 处理错误信息 + for (FieldError error : bindingResult.getFieldErrors()) { + String baseErrorMessage = result.getMessage(); + if(error.getField()!=null){ + baseErrorMessage=baseErrorMessage+","+error.getField(); + result.setMessage(baseErrorMessage); + } + if(error.getDefaultMessage()!=null){ + baseErrorMessage=baseErrorMessage+":"+error.getDefaultMessage(); + result.setMessage(baseErrorMessage); + } + } + return result; + } + + public static Result failed(String message) { + return new Result<>(ResultEnum.COMMON_FAILED.getCode(), message, null); + } + + public static Result failed(IResult errorResult) { + return new Result<>(errorResult.getCode(), errorResult.getMessage(), null); + } + + public static Result instance(Integer code, String message, T data) { + Result result = new Result<>(); + result.setCode(code); + result.setMessage(message); + result.setData(data); + return result; + } +} + diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/ResultEnum.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/ResultEnum.java new file mode 100644 index 0000000..b0f737c --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/response/ResultEnum.java @@ -0,0 +1,38 @@ +package com.rehome.disruptor_nmc.response; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +//常用结果的枚举 +public enum ResultEnum implements IResult { + SUCCESS(2001, "接口调用成功"), + VALIDATE_FAILED(2002, "参数校验失败"), + COMMON_FAILED(2003, "接口调用失败"), + FORBIDDEN(2004, "没有权限访问资源"), + REQUEST_PARAM_VALIDATED_FAILED(2005, "请求参数校验失败"); + + private Integer code; + private String message; + + @Override + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + @Override + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + //省略get、set方法和构造方法 +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/DisruptorMqService.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/DisruptorMqService.java new file mode 100644 index 0000000..4212961 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/DisruptorMqService.java @@ -0,0 +1,14 @@ +package com.rehome.disruptor_nmc.service; + +import com.rehome.disruptor_nmc.entity.NmcNowWeather; + +public interface DisruptorMqService { + /** + * 消息 + * @param message + */ + void pushMessageToMq(NmcNowWeather message); + + void pushTemperatureToMq(String temperatureAndHumidityData,String topic); + +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/NmcCityService.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/NmcCityService.java new file mode 100644 index 0000000..dfae2c9 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/NmcCityService.java @@ -0,0 +1,23 @@ +package com.rehome.disruptor_nmc.service; + +import com.rehome.disruptor_nmc.entity.NmcCity; +import com.rehome.disruptor_nmc.entity.NmcProvince; + +import java.util.List; + +public interface NmcCityService { + //code查询所有省份 + NmcProvince findProvinceByCode(String code); + + //根据code查询城市 + NmcCity findCityByCode(String code); + + //保存省份 + void saveProvince(NmcProvince province); + + //保存城市 + void saveCity(NmcCity city); + + //查询所有城市 + List findAllCityList(); +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/NmcWeatherService.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/NmcWeatherService.java new file mode 100644 index 0000000..aed42a6 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/NmcWeatherService.java @@ -0,0 +1,16 @@ +package com.rehome.disruptor_nmc.service; + +import com.rehome.disruptor_nmc.entity.NmcForecastWeather; +import com.rehome.disruptor_nmc.entity.NmcNowWeather; + +public interface NmcWeatherService { + /** + * 保存实时天气数据 + */ + void saveNowWeather(NmcNowWeather nowWeather); + + /** + * 保存预报天气数据 + */ + void saveForecastWeather(NmcForecastWeather forecastWeather); +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/ScheduledService.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/ScheduledService.java new file mode 100644 index 0000000..fb73885 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/ScheduledService.java @@ -0,0 +1,212 @@ +package com.rehome.disruptor_nmc.service; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.rehome.disruptor_nmc.dto.NmcBaseDto; +import com.rehome.disruptor_nmc.entity.*; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import javax.annotation.Resource; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.TimeUnit; +import com.liuhuiyu.spring_util.SpringUtil; + +/** + * @author huangwenfei + * @version v1.0.0.0 + * Created DateTime 2023-10-25 11:35 + * @description: 定时任务服务 + */ + +@Slf4j +@Component +public class ScheduledService { + + @Resource + private NmcCityService nmcCityService; +// @Resource +// private NmcWeatherService nmcWeatherService; + + /** + * @date 2022-03-16 09:41 + * @description: 从中央气象台获取省份列表 + * @Param: null + */ + //@Scheduled(cron = "0 49 * * * *") + public void getNmcWeatherProvince() { + System.out.println("scheduledGetWeather"); + System.out.println("=====>>>>>使用cron:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + System.out.println(String.valueOf(System.currentTimeMillis())); + String url = "http://www.nmc.cn/rest/province/all?_=" + String.valueOf(System.currentTimeMillis()); + System.out.println(url); + // 初始化 OkHttpClient + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .build(); + + // 初始化请求体 + Request request = new Request.Builder() + .get() + .url(url) + .build(); + + try { + // 得到返回Response + Response response = client.newCall(request).execute(); + String body = response.body().string(); + System.out.println(body); + if (StringUtils.hasText(body)) { + Gson gson = new Gson(); + List provinces = gson.fromJson(body, new TypeToken>() { + }.getType()); + ; + for (NmcProvince province : provinces) { + System.out.println(gson.toJson(province)); + this.nmcCityService.saveProvince(province); + getNmcWeatherCityByCode(province.getCode()); + try { + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + } + System.out.println(provinces.size()); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + * @date 2022-03-16 09:41 + * @description: 根据省份code获取城市列表 + * @Param: null + */ + public void getNmcWeatherCityByCode(String code) { + String url = "http://www.nmc.cn/rest/province/" + code + "?_=" + String.valueOf(System.currentTimeMillis()); + System.out.println(url); + // 初始化 OkHttpClient + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .build(); + + // 初始化请求体 + Request request = new Request.Builder() + .get() + .url(url) + .build(); + + try { + // 得到返回Response + Response response = client.newCall(request).execute(); + String body = response.body().string(); + System.out.println(body); + if (StringUtils.hasText(body)) { + Gson gson = new Gson(); + List citys = gson.fromJson(body, new TypeToken>() { + }.getType()); + ; + for (NmcCity city : citys) { + System.out.println(gson.toJson(city)); + this.nmcCityService.saveCity(city); + } + System.out.println(citys.size()); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + * @date 2022-03-16 09:41 + * @description: 从中央气象台获取天气数据 + * @Param: null + */ + @Scheduled(cron = "0 15 * * * *") + public void getNmcNowWeather() { + System.out.println("scheduledGetWeather"); + System.out.println("=====>>>>>使用cron:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + System.out.println(String.valueOf(System.currentTimeMillis())); + + + // 初始化 OkHttpClient + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .build(); + + List citys = this.nmcCityService.findAllCityList(); + + for (NmcCity city : citys) { + String url = "http://www.nmc.cn/rest/weather?stationid=" + city.getCode() + "&_=" + String.valueOf(System.currentTimeMillis()); + System.out.println(url); + // 初始化请求体 + Request request = new Request.Builder() + .get() + .url(url) + .build(); + + try { + Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + String body = response.body().string(); + System.out.println(body); + if (StringUtils.hasText(body)) { + try { + Gson gson = new Gson(); + NmcBaseDto nmcBaseDto = gson.fromJson(body, NmcBaseDto.class); + if (nmcBaseDto != null && nmcBaseDto.getCode() == 0) { + Date now = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + String nowDate = sdf.format(new Date()); + + NmcNowWeather nowWeather = new NmcNowWeather(); + nowWeather.setCode(city.getCode()); + nowWeather.setWeather(body); + nowWeather.setWeatherDate(nowDate); + nowWeather.setLastUpdateDate(now); + nowWeather.setCreateDate(now); + + //用 Disruptor 消息队列 实现特快高并发处理,支撑每秒 600 万订单无压力! + DisruptorMqService disruptorMqService = SpringUtil.getBean(DisruptorMqService.class); + disruptorMqService.pushMessageToMq(nowWeather); + + //直接jpa存储数据到表 +// NmcWeatherService nmcWeatherServiceTemp = SpringUtil.getBean(NmcWeatherService.class); +// nmcWeatherServiceTemp.saveNowWeather(nowWeather); + log.info("消息队列已发送完毕"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }); + } + } + +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/TemperatureService.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/TemperatureService.java new file mode 100644 index 0000000..3dfe17c --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/TemperatureService.java @@ -0,0 +1,6 @@ +package com.rehome.disruptor_nmc.service; + +public interface TemperatureService { + //温度和湿度 + void saveTemperature(String temperatureAndHumidityData,String topic); +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/DisruptorMqServiceImpl.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/DisruptorMqServiceImpl.java new file mode 100644 index 0000000..5727ae0 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/DisruptorMqServiceImpl.java @@ -0,0 +1,62 @@ +package com.rehome.disruptor_nmc.service.impl; + +import com.lmax.disruptor.RingBuffer; +import com.rehome.disruptor_nmc.entity.NmcNowWeather; +import com.rehome.disruptor_nmc.mq.MessageModel; +import com.rehome.disruptor_nmc.service.DisruptorMqService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + + +@Slf4j +@Component +@Service +public class DisruptorMqServiceImpl implements DisruptorMqService { + + @Resource + private RingBuffer messageModelRingBuffer; + + @Override + public void pushMessageToMq(NmcNowWeather message) { + log.info("record the message: {}", message); + //获取下一个Event槽的下标 + long sequence = messageModelRingBuffer.next(); + try { + //给Event填充数据 + MessageModel event = messageModelRingBuffer.get(sequence); + event.setMessage(message); + event.setType("NmcWeather"); + log.info("往消息队列中添加消息:{}", event); + } catch (Exception e) { + log.error("failed to add event to messageModelRingBuffer for : e = {},{}", e, e.getMessage()); + } finally { + //发布Event,激活观察者去消费,将sequence传递给改消费者 + //注意最后的publish方法必须放在finally中以确保必须得到调用;如果某个请求的sequence未被提交将会堵塞后续的发布操作或者其他的producer + messageModelRingBuffer.publish(sequence); + } + } + + @Override + public void pushTemperatureToMq(String temperatureAndHumidityData,String topic) { + log.info("record the message: {},{}", temperatureAndHumidityData,topic); + //获取下一个Event槽的下标 + long sequence = messageModelRingBuffer.next(); + try { + //给Event填充数据 + MessageModel event = messageModelRingBuffer.get(sequence); + event.setTemperatureAndHumidityData(temperatureAndHumidityData); + event.setType("mqttTemperature"); + event.setTopic(topic); + log.info("往消息队列中添加消息:{}", event); + } catch (Exception e) { + log.error("failed to add event to messageModelRingBuffer for : e = {},{}", e, e.getMessage()); + } finally { + //发布Event,激活观察者去消费,将sequence传递给改消费者 + //注意最后的publish方法必须放在finally中以确保必须得到调用;如果某个请求的sequence未被提交将会堵塞后续的发布操作或者其他的producer + messageModelRingBuffer.publish(sequence); + } + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/NmcCityServiceImpl.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/NmcCityServiceImpl.java new file mode 100644 index 0000000..4af317d --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/NmcCityServiceImpl.java @@ -0,0 +1,75 @@ +package com.rehome.disruptor_nmc.service.impl; + + + +import com.rehome.disruptor_nmc.dao.NmcCityRepository; +import com.rehome.disruptor_nmc.dao.NmcProvinceRepository; +import com.rehome.disruptor_nmc.entity.NmcCity; +import com.rehome.disruptor_nmc.entity.NmcProvince; +import com.rehome.disruptor_nmc.service.NmcCityService; +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +@Service +public class NmcCityServiceImpl implements NmcCityService { + + @Resource + private NmcCityRepository nmcCityRepository; + @Resource + private NmcProvinceRepository nmcProvinceRepository; + + @Override + public NmcProvince findProvinceByCode(String code) { + return this.nmcProvinceRepository.findByCode(code); + } + + @Override + public NmcCity findCityByCode(String code) { + return this.nmcCityRepository.findByCode(code); + } + + + @Override + public void saveProvince(NmcProvince province) { + if (province != null) { + Date now = new Date(); + NmcProvince provinceDB = this.nmcProvinceRepository.findByCode(province.getCode()); + if (provinceDB != null) { + provinceDB.setName(province.getName()); + provinceDB.setUrl(province.getUrl()); + provinceDB.setLastUpdateDate(now); + this.nmcProvinceRepository.save(provinceDB); + } else { + province.setLastUpdateDate(now); + province.setCreateDate(now); + this.nmcProvinceRepository.save(province); + } + } + } + + @Override + public void saveCity(NmcCity city) { + if (city != null) { + Date now = new Date(); + NmcCity cityDB = this.nmcCityRepository.findByCode(city.getCode()); + if (cityDB != null) { + cityDB.setCity(city.getCity()); + cityDB.setProvince(city.getProvince()); + cityDB.setUrl(city.getUrl()); + cityDB.setLastUpdateDate(now); + this.nmcCityRepository.save(cityDB); + } else { + city.setLastUpdateDate(now); + city.setCreateDate(now); + this.nmcCityRepository.save(city); + } + } + } + + @Override + public List findAllCityList() { + return this.nmcCityRepository.findAll(); + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/NmcWeatherServiceImpl.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/NmcWeatherServiceImpl.java new file mode 100644 index 0000000..0af02a4 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/NmcWeatherServiceImpl.java @@ -0,0 +1,30 @@ +package com.rehome.disruptor_nmc.service.impl; + + +import com.rehome.disruptor_nmc.dao.NmcForecastWeatherRepository; +import com.rehome.disruptor_nmc.dao.NmcNowWeatherRepository; +import com.rehome.disruptor_nmc.entity.NmcForecastWeather; +import com.rehome.disruptor_nmc.entity.NmcNowWeather; +import com.rehome.disruptor_nmc.service.NmcWeatherService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +@Service +public class NmcWeatherServiceImpl implements NmcWeatherService { + @Resource + private NmcNowWeatherRepository nmcNowWeatherRepository; + @Resource + private NmcForecastWeatherRepository nmcForecastWeatherRepository; + + + @Override + public void saveNowWeather(NmcNowWeather nowWeather) { + this.nmcNowWeatherRepository.save(nowWeather); + } + + @Override + public void saveForecastWeather(NmcForecastWeather forecastWeather) { + this.nmcForecastWeatherRepository.save(forecastWeather); + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/TemperatureServiceImpl.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/TemperatureServiceImpl.java new file mode 100644 index 0000000..9d98fc5 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/service/impl/TemperatureServiceImpl.java @@ -0,0 +1,54 @@ +package com.rehome.disruptor_nmc.service.impl; + + +import com.rehome.disruptor_nmc.dao.TemperatureRepository; +import com.rehome.disruptor_nmc.entity.Temperature; +import com.rehome.disruptor_nmc.service.TemperatureService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.Date; + +@Service +public class TemperatureServiceImpl implements TemperatureService { + + @Resource + private TemperatureRepository temperatureRepository; + + @Override + public void saveTemperature(String temperatureAndHumidityData,String topic) { + if(temperatureAndHumidityData!=null&&temperatureAndHumidityData.length()>0){ + String[] strDataTemperature = temperatureAndHumidityData.split(" "); + Date now = new Date(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat sdfHour = new SimpleDateFormat("yyyy-MM-dd HH"); + SimpleDateFormat sdfMinute = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + String nowDate = sdf.format(now); + String nowHour = sdfHour.format(now); + String dataMinute = sdfMinute.format(now); + Temperature temperature = new Temperature(); + temperature.setCreateDate(now); + temperature.setDataDate(nowDate); + temperature.setDataHour(nowHour); + temperature.setDataMinute(dataMinute); + if(topic!=null){ + temperature.setTopic(topic); + if(topic.equals("WifiSHT/7C87CE9CA4E6/SHT20")){ + temperature.setLocationDesc("广东省珠海市高新区唐家湾镇东岸村水风三街28号501"); + } + if(topic.equals("WifiSHT/7C87CE9F5CBF/SHT20")){ + temperature.setLocationDesc("广东省珠海市金湾区三灶镇百川路1号1栋1单元1508"); + } + if(topic.equals("WifiSHT/4CEBD686B6AA/SHT20")){ + temperature.setLocationDesc("广西壮族自治区崇左市天等县天等镇荣华村弄在屯113号"); + } + } + temperature.setHumidity(Double.valueOf(strDataTemperature[0])); + temperature.setTemperature(Double.valueOf(strDataTemperature[1])); + + this.temperatureRepository.save(temperature); + } + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/HttpURLConnectionUtil.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/HttpURLConnectionUtil.java new file mode 100644 index 0000000..cd2b836 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/HttpURLConnectionUtil.java @@ -0,0 +1,91 @@ +package com.rehome.disruptor_nmc.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * @author huangwenfei + * @version v1.0.0.0 + * Created DateTime 2021-04-27 9:35 + * @description: http请求工具类 + */ +public class HttpURLConnectionUtil { + + /** + * @date 2021-04-29 11:23 + * @description: get请求 + * @Param: urlStr get请求的url + */ + public static String getNetData(String urlStr) { + HttpURLConnection conn = null; + + //连接成功后我们是要读取数据的 所以要有一个输入流 + InputStream inputStream = null; + + // 因为读取的都是文本信息 所以使用BufferedReader + BufferedReader bufferedReader = null; + + //StringBuilder来把接收到的数据拼接起来 + StringBuilder result = new StringBuilder(); + try { + // 读取初始url 并且创建对象 + URL url = new URL(urlStr); + //打开url连接 + conn = (HttpURLConnection) url.openConnection(); + //设置连接 + //请求的方法 + conn.setRequestMethod("GET"); + //设置主机连接超时(单位:毫秒) + // 发送请求端 连接到 url目标地址端的时间 受距离长短和网络速度的影响 + conn.setConnectTimeout(15000); + //设置从主机读取数据超时(单位:毫秒) + // 连接成功后 获取数据的时间 受数据量和服务器处理数据的影响 + conn.setReadTimeout(60000); + + //设置请求参数 可以指定接收json参数 服务端的key为content-type + conn.setRequestProperty("Accept", "application/json"); + + //发送请求 + conn.connect(); + + //获取响应码 如果响应码不为200 表示请求不成功 + if (conn.getResponseCode() != 200) { + //todo 此处应该增加异常处理手段 + return "请求失败!!!"; + } + + //获取响应码 如果响应码为200 表示请求成功 然后可以读取数据 + //获取输入流 然后读取数据 + inputStream = conn.getInputStream(); + bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + + //逐行读取数据 + String line;//用来读取数据 + while ((line = bufferedReader.readLine()) != null) { + result.append(line); + //System.out.print(line); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + //关闭各种流 + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + return result.toString(); + } +} \ No newline at end of file diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/MqttSSLSocketFactory.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/MqttSSLSocketFactory.java new file mode 100644 index 0000000..f7dd53a --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/MqttSSLSocketFactory.java @@ -0,0 +1,90 @@ +package com.rehome.disruptor_nmc.utils; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.Security; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +public class MqttSSLSocketFactory { + public static SSLSocketFactory getSingleSocketFactory(InputStream caCrtFileInputStream) throws Exception { + Security.addProvider(new BouncyCastleProvider()); + X509Certificate caCert = null; + + BufferedInputStream bis = new BufferedInputStream(caCrtFileInputStream); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + while (bis.available() > 0) { + caCert = (X509Certificate) cf.generateCertificate(bis); + } + KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); + caKs.load(null, null); + caKs.setCertificateEntry("cert-certificate", caCert); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(caKs); + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(null, tmf.getTrustManagers(), null); + return sslContext.getSocketFactory(); + } + + public static SSLSocketFactory getTwoDirSocketFactory(InputStream caCrtFile, InputStream crtFile, InputStream keyFile, + String password) throws Exception { + Security.addProvider(new BouncyCastleProvider()); + + // load CA certificate + X509Certificate caCert = null; + + BufferedInputStream bis = new BufferedInputStream(caCrtFile); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + while (bis.available() > 0) { + caCert = (X509Certificate) cf.generateCertificate(bis); + } + + // load client certificate + bis = new BufferedInputStream(crtFile); + X509Certificate cert = null; + while (bis.available() > 0) { + cert = (X509Certificate) cf.generateCertificate(bis); + } + + // load client private cert + PEMParser pemParser = new PEMParser(new InputStreamReader(keyFile)); + Object object = pemParser.readObject(); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); + KeyPair key = converter.getKeyPair((PEMKeyPair) object); + + KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); + caKs.load(null, null); + caKs.setCertificateEntry("cert-certificate", caCert); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(caKs); + + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null, null); + ks.setCertificateEntry("certificate", cert); + ks.setKeyEntry("private-cert", key.getPrivate(), password.toCharArray(), + new java.security.cert.Certificate[]{cert}); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password.toCharArray()); + + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + return sslContext.getSocketFactory(); + } + + +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/UUIDUtil.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/UUIDUtil.java new file mode 100644 index 0000000..b3d269b --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/UUIDUtil.java @@ -0,0 +1,9 @@ +package com.rehome.disruptor_nmc.utils; + +import java.util.UUID; + +public class UUIDUtil { + public static String getUUID() { + return UUID.randomUUID().toString(); + } +} diff --git a/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/WeatherUtil.java b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/WeatherUtil.java new file mode 100644 index 0000000..6689111 --- /dev/null +++ b/disruptor_nmc/src/main/java/com/rehome/disruptor_nmc/utils/WeatherUtil.java @@ -0,0 +1,68 @@ +package com.rehome.disruptor_nmc.utils; + +import org.apache.commons.io.IOUtils; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.zip.GZIPInputStream; + +/** + * @author huangwenfei + * @version v1.0.0.0 + * Created DateTime 2021-04-26 9:35 + * @description: http请求工具类 + */ +public class WeatherUtil { + /** + * @date 2021-04-29 11:23 + * @description: get请求 + * @Param: url get请求的url + */ + public static String analysisUrl(String url){ + HttpURLConnection httpConnection = null; + String output = ""; + try { + URL targetUrl = new URL(url); + httpConnection = (HttpURLConnection) targetUrl.openConnection(); + httpConnection.setDoOutput(true); + httpConnection.setRequestMethod("GET"); + httpConnection.setRequestProperty("Content-Type", + "application/json"); + InputStreamReader isr = new InputStreamReader(httpConnection + .getInputStream(),"utf-8"); + BufferedReader responseBuffer = new BufferedReader(isr); + output = responseBuffer.readLine(); + } catch (Exception e) { + + } finally { + httpConnection.disconnect(); + } + return output; + } + /** + * @date 2021-04-29 11:23 + * @description: get请求 + * @Param: url get请求的url + */ + public static String analysisUrlGzip(String url){ + HttpURLConnection httpConnection = null; + String output = ""; + try { + URL targetUrl = new URL(url); + httpConnection = (HttpURLConnection) targetUrl.openConnection(); + httpConnection.setDoOutput(true); + httpConnection.setRequestMethod("GET"); + httpConnection.setRequestProperty("Content-Type", "application/json"); + InputStream stream = new GZIPInputStream(httpConnection.getInputStream()); + output = IOUtils.toString(stream,"utf-8"); + } catch (Exception e) { + + } finally { + httpConnection.disconnect(); + } + return output; + } +} diff --git a/disruptor_nmc/src/main/resources/application.yml b/disruptor_nmc/src/main/resources/application.yml new file mode 100644 index 0000000..b57e071 --- /dev/null +++ b/disruptor_nmc/src/main/resources/application.yml @@ -0,0 +1,50 @@ +server: + port: 18080 +spring: + datasource: + type: com.zaxxer.hikari.HikariDataSource + #driverClassName: com.mysql.jdbc.Driver #com.mysql.cj.jdbc.Driver com.mysql.jdbc.Driver + driverClassName: com.mysql.cj.jdbc.Driver #com.mysql.cj.jdbc.Driver com.mysql.jdbc.Driver + # url: jdbc:mysql://localhost:3306/head_office_data_center?characterEncoding=utf-8&serverTimezone=UTC&autoReconnect=true + # url: jdbc:mysql://127.0.0.1:3306/head_office_data_center?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&allowMultiQueries=true + # url: jdbc:mysql://localhost:3306/head_office_data_center?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=UTC + # url: jdbc:mysql://192.168.2.18:3306/disruptor_nmc?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true + url: jdbc:mysql://192.168.3.7:3306/disruptor_nmc?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true + username: root + password: Skyinno251, +# driverClassName: oracle.jdbc.driver.OracleDriver +# url: jdbc:oracle:thin:@192.168.1.38:1521/orcl +# username: huangwenfei +# password: huangwenfei + hikari: + #最小空闲连接,默认值10,小于0或大于maximum-pool-size,都会重置为maximum-pool-size + minimum-idle: 10 + #最大连接数,小于等于0会被重置为默认值10;大于零小于1会被重置为minimum-idle的值 + maximum-pool-size: 20 + #空闲连接超时时间,默认值600000(10分钟),大于等于max-lifetime且max-lifetime>0,会被重置为0;不等于0且小于10秒,会被重置为10秒 + idle-timeout: 600000 + #连接最大存活时间,不等于0且小于30秒,会被重置为默认值30分钟.设置应该比mysql设置的超时时间短 + max-lifetime: 1800000 + #连接超时时间:毫秒,小于250毫秒,否则被重置为默认值30秒 + connection-timeout: 60000 + jpa: + # 配置 DBMS 类型 + database: mysql + # 配置是否将执行的 SQL 输出到日志 + show-sql: false + open-in-view: true + hibernate: + ddl-auto: update # 第一次建表create 后面用update,要不然每次重启都会新建表 + naming: + physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy + servlet: + multipart: + # 开启 multipart 上传功能 + enabled: true + # 文件写入磁盘的阈值 + file-size-threshold: 2KB + # 最大文件大小 + max-file-size: 200MB + # 最大请求大小 + max-request-size: 215MB + diff --git a/disruptor_nmc/src/main/resources/ssl/client.crt b/disruptor_nmc/src/main/resources/ssl/client.crt new file mode 100644 index 0000000..a4813dd Binary files /dev/null and b/disruptor_nmc/src/main/resources/ssl/client.crt differ diff --git a/disruptor_nmc/src/main/resources/ssl/client.key b/disruptor_nmc/src/main/resources/ssl/client.key new file mode 100644 index 0000000..011629d --- /dev/null +++ b/disruptor_nmc/src/main/resources/ssl/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA4omYWBuiZ2bPhpmZFuvX50FMP07k/rI4uajLT1irRwoUn0ZR +xLO+voWb+0pMnLH6Aq/ehBW+WVOn4eQ4BBpSNXm4n5tJo71+FKKMk0uaX7NnBJ+P +FJxJxoBn5kFNAXUWdDojCTVMBX3k/QG679n6bYzzguk5Ky/pIEvePleox49MJJ5W +C3fHWNMODhWEYJXGgxjCSmWynLPmEdOyi2/KfKfplgCx1NYPbPW1JtZSRjJ9zK6b +5g2uGts50JEDuWAkYXpztAetaBF68+h79aHKP78AAHRa+0cT+4J1uxwcf9XK7fQt +5UGkuDZpUVWjQ9a44ciwaAXcKy9hqYRfSm9GBQIDAQABAoIBAQDCVBxOgK4pG2Ws +ZjiQFBJqe3ZH3IrN/d5xTV3SnBKZZwlXtD/SiAp5by3mO89Kn9YC1hEAp5JZGE0s +ltSCmH2rB9abe9+IybXNR79lX3Z23/PgYGuh14vl7yKxv5SqSmHPpEuHy6OCFoQH +kaNlu0x7C22dACodZQULwmlMe2/6dtHQbs9x0OROnJa9SpnScXfaPW/g/ONqR7S1 +rytHsM8dWUSEvNCUBqGqUFCTBPX44+w1RBLji36ZP1zeenlcBSMGlBifVJKH5OCk +MFR33iwh3BXxIi+he+DGBX8c1CRplgfitQZlSnX5I0OXcBm1r0I9zrC2hs1w4WVd +KNpr556FAoGBAPxqeqp7UaVfSQOMLQrpFAEBP6sqYd9dM3S81COpEB0i1i/6eZiE +dPiP92OXp5Ka3/0pT0h66K+enkmKQ788OaGtJpz6KIU25ZRN+t+tS4UslFg67BY5 +bdFad2pIF2Ql89EzqCmzHz6q2xc0SD467jEPS4FcNf8G91lJvamuLYkvAoGBAOXB +DIP8FiF3jn0DaoQpv3sX4R9UKNXOcaJmaprVZ5VHml8vrszrKju2HogKtyEzCMiS +I+MBSg9Vum5n9MFHUd/eRAqV1oh3l2QsR0AEJe230xXotoZ8Vdid32JNtsnR7YRL +q/OcMFhdpk50J8cVlx3gnC61S54jl1pAEFWSMW8LAoGATjZkKf0qMFbVFe9SaaYN +F76eTthEGWUUs6BrD12sa4rG2XkAQn0QjZB2dHqiZu/sZdJuCaRkAz7gByN7mH79 +0JYJd+yfr59yBcEf8j0NQIeus6QWUVCcMZmZlOofrV2BLhqWic1B6jYgyxDdLcMu +2S7HE59R7+Lls9oAldotq+sCgYEAhd6IFldJ5dItufXFmKBiq6xsRb7Z1Epnt8KJ +FxKFOlvwPMohxdC4WPZyr73emn+L/KH6OwjDSFAhQrdby0ptEE4Hw0svJ3DXS0zp +bwl7uBlF6xwfThkgRAko4bR6bvnctRsKY/V7zeEzR78ydjPES2pWVnjYSJpgU/vE +CLgYCaUCgYBzgGR2IrTfGdu9TVkEt9dAYS2QKwI+iEpTBLdJBCPiXbfg1Jh8xH5t +vmFOYQPnvyu6cRg9JQFXAVmEHcjC0VPwy/wURxVcgw1il/zmUrUAERVhpG/4uC4N +XQK0ipg/gvSEJKyiqeQN+nLv0PrdQ9vCQSG9sSMvWHL6dTcQDeNDiw== +-----END RSA PRIVATE KEY----- diff --git a/disruptor_nmc/src/main/resources/ssl/my_root_ca.crt b/disruptor_nmc/src/main/resources/ssl/my_root_ca.crt new file mode 100644 index 0000000..01774be Binary files /dev/null and b/disruptor_nmc/src/main/resources/ssl/my_root_ca.crt differ diff --git a/disruptor_nmc/src/main/resources/sslHk/client.crt b/disruptor_nmc/src/main/resources/sslHk/client.crt new file mode 100644 index 0000000..5cb20e1 Binary files /dev/null and b/disruptor_nmc/src/main/resources/sslHk/client.crt differ diff --git a/disruptor_nmc/src/main/resources/sslHk/client.key b/disruptor_nmc/src/main/resources/sslHk/client.key new file mode 100644 index 0000000..cabb045 --- /dev/null +++ b/disruptor_nmc/src/main/resources/sslHk/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApkLWaF5mqX/9Qv0PiFgvsEO9vNNzKcGjyAyLZBNQb70PgF33 +i7XsOBwNzo/xdisBXmWsCOPWVM60MUIGT4v7iCNueWQlMOsYYNxV47EV3ZclZbz4 +Ji5sKKczn1U1l25w5v3jNZEYcxHU6uwmtiBFCZa2SeEV0jI356qNU5Wvt9u/Io9Z +tb5tZOMa71ERejViqZtfNIg5Q3oRB7gyhyFKVKjPZI5MnfA895+7SrL4Nm4OIApm +dKM0dTV7Xz1VsRnO3IlivnmaQy7sBMv7ak8vNXCMO1qHQGKOmNrKHtQTswxOdute +5kSSzVRBE25Xrk/RyG+01mtccU2liNWMjfTEwwIDAQABAoIBAEkt9g1uL6W/jgvk +MugCWMsupd7s+y2P67TrwJbF4YutHZuUwJaf9l8kCfe3Z8JpX2rbOYOYNQiTCsD7 +nKd6p7XeUovfxnbno41OrgdQNJ2aH33OVTMJD9Y88f3ZlYMXu14Qtecn/Cj52kuk +sc1MGtcDnSybg+1G6VBww0/c/MDhpHSEevJ8LZaxTOyNPvt4qVJZKtArBGnFPh81 +VKiBQy6Aumm4k9gRkrVbAR0xo9DiOYE0hfga04J3EwYdI2uhGvgew2zeRVSdsN81 +TN8mNJ/BTra2Yqf4bp22IhNT6G9AgfjqTb1mDfaQHkN5SABgB8TE/HubJ4wH/Jn+ +ptVLR5ECgYEA0gzbolhfskVJ00eNs1ik6SKpBQwKz27OokNILfG5+BzLTK5kBYtU +jov9lSRz/PWHX+g7Do3ncdueSvHpBALaUcsxVsY1QoWcxQ8NLlZfcY1dm1Vuudzg +dy3Ccl7vKsoQBkI/an+3+ooiy/XX9pydt4/QfkmzCaAre0SuLavNWJcCgYEAyqG4 +DUf41LFQTDNTTUxcg924JDk6pxO3+4Qr98CSJz+6pICkTw3fy/cKOj1wFc1RA4/0 +DndiXBXnA0wnfPb2dktZ970cXofaIXMbpcteBSJC/Atqd8Mmcit+A21FTx5nI/dv +CGgmAj0j0Y7nX91+jos4l6/ihXskQQDfUYA2LrUCgYBqGOKLsxXLRyJOHPNfJqRN +uhsjmHyRYEfxQAjiZBnqUCkEN4YAIut4AQ/6WGpZ2G8jq3rBFD5WjXb8Jgrr4sEB +1Z+7U+ytCC4yfzLKOAiHo78nadS+/ulGaY+xE3C87UmAz8+WbKKyYznGSgxm3Z7w +jCzkzTco4oV0AzHzkbbsSwKBgDaOVgyVXSR+3Py3MO116s7CKmruUaFcSMPaMTBS +U8dnfCwASrzSIng6+jD2C7CDCBXqcy5V7FCYwQr9PQCDSZZN8VonO3UkJJGu+Tmp +SJYfRGOx+ydljntcxF/N0sRbji971hQwXlNp/LPWQutnqkRcrY8Blv6TSg6KWpYJ +7AylAoGAMp/nSsfpjnoYW+8KdC+iEZw66FjCg5HV11rWCUqj7gsgNOfCUhku826M +23SwZWWVQzOR5dJsmtUuzO1cXcpxKSpMdpVikB4TYFm4U1l5QZuSG+L2516IjwwJ +q96skUIZ649Tu1B5ecQLMPD0S/Hc8Guhcr31KGnisOQt/CbSA1w= +-----END RSA PRIVATE KEY----- diff --git a/disruptor_nmc/src/main/resources/sslHk/my_root_ca.crt b/disruptor_nmc/src/main/resources/sslHk/my_root_ca.crt new file mode 100644 index 0000000..cc8f146 Binary files /dev/null and b/disruptor_nmc/src/main/resources/sslHk/my_root_ca.crt differ diff --git a/disruptor_nmc/src/test/java/com/rehome/disruptor_nmc/DisruptorNmcApplicationTests.java b/disruptor_nmc/src/test/java/com/rehome/disruptor_nmc/DisruptorNmcApplicationTests.java new file mode 100644 index 0000000..a6c9b13 --- /dev/null +++ b/disruptor_nmc/src/test/java/com/rehome/disruptor_nmc/DisruptorNmcApplicationTests.java @@ -0,0 +1,13 @@ +package com.rehome.disruptor_nmc; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DisruptorNmcApplicationTests { + + @Test + void contextLoads() { + } + +}