commit 5dcc8f67c62aa1b50f07cbd834480b60b9b4e041 Author: bgy Date: Thu May 7 16:41:04 2026 +0800 定时检查服务 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2a3040 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### 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/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..7f91a56 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,114 @@ +/* +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. +*/ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.Properties; + +public class MavenWrapperDownloader { + + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = + "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: : " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..01e6799 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..cd0d451 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..8b9da3b --- /dev/null +++ b/mvnw @@ -0,0 +1,286 @@ +#!/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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..fef5a8f --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,161 @@ +@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 Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke 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 my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..73731ef --- /dev/null +++ b/pom.xml @@ -0,0 +1,144 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.8.RELEASE + + + com.topsail + scheduletask + 0.0.1-SNAPSHOT + scheduletask + scheduletask + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-amqp + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.0 + + + + mysql + mysql-connector-java + 8.0.13 + + + org.springframework.boot + spring-boot-starter-test + + + org.springframework.amqp + spring-rabbit-test + test + + + com.alibaba + fastjson + 1.2.15 + + + com.google.code.gson + gson + + + com.influxdb + influxdb-client-java + 1.8.0 + + + + + + + + + + + + org.springframework + spring-test + 4.3.6.RELEASE + + + + junit + junit + 4.12 + + + org.projectlombok + lombok + 1.18.6 + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.10 + + + + org.springframework.boot + spring-boot-starter-mail + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.8.RELEASE + + + org.mybatis.generator + mybatis-generator-maven-plugin + 1.3.5 + + + + mysql + mysql-connector-java + 5.1.40 + + + com.itfsw + mybatis-generator-plugin + 1.2.20 + + + + + + + src/main/java + + **/*.properties + **/*.xml + + false + + + src/main/resources + + **/*.properties + **/*.xml + + false + + + + + diff --git a/src/main/java/com/topsail/scheduletask/ScheduleTaskApplication.java b/src/main/java/com/topsail/scheduletask/ScheduleTaskApplication.java new file mode 100644 index 0000000..a07890b --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/ScheduleTaskApplication.java @@ -0,0 +1,16 @@ +package com.topsail.scheduletask; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import java.util.TimeZone; + +@SpringBootApplication +@MapperScan("com.topsail.scheduletask.mapper") +public class ScheduleTaskApplication { + public static void main(String[] args) { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + SpringApplication.run(ScheduleTaskApplication.class, args); + } +} diff --git a/src/main/java/com/topsail/scheduletask/mapper/InformLogDao.java b/src/main/java/com/topsail/scheduletask/mapper/InformLogDao.java new file mode 100644 index 0000000..f561e03 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/mapper/InformLogDao.java @@ -0,0 +1,77 @@ +package com.topsail.scheduletask.mapper; + +import com.topsail.scheduletask.pojo.InformLog; +import com.topsail.scheduletask.pojo.InformLogVo; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * + * 信息推送日志表Dao + * + * @version + *
+ * Author	Version		Date		Changes
+ * Administrator 	1.0  		2021年11月24日 	Created
+ *
+ * 
+ * @since 1. + */ +@Repository +public interface InformLogDao { + + /** + * 信息推送日志表 新增 + * + * @param informLog + * @return + */ + int saveInformLog(@Param("informLog") InformLog informLog); + + + /** + * 信息推送日志表 更新 + * + * @param informLog + * @return + */ + int updateInformLog(InformLog informLog); + + /** + *信息推送日志表 删除 + * + * @param id + * @return + */ + int deleteInformLog(Integer id); + + /** + * 信息推送日志表 查询列表 + * + * @param informLog + * @param start + * @param pageSize + * @return + */ + List pageListInformLog(@Param("informLog") InformLogVo informLog, @Param("start") Integer start, @Param("pageSize") Integer pageSize); + + /** + * 信息推送日志表 count + * + * @param informLog + * @return + */ + Integer findCountInformLog(@Param("informLog") InformLogVo informLog); + + /** + * 信息推送日志表 根据id查询 + * + * @param id + * @return + */ + InformLogVo findInformLog(Integer id); + + Integer getNewInformLogCount(@Param("subject") String subject,@Param("today") String today); +} \ No newline at end of file diff --git a/src/main/java/com/topsail/scheduletask/pojo/InformLog.java b/src/main/java/com/topsail/scheduletask/pojo/InformLog.java new file mode 100644 index 0000000..237d2fb --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/pojo/InformLog.java @@ -0,0 +1,62 @@ +package com.topsail.scheduletask.pojo; + +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + + +/** + * + * 信息推送日志表实体 + * + * @version + * +
+ * Author	Version		Date		Changes
+ * Administrator 	1.0  2021年11月24日 Created
+ *
+ * 
+ * @since 1. + */ +@Data +public class InformLog implements Serializable { + private static final long serialVersionUID = 5892789166672676L; + + /** + *id + */ + private Integer id; + /** + *推送方式 + */ + private String informType; + /** + *推送地址 + */ + private String informAddress; + /** + *推送内容 + */ + private String informData; + /** + *推送结果(0失败1成功) + */ + private Integer state; + /** + *推送返回值记录 + */ + private String resultMsg; + /** + *推送场景 + */ + private String sendScenarios; + /** + *创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime = new Date(); + + +} \ No newline at end of file diff --git a/src/main/java/com/topsail/scheduletask/pojo/InformLogVo.java b/src/main/java/com/topsail/scheduletask/pojo/InformLogVo.java new file mode 100644 index 0000000..a618ca2 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/pojo/InformLogVo.java @@ -0,0 +1,74 @@ +package com.topsail.scheduletask.pojo; + +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + + +/** + * + * 信息推送日志表实体 + * + * @version + * +
+ * Author	Version		Date		Changes
+ * Administrator 	1.0  2021年11月24日 Created
+ *
+ * 
+ * @since 1. + */ +@Data +public class InformLogVo implements Serializable { + private static final long serialVersionUID = 6509367370157091L; + + /** + *id + */ + private Integer id; + /** + *推送方式 + */ + private String informType; + /** + *推送地址 + */ + private String informAddress; + /** + *推送内容 + */ + private String informData; + /** + *推送结果(0失败1成功) + */ + private Integer state; + /** + *推送返回值记录 + */ + private String resultMsg; + /** + *推送场景 + */ + private String sendScenarios; + /** + *创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 开始时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date startTime; + + /** + * 结束时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date endTime; + + +} diff --git a/src/main/java/com/topsail/scheduletask/receiver/AmqpListener.java b/src/main/java/com/topsail/scheduletask/receiver/AmqpListener.java new file mode 100644 index 0000000..62fbdbf --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/receiver/AmqpListener.java @@ -0,0 +1,55 @@ +package com.topsail.scheduletask.receiver; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.rabbitmq.client.Channel; +import com.topsail.scheduletask.mapper.InformLogDao; +import com.topsail.scheduletask.service.AmqpService; +import com.topsail.scheduletask.util.MaiSenderlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.support.AmqpHeaders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.Date; + + +@Component +public class AmqpListener { + public static final Logger LOG = LoggerFactory.getLogger(AmqpListener.class); + //初始化设备时钟错误的设备号集合 + @Autowired + private MaiSenderlUtil maiSenderlUtil; + @Autowired + AmqpService amqpService; + @Autowired + InformLogDao informLogDao; + + @RabbitListener(queues = "mailNotice") + public void sendMailMessage(@Payload String message, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, Channel channel) throws Exception { + try { + JSONObject jsonObject = JSONObject.parseObject(message); + String subject = "设备数据流转服务异常"; + + StringBuffer mailMessage = new StringBuffer(); + String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); + String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + Integer count = informLogDao.getNewInformLogCount(subject, today); + if (count == null || (count != null && count < 2)) { + mailMessage.append("尊敬的 ").append(",你好!:
     ").append("截止:").append(time).append("  ").append("堆积消息超过2000条消息未消费,请检查服务器和后台服务程序").append("  ").append("告警队列信息:").append(JSON.toJSONString(jsonObject)); + maiSenderlUtil.sendMail("1129801211@qq.com", subject, mailMessage.toString(), true, null, "设备数据流转服务异常"); + } + channel.basicAck(deliveryTag, false); + } catch (Exception e) { + e.printStackTrace(); + channel.basicAck(deliveryTag, false); + } + } + + +} diff --git a/src/main/java/com/topsail/scheduletask/result/CodeMsg.java b/src/main/java/com/topsail/scheduletask/result/CodeMsg.java new file mode 100644 index 0000000..667f97d --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/result/CodeMsg.java @@ -0,0 +1,65 @@ +package com.topsail.scheduletask.result; + +public class CodeMsg { + + private int code; + private String msg; + + //通用的错误码 + public static CodeMsg SUCCESS = new CodeMsg(0, "success"); + public static CodeMsg FAILED = new CodeMsg(502, "failed"); + public static CodeMsg TOKEN_EXPIRED = new CodeMsg(400, "token过期"); + public static CodeMsg TOKEN_INVALID = new CodeMsg(401, "token解析异常"); + public static CodeMsg USER_NOT_LOGGED_IN = new CodeMsg(402, "未登录,请登录!"); + public static CodeMsg SIGNATURE_ERROR = new CodeMsg(506, "签名失败"); + public static CodeMsg SERVER_ERROR = new CodeMsg(500, "服务端异常"); + public static CodeMsg FILE_ERROR = new CodeMsg(501, "文件不存在"); + public static CodeMsg FILE_EXIST = new CodeMsg(5012, "文件已存在"); + public static CodeMsg TIME_ERROR = new CodeMsg(502, "时间格式错误,应为 yyyy-MM-dd HH:mm:ss"); + public static CodeMsg DUPLICATEKEY_ERROR = new CodeMsg(502, "IMEI已注册"); + public static CodeMsg TIMEMISS_ERROR = new CodeMsg(503, "查询时间缺失,应为 yyyy-MM-dd HH:mm:ss"); + public static CodeMsg BIND_ERROR = new CodeMsg(504, "参数绑定异常"); + public static CodeMsg CONTROL_ERROR = new CodeMsg(505, "命令下发失败,请检查设备相关信息是否存在或正确以及参数输入是否正确"); + + private CodeMsg() { + } + + public CodeMsg(int code, String msg) { + this.code = code; + this.msg = msg; + } + + 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; + } + + /** + * 返回带参数的错误码 + * @param args + * @return + */ + public CodeMsg fillArgs(Object... args) { + int code = this.code; + String message = String.format(this.msg, args); + return new CodeMsg(code, message); + } + + @Override + public String toString() { + return "CodeMsg [code=" + code + ", msg=" + msg + "]"; + } + + +} diff --git a/src/main/java/com/topsail/scheduletask/result/Result.java b/src/main/java/com/topsail/scheduletask/result/Result.java new file mode 100644 index 0000000..e826a5d --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/result/Result.java @@ -0,0 +1,89 @@ +package com.topsail.scheduletask.result; + + +import com.github.pagehelper.PageInfo; +import lombok.Data; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Data +public class Result { + + private int code; + private String msg="success"; + private T data; + + private Result(T data) { + this.data = data; + } + + private Result(int code, String msg) { + this.code = code; + this.msg = msg; + } + + private Result(CodeMsg codeMsg) { + if(codeMsg != null) { + this.code = codeMsg.getCode(); + this.msg = codeMsg.getMsg(); + } + } + + /** + * 成功时候的调用 + * */ + public static Result success(T data){ + return new Result(data); + } + + /** + * 失败时候的调用 + * */ + public static Result error(CodeMsg codeMsg){ + return new Result(codeMsg); + } + + public static Result error(){ + return new Result(CodeMsg.FAILED); + } + + + + + + /** + * BindingResult统一处理 + */ + public static Result resolveBindResult(BindingResult bindingResult){ + StringBuilder stringBuilder = new StringBuilder(); + for (String s : bindingResult.getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.toList())) { + stringBuilder.append(",").append(s); + } + return Result.error(new CodeMsg(502,stringBuilder.toString().substring(1))); + } + + + /** + *分页之后的统一返回对象 + * @param t + * @param + * @return + */ + public static Map returnPageMap(List t){ + PageInfo pageInfo=new PageInfo(t); + int count=(int)pageInfo.getTotal(); + Map map=new HashMap<>(); + map.put("list", new ArrayList(pageInfo.getList())); + map.put("count",count); + return map; + } + + + +} diff --git a/src/main/java/com/topsail/scheduletask/service/AmqpService.java b/src/main/java/com/topsail/scheduletask/service/AmqpService.java new file mode 100644 index 0000000..cf28c38 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/service/AmqpService.java @@ -0,0 +1,261 @@ +package com.topsail.scheduletask.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.rabbitmq.client.Channel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.AmqpAdmin; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.concurrent.TimeoutException; + +@Service +public class AmqpService { + public static final Logger LOG = LoggerFactory.getLogger(AmqpService.class); + + private final AmqpAdmin amqpAdmin; + private final AmqpTemplate amqpTemplate; + private final ConnectionFactory connectionFactory; + + // 从配置文件读取 RabbitMQ Management API 配置 + @Value("${rabbitmq.management.url:http://localhost:15672}") + private String managementUrl; + + @Value("${rabbitmq.management.username:guest}") + private String managementUsername; + + @Value("${rabbitmq.management.password:guest}") + private String managementPassword; + + @Value("${rabbitmq.management.vhost:/}") + private String managementVhost; + + // 缓存认证头,避免重复计算 + private String cachedAuthHeader = null; + + @Autowired + public AmqpService(AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate, ConnectionFactory connectionFactory) { + this.amqpAdmin = amqpAdmin; + this.amqpTemplate = amqpTemplate; + this.connectionFactory = connectionFactory; + } + + public void SendMessage(String queue,String content){ + //LOG.info("Send ampg" + content); + this.amqpTemplate.convertAndSend(queue,content); + } + + public void SendExchange(String exchange,String content){ + this.amqpTemplate.convertAndSend(exchange,"",content); + } + + public boolean IsQueuesEmpty(String queue){ + try{ + Message msg = this.amqpTemplate.receive(queue); + if(msg!=null){ + this.amqpTemplate.send(queue,msg); + return false; + }else{ + return true; + } + }catch (Exception e){ + return true; + } + } + /** + * 获取指定队列的消息数量(兼容 Spring Boot 2.1.8) + * @param queueName 队列名称 + * @return 队列中待消费的消息数量,如果获取失败或队列不存在则返回-1 + */ + public long getQueueMessageCount(String queueName) { + if (queueName == null || queueName.trim().isEmpty()) { + LOG.warn("队列名称不能为空"); + return -1; + } + + // 使用 Spring AMQP 的 Connection,由 Spring 管理生命周期 + org.springframework.amqp.rabbit.connection.Connection connection = null; + Channel channel = null; + + try { + // 从 Spring 连接工厂获取连接(有连接池支持) + connection = connectionFactory.createConnection(); + channel = connection.createChannel(false); + + // queueDeclarePassive 不会创建队列,只是获取队列信息,如果队列不存在会抛出异常 + com.rabbitmq.client.AMQP.Queue.DeclareOk declareOk = channel.queueDeclarePassive(queueName); + long messageCount = declareOk.getMessageCount(); + LOG.debug("队列 [{}] 当前消息数量: {}", queueName, messageCount); + return messageCount; + + } catch (IOException e) { + // 队列不存在时也会抛出 IOException + String errorMsg = e.getMessage(); + if (errorMsg != null && (errorMsg.contains("NOT_FOUND") || errorMsg.contains("404"))) { + LOG.warn("队列 [{}] 不存在", queueName); + } else { + LOG.error("获取队列 [{}] 消息数量时发生IO异常: {}", queueName, errorMsg); + } + return -1; + } catch (Exception e) { + LOG.error("获取队列 [{}] 消息数量时发生异常", queueName, e); + return -1; + } finally { + // 关闭资源(从内到外) + if (channel != null && channel.isOpen()) { + try { + channel.close(); + } catch (IOException | TimeoutException e) { + LOG.warn("关闭 Channel 时发生异常", e); + } + } + if (connection != null) { + try { + connection.close(); + } catch (Exception e) { + LOG.warn("关闭 Connection 时发生异常", e); + } + } + } + } + /** + * 获取RabbitMQ中所有的队列名称(通过 Management HTTP API) + * @return 队列名称列表,如果获取失败则返回空列表 + */ + public List getAllQueueNames() { + List queueNames = new ArrayList<>(); + + // 构建完整的 API URL(处理 URL 末尾可能的斜杠) + String baseUrl = managementUrl.endsWith("/") ? managementUrl.substring(0, managementUrl.length() - 1) : managementUrl; + String apiUrl = baseUrl + "/api/queues"; + + // 如果需要指定虚拟主机,使用:/api/queues/{vhost} + if (managementVhost != null && !managementVhost.trim().isEmpty() && !"/".equals(managementVhost)) { + try { + // URL 编码虚拟主机名称(因为 / 需要编码为 %2F) + String encodedVhost = java.net.URLEncoder.encode(managementVhost, StandardCharsets.UTF_8.name()); + apiUrl = baseUrl + "/api/queues/" + encodedVhost; + } catch (Exception e) { + LOG.warn("虚拟主机名称编码失败,使用默认队列列表", e); + } + } + + HttpURLConnection connection = null; + InputStream inputStream = null; + BufferedReader reader = null; + + try { + LOG.debug("正在连接 RabbitMQ Management API: {}", apiUrl); + + URL url = new URL(apiUrl); + connection = (HttpURLConnection) url.openConnection(); + + // 设置基本认证(使用缓存的认证头) + String authHeader = getAuthHeader(); + connection.setRequestProperty("Authorization", authHeader); + connection.setRequestProperty("Accept", "application/json"); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(5000); + connection.setReadTimeout(10000); + + int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_OK) { + inputStream = connection.getInputStream(); + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + + // 使用 StringBuilder 高效读取响应 + StringBuilder response = new StringBuilder(); + char[] buffer = new char[4096]; + int bytesRead; + while ((bytesRead = reader.read(buffer)) != -1) { + response.append(buffer, 0, bytesRead); + } + + // 使用 FastJSON 解析响应 + String jsonResponse = response.toString().trim(); + if (!jsonResponse.isEmpty()) { + try { + JSONArray queues = JSONArray.parseArray(jsonResponse); + if (queues != null && !queues.isEmpty()) { + for (int i = 0; i < queues.size(); i++) { + JSONObject queue = queues.getJSONObject(i); + String queueName = queue.getString("name"); + if (queueName != null && !queueName.trim().isEmpty()) { + queueNames.add(queueName); + } + } + LOG.info("成功获取 {} 个队列名称", queueNames.size()); + } else { + LOG.info("RabbitMQ 中暂无队列"); + } + } catch (Exception jsonEx) { + LOG.error("解析 RabbitMQ Management API 响应失败", jsonEx); + } + } else { + LOG.warn("RabbitMQ Management API 返回空响应"); + } + } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { + LOG.error("RabbitMQ Management API 认证失败,请检查用户名和密码配置"); + } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) { + LOG.error("RabbitMQ Management API 未找到,请确认 rabbitmq_management 插件已启用"); + } else { + LOG.warn("RabbitMQ Management API 响应码: {}, 消息: {}", responseCode, connection.getResponseMessage()); + } + + } catch (IOException e) { + LOG.error("获取队列列表时发生IO异常,请确认 RabbitMQ Management 插件已启用且服务正常运行", e); + } catch (Exception e) { + LOG.error("获取队列列表时发生未知异常", e); + } finally { + // 关闭资源(从内到外) + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + LOG.warn("关闭 BufferedReader 时发生异常", e); + } + } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + LOG.warn("关闭 InputStream 时发生异常", e); + } + } + if (connection != null) { + connection.disconnect(); + } + } + + return queueNames; + } + + /** + * 获取或生成 Basic Auth 认证头 + * @return Authorization header 值 + */ + private String getAuthHeader() { + if (cachedAuthHeader == null) { + String auth = managementUsername + ":" + managementPassword; + String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8)); + cachedAuthHeader = "Basic " + encodedAuth; + } + return cachedAuthHeader; + } +} diff --git a/src/main/java/com/topsail/scheduletask/task/CheckRabbitMqScheduleTask.java b/src/main/java/com/topsail/scheduletask/task/CheckRabbitMqScheduleTask.java new file mode 100644 index 0000000..77c8297 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/task/CheckRabbitMqScheduleTask.java @@ -0,0 +1,60 @@ +package com.topsail.scheduletask.task; + +import com.alibaba.fastjson.JSON; +import com.topsail.scheduletask.service.AmqpService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +@Configuration //1.主要用于标记配置类,兼备Component的效果。 +@EnableScheduling // 2.开启定时任务 +public class CheckRabbitMqScheduleTask { + + @Autowired + private Environment env; + @Autowired + AmqpService amqpService; + + //1.每个小时定时检查rabbitmq +// @Scheduled(cron = "0 0 0/1 * * ?") + @Scheduled(cron = "0 0/30 * * * ?") + //或直接指定时间间隔,例如:5秒 +// @Scheduled(fixedRate=5000) + private void checkRabbitMqCount() { + //查询rabbitmq的队列名称 + List allQueueNames = amqpService.getAllQueueNames(); + Map queueMessageCountMap = new HashMap<>(); + for (String queueName : allQueueNames) { + //获取队列中待消费的消息数量 + long count = amqpService.getQueueMessageCount(queueName); + if (count > 2000) { + System.err.println("队列名称:" + queueName + ",待消费消息数量:" + count); + queueMessageCountMap.put(queueName, count); + } + } + if (queueMessageCountMap.size() > 0) { + //将queueMessageCountMap转成json字符串 + String json = JSON.toJSONString(queueMessageCountMap); + amqpService.SendMessage("mailNotice", json); + } + } + + public static void main(String[] args) { + Map queueMessageCountMap = new HashMap<>(); + queueMessageCountMap.put("queue1", 1000L); + queueMessageCountMap.put("queue2", 2000L); + queueMessageCountMap.put("queue3", 3000L); + queueMessageCountMap.put("queue4", 4000L); + String json = JSON.toJSONString(queueMessageCountMap); + System.out.println( json); + } +} diff --git a/src/main/java/com/topsail/scheduletask/task/ScheduleDeleteTask.java b/src/main/java/com/topsail/scheduletask/task/ScheduleDeleteTask.java new file mode 100644 index 0000000..90587c0 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/task/ScheduleDeleteTask.java @@ -0,0 +1,39 @@ +package com.topsail.scheduletask.task; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +public class ScheduleDeleteTask { +// @Autowired +// SystemLogDao systemLogDao; +// /** +// * 每天凌晨0点45清空数据表collection_meter_mbus_command_step_log +// */ +// @Scheduled(cron = "0 45 0 * * ?") +// public void truncateTableRecordsTask() { +// try { +// systemLogDao.truncateTableRecords(); +// System.out.println("清空数据表collection_meter_mbus_command_step_log成功!"); +// }catch (Exception e){ +// e.printStackTrace(); +// System.out.println("清空数据表collection_meter_mbus_command_step_log失败!"); +// } +// } +// +// /** +// * 每周周一0点删除数据表online_rate(最新前10万条数据) +// */ +// @Scheduled(cron = "0 0 0 * * 1") +// public void deleteTableRecordsTask() { +// try { +// Integer minId = systemLogDao.queryNeedDeleteMinId(); +// systemLogDao.deleteTableRecordsTask(minId); +// System.out.println("清空数据表online_rate成功!"+minId); +// }catch (Exception e){ +// e.printStackTrace(); +// System.out.println("清空数据表online_rate失败!"); +// } +// } +} diff --git a/src/main/java/com/topsail/scheduletask/util/MaiSenderlUtil.java b/src/main/java/com/topsail/scheduletask/util/MaiSenderlUtil.java new file mode 100644 index 0000000..33c1be6 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/util/MaiSenderlUtil.java @@ -0,0 +1,168 @@ +package com.topsail.scheduletask.util; + +import com.topsail.scheduletask.mapper.InformLogDao; +import com.topsail.scheduletask.pojo.InformLog; +import com.topsail.scheduletask.result.CodeMsg; +import com.topsail.scheduletask.result.Result; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import javax.mail.internet.MimeMessage; +import java.util.List; + +/** + * @ClassName MaiSenderlUtil + * @Deacription TODO + * @Author Administrator + * @Date 2021/3/15 11:00 + * @Version 1.0 + **/ +@Component +public class MaiSenderlUtil { + + static final Logger logger = LoggerFactory.getLogger(MaiSenderlUtil.class); + + @Autowired + private JavaMailSender mailSender; + + @Autowired + private InformLogDao informLogDao; + + @Value("${spring.mail.username}") + private String from; + +// @Autowired +// public void setQueryMapper(JavaMailSender mailSender) { +// this.mailSender = mailSender; +// } + + + public Result sendMail(String to, String subject, String text , String sendScenarios){ + InformLog informLog = new InformLog(); + informLog.setInformAddress(to); + informLog.setInformType("email"); + informLog.setInformData(text); + informLog.setSendScenarios(sendScenarios); + + +// //设置服务器验证信息 +// Properties prop = new Properties(); +// prop.setProperty("mail.smtp.auth", "true"); +// prop.setProperty("mail.smtp.timeout", "994"); // 加密端口(ssl) 可通过 https://qiye.163.com/help/client-profile.html 进行查询 +// +// MailSSLSocketFactory sf = new MailSSLSocketFactory();// SSL加密 +// sf.setTrustAllHosts(true); // 设置信任所有的主机 +// prop.put("mail.smtp.ssl.enable", "true"); +// prop.put("mail.smtp.ssl.socketFactory", sf); + + SimpleMailMessage message = new SimpleMailMessage(); + + //发件人昵称展示 要与邮箱设置的发送名称一致,不然报错 + message.setFrom(from); + //接收邮箱 + message.setTo(to); + //邮件主题 + message.setSubject(subject); + //邮箱内容 + message.setText(text); + + + try { + + mailSender.send(message); + logger.info("send mail success"); + informLog.setState(1); + informLog.setResultMsg("send mail success"); + return Result.success(null); + + + } catch (Exception e) { + logger.error("send mail fail:", e); + informLog.setState(0); + informLog.setResultMsg("send mail fail:"+ e); + + return Result.error(new CodeMsg(502,"失败")); + }finally { + informLogDao.saveInformLog(informLog); + } + + } + + public Result sendMail(String to, String subject, String text, boolean html, List fileUrls, String sendScenarios){ + + InformLog informLog = new InformLog(); + informLog.setInformAddress(to); + informLog.setInformType("email"); + informLog.setInformData(text); + informLog.setSendScenarios(sendScenarios); + try { +// Properties prop = new Properties(); +// prop.setProperty("mail.smtp.auth", "true"); // 需要验证用户名密码 +// //设置超时时间 +// prop.setProperty("mail.smtp.timeout", "25000"); +// +// // 关于QQ邮箱,还要设置SSL加密,加上以下代码即可 +// MailSSLSocketFactory sf = new MailSSLSocketFactory(); +// sf.setTrustAllHosts(true); +// prop.put("mail.smtp.ssl.enable", "true"); +// prop.put("mail.smtp.ssl.socketFactory", sf); + + + MimeMessage mimeMessage = mailSender.createMimeMessage(); + + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + + + + helper.setFrom(from); + + helper.setTo(to); + + helper.setSubject(subject); + + helper.setText(text,html); + + + if(fileUrls != null && fileUrls.size() > 0){ + for(String fileUrl : fileUrls){ + FileSystemResource fsr = new FileSystemResource(fileUrl); + String fileName = fsr.getFilename(); + helper.addAttachment(fileName, fsr); + } + } + mailSender.send(mimeMessage); + logger.info("send mail success"); + informLog.setState(1); + informLog.setResultMsg("send mail success"); + return Result.success(null); + } catch (Exception e) { + logger.error("send mail fail", e); + informLog.setState(0); + informLog.setResultMsg("send mail fail:"+ e); + return Result.error(new CodeMsg(502,"失败")); + }finally { + try { + informLogDao.saveInformLog(informLog); + }catch (Exception e){ + logger.error("保存异常信息失败",e); + } + } + + } + + public static void main(String[] args) { + String fileUrl = "D:\\test\\report\\2020年按照产品进行异常问题统计.xlsx"; + if(fileUrl.contains("\\")){ + String fileName = fileUrl.substring(fileUrl.lastIndexOf("\\")+1); + System.out.println(fileName); + } + } + +} diff --git a/src/main/java/com/topsail/scheduletask/util/StringHandleUtil.java b/src/main/java/com/topsail/scheduletask/util/StringHandleUtil.java new file mode 100644 index 0000000..2404f78 --- /dev/null +++ b/src/main/java/com/topsail/scheduletask/util/StringHandleUtil.java @@ -0,0 +1,111 @@ +package com.topsail.scheduletask.util; + +import java.math.BigInteger; + +public class StringHandleUtil { + /** + * 判断字符串是否头部和尾部都以两个双引号包裹 + * + * @param str 待检查的字符串 + * @return 若字符串首尾各有两个双引号则返回true,否则返回false + */ + public static boolean isWrappedWithTwoQuotes(String str) { + // 检查字符串是否为null或长度不足4(至少需要4个字符:2个前引号+2个后引号) + if (str == null || str.length() < 4) { + return false; + } + + // 检查头部两个字符是否为双引号 + boolean startsWithTwoQuotes = str.charAt(0) == '"' && str.charAt(1) == '"'; + + // 检查尾部两个字符是否为双引号 + int length = str.length(); + boolean endsWithTwoQuotes = str.charAt(length - 2) == '"' && str.charAt(length - 1) == '"'; + + // 只有两者都满足才返回true + return startsWithTwoQuotes && endsWithTwoQuotes; + } + + /** + * 处理字符串,使其前后只保留一个双引号 + * + * @param str 输入字符串 + * @return 处理后的字符串 + */ + public static String keepSingleQuotesAtBothEnds(String str) { + // 处理null情况 + if (str == null) { + return null; + } + + // 去除所有前导双引号 + String trimmedStart = str.replaceAll("^\"+", ""); + // 去除所有尾随双引号 + String trimmed = trimmedStart.replaceAll("\"+$", ""); + + // 如果原字符串没有引号,直接返回 + if (trimmed.equals(str)) { + return str; + } + + // 在处理后的字符串前后各添加一个双引号 + return "\"" + trimmed + "\""; + } + /** + * 去除字符串头部和尾部所有的双引号 + * @param str 输入字符串 + * @return 处理后的字符串(首尾无引号) + */ + public static String trimAllQuotes(String str) { + // 处理null情况 + if (str == null) { + return null; + } + + // 使用正则表达式去除开头和结尾的所有双引号 + // ^\"+ 匹配字符串开头的一个或多个双引号 + // \"+$ 匹配字符串结尾的一个或多个双引号 + return str.replaceAll("^\"+", "").replaceAll("\"+$", ""); + } + /** + * 16进制转换为10进制 + * + * @return + */ + + public static int hexToDecimal(String hex) { +/* int decimalValue = 0; + for (int i = 0; i < hex.length(); i++) { + char hexChar = hex.charAt(i); + decimalValue = decimalValue * 16 + hexCharToDecimal(hexChar); + } + return decimalValue;*/ + int parseInt = new BigInteger(hex, 16).intValue(); + return parseInt; + } + /** + * 将8位字符串截取为4段(每段2字符)并返回点分格式 + * + * @param input 8位字符串 + * @return 点分格式结果(如"12.34.56.78") + * @throws IllegalArgumentException 输入长度不为8时抛出 + */ + public static String splitToDottedVersionFormat(String input) { + // 截取4段并拼接 + StringBuilder result = new StringBuilder(); + try { + // 验证输入长度 + if (input == null || input.length() != 8) { + throw new IllegalArgumentException("输入必须是8位字符串"); + } + for (int i = 0; i < 8; i += 2) { + int decimalPart = hexToDecimal(input.substring(i, i + 2)); + if (i > 0) result.append('.'); // 添加分隔符 + result.append(decimalPart); + } + } catch (Exception e) { + e.printStackTrace(); + } + return result.toString(); + } +} diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..1bd8324 --- /dev/null +++ b/src/main/resources/application-prod.properties @@ -0,0 +1,6 @@ +spring.rabbitmq.host=182.92.218.150 +spring.rabbitmq.username=topsail +spring.rabbitmq.password=topsail +#spring.datasource.url=jdbc:mysql://localhost:3306/iot?useSSL=false&useUnicode=true&characterEncoding=utf-8 +#spring.datasource.username=topsail +#spring.datasource.password=topsail2020 \ No newline at end of file diff --git a/src/main/resources/application-rds.properties b/src/main/resources/application-rds.properties new file mode 100644 index 0000000..82f7ad7 --- /dev/null +++ b/src/main/resources/application-rds.properties @@ -0,0 +1,11 @@ +#spring.rabbitmq.host=182.92.218.150 +spring.rabbitmq.host=182.92.218.150 +spring.rabbitmq.username=topsail +spring.rabbitmq.password=topsail + +spring.datasource.url=jdbc:mysql://rm-2ze77qng1ddlfur9g4o.mysql.rds.aliyuncs.com/iot?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai +spring.datasource.username=topsail +spring.datasource.password=Topsail2020 +#spring.datasource.url=jdbc:mysql://localhost:3306/iot?useSSL=false&useUnicode=true&characterEncoding=utf-8 +#spring.datasource.username=topsail +#spring.datasource.password=topsail2020 diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties new file mode 100644 index 0000000..7cf8979 --- /dev/null +++ b/src/main/resources/application-test.properties @@ -0,0 +1,6 @@ +spring.rabbitmq.host=47.97.117.253 +#spring.rabbitmq.username=topsail +#spring.rabbitmq.password=top +#spring.datasource.url=jdbc:mysql://localhost:3306/iot?useSSL=false&useUnicode=true&characterEncoding=utf-8 +#spring.datasource.username=topsail +#spring.datasource.password=topsail2020 \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..cf86bb6 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,52 @@ + +spring.rabbitmq.host=182.92.218.150 +#spring.rabbitmq.host=localhost +spring.rabbitmq.username=topsail +spring.rabbitmq.password=topsail +spring.rabbitmq.virtualHost=/ +spring.rabbitmq.listener.simple.acknowledge-mode=manual +spring.rabbitmq.listener.simple.prefetch=100 +spring.rabbitmq.listener.simple.concurrency=5 +spring.rabbitmq.listener.simple.max-concurrency=10 + + +# RabbitMQ Management API 配置(用于获取队列列表) +rabbitmq.management.url=http://182.92.218.150:15672 +rabbitmq.management.username=topsail +rabbitmq.management.password=topsail +rabbitmq.management.vhost=/ + +spring.datasource.url=jdbc:mysql://47.98.32.177:3306/iot?useSSL=false&useUnicode=true&characterEncoding=utf-8 +spring.datasource.username=yunmei +spring.datasource.password=yunmei1234 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +# 启用 MyBatis 日志输出 +#mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl +mybatis.type-aliases-package=com.topsail.scheduletask.pojo +mybatis.mapper-locations=classpath:com/topsail/scheduletask/mapper/*.xml +compute.schedule=0 +offline.gap=120 + +spring.profiles.active=rds + +#spring.influx.url=http://47.97.117.253:9999 +#spring.influx.user=topsail +#spring.influx.password=topsail +#spring.influx.database=iot +### mial config ### +spring.mail.host=smtp.ym.163.com +spring.mail.username=topsail_mail@topsail-tech.com +spring.mail.password=topsail2020# +spring.mail.protocol=smtp +spring.mail.test-connection=false +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.auth.starttls.enable=true +spring.mail.properties.mail.smtp.auth.starttls.required=true + +# ssl 配置 (非ssl发送一般是25端口,linux服务器一般都是禁用的,所以要切换465,免费企业邮是994) +spring.mail.port=994 +spring.mail.default-encoding=UTF-8 +spring.mail.properties.mail.smtp.ssl.enable=true +spring.mail.properties.mail.smtp.socketFactory.port=994 +spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory +mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file diff --git a/src/main/resources/com/topsail/scheduletask/mapper/InformLogMapper.xml b/src/main/resources/com/topsail/scheduletask/mapper/InformLogMapper.xml new file mode 100644 index 0000000..0cb3359 --- /dev/null +++ b/src/main/resources/com/topsail/scheduletask/mapper/InformLogMapper.xml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + il.id, + + il.inform_type, + + il.inform_address, + + il.inform_data, + + il.state, + + il.result_msg, + + il.send_scenarios, + + il.create_time + + + + + insert into inform_log + + inform_type, + inform_address, + inform_data, + state, + result_msg, + send_scenarios, + create_time + + + #{informLog.informType,jdbcType=VARCHAR}, + #{informLog.informAddress,jdbcType=VARCHAR}, + #{informLog.informData,jdbcType=VARCHAR}, + #{informLog.state,jdbcType=INTEGER}, + #{informLog.resultMsg,jdbcType=VARCHAR}, + #{informLog.sendScenarios,jdbcType=VARCHAR}, + #{informLog.createTime,jdbcType=TIMESTAMP} + + + + + + + + update inform_log + + + inform_type=#{informType,jdbcType=VARCHAR}, + + + inform_address=#{informAddress,jdbcType=VARCHAR}, + + + inform_data=#{informData,jdbcType=VARCHAR}, + + + state=#{state,jdbcType=INTEGER}, + + + result_msg=#{resultMsg,jdbcType=VARCHAR}, + + + send_scenarios=#{sendScenarios,jdbcType=VARCHAR}, + + + create_time=#{createTime,jdbcType=TIMESTAMP}, + + + where id = #{id} + + + + + + + delete from inform_log + where id = #{id} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/generatorConfig.xml b/src/main/resources/generatorConfig.xml new file mode 100644 index 0000000..4761f63 --- /dev/null +++ b/src/main/resources/generatorConfig.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file