summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhyx <[email protected]>2021-07-09 17:01:27 +0800
committerhyx <[email protected]>2021-07-09 17:01:27 +0800
commite7253290630b32c1ae14cbb36ff7cd0f48c62561 (patch)
treec0d3a265a5988772fe5023aa3e5b068b7b1d541b
parent2db96629a76d780fcaff16045255fd5f4d100e76 (diff)
nz-talon首次提交
-rw-r--r--.classpath32
-rw-r--r--.gitignore1
-rw-r--r--.project23
-rw-r--r--mvnw310
-rw-r--r--mvnw.cmd182
-rw-r--r--pom.xml132
-rw-r--r--src/main/java/net/geedge/confagent/ConfagentApplication.java13
-rw-r--r--src/main/java/net/geedge/confagent/annotation/UnCheckToken.java9
-rw-r--r--src/main/java/net/geedge/confagent/config/ConfagentConfiguration.java39
-rw-r--r--src/main/java/net/geedge/confagent/controller/AuthController.java101
-rw-r--r--src/main/java/net/geedge/confagent/controller/BaseController.java45
-rw-r--r--src/main/java/net/geedge/confagent/controller/HealthyController.java102
-rw-r--r--src/main/java/net/geedge/confagent/controller/PromtailController.java138
-rw-r--r--src/main/java/net/geedge/confagent/entity/AuthEntity.java9
-rw-r--r--src/main/java/net/geedge/confagent/interceptor/TokenInterceptor.java66
-rw-r--r--src/main/java/net/geedge/confagent/util/ConfagentUtil.java138
-rw-r--r--src/main/java/net/geedge/confagent/util/IdUtil.java10
-rw-r--r--src/main/java/net/geedge/confagent/util/IoUtil.java17
-rw-r--r--src/main/java/net/geedge/confagent/util/JSONUtil.java907
-rw-r--r--src/main/java/net/geedge/confagent/util/R.java66
-rw-r--r--src/main/java/net/geedge/confagent/util/RCode.java33
-rw-r--r--src/main/java/net/geedge/confagent/util/Tool.java1106
-rw-r--r--src/main/java/net/geedge/confagent/util/YamlUtil.java112
-rw-r--r--src/main/resources/application-dev.yml10
-rw-r--r--src/main/resources/application-prod.yml8
-rw-r--r--src/main/resources/application.yml19
-rw-r--r--src/main/resources/config/auth.yml3
-rw-r--r--src/main/resources/config/promtail.version1
-rw-r--r--src/main/resources/config/token.auth1
-rw-r--r--src/main/resources/logback-spring.xml68
-rw-r--r--src/test/java/net/geedge/confagent/ConfagentApplicationTests.java13
31 files changed, 3714 insertions, 0 deletions
diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..1c983a1
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ <attribute name="test" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/.project b/.project
new file mode 100644
index 0000000..835f88c
--- /dev/null
+++ b/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>nz-talon</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
diff --git a/mvnw b/mvnw
new file mode 100644
index 0000000..a16b543
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..c8d4337
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ef89d65
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>2.4.4</version>
+ <relativePath /> <!-- lookup parent from repository -->
+ </parent>
+ <groupId>net.geedge</groupId>
+ <artifactId>nz-talon</artifactId>
+ <version>2.0</version>
+ <name>nz-talon</name>
+ <description>nezha promtail config sync talon</description>
+ <properties>
+ <java.version>1.8</java.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>cn.hutool</groupId>
+ <artifactId>hutool-all</artifactId>
+ <version>5.5.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ <version>1.2.45</version>
+ </dependency>
+ <!-- 添加 XJar 依赖 -->
+<!-- <dependency>-->
+<!-- <groupId>com.github.core-lib</groupId>-->
+<!-- <artifactId>xjar</artifactId>-->
+<!-- <version>4.0.1</version>-->
+<!-- &lt;!&ndash; <scope>test</scope> &ndash;&gt;-->
+<!-- </dependency>-->
+ </dependencies>
+
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ </exclude>
+ </excludes>
+ </configuration>
+
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <!-- 配置私服地址 -->
+ <repository>
+ <id>nexus</id>
+ <name>Team Nexus Repository</name>
+ <url>http://192.168.40.125:8099/content/groups/public/</url>
+ </repository>
+ <repository>
+ <id>public</id>
+ <name>aliyun nexus</name>
+ <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </repository>
+
+ <!--opennum仓库-->
+ <repository>
+ <id>opennms</id>
+ <name>opennms</name>
+ <url>https://repo.opennms.org/maven2/</url>
+ </repository>
+
+ <!-- 设置 jitpack.io 仓库 -->
+ <repository>
+ <id>jitpack.io</id>
+ <url>https://jitpack.io</url>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>nexus</id>
+ <name>Team Nexus Repository</name>
+ <url>http://192.168.40.125:8099/content/groups/public/</url>
+ </pluginRepository>
+ <pluginRepository>
+ <id>public</id>
+ <name>aliyun nexus</name>
+ <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+
+ <!-- 设置 jitpack.io 插件仓库 -->
+ <pluginRepository>
+ <id>jitpack.io</id>
+ <url>https://jitpack.io</url>
+ </pluginRepository>
+ </pluginRepositories>
+</project>
diff --git a/src/main/java/net/geedge/confagent/ConfagentApplication.java b/src/main/java/net/geedge/confagent/ConfagentApplication.java
new file mode 100644
index 0000000..18887c5
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/ConfagentApplication.java
@@ -0,0 +1,13 @@
+package net.geedge.confagent;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ConfagentApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConfagentApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/annotation/UnCheckToken.java b/src/main/java/net/geedge/confagent/annotation/UnCheckToken.java
new file mode 100644
index 0000000..20af5f7
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/annotation/UnCheckToken.java
@@ -0,0 +1,9 @@
+package net.geedge.confagent.annotation;
+
+import java.lang.annotation.*;
+
+@Target( {ElementType.METHOD,ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface UnCheckToken {
+}
diff --git a/src/main/java/net/geedge/confagent/config/ConfagentConfiguration.java b/src/main/java/net/geedge/confagent/config/ConfagentConfiguration.java
new file mode 100644
index 0000000..4406529
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/config/ConfagentConfiguration.java
@@ -0,0 +1,39 @@
+package net.geedge.confagent.config;
+
+import net.geedge.confagent.interceptor.TokenInterceptor;
+import org.apache.catalina.connector.Connector;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class ConfagentConfiguration implements WebMvcConfigurer {
+
+ @Autowired
+ private TokenInterceptor tokenInterceptor;
+
+ @Bean(name={"tomcatServletWebServerFactory"})
+ public ConfigurableServletWebServerFactory webServerFactory() {
+ TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
+ factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
+ @Override
+ public void customize(Connector connector) {
+ connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");
+
+ connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
+ }
+ });
+
+ return factory;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
+ }
+}
diff --git a/src/main/java/net/geedge/confagent/controller/AuthController.java b/src/main/java/net/geedge/confagent/controller/AuthController.java
new file mode 100644
index 0000000..237adea
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/controller/AuthController.java
@@ -0,0 +1,101 @@
+package net.geedge.confagent.controller;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hutool.log.Log;
+import net.geedge.confagent.annotation.UnCheckToken;
+import net.geedge.confagent.entity.AuthEntity;
+import net.geedge.confagent.util.R;
+import net.geedge.confagent.util.RCode;
+import net.geedge.confagent.util.Tool;
+
+@RestController
+@RequestMapping(value={"/auth"})
+public class AuthController extends BaseController{
+ private final static Log log = Log.get();
+
+ @Value("${confagent.authFile:auth.yml}")
+ private String authFile;
+
+ private static String rootPath = Tool.WebPathUtil.getRootPath();
+ /**
+ * @Description 每次请求auth接口重新生成 token并记录到文件
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ @RequestMapping
+ @UnCheckToken
+ public R auth(AuthEntity auth){
+
+ if(Tool.StrUtil.isBlank(auth.getName())||Tool.StrUtil.isBlank(auth.getPin())){
+ return R.error(RCode.AUTH_NAME_PIN_ISNULL);
+ }
+
+ File af = Tool.FileUtil.file(rootPath, authFile);
+ log.debug("auth file path : {}" ,af.getAbsolutePath());
+ Properties properties = Tool.YamlUtil.yamlToProperties(af.getAbsolutePath());
+
+ String name = properties.getProperty("auth.name","nezha");
+ String pin = properties.getProperty("auth.pin","nezha");
+
+ if(Tool.StrUtil.equals(name,auth.getName())&& Tool.StrUtil.equals(pin,auth.getPin())){
+ String token = Tool.IdUtil.fastShortUUID();
+ log.debug("write token {} to {}",token,af.getAbsolutePath());
+ writeToken(token);
+ Map<String,String> map = new HashMap<>();
+ map.put("token", token);
+ return R.ok(map);
+ }
+
+ return R.error(RCode.AUTH_NAME_PIN_INVALID);
+ }
+
+ /**
+ * @Description 验证当前token是否和文件记录一致,一致后重新生成则更新文件并返回最新token
+ * @Author rui
+ * @Date 2021/3/24
+ */
+ @GetMapping("/refresh")
+ public R refresh(){
+ String t = Tool.IdUtil.fastShortUUID();
+ writeToken(t);
+ Map<String,String> map = new HashMap<>();
+ map.put("token", t);
+ return R.ok(map);
+ }
+
+ /**
+ * @Description 注销当前 token
+ * @Author rui
+ * @Date 2021/3/24
+ */
+ @GetMapping("logout")
+ public R logout(){
+ File tf = Tool.FileUtil.file(rootPath, tokenFile);
+ log.debug("token file path : {}" ,tf.getAbsolutePath());
+
+ if(Tool.FileUtil.exist(tf)){
+ Tool.FileUtil.del(tf);
+ }
+ if(Tool.FileUtil.exist(promtailConfPath)){
+ Tool.YamlUtil.writeAsMap(null,promtailConfPath);
+ }
+
+ return R.ok();
+ }
+
+ private void writeToken(String token){
+ File tf = Tool.FileUtil.file(rootPath, tokenFile);
+ log.debug("token file path : {}" ,tf.getAbsolutePath());
+ Tool.FileUtil.writeUtf8String(token, tf);
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/controller/BaseController.java b/src/main/java/net/geedge/confagent/controller/BaseController.java
new file mode 100644
index 0000000..6d19f2f
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/controller/BaseController.java
@@ -0,0 +1,45 @@
+package net.geedge.confagent.controller;
+
+import cn.hutool.log.Log;
+import org.springframework.beans.factory.annotation.Value;
+
+public abstract class BaseController {
+ private Log log = Log.get();
+
+ protected static final String PROMTAIL_LISTEN_SERVER = "server";
+ protected static final String PROMTAIL_LISTEN_PORT = "http_listen_port";
+
+ @Value("${confagent.tokenFile:config/token.auth}")
+ protected String tokenFile; //token文件位置
+
+ @Value("${confagent.promtail.cmdLine}")
+ protected String promtailCmdLinePath; // promtail config.conf 启动参数文件存放位置
+
+ @Value("${confagent.promtail.defaultIP:127.0.0.1}")
+ protected String defaultPromtailIP; //promtail 默认监听ip
+
+ protected static final int DEFAULT_PROMTAIL_PORT=9080; //prometheus 默认监听端口
+
+ @Value("${confagent.promtail.config}")
+ protected String promtailConfPath;
+
+ /**
+ * 调用 /-/reload 接口,热加载 server 配置文件,
+ *
+ * @param cmdLinePath
+ * @param serverListenAddr
+ * @param defaultServerPort
+ * @param defaultServerIP
+ * @return
+ */
+// public boolean reloadServerConfiguration(String cmdLinePath, String serverListenAddr, int defaultServerPort, String defaultServerIP) {
+// UrlBuilder serverReloadUrl = new UrlBuilder();
+// int serverPort = ConfagentUtil.getConfFilePort(cmdLinePath, serverListenAddr, defaultServerPort);
+// serverReloadUrl.setScheme("http").setHost(defaultServerIP).setPort(serverPort).addPath("/-/reload");
+//
+// String url = serverReloadUrl.toString();
+// HttpRequest post = Tool.HttpUtil.createPost(url);
+// HttpResponse response = post.execute();
+// return 200 == response.getStatus();
+// }
+}
diff --git a/src/main/java/net/geedge/confagent/controller/HealthyController.java b/src/main/java/net/geedge/confagent/controller/HealthyController.java
new file mode 100644
index 0000000..a8e378a
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/controller/HealthyController.java
@@ -0,0 +1,102 @@
+package net.geedge.confagent.controller;
+
+import cn.hutool.core.net.url.UrlBuilder;
+import cn.hutool.http.HttpConnection;
+import cn.hutool.log.Log;
+import net.geedge.confagent.annotation.UnCheckToken;
+import net.geedge.confagent.util.ConfagentUtil;
+import net.geedge.confagent.util.R;
+import net.geedge.confagent.util.RCode;
+import net.geedge.confagent.util.Tool;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("healthy")
+public class HealthyController extends BaseController{
+
+ @Autowired
+ private ConfagentUtil confagentUtil;
+ private final static Log log = Log.get();
+
+ private UrlBuilder promtailHealthy;
+
+ @GetMapping
+ @UnCheckToken
+ public R checkHealthy(@RequestHeader(value="Authorization",required = false) String token) {
+
+ Map<String,String> result = new HashMap<>();
+
+ buildHealthyURL(result);
+
+ if(Tool.StrUtil.isNotBlank(token)){
+ if(confagentUtil.checkToken(token).getCode() == RCode.SUCCESS.getCode()){
+ result.put("auth","TRUE");
+ }else{
+ result.put("auth","FALSE");
+ }
+ }
+ return R.ok(result);
+ }
+
+ public void buildHealthyURL(Map<String,String> result){
+
+ Map<String,Object> promtailConf = Tool.YamlUtil.readAsMap(promtailConfPath);
+
+ if(promtailConf==null) {
+ result.put("promtail","DOWN");
+ return ;
+ }
+
+ Map<String,Integer> promtailPortMap = (Map<String,Integer>)promtailConf.get(PROMTAIL_LISTEN_SERVER);
+
+ if(promtailPortMap==null) {
+ result.put("promtail","DOWN");
+ return ;
+ }
+
+ Integer promtailPort = promtailPortMap.get(PROMTAIL_LISTEN_PORT);
+ if(promtailPort==null) {
+ promtailPort = DEFAULT_PROMTAIL_PORT;
+ }
+ promtailHealthy = new UrlBuilder();
+ promtailHealthy.setScheme("http").setHost(defaultPromtailIP).setPort(promtailPort).addPath("/ready");
+
+ result.put("promtail",checkState(promtailHealthy.toString()));
+ }
+
+
+ private String checkState(String url){
+ HttpURLConnection conn = null;
+ try{
+ conn = HttpConnection.create(url,null).getHttpURLConnection();
+ log.debug("connect to {}",url);
+ conn.connect();
+ int responseCode = conn.getResponseCode();
+
+ if(200 == responseCode){
+ return "UP";
+ }
+
+ return "DOWN";
+ }catch (IOException e){
+ log.error("failed connect ",e);
+ return "DOWN";
+ }finally {
+ if (conn != null) {
+ conn.disconnect();
+ conn = null;
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/controller/PromtailController.java b/src/main/java/net/geedge/confagent/controller/PromtailController.java
new file mode 100644
index 0000000..5e5b44c
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/controller/PromtailController.java
@@ -0,0 +1,138 @@
+package net.geedge.confagent.controller;
+
+import cn.hutool.log.Log;
+import net.geedge.confagent.util.ConfagentUtil;
+import net.geedge.confagent.util.R;
+import net.geedge.confagent.util.RCode;
+import net.geedge.confagent.util.Tool;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.File;
+import java.util.*;
+
+@RestController
+@RequestMapping("/promtail")
+public class PromtailController extends BaseController{
+ private final static Log log = Log.get();
+
+ @Autowired
+ private ConfagentUtil confagentUtil;
+
+ @Value("${confagent.promtail.query.auth:true}")
+ private Boolean queryAuth;
+
+ private final String[] QUERY_API_SUFFIX = {"query","query_range","series","labels","values"};
+
+ @Value("${confagent.promtail.restart:systemctl restart promtail}")
+ private String restartCmd;
+
+ @Value("${confagent.versionFile:promtail.version}")
+ private String versionFile;
+
+ private static String rootPath = Tool.WebPathUtil.getRootPath();
+
+ /**
+ * @Description 获取promtail相关配置
+ * @Author rui
+ * @Date 2021/3/24
+ */
+ @GetMapping("/config")
+ public R queryConfig(){
+ Map<String,String> cmdLine = ConfagentUtil.loadServiceConfigFile(promtailCmdLinePath);
+ Map<String,Object> promtailConf = Tool.YamlUtil.readAsMap(promtailConfPath);
+ String version = confagentUtil.readVersion();
+
+ Map<String,Object> result = new LinkedHashMap<>();
+
+ result.put("version",version);
+ result.put("cmdline",cmdLine);
+ result.put("config",promtailConf);
+
+ return R.ok(result);
+ }
+
+ /**
+ * @Description 写入promtail配置文件
+ * @Author rui
+ * @Date 2021/3/25
+ */
+ @PostMapping("/config")
+ public R overwriteConfig( @RequestBody Map<String,Object> configs){
+
+ Object version = configs.get("version");
+ File tf = Tool.FileUtil.file(rootPath, versionFile);
+ log.debug("version file path : {}" ,tf.getAbsolutePath());
+ if(version==null){
+ return R.error(RCode.PROMTAIL_CONFIG_VERSION_ISNULL);
+ }else {
+ Tool.FileUtil.writeUtf8String(version.toString(), tf);
+ }
+
+ Map<String,String> cmdLine =(Map<String,String>) configs.get("cmdline");
+ Map<String,Object> promtailConf =(Map<String,Object>) configs.get("config");
+
+// boolean reload = false;
+// boolean restart = false;
+ if(!Tool.MapUtil.isEmpty(cmdLine)){
+ log.info("write promtail cmdLine conf:{}", Tool.JSONUtil.toJsonStr(cmdLine));
+ writeServiceConfigFile(cmdLine,promtailCmdLinePath);
+// restart = true;
+ }
+ if(!Tool.MapUtil.isEmpty(promtailConf)){
+ log.info("write promtail conf:{}", Tool.JSONUtil.toJsonStr(promtailConf));
+ Tool.YamlUtil.writeAsMap(promtailConf,promtailConfPath);
+// reload = true;
+ }
+
+ return R.ok();
+ }
+
+ /**
+ * @Description 获取promtail相关配置版本
+ * @Author rui
+ * @Date 2021/3/24
+ */
+ @GetMapping("/config/version")
+ public R queryVersion(){
+ Map<String,Object> result = new HashMap<>();
+ String version = confagentUtil.readVersion();
+ result.put("version",version);
+ return R.ok(result);
+ }
+
+ /**
+ * @Description 写 promtail config.conf 启动参数配置文件
+ * @Author rui
+ * @Date 2021/3/25
+ */
+ private void writeServiceConfigFile(Map<String,String> conf,String path){
+ StringBuffer sb = new StringBuffer();
+ sb.append("OPTION=\"");
+ for (Map.Entry<String,String> entry:conf.entrySet()){
+ String key = entry.getKey();
+ String value = entry.getValue();
+ sb.append("--"+key+"=");
+ sb.append("'"+value+"' ");
+ }
+ sb.append("\"");
+
+ Tool.FileUtil.writeUtf8String(sb.toString(),path);
+
+ }
+
+// private boolean reloadPromtail(){
+//
+// UrlBuilder promtailReload = new UrlBuilder();
+// int promtailPort = ConfagentUtil.getConfFilePort(promtailCmdLinePath, PROMTAIL_LISTEN_ADDR, DEFAULT_PROMTAIL_PORT);
+// promtailReload.setScheme("http").setHost(defaultPromtailIP).setPort(promtailPort).addPath("/-/reload");
+//
+// String url = promtailReload.toString();
+// HttpRequest post = Tool.HttpUtil.createPost(url);
+// HttpResponse response = post.execute();
+// return 200 == response.getStatus();
+// }
+
+}
diff --git a/src/main/java/net/geedge/confagent/entity/AuthEntity.java b/src/main/java/net/geedge/confagent/entity/AuthEntity.java
new file mode 100644
index 0000000..2d3cc42
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/entity/AuthEntity.java
@@ -0,0 +1,9 @@
+package net.geedge.confagent.entity;
+
+import lombok.Data;
+
+@Data
+public class AuthEntity {
+ private String name;
+ private String pin;
+}
diff --git a/src/main/java/net/geedge/confagent/interceptor/TokenInterceptor.java b/src/main/java/net/geedge/confagent/interceptor/TokenInterceptor.java
new file mode 100644
index 0000000..c2965b2
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/interceptor/TokenInterceptor.java
@@ -0,0 +1,66 @@
+package net.geedge.confagent.interceptor;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import cn.hutool.log.Log;
+import net.geedge.confagent.annotation.UnCheckToken;
+import net.geedge.confagent.util.ConfagentUtil;
+import net.geedge.confagent.util.R;
+import net.geedge.confagent.util.RCode;
+import net.geedge.confagent.util.Tool;
+
+@Component
+public class TokenInterceptor implements HandlerInterceptor {
+ private final static Log log = Log.get();
+ @Autowired
+ private ConfagentUtil confagentUtil;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+
+ if(handler instanceof HandlerMethod){
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
+ Boolean hasAnnotation = Tool.AnnotationUtil.hasAnnotation(handlerMethod.getMethod(), UnCheckToken.class);
+ if(hasAnnotation){
+ return true;
+ }
+ hasAnnotation = Tool.AnnotationUtil.hasAnnotation(handlerMethod.getBeanType(),UnCheckToken.class);
+ if(hasAnnotation){
+ return true;
+ }
+ }
+
+ String token = request.getHeader("Authorization");
+ R r = confagentUtil.checkToken(token);
+ if(r.getCode() == RCode.SUCCESS.getCode()){
+ return true;
+ }
+ writeResult(response,r);
+ return false;
+ }
+
+ private void writeResult(HttpServletResponse response,Object o){
+ PrintWriter writer=null;
+ try{
+ writer = response.getWriter();
+ writer.print(Tool.JSONUtil.parse(o));
+ writer.flush();
+ }catch (IOException e){
+ log.error("un-know error",e);
+ }finally {
+ Tool.IoUtil.close(writer);
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/net/geedge/confagent/util/ConfagentUtil.java b/src/main/java/net/geedge/confagent/util/ConfagentUtil.java
new file mode 100644
index 0000000..96a2a8f
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/ConfagentUtil.java
@@ -0,0 +1,138 @@
+package net.geedge.confagent.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.log.Log;
+
+@Configuration
+@Order(value = 1)
+public class ConfagentUtil {
+ private final static Log log = Log.get();
+
+ @Value("${confagent.tokenFile:config/token.auth}")
+ protected String tokenFile; //token文件位置
+ @Value("${confagent.versionFile:promtail.version}")
+ private String versionFile;
+ private static String rootPath = Tool.WebPathUtil.getRootPath();
+ /**
+ * @Description 读取token文件中的token
+ * @Author rui
+ * @Date 2021/3/25
+ */
+ public String readToken() throws IORuntimeException {
+ File tf = Tool.FileUtil.file(rootPath, tokenFile);
+ log.info("token file path : {}" ,tf.getAbsolutePath());
+ String token = Tool.FileUtil.readString(tf, Tool.CharsetUtil.UTF_8);
+ return token;
+ }
+
+ /**
+ * @Description 读取version
+ * @Author rui
+ * @Date 2021/3/25
+ */
+ public String readVersion() throws IORuntimeException {
+ String version = "1";
+ File tf = Tool.FileUtil.file(rootPath, versionFile);
+ if(tf!=null && tf.exists()) {
+ log.info("version file path : {}" ,tf.getAbsolutePath());
+ version = Tool.FileUtil.readString(tf, Tool.CharsetUtil.UTF_8);
+ }
+ return version;
+ }
+
+ /**
+ * @Description 检查token 是否和文件中的一致
+ * @Author rui
+ * @Date 2021/3/25
+ */
+ public R checkToken(String token){
+ if(Tool.StrUtil.isBlank(token)){
+ return R.error(RCode.AUTH_TOKEN_ISNULL);
+ }
+ try{
+ String readToken = this.readToken();
+ if(Tool.StrUtil.equals(readToken,token)){
+ return R.ok();
+ }
+ return R.error(RCode.AUTH_TOKEN_INVALID);
+ }catch (IORuntimeException e){
+ log.error("read token file failed",e);
+ return R.error(RCode.AUTH_READ_TOKEN_FAILD);
+ }
+ }
+
+ /**
+ * @Description 加载service EnvironmentFile中的内容,并整理为map
+ * @Author rui
+ * @Date 2021/3/24
+ */
+ public static Map<String,String> loadServiceConfigFile(String path){
+ File file = Tool.FileUtil.file(path);
+ if(!Tool.FileUtil.exist(file)){
+ return null;
+ }
+
+ String readLine = Tool.FileUtil.readUtf8String(file);
+
+ //匹配有参类型 --[\w\.-]+?\s 可匹配无参类型
+ Pattern pattern = Pattern.compile("--([\\w\\.-]+?)='?(.+?)'?\\s+?");
+ Matcher matcher = pattern.matcher(readLine);
+
+ Map<String, String> result = new HashMap<>();
+ while(matcher.find()){
+ result.put(matcher.group(1).trim(),matcher.group(2).trim());
+ }
+ return result;
+ }
+
+
+
+ /**
+ * @Description 获取配置在config.conf启动参数文件中的端口
+ * @Author rui
+ * @Date 2021/3/25
+ */
+ public static Integer getConfFilePort(String path,String key,Integer defaultValue){
+ Map<String, String> configs = loadServiceConfigFile(path);
+
+ if(configs!=null) {
+ String address = configs.get(key);
+
+ String[] split = address.split(":");
+
+ return Tool.StrUtil.isNotBlank(split[1])? Integer.parseInt(split[1]):defaultValue;
+ }else {
+ return defaultValue;
+ }
+
+ }
+
+ public static void writeResponse(HttpServletResponse response, Object o) {
+ OutputStream outputStream = null;
+
+ try {
+ outputStream = response.getOutputStream();
+
+ Tool.IoUtil.writeUtf8 (outputStream,true, Tool.JSONUtil.parseObj(o).toString());
+ outputStream.flush();
+ }catch (IOException e){
+ log.error("write response failed :",e);
+ }finally {
+ Tool.IoUtil.close(outputStream);
+ }
+ }
+}
diff --git a/src/main/java/net/geedge/confagent/util/IdUtil.java b/src/main/java/net/geedge/confagent/util/IdUtil.java
new file mode 100644
index 0000000..deb7658
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/IdUtil.java
@@ -0,0 +1,10 @@
+package net.geedge.confagent.util;
+
+public class IdUtil extends cn.hutool.core.util.IdUtil {
+
+ public static String fastShortUUID(){
+ String uuid = fastSimpleUUID();
+ return uuid.substring(0,8);
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/util/IoUtil.java b/src/main/java/net/geedge/confagent/util/IoUtil.java
new file mode 100644
index 0000000..6cfc548
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/IoUtil.java
@@ -0,0 +1,17 @@
+package net.geedge.confagent.util;
+
+import java.io.Closeable;
+
+public class IoUtil extends cn.hutool.core.io.IoUtil {
+
+
+ public static void close(final Closeable ... closeables){
+ if (closeables == null) {
+ return;
+ }
+ for (final Closeable closeable:closeables){
+ close(closeable);
+ }
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/util/JSONUtil.java b/src/main/java/net/geedge/confagent/util/JSONUtil.java
new file mode 100644
index 0000000..07081b2
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/JSONUtil.java
@@ -0,0 +1,907 @@
+package net.geedge.confagent.util;
+
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.io.file.FileReader;
+import cn.hutool.core.lang.TypeReference;
+import cn.hutool.core.util.*;
+import cn.hutool.json.*;
+import cn.hutool.json.serialize.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.time.temporal.TemporalAccessor;
+import java.util.*;
+
+/**
+ * JSON工具类
+ *
+ * @author Looly
+ */
+public class JSONUtil {
+
+ // -------------------------------------------------------------------- Pause start
+
+ /**
+ * 创建JSONObject
+ *
+ * @return JSONObject
+ */
+ public static JSONObject createObj() {
+ return new JSONObject();
+ }
+
+ /**
+ * 创建JSONObject
+ *
+ * @param config JSON配置
+ * @return JSONObject
+ * @since 5.2.5
+ */
+ public static JSONObject createObj(JSONConfig config) {
+ return new JSONObject(config);
+ }
+
+ /**
+ * 创建 JSONArray
+ *
+ * @return JSONArray
+ */
+ public static JSONArray createArray() {
+ return new JSONArray();
+ }
+
+ /**
+ * 创建 JSONArray
+ *
+ * @param config JSON配置
+ * @return JSONArray
+ * @since 5.2.5
+ */
+ public static JSONArray createArray(JSONConfig config) {
+ return new JSONArray(config);
+ }
+
+ /**
+ * JSON字符串转JSONObject对象
+ *
+ * @param jsonStr JSON字符串
+ * @return JSONObject
+ */
+ public static JSONObject parseObj(String jsonStr) {
+ return new JSONObject(jsonStr);
+ }
+
+ /**
+ * JSON字符串转JSONObject对象<br>
+ * 此方法会忽略空值,但是对JSON字符串不影响
+ *
+ * @param obj Bean对象或者Map
+ * @return JSONObject
+ */
+ public static JSONObject parseObj(Object obj) {
+ return new JSONObject(obj);
+ }
+
+ /**
+ * JSON字符串转JSONObject对象<br>
+ * 此方法会忽略空值,但是对JSON字符串不影响
+ *
+ * @param obj Bean对象或者Map
+ * @param config JSON配置
+ * @return JSONObject
+ * @since 5.3.1
+ */
+ public static JSONObject parseObj(Object obj, JSONConfig config) {
+ return new JSONObject(obj, config);
+ }
+
+ /**
+ * JSON字符串转JSONObject对象
+ *
+ * @param obj Bean对象或者Map
+ * @param ignoreNullValue 是否忽略空值,如果source为JSON字符串,不忽略空值
+ * @return JSONObject
+ * @since 3.0.9
+ */
+ public static JSONObject parseObj(Object obj, boolean ignoreNullValue) {
+ return new JSONObject(obj, ignoreNullValue);
+ }
+
+ /**
+ * JSON字符串转JSONObject对象
+ *
+ * @param obj Bean对象或者Map
+ * @param ignoreNullValue 是否忽略空值,如果source为JSON字符串,不忽略空值
+ * @param isOrder 是否有序
+ * @return JSONObject
+ * @since 4.2.2
+ */
+ public static JSONObject parseObj(Object obj, boolean ignoreNullValue, boolean isOrder) {
+ return new JSONObject(obj, ignoreNullValue, isOrder);
+ }
+
+ /**
+ * JSON字符串转JSONArray
+ *
+ * @param jsonStr JSON字符串
+ * @return JSONArray
+ */
+ public static JSONArray parseArray(String jsonStr) {
+ return new JSONArray(jsonStr);
+ }
+
+ /**
+ * JSON字符串转JSONArray
+ *
+ * @param arrayOrCollection 数组或集合对象
+ * @return JSONArray
+ * @since 3.0.8
+ */
+ public static JSONArray parseArray(Object arrayOrCollection) {
+ return new JSONArray(arrayOrCollection);
+ }
+
+ /**
+ * JSON字符串转JSONArray
+ *
+ * @param arrayOrCollection 数组或集合对象
+ * @param config JSON配置
+ * @return JSONArray
+ * @since 5.3.1
+ */
+ public static JSONArray parseArray(Object arrayOrCollection, JSONConfig config) {
+ return new JSONArray(arrayOrCollection, config);
+ }
+
+ /**
+ * JSON字符串转JSONArray
+ *
+ * @param arrayOrCollection 数组或集合对象
+ * @param ignoreNullValue 是否忽略空值
+ * @return JSONArray
+ * @since 3.2.3
+ */
+ public static JSONArray parseArray(Object arrayOrCollection, boolean ignoreNullValue) {
+ return new JSONArray(arrayOrCollection, ignoreNullValue);
+ }
+
+ /**
+ * 转换对象为JSON<br>
+ * 支持的对象:<br>
+ * String: 转换为相应的对象<br>
+ * Array Collection:转换为JSONArray<br>
+ * Bean对象:转为JSONObject
+ *
+ * @param obj 对象
+ * @return JSON
+ */
+ public static JSON parse(Object obj) {
+ return parse(obj, JSONConfig.create());
+ }
+
+ /**
+ * 转换对象为JSON<br>
+ * 支持的对象:<br>
+ * String: 转换为相应的对象<br>
+ * Array、Iterable、Iterator:转换为JSONArray<br>
+ * Bean对象:转为JSONObject
+ *
+ * @param obj 对象
+ * @param config JSON配置
+ * @return JSON
+ * @since 5.3.1
+ */
+ public static JSON parse(Object obj, JSONConfig config) {
+ if (null == obj) {
+ return null;
+ }
+
+ JSON json;
+ if (obj instanceof JSON) {
+ json = (JSON) obj;
+ } else if (obj instanceof CharSequence) {
+ final String jsonStr = StrUtil.trim((CharSequence) obj);
+ json = StrUtil.startWith(jsonStr, '[') ? parseArray(jsonStr) : parseObj(jsonStr);
+ } else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表
+ json = new JSONArray(obj, config);
+ } else {// 对象
+ json = new JSONObject(obj, config);
+ }
+
+ return json;
+ }
+
+ /**
+ * XML字符串转为JSONObject
+ *
+ * @param xmlStr XML字符串
+ * @return JSONObject
+ */
+ public static JSONObject parseFromXml(String xmlStr) {
+ return XML.toJSONObject(xmlStr);
+ }
+
+ /**
+ * Map转化为JSONObject
+ *
+ * @param map {@link Map}
+ * @return JSONObjec
+ * @deprecated 请直接使用 {@link #parseObj(Object)}
+ */
+ @Deprecated
+ public static JSONObject parseFromMap(Map<?, ?> map) {
+ return new JSONObject(map);
+ }
+
+ /**
+ * ResourceBundle转化为JSONObject
+ *
+ * @param bundle ResourceBundle文件
+ * @return JSONObject
+ * @deprecated 请直接使用 {@link #parseObj(Object)}
+ */
+ @Deprecated
+ public static JSONObject parseFromResourceBundle(ResourceBundle bundle) {
+ return new JSONObject(bundle);
+ }
+ // -------------------------------------------------------------------- Pause end
+
+ // -------------------------------------------------------------------- Read start
+
+ /**
+ * 读取JSON
+ *
+ * @param file JSON文件
+ * @param charset 编码
+ * @return JSON(包括JSONObject和JSONArray)
+ * @throws IORuntimeException IO异常
+ */
+ public static JSON readJSON(File file, Charset charset) throws IORuntimeException {
+ return parse(FileReader.create(file, charset).readString());
+ }
+
+ /**
+ * 读取JSONObject
+ *
+ * @param file JSON文件
+ * @param charset 编码
+ * @return JSONObject
+ * @throws IORuntimeException IO异常
+ */
+ public static JSONObject readJSONObject(File file, Charset charset) throws IORuntimeException {
+ return parseObj(FileReader.create(file, charset).readString());
+ }
+
+ /**
+ * 读取JSONArray
+ *
+ * @param file JSON文件
+ * @param charset 编码
+ * @return JSONArray
+ * @throws IORuntimeException IO异常
+ */
+ public static JSONArray readJSONArray(File file, Charset charset) throws IORuntimeException {
+ return parseArray(FileReader.create(file, charset).readString());
+ }
+ // -------------------------------------------------------------------- Read end
+
+ // -------------------------------------------------------------------- toString start
+
+ /**
+ * 转为JSON字符串
+ *
+ * @param json JSON
+ * @param indentFactor 每一级别的缩进
+ * @return JSON字符串
+ */
+ public static String toJsonStr(JSON json, int indentFactor) {
+ if (null == json) {
+ return null;
+ }
+ return json.toJSONString(indentFactor);
+ }
+
+ /**
+ * 转为JSON字符串
+ *
+ * @param json JSON
+ * @return JSON字符串
+ */
+ public static String toJsonStr(JSON json) {
+ if (null == json) {
+ return null;
+ }
+ return json.toJSONString(0);
+ }
+
+ /**
+ * 转为JSON字符串,并写出到write
+ *
+ * @param json JSON
+ * @param writer Writer
+ * @since 5.3.3
+ */
+ public static void toJsonStr(JSON json, Writer writer) {
+ if (null != json) {
+ json.write(writer);
+ }
+ }
+
+ /**
+ * 转为JSON字符串
+ *
+ * @param json JSON
+ * @return JSON字符串
+ */
+ public static String toJsonPrettyStr(JSON json) {
+ if (null == json) {
+ return null;
+ }
+ return json.toJSONString(4);
+ }
+
+ /**
+ * 转换为JSON字符串
+ *
+ * @param obj 被转为JSON的对象
+ * @return JSON字符串
+ */
+ public static String toJsonStr(Object obj) {
+ if (null == obj) {
+ return null;
+ }
+ if (obj instanceof CharSequence) {
+ return StrUtil.str((CharSequence) obj);
+ }
+ return toJsonStr(parse(obj));
+ }
+
+ /**
+ * 转换为JSON字符串并写出到writer
+ *
+ * @param obj 被转为JSON的对象
+ * @param writer Writer
+ * @since 5.3.3
+ */
+ public static void toJsonStr(Object obj, Writer writer) {
+ if (null != obj) {
+ toJsonStr(parse(obj), writer);
+ }
+ }
+
+ /**
+ * 转换为格式化后的JSON字符串
+ *
+ * @param obj Bean对象
+ * @return JSON字符串
+ */
+ public static String toJsonPrettyStr(Object obj) {
+ return toJsonPrettyStr(parse(obj));
+ }
+
+ /**
+ * 转换为XML字符串
+ *
+ * @param json JSON
+ * @return XML字符串
+ */
+ public static String toXmlStr(JSON json) {
+ return XML.toXml(json);
+ }
+ // -------------------------------------------------------------------- toString end
+
+ // -------------------------------------------------------------------- toBean start
+
+ /**
+ * JSON字符串转为实体类对象,转换异常将被抛出
+ *
+ * @param <T> Bean类型
+ * @param jsonString JSON字符串
+ * @param beanClass 实体类对象
+ * @return 实体类对象
+ * @since 3.1.2
+ */
+ public static <T> T toBean(String jsonString, Class<T> beanClass) {
+ return toBean(parseObj(jsonString), beanClass);
+ }
+
+ /**
+ * 转为实体类对象,转换异常将被抛出
+ *
+ * @param <T> Bean类型
+ * @param json JSONObject
+ * @param beanClass 实体类对象
+ * @return 实体类对象
+ */
+ public static <T> T toBean(JSONObject json, Class<T> beanClass) {
+ return null == json ? null : json.toBean(beanClass);
+ }
+
+ /**
+ * JSON字符串转为实体类对象,转换异常将被抛出
+ *
+ * @param <T> Bean类型
+ * @param jsonString JSON字符串
+ * @param typeReference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型
+ * @param ignoreError 是否忽略错误
+ * @return 实体类对象
+ * @since 4.3.2
+ */
+ public static <T> T toBean(String jsonString, TypeReference<T> typeReference, boolean ignoreError) {
+ return toBean(jsonString, typeReference.getType(), ignoreError);
+ }
+
+ /**
+ * JSON字符串转为实体类对象,转换异常将被抛出
+ *
+ * @param <T> Bean类型
+ * @param jsonString JSON字符串
+ * @param beanType 实体类对象类型
+ * @param ignoreError 是否忽略错误
+ * @return 实体类对象
+ * @since 4.3.2
+ */
+ public static <T> T toBean(String jsonString, Type beanType, boolean ignoreError) {
+ return toBean(parse(jsonString), beanType, ignoreError);
+ }
+
+ /**
+ * 转为实体类对象
+ *
+ * @param <T> Bean类型
+ * @param json JSONObject
+ * @param typeReference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型
+ * @param ignoreError 是否忽略转换错误
+ * @return 实体类对象
+ * @since 4.6.2
+ */
+ public static <T> T toBean(JSON json, TypeReference<T> typeReference, boolean ignoreError) {
+ return toBean(json, typeReference.getType(), ignoreError);
+ }
+
+ /**
+ * 转为实体类对象
+ *
+ * @param <T> Bean类型
+ * @param json JSONObject
+ * @param beanType 实体类对象类型
+ * @param ignoreError 是否忽略转换错误
+ * @return 实体类对象
+ * @since 4.3.2
+ */
+ public static <T> T toBean(JSON json, Type beanType, boolean ignoreError) {
+ if (null == json) {
+ return null;
+ }
+ return json.toBean(beanType, ignoreError);
+ }
+ // -------------------------------------------------------------------- toBean end
+
+ /**
+ * 将JSONArray字符串转换为Bean的List,默认为ArrayList
+ *
+ * @param <T> Bean类型
+ * @param jsonArray JSONArray字符串
+ * @param elementType List中元素类型
+ * @return List
+ * @since 5.5.2
+ */
+ public static <T> List<T> toList(String jsonArray, Class<T> elementType) {
+ return toList(parseArray(jsonArray), elementType);
+ }
+
+ /**
+ * 将JSONArray转换为Bean的List,默认为ArrayList
+ *
+ * @param <T> Bean类型
+ * @param jsonArray {@link JSONArray}
+ * @param elementType List中元素类型
+ * @return List
+ * @since 4.0.7
+ */
+ public static <T> List<T> toList(JSONArray jsonArray, Class<T> elementType) {
+ return null == jsonArray ? null : jsonArray.toList(elementType);
+ }
+
+ /**
+ * 通过表达式获取JSON中嵌套的对象<br>
+ * <ol>
+ * <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
+ * <li>[]表达式,可以获取集合等对象中对应index的值</li>
+ * </ol>
+ * <p>
+ * 表达式栗子:
+ *
+ * <pre>
+ * persion
+ * persion.name
+ * persons[3]
+ * person.friends[5].name
+ * </pre>
+ *
+ * @param json {@link JSON}
+ * @param expression 表达式
+ * @return 对象
+ * @see JSON#getByPath(String)
+ */
+ public static Object getByPath(JSON json, String expression) {
+ return (null == json || StrUtil.isBlank(expression)) ? null : json.getByPath(expression);
+ }
+
+ /**
+ * 设置表达式指定位置(或filed对应)的值<br>
+ * 若表达式指向一个JSONArray则设置其坐标对应位置的值,若指向JSONObject则put对应key的值<br>
+ * 注意:如果为JSONArray,则设置值得下标不能大于已有JSONArray的长度<br>
+ * <ol>
+ * <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
+ * <li>[]表达式,可以获取集合等对象中对应index的值</li>
+ * </ol>
+ * <p>
+ * 表达式栗子:
+ *
+ * <pre>
+ * persion
+ * persion.name
+ * persons[3]
+ * person.friends[5].name
+ * </pre>
+ *
+ * @param json JSON,可以为JSONObject或JSONArray
+ * @param expression 表达式
+ * @param value 值
+ */
+ public static void putByPath(JSON json, String expression, Object value) {
+ json.putByPath(expression, value);
+ }
+
+ /**
+ * 对所有双引号做转义处理(使用双反斜杠做转义)<br>
+ * 为了能在HTML中较好的显示,会将&lt;/转义为&lt;\/<br>
+ * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
+ *
+ * @param string 字符串
+ * @return 适合在JSON中显示的字符串
+ */
+ public static String quote(String string) {
+ return quote(string, true);
+ }
+
+ /**
+ * 对所有双引号做转义处理(使用双反斜杠做转义)<br>
+ * 为了能在HTML中较好的显示,会将&lt;/转义为&lt;\/<br>
+ * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
+ *
+ * @param string 字符串
+ * @param isWrap 是否使用双引号包装字符串
+ * @return 适合在JSON中显示的字符串
+ * @since 3.3.1
+ */
+ public static String quote(String string, boolean isWrap) {
+ StringWriter sw = new StringWriter();
+ try {
+ return quote(string, sw, isWrap).toString();
+ } catch (IOException ignored) {
+ // will never happen - we are writing to a string writer
+ return StrUtil.EMPTY;
+ }
+ }
+
+ /**
+ * 对所有双引号做转义处理(使用双反斜杠做转义)<br>
+ * 为了能在HTML中较好的显示,会将&lt;/转义为&lt;\/<br>
+ * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
+ *
+ * @param str 字符串
+ * @param writer Writer
+ * @return Writer
+ * @throws IOException IO异常
+ */
+ public static Writer quote(String str, Writer writer) throws IOException {
+ return quote(str, writer, true);
+ }
+
+ /**
+ * 对所有双引号做转义处理(使用双反斜杠做转义)<br>
+ * 为了能在HTML中较好的显示,会将&lt;/转义为&lt;\/<br>
+ * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
+ *
+ * @param str 字符串
+ * @param writer Writer
+ * @param isWrap 是否使用双引号包装字符串
+ * @return Writer
+ * @throws IOException IO异常
+ * @since 3.3.1
+ */
+ public static Writer quote(String str, Writer writer, boolean isWrap) throws IOException {
+ if (StrUtil.isEmpty(str)) {
+ if (isWrap) {
+ writer.write("\"\"");
+ }
+ return writer;
+ }
+
+ char b; // 前一个字符
+ char c; // 当前字符
+ int len = str.length();
+ if (isWrap) {
+ writer.write('"');
+ }
+ for (int i = 0; i < len; i++) {
+// b = c;
+ c = str.charAt(i);
+ switch (c) {
+ case '\\':
+ case '"':
+ writer.write("\\");
+ writer.write(c);
+ break;
+ //此处转义导致输出不和预期一致
+// case '/':
+// if (b == '<') {
+// writer.write('\\');
+// }
+// writer.write(c);
+// break;
+ default:
+ writer.write(escape(c));
+ }
+ }
+ if (isWrap) {
+ writer.write('"');
+ }
+ return writer;
+ }
+
+ /**
+ * 转义显示不可见字符
+ *
+ * @param str 字符串
+ * @return 转义后的字符串
+ */
+ public static String escape(String str) {
+ if (StrUtil.isEmpty(str)) {
+ return str;
+ }
+
+ final int len = str.length();
+ final StringBuilder builder = new StringBuilder(len);
+ char c;
+ for (int i = 0; i < len; i++) {
+ c = str.charAt(i);
+ builder.append(escape(c));
+ }
+ return builder.toString();
+ }
+
+ /**
+ * 在需要的时候包装对象<br>
+ * 包装包括:
+ * <ul>
+ * <li><code>null</code> =》 <code>JSONNull.NULL</code></li>
+ * <li>array or collection =》 JSONArray</li>
+ * <li>map =》 JSONObject</li>
+ * <li>standard property (Double, String, et al) =》 原对象</li>
+ * <li>来自于java包 =》 字符串</li>
+ * <li>其它 =》 尝试包装为JSONObject,否则返回<code>null</code></li>
+ * </ul>
+ *
+ * @param object 被包装的对象
+ * @param jsonConfig JSON选项
+ * @return 包装后的值,null表示此值需被忽略
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public static Object wrap(Object object, JSONConfig jsonConfig) {
+ if (object == null) {
+ return jsonConfig.isIgnoreNullValue() ? null : JSONNull.NULL;
+ }
+ if (object instanceof JSON //
+ || JSONNull.NULL.equals(object) //
+ || object instanceof JSONString //
+ || object instanceof CharSequence //
+ || object instanceof Number //
+ || ObjectUtil.isBasicType(object) //
+ ) {
+ return object;
+ }
+
+ // 自定义序列化
+ final JSONSerializer serializer = GlobalSerializeMapping.getSerializer(object.getClass());
+ if (null != serializer) {
+ final Type jsonType = TypeUtil.getTypeArgument(serializer.getClass());
+ if (null != jsonType) {
+ if (serializer instanceof JSONObjectSerializer) {
+ serializer.serialize(new JSONObject(jsonConfig), object);
+ } else if (serializer instanceof JSONArraySerializer) {
+ serializer.serialize(new JSONArray(jsonConfig), object);
+ }
+ }
+ }
+
+ try {
+ // JSONArray
+ if (object instanceof Iterable || ArrayUtil.isArray(object)) {
+ return new JSONArray(object, jsonConfig);
+ }
+ // JSONObject
+ if (object instanceof Map) {
+ return new JSONObject(object, jsonConfig);
+ }
+
+ // 日期类型原样保存,便于格式化
+ if (object instanceof Date
+ || object instanceof Calendar
+ || object instanceof TemporalAccessor
+ ) {
+ return object;
+ }
+ // 枚举类保存其字符串形式(4.0.2新增)
+ if (object instanceof Enum) {
+ return object.toString();
+ }
+
+ // Java内部类不做转换
+ if (ClassUtil.isJdkClass(object.getClass())) {
+ return object.toString();
+ }
+
+ // 默认按照JSONObject对待
+ return new JSONObject(object, jsonConfig);
+ } catch (Exception exception) {
+ return null;
+ }
+ }
+
+ /**
+ * 格式化JSON字符串,此方法并不严格检查JSON的格式正确与否
+ *
+ * @param jsonStr JSON字符串
+ * @return 格式化后的字符串
+ * @since 3.1.2
+ */
+ public static String formatJsonStr(String jsonStr) {
+ return JSONStrFormater.format(jsonStr);
+ }
+
+ /**
+ * 是否为JSON字符串,首尾都为大括号或中括号判定为JSON字符串
+ *
+ * @param str 字符串
+ * @return 是否为JSON字符串
+ * @since 3.3.0
+ */
+ public static boolean isJson(String str) {
+ return isJsonObj(str) || isJsonArray(str);
+ }
+
+ /**
+ * 是否为JSONObject字符串,首尾都为大括号判定为JSONObject字符串
+ *
+ * @param str 字符串
+ * @return 是否为JSON字符串
+ * @since 3.3.0
+ */
+ public static boolean isJsonObj(String str) {
+ if (StrUtil.isBlank(str)) {
+ return false;
+ }
+ return StrUtil.isWrap(str.trim(), '{', '}');
+ }
+
+ /**
+ * 是否为JSONArray字符串,首尾都为中括号判定为JSONArray字符串
+ *
+ * @param str 字符串
+ * @return 是否为JSON字符串
+ * @since 3.3.0
+ */
+ public static boolean isJsonArray(String str) {
+ if (StrUtil.isBlank(str)) {
+ return false;
+ }
+ return StrUtil.isWrap(str.trim(), '[', ']');
+ }
+
+ /**
+ * 是否为null对象,null的情况包括:
+ *
+ * <pre>
+ * 1. {@code null}
+ * 2. {@link JSONNull}
+ * </pre>
+ *
+ * @param obj 对象
+ * @return 是否为null
+ * @since 4.5.7
+ */
+ public static boolean isNull(Object obj) {
+ return null == obj || obj instanceof JSONNull;
+ }
+
+ /**
+ * XML转JSONObject<br>
+ * 转换过程中一些信息可能会丢失,JSON中无法区分节点和属性,相同的节点将被处理为JSONArray。
+ *
+ * @param xml XML字符串
+ * @return JSONObject
+ * @since 4.0.8
+ */
+ public static JSONObject xmlToJson(String xml) {
+ return XML.toJSONObject(xml);
+ }
+
+ /**
+ * 加入自定义的序列化器
+ *
+ * @param type 对象类型
+ * @param serializer 序列化器实现
+ * @see GlobalSerializeMapping#put(Type, JSONArraySerializer)
+ * @since 4.6.5
+ */
+ public static void putSerializer(Type type, JSONArraySerializer<?> serializer) {
+ GlobalSerializeMapping.put(type, serializer);
+ }
+
+ /**
+ * 加入自定义的序列化器
+ *
+ * @param type 对象类型
+ * @param serializer 序列化器实现
+ * @see GlobalSerializeMapping#put(Type, JSONObjectSerializer)
+ * @since 4.6.5
+ */
+ public static void putSerializer(Type type, JSONObjectSerializer<?> serializer) {
+ GlobalSerializeMapping.put(type, serializer);
+ }
+
+ /**
+ * 加入自定义的反序列化器
+ *
+ * @param type 对象类型
+ * @param deserializer 反序列化器实现
+ * @see GlobalSerializeMapping#put(Type, JSONDeserializer)
+ * @since 4.6.5
+ */
+ public static void putDeserializer(Type type, JSONDeserializer<?> deserializer) {
+ GlobalSerializeMapping.put(type, deserializer);
+ }
+
+ // --------------------------------------------------------------------------------------------- Private method start
+
+ /**
+ * 转义不可见字符<br>
+ * 见:https://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF
+ *
+ * @param c 字符
+ * @return 转义后的字符串
+ */
+ private static String escape(char c) {
+ switch (c) {
+ case '\b':
+ return "\\b";
+ case '\t':
+ return "\\t";
+ case '\n':
+ return "\\n";
+ case '\f':
+ return "\\f";
+ case '\r':
+ return "\\r";
+ default:
+ if (c < StrUtil.C_SPACE || //
+ (c >= '\u0080' && c <= '\u00a0') || //
+ (c >= '\u2000' && c <= '\u2010') || //
+ (c >= '\u2028' && c <= '\u202F') || //
+ (c >= '\u2066' && c <= '\u206F')//
+ ) {
+ return HexUtil.toUnicodeHex(c);
+ } else {
+ return Character.toString(c);
+ }
+ }
+ }
+ // --------------------------------------------------------------------------------------------- Private method end
+}
diff --git a/src/main/java/net/geedge/confagent/util/R.java b/src/main/java/net/geedge/confagent/util/R.java
new file mode 100644
index 0000000..f3792f4
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/R.java
@@ -0,0 +1,66 @@
+package net.geedge.confagent.util;
+
+import java.util.HashMap;
+
+/**
+ * 返回数据
+ *
+ * 错误码、错误内容统一在枚举类RCode中定义, 错误码格式见RCode注释,错误码内容必须用英文,作为国际化的code
+ * 自定义的错误类型必须加注释
+ */
+public class R extends HashMap<String, Object> {
+ private static final long serialVersionUID = 1L;
+
+ public R() {
+ put("code", RCode.SUCCESS.getCode());
+ put("msg", RCode.SUCCESS.getMsg());
+ }
+
+ public static R error() {
+ return error(RCode.ERROR.getCode(), RCode.ERROR.getMsg());
+ }
+
+ public static R error(RCode rCode) {
+ R r = new R();
+ r.put("code", rCode.getCode());
+ r.put("msg", rCode.getMsg());
+ return r;
+ }
+
+ public static R error(Integer code, String msg) {
+ R r = new R();
+ r.put("code", code);
+ r.put("msg", msg);
+ return r;
+ }
+
+ public static R ok(String msg) {
+ R r = new R();
+ r.put("msg", msg);
+ return r;
+ }
+
+ public static R ok() {
+ return new R();
+ }
+
+ public static R ok(Object data) {
+ R r = new R();
+ r.put("data", data);
+ return r;
+ }
+
+ @Override
+ public R put(String key, Object value) {
+ super.put(key, value);
+ return this;
+ }
+
+ public Integer getCode(){
+ return (Integer) super.get("code");
+ }
+ public String getMsg(){
+ return (String) super.get("msg");
+ }
+}
+
diff --git a/src/main/java/net/geedge/confagent/util/RCode.java b/src/main/java/net/geedge/confagent/util/RCode.java
new file mode 100644
index 0000000..cb3f6ac
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/RCode.java
@@ -0,0 +1,33 @@
+package net.geedge.confagent.util;
+
+public enum RCode {
+ SUCCESS(200, "success"), //成功
+
+ AUTH_NAME_PIN_ISNULL(10000,"The name and password is required"),
+ AUTH_NAME_PIN_INVALID(10001,"The name or password is invalid"),
+ AUTH_TOKEN_INVALID(10002,"The token is invalid"),
+ AUTH_TOKEN_ISNULL(10003,"Token is required"),
+ AUTH_READ_TOKEN_FAILD(10004,"Read token failed"),
+
+ CONFIG_PROMTAIL_RELOAD_FAILED(10005,"Reload prometheus failed"),
+ CONFIG_BLAVKBOX_RELOAD_FAILED(10006,"Reload blackbox_exporter failed"),
+ CONFIG_SNMP_EXPORTER_RELOAD_FAILED(10007,"Reload snmp_exporter failed"),
+
+ PROMTAIL_CONFIG_VERSION_ISNULL(10008,"The promtail config version is required"),
+
+ ERROR(999, "error"); //通用错误/未知错误
+ private RCode(Integer code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+ private Integer code;
+ private String msg;
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getMsg() {
+ return msg;
+ }
+}
diff --git a/src/main/java/net/geedge/confagent/util/Tool.java b/src/main/java/net/geedge/confagent/util/Tool.java
new file mode 100644
index 0000000..250b0c2
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/Tool.java
@@ -0,0 +1,1106 @@
+package net.geedge.confagent.util;
+
+import cn.hutool.log.Log;
+import net.geedge.confagent.ConfagentApplication;
+
+import java.awt.Graphics;
+import java.awt.Robot;
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.net.URLDecoder;
+import java.nio.ByteBuffer;
+import java.time.LocalDateTime;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAccessor;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Spliterator;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+
+public class Tool {
+
+ /**
+ * 数据库操作工具类
+ */
+ public final static cn.hutool.db.DbUtil DbUtil = new cn.hutool.db.DbUtil();
+ /**
+ * 安全相关工具类<br>
+ * 加密分为三种:<br>
+ * 1、对称加密(symmetric),例如:AES、DES等<br>
+ * 2、非对称加密(asymmetric),例如:RSA、DSA等<br>
+ * 3、摘要加密(digest),例如:MD5、SHA-1、SHA-256、HMAC等<br>
+ */
+ public final static cn.hutool.crypto.SecureUtil SecureUtil = new cn.hutool.crypto.SecureUtil();
+ /**
+ * 代理工具类
+ */
+ public final static cn.hutool.aop.ProxyUtil ProxyUtil = new cn.hutool.aop.ProxyUtil();
+ /**
+ * 敏感词工具类
+ */
+ public final static cn.hutool.dfa.SensitiveUtil SensitiveUtil = new cn.hutool.dfa.SensitiveUtil();
+
+ /**
+ * 数据库元数据信息工具类
+ *
+ * <p>
+ * 需要注意的是,此工具类在某些数据库(比如Oracle)下无效,此时需要手动在数据库配置中增加:
+ * <pre>
+ * remarks = true
+ * useInformationSchema = true
+ * </pre>
+ *
+ * @author looly
+ */
+ public static class MetaUtil extends cn.hutool.db.meta.MetaUtil {}
+ /**
+ * 异常工具类
+ *
+ * @author Looly
+ */
+ public static class ExceptionUtil extends cn.hutool.core.exceptions.ExceptionUtil {}
+ /**
+ * 正则相关工具类<br>
+ * 常用正则请见 {@link cn.hutool.core.lang.Validator}
+ *
+ * @author xiaoleilu
+ */
+ public static class ReUtil extends cn.hutool.core.util.ReUtil {}
+ /**
+ * SOAP相关工具类
+ *
+ * @author looly
+ * @since 4.5.7
+ */
+ public static class SoapUtil extends cn.hutool.http.webservice.SoapUtil {}
+ /**
+ * 脚本工具类
+ *
+ * @author Looly
+ */
+ public static class ScriptUtil extends cn.hutool.script.ScriptUtil {}
+ /**
+ * 提供Unicode字符串和普通字符串之间的转换
+ *
+ * @author 兜兜毛毛, looly
+ * @since 4.0.0
+ */
+ public static class UnicodeUtil extends cn.hutool.core.text.UnicodeUtil {}
+ /**
+ * 时间工具类
+ *
+ * @author xiaoleilu
+ */
+ public static class DateUtil extends cn.hutool.core.date.DateUtil {}
+ /**
+ * EC密钥参数相关工具类封装
+ *
+ * @author looly
+ * @since 5.4.3
+ */
+ public static class ECKeyUtil extends cn.hutool.crypto.ECKeyUtil {}
+ /**
+ * 枚举工具类
+ *
+ * @author looly
+ * @since 3.3.0
+ */
+ public static class EnumUtil extends cn.hutool.core.util.EnumUtil {}
+ /**
+ * 数学相关方法工具类<br>
+ * 此工具类与{@link cn.hutool.core.util.NumberUtil}属于一类工具,NumberUtil偏向于简单数学计算的封装,MathUtil偏向复杂数学计算
+ *
+ * @author looly
+ * @since 4.0.7
+ */
+ public static class MathUtil extends cn.hutool.core.math.MathUtil {}
+ /**
+ * Sax方式读取Excel相关工具类
+ *
+ * @author looly
+ */
+ public static class ExcelSaxUtil extends cn.hutool.poi.excel.sax.ExcelSaxUtil {}
+ /**
+ * 数字工具类<br>
+ * 对于精确值计算应该使用 {@link BigDecimal}<br>
+ * JDK7中<strong>BigDecimal(double val)</strong>构造方法的结果有一定的不可预知性,例如:
+ *
+ * <pre>
+ * new BigDecimal(0.1)
+ * </pre>
+ * <p>
+ * 表示的不是<strong>0.1</strong>而是<strong>0.1000000000000000055511151231257827021181583404541015625</strong>
+ *
+ * <p>
+ * 这是因为0.1无法准确的表示为double。因此应该使用<strong>new BigDecimal(String)</strong>。
+ * </p>
+ * 相关介绍:
+ * <ul>
+ * <li>http://www.oschina.net/code/snippet_563112_25237</li>
+ * <li>https://github.com/venusdrogon/feilong-core/wiki/one-jdk7-bug-thinking</li>
+ * </ul>
+ *
+ * @author Looly
+ */
+ public static class NumberUtil extends cn.hutool.core.util.NumberUtil {}
+ /**
+ * Jsch工具类<br>
+ * Jsch是Java Secure Channel的缩写。JSch是一个SSH2的纯Java实现。<br>
+ * 它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等。<br>
+ *
+ * @author Looly
+ * @since 4.0.0
+ */
+ public static class JschUtil extends cn.hutool.extra.ssh.JschUtil {}
+ /**
+ * 线程池工具
+ *
+ * @author luxiaolei
+ */
+ public static class ThreadUtil extends cn.hutool.core.thread.ThreadUtil {}
+ /**
+ * Oshi库封装的工具类,通过此工具类,可获取系统、硬件相关信息
+ *
+ * <pre>
+ * 1、系统信息
+ * 2、硬件信息
+ * </pre>
+ *
+ * 相关内容见:https://github.com/oshi/oshi
+ *
+ * @author Looly
+ * @since 4.6.4
+ */
+ public static class OshiUtil extends cn.hutool.system.oshi.OshiUtil {}
+ /**
+ * URL(Uniform Resource Locator)统一资源定位符相关工具类
+ *
+ * <p>
+ * 统一资源定位符,描述了一台特定服务器上某资源的特定位置。
+ * </p>
+ * URL组成:
+ * <pre>
+ * 协议://主机名[:端口]/ 路径/[:参数] [?查询]#Fragment
+ * protocol :// hostname[:port] / path / [:parameters][?query]#fragment
+ * </pre>
+ *
+ * @author xiaoleilu
+ */
+ public static class URLUtil extends cn.hutool.core.util.URLUtil {}
+ /**
+ * ID生成器工具类,此工具类中主要封装:
+ *
+ * <pre>
+ * 1. 唯一性ID生成器:UUID、ObjectId(MongoDB)、Snowflake
+ * </pre>
+ *
+ * <p>
+ * ID相关文章见:http://calvin1978.blogcn.com/articles/uuid.html
+ *
+ * @author looly
+ * @since 4.1.13
+ */
+ public static class IdUtil extends net.geedge.confagent.util.IdUtil {}
+ /**
+ * Http请求工具类
+ *
+ * @author xiaoleilu
+ */
+ public static class HttpUtil extends cn.hutool.http.HttpUtil {}
+ /**
+ * 桌面相关工具(平台相关)<br>
+ * Desktop 类允许 Java 应用程序启动已在本机桌面上注册的关联应用程序,以处理 URI 或文件。
+ *
+ * @author looly
+ * @since 4.5.7
+ */
+ public static class DesktopUtil extends cn.hutool.core.swing.DesktopUtil {}
+ /**
+ * 图片处理工具类:<br>
+ * 功能:缩放图像、切割图像、旋转、图像类型转换、彩色转黑白、文字水印、图片水印等 <br>
+ * 参考:http://blog.csdn.net/zhangzhikaixinya/article/details/8459400
+ *
+ * @author Looly
+ */
+ public static class ImgUtil extends cn.hutool.core.img.ImgUtil {}
+ /**
+ * 分页工具类
+ *
+ * @author xiaoleilu
+ */
+ public static class PageUtil extends cn.hutool.core.util.PageUtil {}
+ /**
+ * HTML工具类
+ *
+ * <p>
+ * 比如我们在使用爬虫爬取HTML页面后,需要对返回页面的HTML内容做一定处理,<br>
+ * 比如去掉指定标签(例如广告栏等)、去除JS、去掉样式等等,这些操作都可以使用此工具类完成。
+ *
+ * @author xiaoleilu
+ *
+ */
+ public static class HtmlUtil extends cn.hutool.http.HtmlUtil {}
+ /**
+ * PEM(Privacy Enhanced Mail)格式相关工具类。(基于Bouncy Castle)
+ *
+ * <p>
+ * PEM一般为文本格式,以 -----BEGIN... 开头,以 -----END... 结尾,中间的内容是 BASE64 编码。
+ * <p>
+ * 这种格式可以保存证书和私钥,有时我们也把PEM格式的私钥的后缀改为 .key 以区别证书与私钥。
+ *
+ * @author looly
+ * @since 5.1.6
+ */
+ public static class PemUtil extends cn.hutool.crypto.PemUtil {}
+ /**
+ * 分词工具类
+ *
+ * @author looly
+ * @since 4.3.3
+ */
+ public static class TokenizerUtil extends cn.hutool.extra.tokenizer.TokenizerUtil {}
+ /**
+ * 工具封装
+ *
+ * @author looly
+ * @since 5.4.4
+ */
+ public static class ExcelExtractorUtil extends cn.hutool.poi.excel.ExcelExtractorUtil {}
+ /**
+ * 邮件工具类,基于javax.mail封装
+ *
+ * @author looly
+ * @since 3.1.2
+ */
+ public static class MailUtil extends cn.hutool.extra.mail.MailUtil {}
+ /**
+ * NIO中Path对象操作封装
+ *
+ * @author looly
+ * @since 5.4.1
+ */
+ public static class PathUtil extends cn.hutool.core.io.file.PathUtil {}
+ /**
+ * 邮件内部工具类
+ * @author looly
+ * @since 3.2.3
+ */
+ public static class InternalMailUtil extends cn.hutool.extra.mail.InternalMailUtil {}
+ /**
+ * 定时任务工具类<br>
+ * 此工具持有一个全局{@link cn.hutool.cron.Scheduler},所有定时任务在同一个调度器中执行<br>
+ * {@link #setMatchSecond(boolean)} 方法用于定义是否使用秒匹配模式,如果为true,则定时任务表达式中的第一位为秒,否则为分,默认是分
+ *
+ * @author xiaoleilu
+ *
+ */
+ public static class CronUtil extends cn.hutool.cron.CronUtil {}
+ /**
+ * Java的System类封装工具类。<br>
+ * 参考:http://blog.csdn.net/zhongweijian/article/details/7619383
+ *
+ * @author Looly
+ */
+ public static class SystemUtil extends cn.hutool.system.SystemUtil {}
+ /**
+ * 压缩工具类<br>
+ * 基于commons-compress的压缩解压封装
+ *
+ * @author looly
+ * @since 5.5.0
+ */
+ public static class CompressUtil extends cn.hutool.extra.compress.CompressUtil {}
+ /**
+ * {@link ClassLoader}工具类
+ *
+ * @author Looly
+ * @since 3.0.9
+ */
+ public static class ClassLoaderUtil extends cn.hutool.core.util.ClassLoaderUtil {}
+ /**
+ * {@link Spliterator}相关工具类
+ *
+ * @author looly
+ * @since 5.4.3
+ */
+ public static class SpliteratorUtil extends cn.hutool.core.collection.SpliteratorUtil {}
+ /**
+ * 监听工具类<br>
+ * 主要负责文件监听器的快捷创建
+ *
+ * @author Looly
+ * @since 3.1.0
+ */
+ public static class WatchUtil extends cn.hutool.core.io.watch.WatchUtil {}
+ /**
+ * Excel样式工具类
+ *
+ * @author looly
+ * @since 4.0.0
+ */
+ public static class StyleUtil extends cn.hutool.poi.excel.style.StyleUtil {}
+ /**
+ * 系统剪贴板工具类
+ *
+ * @author looly
+ * @since 3.2.0
+ */
+ public static class ClipboardUtil extends cn.hutool.core.swing.clipboard.ClipboardUtil {}
+ /**
+ * 文件类型判断工具类
+ *
+ * <p>此工具根据文件的前几位bytes猜测文件类型,对于文本、zip判断不准确,对于视频、图片类型判断准确</p>
+ *
+ * <p>需要注意的是,xlsx、docx等Office2007格式,全部识别为zip,因为新版采用了OpenXML格式,这些格式本质上是XML文件打包为zip</p>
+ *
+ * @author Looly
+ */
+ public static class FileTypeUtil extends cn.hutool.core.io.FileTypeUtil {}
+ /**
+ * 引用工具类,主要针对{@link Reference} 工具化封装<br>
+ * 主要封装包括:
+ * <pre>
+ * 1. {@link SoftReference} 软引用,在GC报告内存不足时会被GC回收
+ * 2. {@link WeakReference} 弱引用,在GC时发现弱引用会回收其对象
+ * 3. {@link PhantomReference} 虚引用,在GC时发现虚引用对象,会将{@link PhantomReference}插入{@link ReferenceQueue}。 此时对象未被真正回收,要等到{@link ReferenceQueue}被真正处理后才会被回收。
+ * </pre>
+ *
+ * @author looly
+ * @since 3.1.2
+ */
+ public static class ReferenceUtil extends cn.hutool.core.util.ReferenceUtil {}
+ /**
+ * 布隆过滤器工具
+ *
+ * @author looly
+ * @since 4.1.5
+ */
+ public static class BloomFilterUtil extends cn.hutool.bloomfilter.BloomFilterUtil {}
+ /**
+ * 修饰符工具类
+ *
+ * @author looly
+ * @since 4.0.5
+ */
+ public static class ModifierUtil extends cn.hutool.core.util.ModifierUtil {}
+ /**
+ * 集合的stream操作封装
+ *
+ * @author [email protected]
+ * @since 5.5.2
+ */
+ public static class CollStreamUtil extends cn.hutool.core.collection.CollStreamUtil {}
+ /**
+ * 摘要算法工具类
+ *
+ * @author Looly
+ */
+ public static class DigestUtil extends cn.hutool.crypto.digest.DigestUtil {}
+ /**
+ * 对象工具类,包括判空、克隆、序列化等操作
+ *
+ * @author Looly
+ */
+ public static class ObjectUtil extends cn.hutool.core.util.ObjectUtil {}
+ /**
+ * Hash算法大全<br>
+ * 推荐使用FNV1算法
+ *
+ * @author Goodzzp, Looly
+ */
+ public static class HashUtil extends cn.hutool.core.util.HashUtil {}
+ /**
+ * Bouncy Castle相关工具类封装
+ *
+ * @author looly
+ * @since 4.5.0
+ */
+ public static class BCUtil extends cn.hutool.crypto.BCUtil {}
+ /**
+ * 针对 {@link Type} 的工具类封装<br>
+ * 最主要功能包括:
+ *
+ * <pre>
+ * 1. 获取方法的参数和返回值类型(包括Type和Class)
+ * 2. 获取泛型参数类型(包括对象的泛型参数或集合元素的泛型类型)
+ * </pre>
+ *
+ * @author Looly
+ * @since 3.0.8
+ */
+ public static class TypeUtil extends cn.hutool.core.util.TypeUtil {}
+ /**
+ * Excel文件工具类
+ *
+ * @author looly
+ * @since 4.2.1
+ */
+ public static class ExcelFileUtil extends cn.hutool.poi.excel.ExcelFileUtil {}
+ /**
+ * NIO工具类
+ *
+ * @since 5.4.0
+ */
+ public static class NioUtil extends cn.hutool.socket.nio.NioUtil {}
+ /**
+ * 类工具类 <br>
+ *
+ * @author xiaoleilu
+ */
+ public static class ClassUtil extends cn.hutool.core.util.ClassUtil {}
+ /**
+ * 针对{@link Calendar} 对象封装工具类
+ *
+ * @author looly
+ * @since 5.3.0
+ */
+ public static class CalendarUtil extends cn.hutool.core.date.CalendarUtil {}
+ /**
+ * 网络相关工具
+ *
+ * @author xiaoleilu
+ */
+ public static class NetUtil extends cn.hutool.core.net.NetUtil {}
+ /**
+ * 源码编译工具类,主要封装{@link JavaCompiler} 相关功能
+ *
+ * @author looly
+ * @since 5.5.2
+ */
+ public static class CompilerUtil extends cn.hutool.core.compiler.CompilerUtil {}
+ /**
+ * 锁相关工具
+ *
+ * @author looly
+ * @since 5.2.5
+ */
+ public static class LockUtil extends cn.hutool.core.thread.lock.LockUtil {}
+ /**
+ * 文件名相关工具类
+ *
+ * @author looly
+ * @since 5.4.1
+ */
+ public static class FileNameUtil extends cn.hutool.core.io.file.FileNameUtil {}
+ /**
+ * SM国密算法工具类<br>
+ * 此工具类依赖org.bouncycastle:bcpkix-jdk15on
+ *
+ * @author looly
+ * @since 4.3.2
+ */
+ public static class SmUtil extends cn.hutool.crypto.SmUtil {}
+ /**
+ * Props工具类<br>
+ * 提供静态方法获取配置文件
+ *
+ * @author looly
+ * @since 5.1.3
+ */
+ public static class PropsUtil extends cn.hutool.setting.dialect.PropsUtil {}
+ /**
+ * XML工具类<br>
+ * 此工具使用w3c dom工具,不需要依赖第三方包。<br>
+ * 工具类封装了XML文档的创建、读取、写出和部分XML操作
+ *
+ * @author xiaoleilu
+ */
+ public static class XmlUtil extends cn.hutool.core.util.XmlUtil {}
+ /**
+ * Velocity模板引擎工具类<br>
+ * 使用前必须初始化工具类
+ *
+ * @author xiaoleilu
+ * @deprecated 使用TemplateUtil替代
+ */
+ public static class VelocityUtil extends cn.hutool.extra.template.engine.velocity.VelocityUtil {}
+ /**
+ * {@link ByteBuffer} 工具类<br>
+ * 此工具来自于 t-io 项目以及其它项目的相关部分收集<br>
+ * ByteBuffer的相关介绍见:https://www.cnblogs.com/ruber/p/6857159.html
+ *
+ * @author tanyaowu, looly
+ * @since 4.0.0
+ *
+ */
+ public static class BufferUtil extends cn.hutool.core.io.BufferUtil {}
+ /**
+ * 表达式引擎工具类
+ *
+ * @author looly
+ * @since 5.5.0
+ */
+ public static class ExpressionUtil extends cn.hutool.extra.expression.ExpressionUtil {}
+ /**
+ * 驱动相关工具类,包括自动获取驱动类名
+ *
+ * @author looly
+ * @since 4.0.10
+ */
+ public static class DriverUtil extends cn.hutool.db.dialect.DriverUtil {}
+ /**
+ * IO工具类<br>
+ * IO工具类只是辅助流的读写,并不负责关闭流。原因是流可能被多次读写,读写关闭后容易造成问题。
+ *
+ * @author xiaoleilu
+ */
+ public static class IoUtil extends net.geedge.confagent.util.IoUtil {}
+ /**
+ * JDK8+中的{@link LocalDateTime} 工具类封装
+ *
+ * @author looly
+ * @since 5.3.9
+ */
+ public static class LocalDateTimeUtil extends cn.hutool.core.date.LocalDateTimeUtil {}
+ /**
+ * 规范化对象生成工具
+ *
+ * @author looly
+ * @since 5.4.3
+ */
+ public static class InternUtil extends cn.hutool.core.lang.intern.InternUtil {}
+ /**
+ * 压缩工具类
+ *
+ * @author Looly
+ */
+ public static class ZipUtil extends cn.hutool.core.util.ZipUtil {}
+ /**
+ * 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。<br>
+ * 例如十进制数57,在二进制写作111001,在16进制写作39。<br>
+ * 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的32,而不是十进制的20<br>
+ * <p>
+ * 参考:https://my.oschina.net/xinxingegeya/blog/287476
+ *
+ * @author Looly
+ */
+ public static class HexUtil extends cn.hutool.core.util.HexUtil {}
+ /**
+ * 数据大小工具类
+ *
+ * @author looly
+ * @since 5.3.10
+ */
+ public static class DataSizeUtil extends cn.hutool.core.io.unit.DataSizeUtil {}
+ /**
+ * User-Agent工具类
+ *
+ * @author looly
+ *
+ */
+ public static class UserAgentUtil extends cn.hutool.http.useragent.UserAgentUtil {}
+ /**
+ * 统一社会信用代码工具类
+ *
+ * <pre>
+ * 第一部分:登记管理部门代码1位 (数字或大写英文字母)
+ * 第二部分:机构类别代码1位 (数字或大写英文字母)
+ * 第三部分:登记管理机关行政区划码6位 (数字)
+ * 第四部分:主体标识码(组织机构代码)9位 (数字或大写英文字母)
+ * 第五部分:校验码1位 (数字或大写英文字母)
+ * </pre>
+ *
+ * @author looly
+ * @since 5.2.4
+ */
+ public static class CreditCodeUtil extends cn.hutool.core.util.CreditCodeUtil {}
+ /**
+ * {@link Temporal} 工具类封装
+ *
+ * @author looly
+ * @since 5.4.5
+ */
+ public static class TemporalUtil extends cn.hutool.core.date.TemporalUtil {}
+ /**
+ * Setting工具类<br>
+ * 提供静态方法获取配置文件
+ *
+ * @author looly
+ */
+ public static class SettingUtil extends cn.hutool.setting.SettingUtil {}
+ /**
+ * Statement和PreparedStatement工具类
+ *
+ * @author looly
+ * @since 4.0.10
+ */
+ public static class StatementUtil extends cn.hutool.db.StatementUtil {}
+ /**
+ * 基于https://github.com/vdurmont/emoji-java的Emoji表情工具类
+ * <p>
+ * emoji-java文档以及别名列表见:https://github.com/vdurmont/emoji-java
+ *
+ * @author looly
+ * @since 4.2.1
+ */
+ public static class EmojiUtil extends cn.hutool.extra.emoji.EmojiUtil {}
+ /**
+ * Bean工具类
+ *
+ * <p>
+ * 把一个拥有对属性进行set和get方法的类,我们就可以称之为JavaBean。
+ * </p>
+ *
+ * @author Looly
+ * @since 3.1.2
+ */
+ public static class BeanUtil extends cn.hutool.core.bean.BeanUtil {}
+ /**
+ * Servlet相关工具类封装
+ *
+ * @author looly
+ * @since 3.2.0
+ */
+ public static class ServletUtil extends cn.hutool.extra.servlet.ServletUtil {}
+ /**
+ * java bean 校验工具类,此工具类基于validation-api(jakarta.validation-api)封装
+ *
+ * <p>在实际使用中,用户需引入validation-api的实现,如:hibernate-validator</p>
+ * <p>注意:hibernate-validator还依赖了javax.el,需自行引入。</p>
+ *
+ * @author chengqiang
+ * @since 5.5.0
+ */
+ public static class ValidationUtil extends cn.hutool.extra.validation.ValidationUtil {}
+ /**
+ * Excel工作簿相关工具类
+ *
+ * @author looly
+ * @since 4.0.7
+ *
+ */
+ public static class WorkbookUtil extends cn.hutool.poi.excel.WorkbookUtil {}
+ /**
+ * 拼音工具类,封装了TinyPinyin、JPinyin、Pinyin4j,通过SPI自动识别。
+ *
+ * @author looly
+ */
+ public static class PinyinUtil extends cn.hutool.extra.pinyin.PinyinUtil {}
+ /**
+ * 调用者。可以通过此类的方法获取调用者、多级调用者以及判断是否被调用
+ *
+ * @author Looly
+ * @since 4.1.6
+ */
+ public static class CallerUtil extends cn.hutool.core.lang.caller.CallerUtil {}
+ /**
+ * 定时任务表达式工具类
+ *
+ * @author looly
+ *
+ */
+ public static class CronPatternUtil extends cn.hutool.cron.pattern.CronPatternUtil {}
+ /**
+ * 系统运行时工具类,用于执行系统命令的工具
+ *
+ * @author Looly
+ * @since 3.1.1
+ */
+ public static class RuntimeUtil extends cn.hutool.core.util.RuntimeUtil {}
+ /**
+ * {@link TemporalAccessor} 工具类封装
+ *
+ * @author looly
+ * @since 5.3.9
+ */
+ public static class TemporalAccessorUtil extends cn.hutool.core.date.TemporalAccessorUtil {}
+ /**
+ * 图形验证码工具
+ *
+ * @author looly
+ * @since 3.1.2
+ */
+ public static class CaptchaUtil extends cn.hutool.captcha.CaptchaUtil {}
+ /**
+ * 反射工具类
+ *
+ * @author Looly
+ * @since 3.0.9
+ */
+ public static class ReflectUtil extends cn.hutool.core.util.ReflectUtil {}
+ /**
+ * IPV4地址工具类
+ *
+ * <p>pr自:https://gitee.com/loolly/hutool/pulls/161</p>
+ *
+ * @author ZhuKun
+ * @since 5.4.1
+ */
+ public static class Ipv4Util extends cn.hutool.core.net.Ipv4Util {}
+ /**
+ * {@link Robot} 封装工具类,提供截屏等工具
+ *
+ * @author looly
+ * @since 4.1.14
+ */
+ public static class RobotUtil extends cn.hutool.core.swing.RobotUtil {}
+ /**
+ * {@link Graphics}相关工具类
+ *
+ * @author looly
+ * @since 4.5.2
+ */
+ public static class GraphicsUtil extends cn.hutool.core.img.GraphicsUtil {}
+ /**
+ * Cglib工具类
+ *
+ * @author looly
+ * @since 5.4.1
+ */
+ public static class CglibUtil extends cn.hutool.extra.cglib.CglibUtil {}
+ /**
+ * 转义和反转义工具类Escape / Unescape<br>
+ * escape采用ISO Latin字符集对指定的字符串进行编码。<br>
+ * 所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。
+ *
+ * @author xiaoleilu
+ */
+ public static class EscapeUtil extends cn.hutool.core.util.EscapeUtil {}
+ /**
+ * 诊断工具类
+ *
+ * @author looly
+ * @since 5.5.2
+ */
+ public static class DiagnosticUtil extends cn.hutool.core.compiler.DiagnosticUtil {}
+ /**
+ * Excel中的行封装工具类
+ *
+ * @author looly
+ * @since 4.0.7
+ */
+ public static class RowUtil extends cn.hutool.poi.excel.RowUtil {}
+ /**
+ * 密钥工具类
+ *
+ * <p>
+ * 包括:
+ * <pre>
+ * 1、生成密钥(单密钥、密钥对)
+ * 2、读取密钥文件
+ * </pre>
+ *
+ * @author looly, Gsealy
+ * @since 4.4.1
+ */
+ public static class KeyUtil extends cn.hutool.crypto.KeyUtil {}
+ /**
+ * 基于Zxing的二维码工具类
+ *
+ * @author looly
+ * @since 4.0.2
+ */
+ public static class QrCodeUtil extends cn.hutool.extra.qrcode.QrCodeUtil {}
+ /**
+ * SQL相关工具类,包括相关SQL语句拼接等
+ *
+ * @author looly
+ * @since 4.0.10
+ */
+ public static class SqlUtil extends cn.hutool.db.sql.SqlUtil {}
+ /**
+ * Excel工具类,不建议直接使用index直接操作sheet,在wps/excel中sheet显示顺序与index无关,还有隐藏sheet
+ *
+ * @author Looly
+ *
+ */
+ public static class ExcelUtil extends cn.hutool.poi.excel.ExcelUtil {}
+ /**
+ * 缓存工具类
+ * @author Looly
+ *@since 3.0.1
+ */
+ public static class CacheUtil extends cn.hutool.cache.CacheUtil {}
+ /**
+ * Word工具类
+ *
+ * @author Looly
+ * @since 4.5.16
+ */
+ public static class WordUtil extends cn.hutool.poi.word.WordUtil {}
+ /**
+ * 注解工具类<br>
+ * 快速获取注解对象、注解值等工具封装
+ *
+ * @author looly
+ * @since 4.0.9
+ */
+ public static class AnnotationUtil extends cn.hutool.core.annotation.AnnotationUtil {}
+ /**
+ * Excel图片工具类
+ *
+ * @author looly
+ * @since 4.0.7
+ */
+ public static class ExcelPicUtil extends cn.hutool.poi.excel.ExcelPicUtil {}
+ /**
+ * 屏幕相关(当前显示设置)工具类
+ *
+ * @author looly
+ * @since 4.1.14
+ */
+ public static class ScreenUtil extends cn.hutool.core.swing.ScreenUtil {}
+ /**
+ * 文件工具类
+ *
+ * @author looly
+ */
+ public static class FileUtil extends cn.hutool.core.io.FileUtil {}
+ /**
+ * Word Document工具
+ *
+ * @author looly
+ * @since 4.4.1
+ */
+ public static class DocUtil extends cn.hutool.poi.word.DocUtil {}
+ /**
+ * 比较工具类
+ *
+ * @author looly
+ */
+ public static class CompareUtil extends cn.hutool.core.comparator.CompareUtil {}
+ /**
+ * Boolean类型相关工具类
+ *
+ * @author looly
+ * @since 4.1.16
+ */
+ public static class BooleanUtil extends cn.hutool.core.util.BooleanUtil {}
+ /**
+ * {@link Iterable} 和 {@link Iterator} 相关工具类
+ *
+ * @author Looly
+ * @since 3.1.0
+ */
+ public static class IterUtil extends cn.hutool.core.collection.IterUtil {}
+ /**
+ * 树工具类
+ *
+ * @author liangbaikai
+ */
+ public static class TreeUtil extends cn.hutool.core.lang.tree.TreeUtil {}
+ /**
+ * 身份证相关工具类<br>
+ * see https://www.oschina.net/code/snippet_1611_2881
+ *
+ * <p>
+ * 本工具并没有对行政区划代码做校验,如有需求,请参阅(2018年10月):
+ * http://www.mca.gov.cn/article/sj/xzqh/2018/201804-12/20181011221630.html
+ * </p>
+ *
+ * @author Looly
+ * @since 3.0.4
+ */
+ public static class IdcardUtil extends cn.hutool.core.util.IdcardUtil {}
+ /**
+ * 字符工具类<br>
+ * 部分工具来自于Apache Commons系列
+ *
+ * @author looly
+ * @since 4.0.1
+ */
+ public static class CharUtil extends cn.hutool.core.util.CharUtil {}
+ /**
+ * Socket相关工具类
+ *
+ * @author looly
+ * @since 4.5.0
+ */
+ public static class SocketUtil extends cn.hutool.socket.SocketUtil {}
+ /**
+ * 手机号工具类
+ *
+ * @author dahuoyzs
+ * @since 5.3.11
+ */
+ public static class PhoneUtil extends cn.hutool.core.util.PhoneUtil {}
+ /**
+ * 模板工具类
+ *
+ * @author looly
+ * @since 4.1.0
+ */
+ public static class TemplateUtil extends cn.hutool.extra.template.TemplateUtil {}
+ /**
+ * 集合相关工具类
+ * <p>
+ * 此工具方法针对{@link Collection}及其实现类封装的工具。
+ * <p>
+ * 由于{@link Collection} 实现了{@link Iterable}接口,因此部分工具此类不提供,而是在{@link IterUtil} 中提供
+ *
+ * @author xiaoleilu
+ * @see IterUtil
+ * @since 3.1.1
+ */
+ public static class CollUtil extends cn.hutool.core.collection.CollUtil {}
+ /**
+ * {@link JavaFileObject} 相关工具类封装
+ *
+ * @author lzpeng, looly
+ * @since 5.5.2
+ */
+ public static class JavaFileObjectUtil extends cn.hutool.core.compiler.JavaFileObjectUtil {}
+ /**
+ * 数组工具类
+ *
+ * @author Looly
+ */
+ public static class ArrayUtil extends cn.hutool.core.util.ArrayUtil {}
+ /**
+ * SSL(Secure Sockets Layer 安全套接字协议)相关工具封装
+ *
+ * @author looly
+ * @since 5.5.2
+ */
+ public static class SSLUtil extends cn.hutool.core.net.SSLUtil {}
+ /**
+ * 集合相关工具类,包括数组,是{@link CollUtil} 的别名工具类类
+ *
+ * @author xiaoleilu
+ * @see CollUtil
+ */
+ public static class CollectionUtil extends cn.hutool.core.collection.CollectionUtil {}
+ /**
+ * Excel表格中单元格工具类
+ *
+ * @author looly
+ * @since 4.0.7
+ */
+ public static class CellUtil extends cn.hutool.poi.excel.cell.CellUtil {}
+ /**
+ * 字符集工具类
+ *
+ * @author xiaoleilu
+ */
+ public static class CharsetUtil extends cn.hutool.core.util.CharsetUtil {}
+ /**
+ * 字符串工具类
+ *
+ * @author xiaoleilu
+ */
+ public static class StrUtil extends cn.hutool.core.util.StrUtil {}
+ /**
+ * Map相关工具类
+ *
+ * @author Looly
+ * @since 3.1.1
+ */
+ public static class MapUtil extends cn.hutool.core.map.MapUtil {}
+ /**
+ * SPI机制中的服务加载工具类,流程如下
+ *
+ * <pre>
+ * 1、创建接口,并创建实现类
+ * 2、ClassPath/META-INF/services下创建与接口全限定类名相同的文件
+ * 3、文件内容填写实现类的全限定类名
+ * </pre>
+ * 相关介绍见:https://www.jianshu.com/p/3a3edbcd8f24
+ *
+ * @author looly
+ * @since 5.1.6
+ */
+ public static class ServiceLoaderUtil extends cn.hutool.core.util.ServiceLoaderUtil {}
+ /**
+ * Spring(Spring boot)工具封装,包括:
+ *
+ * <pre>
+ * 1、Spring IOC容器中的bean对象获取
+ * </pre>
+ *
+ * @author loolly
+ * @since 5.1.0
+ */
+ public static class SpringUtil extends cn.hutool.extra.spring.SpringUtil {}
+ /**
+ * 随机工具类
+ *
+ * @author xiaoleilu
+ */
+ public static class RandomUtil extends cn.hutool.core.util.RandomUtil {}
+ public static class ListUtil extends cn.hutool.core.collection.ListUtil {}
+ /**
+ * Resource资源工具类
+ *
+ * @author Looly
+ *
+ */
+ public static class ResourceUtil extends cn.hutool.core.io.resource.ResourceUtil {}
+ /**
+ * AWT中字体相关工具类
+ *
+ * @author looly
+ * @since 5.3.6
+ */
+ public static class FontUtil extends cn.hutool.core.img.FontUtil {}
+ /**
+ * CSV工具
+ *
+ * @author looly
+ * @since 4.0.5
+ */
+ public static class CsvUtil extends cn.hutool.core.text.csv.CsvUtil {}
+ /**
+ * Word中表格相关工具
+ *
+ * @author Looly
+ * @since 4.5.14
+ */
+ public static class TableUtil extends cn.hutool.poi.word.TableUtil {}
+ /**
+ * 原始类型数组工具类
+ *
+ * @author looly
+ * @since 5.5.2
+ */
+ public static class PrimitiveArrayUtil extends cn.hutool.core.util.PrimitiveArrayUtil {}
+
+
+ /**
+ * @Description
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public static class JSONUtil extends net.geedge.confagent.util.JSONUtil{}
+
+ public static class YamlUtil extends net.geedge.confagent.util.YamlUtil{}
+
+ /**
+ * 获取项目中各种路径
+ * @author ThinkPad
+ *
+ */
+ public static class WebPathUtil {
+ static Log log= Log.get();
+ /**
+ * 如果已打成jar包,则返回jar包所在目录
+ * 如果未打成jar,则返回target所在目录
+ * @return
+ */
+ public static String getClassPath() {
+ try {
+ // 项目的编译文件的根目录
+ String path = URLDecoder.decode(System.getProperty("user.dir"), "utf-8");
+ log.debug("root path:{}",path);
+ return path;
+ } catch (UnsupportedEncodingException e) {
+ return null;
+ }
+ }
+
+ public static String getRootPath() {
+ File file = Tool.FileUtil.file(WebPathUtil.getClassPath());
+ return file.getAbsolutePath();
+ }
+
+ }
+}
diff --git a/src/main/java/net/geedge/confagent/util/YamlUtil.java b/src/main/java/net/geedge/confagent/util/YamlUtil.java
new file mode 100644
index 0000000..ef55436
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/YamlUtil.java
@@ -0,0 +1,112 @@
+package net.geedge.confagent.util;
+
+import cn.hutool.core.util.StrUtil;
+import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+public class YamlUtil {
+
+ public static void writeAsMap(Map map,String path){
+ Map writeObj = map;
+ if(writeObj == null)
+ writeObj = new HashMap<>();
+ Yaml yaml = new Yaml();
+ Tool.FileUtil.writeUtf8String(yaml.dumpAsMap(writeObj), path);
+ }
+
+ /**
+ * @Description 将yaml文件中的内容读取到map中
+ * @Author rui
+ * @Date 2021/3/24
+ */
+ public static Map<String,Object> readAsMap(String path){
+ File file = Tool.FileUtil.file(path);
+ Yaml yaml = new Yaml();
+ BufferedReader reader = Tool.FileUtil.getReader(file, Tool.CharsetUtil.UTF_8);
+ Map<String,Object> map = yaml.loadAs(reader, Map.class);
+
+ Tool.IoUtil.close(reader);
+ return map;
+ }
+
+ /**
+ * @Description 读取yaml文件中的属性,支持spring.profiles.active 连点形式
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public String readProperty(String file,String key){
+ Resource resource = getResource(file);
+ Properties properties = yamlToProperties(resource);
+ return properties.getProperty(key);
+ }
+
+ /**
+ * @Description 读取yaml文件中的属性,可以指定默认值
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public String readProperty(String file,String key,String defValue){
+ Resource resource = getResource(file);
+ Properties properties = yamlToProperties(resource);
+ return properties.getProperty(key,defValue);
+ }
+
+ /**
+ * @Description 获取application相关配置文件
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public static Resource getApplication(String mode, String profile){
+ return getResource("application"+ (StrUtil.isEmpty(profile)?"":"-"+profile )+".yml");
+ }
+
+ /**
+ * @Description 获取配置文件
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public static Resource getResource(String file){
+ return new FileSystemResource(file);
+ }
+
+ /**
+ * @Description 读取yaml文件并转为properties对象
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public static Properties yamlToProperties(String file){
+ Resource resource = getResource(file);
+ return yamlToProperties(resource);
+ }
+
+ public static Properties yamlToProperties(String ... filepath){
+ return yamlToProperties(getFileAbsolutePath(filepath));
+ }
+
+ /**
+ * @Description 读取yaml文件并转为properties对象
+ * @Author rui
+ * @Date 2021/3/23
+ */
+ public static Properties yamlToProperties(Resource resource){
+ YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
+ // 2:将加载的配置文件交给 YamlPropertiesFactoryBean
+ yamlPropertiesFactoryBean.setResources(resource);
+
+ // 3:将yml转换成 key:val
+ return yamlPropertiesFactoryBean.getObject();
+ }
+
+ public static String getFileAbsolutePath(String ... path){
+ return Tool.FileUtil.file(path).getAbsolutePath();
+ }
+
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..ebf2b81
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,10 @@
+confagent:
+ promtail:
+ cmdLine: D:\config\config.conf
+ config: D:\config\promtail.yml
+ defaultIP: 192.168.40.42
+
+ resourcePath: ./
+
+logging:
+ config: src/main/resources/logback-spring.xml \ No newline at end of file
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
new file mode 100644
index 0000000..5a82001
--- /dev/null
+++ b/src/main/resources/application-prod.yml
@@ -0,0 +1,8 @@
+confagent:
+ promtail:
+ cmdLine: /home/fang/loki/config.conf
+ config: /home/fang/loki/promtail.yml
+ defaultIP: 127.0.0.1
+
+logging:
+ config: config/logback-spring.xml
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..c486da1
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,19 @@
+server:
+ tomcat:
+ uri-encoding: UTF-8
+ basedir: /opt/nezha/nz-talon/tmp
+ port: 10090
+ servlet:
+ context-path: /nz-talon
+
+spring:
+ profiles:
+ active: dev
+
+confagent:
+ tokenFile: src/main/resources/config/token.auth
+ authFile: src/main/resources/config/auth.yml
+ versionFile: src/main/resources/config/promtail.version
+ promtail:
+ query:
+ auth: false \ No newline at end of file
diff --git a/src/main/resources/config/auth.yml b/src/main/resources/config/auth.yml
new file mode 100644
index 0000000..6f07be4
--- /dev/null
+++ b/src/main/resources/config/auth.yml
@@ -0,0 +1,3 @@
+auth:
+ name: nezha
+ pin: nezha \ No newline at end of file
diff --git a/src/main/resources/config/promtail.version b/src/main/resources/config/promtail.version
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/src/main/resources/config/promtail.version
@@ -0,0 +1 @@
+1 \ No newline at end of file
diff --git a/src/main/resources/config/token.auth b/src/main/resources/config/token.auth
new file mode 100644
index 0000000..5a5924c
--- /dev/null
+++ b/src/main/resources/config/token.auth
@@ -0,0 +1 @@
+088723c3 \ No newline at end of file
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..5f461a0
--- /dev/null
+++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <include resource="org/springframework/boot/logging/logback/base.xml" />
+ <logger name="org.springframework.web" level="info" />
+ <logger name="org.springboot.sample" level="info" />
+ <logger name="org.apache" level="info" />
+ <logger name="org.springframework" level="info" />
+ <logger name="druid.sql" level="info" />
+ <logger name="com.springboot" level="debug" />
+
+ <property name="log.path" value="./logs/" />
+ <!-- 输出格式 -->
+ <property name="out.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />
+ <!-- 活动文件的大小 -->
+ <property name="max.file.size" value="100MB"/>
+ <!-- 保留的归档文件的最大数量 -->
+ <property name="max.history" value="30"/>
+ <!-- 控制所有归档日志文件的总大小 -->
+ <property name="total.size.cap" value="5GB"/>
+
+ <!-- 2.2 level为 INFO 日志,时间滚动输出 -->
+ <appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <!-- 正在记录的日志文档的路径及文档名 -->
+ <file>${log.path}/nz-talon.log</file>
+ <!--日志文档输出格式 -->
+ <encoder>
+ <pattern>${out.pattern}</pattern>
+ <charset>UTF-8</charset>
+ </encoder>
+ <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${log.path}/nz-talon-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <maxFileSize>${max.file.size}</maxFileSize>
+ <maxHistory>${max.history}</maxHistory>
+ <totalSizeCap>${total.size.cap}</totalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+ <!-- 2.1 level为 ERROR 日志,时间滚动输出 -->
+ <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <!-- 正在记录的日志文档的路径及文档名 -->
+ <file>${log.path}/nz-talon-error.log</file>
+ <!--日志文档输出格式 -->
+ <encoder>
+ <pattern>${out.pattern}</pattern>
+ <charset>UTF-8</charset>
+ </encoder>
+ <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${log.path}/nz-talon-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <maxFileSize>${max.file.size}</maxFileSize>
+ <maxHistory>${max.history}</maxHistory>
+ <totalSizeCap>${total.size.cap}</totalSizeCap>
+ </rollingPolicy>
+ <!-- 此日志文档只记录debug级别的 -->
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>error</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ </appender>
+
+ <root level="INFO">
+ <appender-ref ref="LOG_FILE" />
+ <appender-ref ref="ERROR_FILE" />
+ </root>
+
+</configuration> \ No newline at end of file
diff --git a/src/test/java/net/geedge/confagent/ConfagentApplicationTests.java b/src/test/java/net/geedge/confagent/ConfagentApplicationTests.java
new file mode 100644
index 0000000..ab3a794
--- /dev/null
+++ b/src/test/java/net/geedge/confagent/ConfagentApplicationTests.java
@@ -0,0 +1,13 @@
+package net.geedge.confagent;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ConfagentApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}