初始提交
This commit is contained in:
commit
7f725c6e65
49 files changed
+2910
No files matched your search
@@ -0,0 +1,2 @@
|
|||||||
|
/mvnw text eol=lf
|
||||||
|
*.cmd text eol=crlf
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
Generated
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 已忽略包含查询文件的默认文件夹
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
||||||
Generated
+5
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
Generated
+18
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CompilerConfiguration">
|
||||||
|
<annotationProcessing>
|
||||||
|
<profile name="Maven default annotation processors profile" enabled="true">
|
||||||
|
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||||
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
|
<outputRelativeToContentRoot value="true" />
|
||||||
|
<module name="pve-back-api" />
|
||||||
|
</profile>
|
||||||
|
</annotationProcessing>
|
||||||
|
</component>
|
||||||
|
<component name="JavacSettings">
|
||||||
|
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||||
|
<module name="pve-back-api" options="-parameters" />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="VulnerableLibrariesLocal" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="isIgnoringEnabled" value="true" />
|
||||||
|
<option name="ignoredModules">
|
||||||
|
<list>
|
||||||
|
<option value="pve-back-api" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="ignoredPackages">
|
||||||
|
<list>
|
||||||
|
<option value="org.assertj:assertj-core:3.27.6" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="ignoredReasons">
|
||||||
|
<list>
|
||||||
|
<option value="进行中" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
Generated
+20
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RemoteRepositoriesConfiguration">
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Central Repository" />
|
||||||
|
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Maven Central repository" />
|
||||||
|
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="jboss.community" />
|
||||||
|
<option name="name" value="JBoss Community repository" />
|
||||||
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+14
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="25" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+220
@@ -0,0 +1,220 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="b81ac005-9b3d-43a0-a86e-8b9849200d36" name="更改" comment="">
|
||||||
|
<change afterPath="$PROJECT_DIR$/.gitattributes" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/.gitignore" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/codeStyles/codeStyleConfig.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/compiler.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/encodings.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/jarRepositories.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/.mvn/wrapper/maven-wrapper.properties" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/HELP.md" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/conf/config.yaml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/examples.md" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/fuck-u-code" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/fuck-u-code.exe" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/mvnw" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/mvnw.cmd" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/Main.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/config/AppConfig.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/config/ConfigManager.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/config/GlobalConfig.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/config/YamlConfigLoader.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/route/pve/status.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/top/gtb520/java/pve_back_api/route/test.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/resources/application.properties" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/resources/config.yaml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/test/java/top/gtb520/java/pve_back_api/MainTests.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/test/java/top/gtb520/java/pve_back_api/ResourcesResultTest.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/application.properties" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/config.yaml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/Main.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/config/AppConfig.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/config/ConfigManager.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/config/GlobalConfig.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/config/YamlConfigLoader.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/route/pve/status.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/classes/top/gtb520/java/pve_back_api/route/test.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/surefire-reports/2026-02-04T18-14-48_524.dumpstream" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/surefire-reports/TEST-top.gtb520.java.pve_back_api.ResourcesResultTest.xml" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/surefire-reports/top.gtb520.java.pve_back_api.ResourcesResultTest.txt" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/test-classes/top/gtb520/java/pve_back_api/MainTests.class" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/target/test-classes/top/gtb520/java/pve_back_api/ResourcesResultTest.class" afterDir="false" />
|
||||||
|
</list>
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="ComposerSettings">
|
||||||
|
<execution />
|
||||||
|
</component>
|
||||||
|
<component name="FileTemplateManagerImpl">
|
||||||
|
<option name="RECENT_TEMPLATES">
|
||||||
|
<list>
|
||||||
|
<option value="Class" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="Git.Settings">
|
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
|
</component>
|
||||||
|
<component name="KubernetesApiPersistence">{}</component>
|
||||||
|
<component name="KubernetesApiProvider">{
|
||||||
|
"isMigrated": true
|
||||||
|
}</component>
|
||||||
|
<component name="MacroExpansionManager">
|
||||||
|
<option name="directoryName" value="IwU62d1q" />
|
||||||
|
</component>
|
||||||
|
<component name="MavenImportPreferences">
|
||||||
|
<option name="generalSettings">
|
||||||
|
<MavenGeneralSettings>
|
||||||
|
<option name="mavenHomeTypeForPersistence" value="WRAPPER" />
|
||||||
|
</MavenGeneralSettings>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="MavenRunner">
|
||||||
|
<option name="skipTests" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PhpWorkspaceProjectConfiguration" interpreter_name="php-7.4" />
|
||||||
|
<component name="ProjectCodeStyleSettingsMigration">
|
||||||
|
<option name="version" value="2" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectColorInfo">{
|
||||||
|
"associatedIndex": 3
|
||||||
|
}</component>
|
||||||
|
<component name="ProjectId" id="397Avb8RVGvCmzdVVMJdi8C4ou0" />
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="flattenModules" value="true" />
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
<option name="showMembers" value="true" />
|
||||||
|
<option name="showVisibilityIcons" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
|
"keyToString": {
|
||||||
|
"JAR 应用程序.pve-back-api-0.0.1-SNAPSHOT.jar.executor": "Run",
|
||||||
|
"JUnit.ResourcesResultTest.executor": "Run",
|
||||||
|
"JUnit.ResourcesResultTest.test.executor": "Run",
|
||||||
|
"Maven.pve-back-api [clean].executor": "Run",
|
||||||
|
"Maven.pve-back-api [org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file].executor": "Run",
|
||||||
|
"Maven.pve-back-api [org.apache.maven.plugins:maven-install-plugin:3.1.4:install].executor": "Run",
|
||||||
|
"Maven.pve-back-api [org.apache.maven.plugins:maven-jar-plugin:3.4.2:jar].executor": "Run",
|
||||||
|
"Maven.pve-back-api [package].executor": "Run",
|
||||||
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||||
|
"RequestMappingsPanelOrder0": "0",
|
||||||
|
"RequestMappingsPanelOrder1": "1",
|
||||||
|
"RequestMappingsPanelWidth0": "75",
|
||||||
|
"RequestMappingsPanelWidth1": "75",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||||
|
"Spring Boot.Main.executor": "Run",
|
||||||
|
"git-widget-placeholder": "main",
|
||||||
|
"go.import.settings.migrated": "true",
|
||||||
|
"ignore.virus.scanning.warn.message": "true",
|
||||||
|
"kotlin-language-version-configured": "true",
|
||||||
|
"last_opened_file_path": "G:/Project/Java/pve-back-api",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||||
|
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
}
|
||||||
|
}]]></component>
|
||||||
|
<component name="RecentsManager">
|
||||||
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="G:\Project\Java\pve-back-api" />
|
||||||
|
</key>
|
||||||
|
<key name="MoveClassesOrPackagesDialog.RECENTS_KEY">
|
||||||
|
<recent name="top.gtb520.java.pve_back_api.route" />
|
||||||
|
</key>
|
||||||
|
</component>
|
||||||
|
<component name="RunManager" selected="JUnit.ResourcesResultTest">
|
||||||
|
<configuration name="ResourcesResultTest" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
||||||
|
<module name="pve-back-api" />
|
||||||
|
<extension name="coverage">
|
||||||
|
<pattern>
|
||||||
|
<option name="PATTERN" value="top.gtb520.java.pve_back_api.*" />
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
</pattern>
|
||||||
|
</extension>
|
||||||
|
<option name="PACKAGE_NAME" value="top.gtb520.java.pve_back_api" />
|
||||||
|
<option name="MAIN_CLASS_NAME" value="top.gtb520.java.pve_back_api.ResourcesResultTest" />
|
||||||
|
<option name="TEST_OBJECT" value="class" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
<configuration name="ResourcesResultTest.test" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
|
||||||
|
<module name="pve-back-api" />
|
||||||
|
<extension name="coverage">
|
||||||
|
<pattern>
|
||||||
|
<option name="PATTERN" value="top.gtb520.java.pve_back_api.*" />
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
</pattern>
|
||||||
|
</extension>
|
||||||
|
<option name="PACKAGE_NAME" value="top.gtb520.java.pve_back_api" />
|
||||||
|
<option name="MAIN_CLASS_NAME" value="top.gtb520.java.pve_back_api.ResourcesResultTest" />
|
||||||
|
<option name="METHOD_NAME" value="test" />
|
||||||
|
<option name="TEST_OBJECT" value="method" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
<configuration name="pve-back-api-0.0.1-SNAPSHOT.jar" type="JarApplication" temporary="true">
|
||||||
|
<option name="JAR_PATH" value="$PROJECT_DIR$/target/pve-back-api-0.0.1-SNAPSHOT.jar" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
<configuration name="Main (1)" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
||||||
|
<module name="pve-back-api" />
|
||||||
|
<option name="SPRING_BOOT_MAIN_CLASS" value="top.gtb520.java.pve_back_api.Main" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
<configuration name="Main" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" nameIsGenerated="true">
|
||||||
|
<module name="pve-back-api" />
|
||||||
|
<option name="SPRING_BOOT_MAIN_CLASS" value="top.gtb520.java.pve_back_api.main.Main" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
<recent_temporary>
|
||||||
|
<list>
|
||||||
|
<item itemvalue="JUnit.ResourcesResultTest" />
|
||||||
|
<item itemvalue="JUnit.ResourcesResultTest.test" />
|
||||||
|
<item itemvalue="JAR 应用程序.pve-back-api-0.0.1-SNAPSHOT.jar" />
|
||||||
|
</list>
|
||||||
|
</recent_temporary>
|
||||||
|
</component>
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="默认任务">
|
||||||
|
<changelist id="b81ac005-9b3d-43a0-a86e-8b9849200d36" name="更改" comment="" />
|
||||||
|
<created>1770036968595</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1770036968595</updated>
|
||||||
|
<workItem from="1770036971569" duration="418000" />
|
||||||
|
<workItem from="1770037429449" duration="210000" />
|
||||||
|
<workItem from="1770037658639" duration="8615000" />
|
||||||
|
<workItem from="1770086564958" duration="25373000" />
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
<option name="version" value="3" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
wrapperVersion=3.3.4
|
||||||
|
distributionType=only-script
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Getting Started
|
||||||
|
|
||||||
|
### Reference Documentation
|
||||||
|
|
||||||
|
For further reference, please consider the following sections:
|
||||||
|
|
||||||
|
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
|
||||||
|
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/4.0.2/maven-plugin)
|
||||||
|
* [Create an OCI image](https://docs.spring.io/spring-boot/4.0.2/maven-plugin/build-image.html)
|
||||||
|
* [Spring Data Redis (Access+Driver)](https://docs.spring.io/spring-boot/4.0.2/reference/data/nosql.html#data.nosql.redis)
|
||||||
|
* [JDBC API](https://docs.spring.io/spring-boot/4.0.2/reference/data/sql.html)
|
||||||
|
* [Spring Shell](https://docs.spring.io/spring-shell/reference/index.html)
|
||||||
|
* [WebSocket](https://docs.spring.io/spring-boot/4.0.2/reference/messaging/websockets.html)
|
||||||
|
|
||||||
|
### Guides
|
||||||
|
|
||||||
|
The following guides illustrate how to use some features concretely:
|
||||||
|
|
||||||
|
* [Messaging with Redis](https://spring.io/guides/gs/messaging-redis/)
|
||||||
|
* [Accessing Relational Data using JDBC with Spring](https://spring.io/guides/gs/relational-data-access/)
|
||||||
|
* [Managing Transactions](https://spring.io/guides/gs/managing-transactions/)
|
||||||
|
* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/)
|
||||||
|
* [Using WebSocket to build an interactive web application](https://spring.io/guides/gs/messaging-stomp-websocket/)
|
||||||
|
|
||||||
|
### Maven Parent overrides
|
||||||
|
|
||||||
|
Due to Maven's design, elements are inherited from the parent POM to the project POM.
|
||||||
|
While most of the inheritance is fine, it also inherits unwanted elements like `<license>` and `<developers>` from the
|
||||||
|
parent.
|
||||||
|
To prevent this, the project POM contains empty overrides for these elements.
|
||||||
|
If you manually switch to a different parent and actually want the inheritance, you need to remove those overrides.
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# 全局配置
|
||||||
|
global:
|
||||||
|
http_ip: "0.0.0.0"
|
||||||
|
http_port: "11554"
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
database:
|
||||||
|
mysql_jdbc: "jdbc:mysql://10.168.2.2:3306/pve_monitor?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrlInLocalInfile=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&allowLoadLocalInfile=true&allowUrlInLocalInfile=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&allowLoadLocalInfile=true&allowUrlInLocal"
|
||||||
|
mysql_username: "root"
|
||||||
|
mysql_password: "Password"
|
||||||
|
|
||||||
|
# PVE配置
|
||||||
|
pve:
|
||||||
|
# PVE后端地址,示例:https://192.168.1.1:8006/ (协议HTTPS,带结尾的“/”,不保留结尾其他参数)
|
||||||
|
url: "https://10.168.2.18:8006/"
|
||||||
|
api_tocken_name: "dev"
|
||||||
|
api_token_id: "root@pam!dev"
|
||||||
|
api_token_secret: "68e9dac5-3110-4f1b-b33a-feeaa4014f63"
|
||||||
+431
@@ -0,0 +1,431 @@
|
|||||||
|
# Basic Examples
|
||||||
|
|
||||||
|
This guide provides common usage patterns and practical examples for getting started with the Proxmox VE API.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### **Basic Connection**
|
||||||
|
|
||||||
|
```java
|
||||||
|
import it.corsinvest.proxmoxve.api.*;
|
||||||
|
|
||||||
|
// Create client and authenticate
|
||||||
|
var client = new PveClient("pve.example.com", 8006);
|
||||||
|
client.setApiToken("user@pve!token=uuid");
|
||||||
|
|
||||||
|
// Test connection
|
||||||
|
var version = client.getVersion().version();
|
||||||
|
if (version.isSuccessStatusCode()) {
|
||||||
|
System.out.println("Connected to Proxmox VE " +
|
||||||
|
version.getResponse().get("data").get("version").asText());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Client Setup with Error Handling**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static PveClient createClient() {
|
||||||
|
var client = new PveClient("pve.local", 8006);
|
||||||
|
client.setValidateCertificate(false); // For development
|
||||||
|
client.setTimeout(120000); // 2 minutes
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use API token or login
|
||||||
|
String token = System.getenv("PVE_TOKEN");
|
||||||
|
if (token != null && !token.isEmpty()) {
|
||||||
|
client.setApiToken(token);
|
||||||
|
} else {
|
||||||
|
boolean success = client.login("root@pam", "password");
|
||||||
|
if (!success) {
|
||||||
|
throw new Exception("Authentication failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return client;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println("Failed to create client: " + ex.getMessage());
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Virtual Machine Operations
|
||||||
|
|
||||||
|
### **List Virtual Machines**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Get all VMs in cluster
|
||||||
|
var resources = client.getCluster().getResources().resources().getData();
|
||||||
|
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
if ("qemu".equals(resource.get("type").asText())) {
|
||||||
|
System.out.printf("VM %d: %s on %s - %s%n",
|
||||||
|
resource.get("vmid").asInt(),
|
||||||
|
resource.get("name").asText(),
|
||||||
|
resource.get("node").asText(),
|
||||||
|
resource.get("status").asText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter running VMs
|
||||||
|
var runningVms = new ArrayList<JsonNode>();
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
if ("qemu".equals(resource.get("type").asText()) &&
|
||||||
|
"running".equals(resource.get("status").asText())) {
|
||||||
|
runningVms.add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Running VMs: " + runningVms.size());
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Get VM Configuration**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Get VM configuration
|
||||||
|
var config = client.getNodes().get("pve1").getQemu().get(100)
|
||||||
|
.getConfig().vmConfig().getData();
|
||||||
|
|
||||||
|
System.out.println("VM Name: " + config.get("name").asText());
|
||||||
|
System.out.println("Memory: " + config.get("memory").asInt() + " MB");
|
||||||
|
System.out.println("CPU Cores: " + config.get("cores").asInt());
|
||||||
|
System.out.println("Boot Order: " + config.get("boot").asText());
|
||||||
|
```
|
||||||
|
|
||||||
|
### **VM Power Management**
|
||||||
|
|
||||||
|
```java
|
||||||
|
var vm = client.getNodes().get("pve1").getQemu().get(100);
|
||||||
|
|
||||||
|
// Start VM
|
||||||
|
vm.getStatus().start();
|
||||||
|
System.out.println("VM started successfully");
|
||||||
|
|
||||||
|
// Stop VM
|
||||||
|
vm.getStatus().stop();
|
||||||
|
System.out.println("VM stopped successfully");
|
||||||
|
|
||||||
|
// Restart VM
|
||||||
|
vm.getStatus().reboot();
|
||||||
|
System.out.println("VM restarted successfully");
|
||||||
|
|
||||||
|
// Get current status
|
||||||
|
var data = vm.getStatus().current().getData();
|
||||||
|
System.out.println("VM Status: " + data.get("status").asText());
|
||||||
|
System.out.printf("CPU Usage: %.2f%%%n", data.get("cpu").asDouble() * 100);
|
||||||
|
System.out.printf("Memory: %.2f%%%n",
|
||||||
|
(data.get("mem").asDouble() / data.get("maxmem").asDouble()) * 100);
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Snapshot Management**
|
||||||
|
|
||||||
|
```java
|
||||||
|
var vm = client.getNodes().get("pve1").getQemu().get(100);
|
||||||
|
|
||||||
|
// Create snapshot
|
||||||
|
vm.getSnapshot().snapshot("backup-2024", "Pre-update backup");
|
||||||
|
System.out.println("Snapshot created successfully");
|
||||||
|
|
||||||
|
// List snapshots
|
||||||
|
var snapshots = vm.getSnapshot().snapshotList().getData();
|
||||||
|
System.out.println("Available snapshots:");
|
||||||
|
for (JsonNode snapshot : snapshots) {
|
||||||
|
System.out.printf(" - %s: %s (%s)%n",
|
||||||
|
snapshot.get("name").asText(),
|
||||||
|
snapshot.get("description").asText(),
|
||||||
|
snapshot.get("snaptime").asText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore snapshot
|
||||||
|
vm.getSnapshot().get("backup-2024").rollback();
|
||||||
|
System.out.println("Snapshot restored successfully");
|
||||||
|
|
||||||
|
// Delete snapshot
|
||||||
|
vm.getSnapshot().get("backup-2024").delsnapshot();
|
||||||
|
System.out.println("Snapshot deleted successfully");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Container Operations
|
||||||
|
|
||||||
|
### **List Containers**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Get all containers
|
||||||
|
var resources = client.getCluster().getResources().resources().getData();
|
||||||
|
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
if ("lxc".equals(resource.get("type").asText())) {
|
||||||
|
System.out.printf("CT %d: %s on %s - %s%n",
|
||||||
|
resource.get("vmid").asInt(),
|
||||||
|
resource.get("name").asText(),
|
||||||
|
resource.get("node").asText(),
|
||||||
|
resource.get("status").asText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Container Management**
|
||||||
|
|
||||||
|
```java
|
||||||
|
var container = client.getNodes().get("pve1").getLxc().get(101);
|
||||||
|
|
||||||
|
// Get container configuration
|
||||||
|
var ctConfig = container.getConfig().vmConfig().getData();
|
||||||
|
System.out.println("Container: " + ctConfig.get("hostname").asText());
|
||||||
|
System.out.println("OS Template: " + ctConfig.get("ostemplate").asText());
|
||||||
|
System.out.println("Memory: " + ctConfig.get("memory").asInt() + " MB");
|
||||||
|
|
||||||
|
// Start container
|
||||||
|
container.getStatus().start();
|
||||||
|
System.out.println("Container started");
|
||||||
|
|
||||||
|
// Get container status
|
||||||
|
var data = container.getStatus().current().getData();
|
||||||
|
System.out.println("Status: " + data.get("status").asText());
|
||||||
|
System.out.println("Uptime: " + data.get("uptime").asInt() + " seconds");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cluster Operations
|
||||||
|
|
||||||
|
### **Cluster Status**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Get cluster status
|
||||||
|
var status = client.getCluster().getStatus().getStatus().getData();
|
||||||
|
System.out.println("Cluster Status:");
|
||||||
|
for (JsonNode item : status) {
|
||||||
|
System.out.printf(" %s: %s - %s%n",
|
||||||
|
item.get("type").asText(),
|
||||||
|
item.get("name").asText(),
|
||||||
|
item.get("status").asText());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Node Information**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Get all nodes
|
||||||
|
var nodes = client.getNodes().index().getData();
|
||||||
|
System.out.println("Available Nodes:");
|
||||||
|
for (JsonNode node : nodes) {
|
||||||
|
System.out.println(" " + node.get("node").asText() + ": " +
|
||||||
|
node.get("status").asText());
|
||||||
|
System.out.printf(" CPU: %.2f%%%n", node.get("cpu").asDouble() * 100);
|
||||||
|
System.out.printf(" Memory: %.2f%%%n",
|
||||||
|
(node.get("mem").asDouble() / node.get("maxmem").asDouble()) * 100);
|
||||||
|
System.out.println(" Uptime: " +
|
||||||
|
java.time.Duration.ofSeconds(node.get("uptime").asInt()));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Storage Information**
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Get storage for a specific node
|
||||||
|
var storages = client.getNodes().get("pve1").getStorage().index().getData();
|
||||||
|
System.out.println("Available Storage:");
|
||||||
|
for (JsonNode storage : storages) {
|
||||||
|
double usedPercent = (storage.get("used").asDouble() /
|
||||||
|
storage.get("total").asDouble()) * 100;
|
||||||
|
System.out.printf(" %s (%s): %.1f%% used%n",
|
||||||
|
storage.get("storage").asText(),
|
||||||
|
storage.get("type").asText(),
|
||||||
|
usedPercent);
|
||||||
|
System.out.printf(" Total: %.2f GB%n",
|
||||||
|
storage.get("total").asLong() / (1024.0 * 1024 * 1024));
|
||||||
|
System.out.printf(" Available: %.2f GB%n",
|
||||||
|
storage.get("avail").asLong() / (1024.0 * 1024 * 1024));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### **Resource Monitoring**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static void monitorResources(PveClient client) throws InterruptedException {
|
||||||
|
while (true) {
|
||||||
|
var resources = client.getCluster().getResources().resources().getData();
|
||||||
|
|
||||||
|
System.out.print("\033[H\033[2J"); // Clear console
|
||||||
|
System.out.flush();
|
||||||
|
System.out.println("Proxmox VE Resource Monitor - " +
|
||||||
|
java.time.LocalTime.now());
|
||||||
|
System.out.println("=".repeat(50));
|
||||||
|
|
||||||
|
// Count by type
|
||||||
|
int nodeCount = 0, vmCount = 0, ctCount = 0;
|
||||||
|
int runningVms = 0, runningCts = 0;
|
||||||
|
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
String type = resource.get("type").asText();
|
||||||
|
String status = resource.get("status").asText();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "node":
|
||||||
|
nodeCount++;
|
||||||
|
System.out.printf(" %s: CPU %.1f%%, Memory %.1f%%%n",
|
||||||
|
resource.get("node").asText(),
|
||||||
|
resource.get("cpu").asDouble() * 100,
|
||||||
|
(resource.get("mem").asDouble() /
|
||||||
|
resource.get("maxmem").asDouble()) * 100);
|
||||||
|
break;
|
||||||
|
case "qemu":
|
||||||
|
vmCount++;
|
||||||
|
if ("running".equals(status)) runningVms++;
|
||||||
|
break;
|
||||||
|
case "lxc":
|
||||||
|
ctCount++;
|
||||||
|
if ("running".equals(status)) runningCts++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("\nNodes: %d%n", nodeCount);
|
||||||
|
System.out.printf("VMs: %d (%d running)%n", vmCount, runningVms);
|
||||||
|
System.out.printf("Containers: %d (%d running)%n", ctCount, runningCts);
|
||||||
|
|
||||||
|
Thread.sleep(5000); // Update every 5 seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Batch Operations**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static void batchVmOperation(PveClient client, int[] vmIds, String operation) {
|
||||||
|
var resources = client.getCluster().getResources().resources().getData();
|
||||||
|
|
||||||
|
for (int vmId : vmIds) {
|
||||||
|
// Find VM location
|
||||||
|
JsonNode vmResource = null;
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
if ("qemu".equals(resource.get("type").asText()) &&
|
||||||
|
resource.get("vmid").asInt() == vmId) {
|
||||||
|
vmResource = resource;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vmResource != null) {
|
||||||
|
String node = vmResource.get("node").asText();
|
||||||
|
var vm = client.getNodes().get(node).getQemu().get(vmId);
|
||||||
|
|
||||||
|
Result result = switch (operation.toLowerCase()) {
|
||||||
|
case "start" -> vm.getStatus().start();
|
||||||
|
case "stop" -> vm.getStatus().stop();
|
||||||
|
case "restart" -> vm.getStatus().reboot();
|
||||||
|
default -> throw new IllegalArgumentException("Unknown operation: " + operation);
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean success = result.isSuccessStatusCode();
|
||||||
|
System.out.printf("VM %d %s: %s%n",
|
||||||
|
vmId, operation, success ? "Success" : "Failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Performance Monitoring**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static void getVmPerformance(PveClient client, String node, int vmId) {
|
||||||
|
var data = client.getNodes().get(node).getQemu().get(vmId)
|
||||||
|
.getStatus().current().getData();
|
||||||
|
|
||||||
|
System.out.println("VM " + vmId + " Performance:");
|
||||||
|
System.out.println(" Status: " + data.get("status").asText());
|
||||||
|
System.out.printf(" CPU Usage: %.2f%%%n", data.get("cpu").asDouble() * 100);
|
||||||
|
System.out.printf(" Memory: %.2f GB / %.2f GB (%.1f%%)%n",
|
||||||
|
data.get("mem").asLong() / (1024.0 * 1024 * 1024),
|
||||||
|
data.get("maxmem").asLong() / (1024.0 * 1024 * 1024),
|
||||||
|
(data.get("mem").asDouble() / data.get("maxmem").asDouble()) * 100);
|
||||||
|
System.out.printf(" Disk Read: %.2f MB%n",
|
||||||
|
data.get("diskread").asLong() / (1024.0 * 1024));
|
||||||
|
System.out.printf(" Disk Write: %.2f MB%n",
|
||||||
|
data.get("diskwrite").asLong() / (1024.0 * 1024));
|
||||||
|
System.out.printf(" Network In: %.2f MB%n",
|
||||||
|
data.get("netin").asLong() / (1024.0 * 1024));
|
||||||
|
System.out.printf(" Network Out: %.2f MB%n",
|
||||||
|
data.get("netout").asLong() / (1024.0 * 1024));
|
||||||
|
System.out.println(" Uptime: " +
|
||||||
|
java.time.Duration.ofSeconds(data.get("uptime").asInt()));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### **Error Handling**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static boolean safeVmOperation(PveClient client, String node, int vmId, String operation) {
|
||||||
|
try {
|
||||||
|
var vm = client.getNodes().get(node).getQemu().get(vmId);
|
||||||
|
|
||||||
|
Result result = switch (operation.toLowerCase()) {
|
||||||
|
case "start" -> vm.getStatus().start();
|
||||||
|
case "stop" -> vm.getStatus().stop();
|
||||||
|
default -> throw new IllegalArgumentException("Unknown operation: " + operation);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (result.isSuccessStatusCode()) {
|
||||||
|
System.out.println("VM " + vmId + " " + operation + " successful");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
System.out.println("VM " + vmId + " " + operation + " failed: " +
|
||||||
|
result.getError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println("Exception during " + operation + " on VM " + vmId + ": " +
|
||||||
|
ex.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Resource Discovery**
|
||||||
|
|
||||||
|
```java
|
||||||
|
public static class VmLocation {
|
||||||
|
public String node;
|
||||||
|
public int vmId;
|
||||||
|
|
||||||
|
public VmLocation(String node, int vmId) {
|
||||||
|
this.node = node;
|
||||||
|
this.vmId = vmId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VmLocation findVm(PveClient client, String vmName) {
|
||||||
|
var resources = client.getCluster().getResources().resources().getData();
|
||||||
|
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
if ("qemu".equals(resource.get("type").asText()) &&
|
||||||
|
vmName.equalsIgnoreCase(resource.get("name").asText())) {
|
||||||
|
return new VmLocation(
|
||||||
|
resource.get("node").asText(),
|
||||||
|
resource.get("vmid").asInt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
var vmLocation = findVm(client, "web-server");
|
||||||
|
if (vmLocation != null) {
|
||||||
|
var vm = client.getNodes().get(vmLocation.node).getQemu().get(vmLocation.vmId);
|
||||||
|
// ... work with VM
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
unknown shorthand flag: 'G' in -G:\Project\Java\pve-back-api
|
||||||
Binary file not shown.
@@ -0,0 +1,295 @@
|
|||||||
|
#!/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
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Apache Maven Wrapper startup batch script, version 3.3.4
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
|
||||||
|
# MVNW_REPOURL - repo url base for downloading maven distribution
|
||||||
|
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||||
|
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set -euf
|
||||||
|
[ "${MVNW_VERBOSE-}" != debug ] || set -x
|
||||||
|
|
||||||
|
# OS specific support.
|
||||||
|
native_path() { printf %s\\n "$1"; }
|
||||||
|
case "$(uname)" in
|
||||||
|
CYGWIN* | MINGW*)
|
||||||
|
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
|
||||||
|
native_path() { cygpath --path --windows "$1"; }
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# set JAVACMD and JAVACCMD
|
||||||
|
set_java_home() {
|
||||||
|
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
|
||||||
|
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"
|
||||||
|
JAVACCMD="$JAVA_HOME/jre/sh/javac"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
JAVACCMD="$JAVA_HOME/bin/javac"
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
|
||||||
|
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
|
||||||
|
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="$(
|
||||||
|
'set' +e
|
||||||
|
'unset' -f command 2>/dev/null
|
||||||
|
'command' -v java
|
||||||
|
)" || :
|
||||||
|
JAVACCMD="$(
|
||||||
|
'set' +e
|
||||||
|
'unset' -f command 2>/dev/null
|
||||||
|
'command' -v javac
|
||||||
|
)" || :
|
||||||
|
|
||||||
|
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
|
||||||
|
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# hash string like Java String::hashCode
|
||||||
|
hash_string() {
|
||||||
|
str="${1:-}" h=0
|
||||||
|
while [ -n "$str" ]; do
|
||||||
|
char="${str%"${str#?}"}"
|
||||||
|
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
|
||||||
|
str="${str#?}"
|
||||||
|
done
|
||||||
|
printf %x\\n $h
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose() { :; }
|
||||||
|
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf %s\\n "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trim() {
|
||||||
|
# MWRAPPER-139:
|
||||||
|
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
|
||||||
|
# Needed for removing poorly interpreted newline sequences when running in more
|
||||||
|
# exotic environments such as mingw bash on Windows.
|
||||||
|
printf "%s" "${1}" | tr -d '[:space:]'
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptDir="$(dirname "$0")"
|
||||||
|
scriptName="$(basename "$0")"
|
||||||
|
|
||||||
|
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
|
||||||
|
while IFS="=" read -r key value; do
|
||||||
|
case "${key-}" in
|
||||||
|
distributionUrl) distributionUrl=$(trim "${value-}") ;;
|
||||||
|
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
|
||||||
|
esac
|
||||||
|
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
|
||||||
|
case "${distributionUrl##*/}" in
|
||||||
|
maven-mvnd-*bin.*)
|
||||||
|
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
|
||||||
|
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
|
||||||
|
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
|
||||||
|
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
|
||||||
|
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
|
||||||
|
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
|
||||||
|
*)
|
||||||
|
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
|
||||||
|
distributionPlatform=linux-amd64
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
|
||||||
|
;;
|
||||||
|
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
|
||||||
|
*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||||
|
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||||
|
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
|
||||||
|
distributionUrlName="${distributionUrl##*/}"
|
||||||
|
distributionUrlNameMain="${distributionUrlName%.*}"
|
||||||
|
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
|
||||||
|
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
|
||||||
|
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
|
||||||
|
|
||||||
|
exec_maven() {
|
||||||
|
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
|
||||||
|
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -d "$MAVEN_HOME" ]; then
|
||||||
|
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||||
|
exec_maven "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${distributionUrl-}" in
|
||||||
|
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
|
||||||
|
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# prepare tmp dir
|
||||||
|
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
|
||||||
|
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
|
||||||
|
trap clean HUP INT TERM EXIT
|
||||||
|
else
|
||||||
|
die "cannot create temp dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p -- "${MAVEN_HOME%/*}"
|
||||||
|
|
||||||
|
# Download and Install Apache Maven
|
||||||
|
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||||
|
verbose "Downloading from: $distributionUrl"
|
||||||
|
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||||
|
|
||||||
|
# select .zip or .tar.gz
|
||||||
|
if ! command -v unzip >/dev/null; then
|
||||||
|
distributionUrl="${distributionUrl%.zip}.tar.gz"
|
||||||
|
distributionUrlName="${distributionUrl##*/}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# verbose opt
|
||||||
|
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
|
||||||
|
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
|
||||||
|
|
||||||
|
# normalize http auth
|
||||||
|
case "${MVNW_PASSWORD:+has-password}" in
|
||||||
|
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||||
|
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
|
||||||
|
verbose "Found wget ... using wget"
|
||||||
|
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
|
||||||
|
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
|
||||||
|
verbose "Found curl ... using curl"
|
||||||
|
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
|
||||||
|
elif set_java_home; then
|
||||||
|
verbose "Falling back to use Java to download"
|
||||||
|
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
|
||||||
|
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||||
|
cat >"$javaSource" <<-END
|
||||||
|
public class Downloader extends java.net.Authenticator
|
||||||
|
{
|
||||||
|
protected java.net.PasswordAuthentication getPasswordAuthentication()
|
||||||
|
{
|
||||||
|
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
|
||||||
|
}
|
||||||
|
public static void main( String[] args ) throws Exception
|
||||||
|
{
|
||||||
|
setDefault( new Downloader() );
|
||||||
|
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END
|
||||||
|
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
|
||||||
|
verbose " - Compiling Downloader.java ..."
|
||||||
|
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
|
||||||
|
verbose " - Running Downloader.java ..."
|
||||||
|
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||||
|
if [ -n "${distributionSha256Sum-}" ]; then
|
||||||
|
distributionSha256Result=false
|
||||||
|
if [ "$MVN_CMD" = mvnd.sh ]; then
|
||||||
|
echo "Checksum validation is not supported for maven-mvnd." >&2
|
||||||
|
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||||
|
exit 1
|
||||||
|
elif command -v sha256sum >/dev/null; then
|
||||||
|
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
|
||||||
|
distributionSha256Result=true
|
||||||
|
fi
|
||||||
|
elif command -v shasum >/dev/null; then
|
||||||
|
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
|
||||||
|
distributionSha256Result=true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
|
||||||
|
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ $distributionSha256Result = false ]; then
|
||||||
|
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
|
||||||
|
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# unzip and move
|
||||||
|
if command -v unzip >/dev/null; then
|
||||||
|
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
|
||||||
|
else
|
||||||
|
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the actual extracted directory name (handles snapshots where filename != directory name)
|
||||||
|
actualDistributionDir=""
|
||||||
|
|
||||||
|
# First try the expected directory name (for regular distributions)
|
||||||
|
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
|
||||||
|
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
|
||||||
|
actualDistributionDir="$distributionUrlNameMain"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If not found, search for any directory with the Maven executable (for snapshots)
|
||||||
|
if [ -z "$actualDistributionDir" ]; then
|
||||||
|
# enable globbing to iterate over items
|
||||||
|
set +f
|
||||||
|
for dir in "$TMP_DOWNLOAD_DIR"/*; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
if [ -f "$dir/bin/$MVN_CMD" ]; then
|
||||||
|
actualDistributionDir="$(basename "$dir")"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
set -f
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$actualDistributionDir" ]; then
|
||||||
|
verbose "Contents of $TMP_DOWNLOAD_DIR:"
|
||||||
|
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
|
||||||
|
die "Could not find Maven distribution directory in extracted archive"
|
||||||
|
fi
|
||||||
|
|
||||||
|
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
|
||||||
|
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
|
||||||
|
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
|
||||||
|
|
||||||
|
clean || :
|
||||||
|
exec_maven "$@"
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
<# : batch portion
|
||||||
|
@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 http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Apache Maven Wrapper startup batch script, version 3.3.4
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
||||||
|
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||||
|
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
|
||||||
|
@SET __MVNW_CMD__=
|
||||||
|
@SET __MVNW_ERROR__=
|
||||||
|
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
|
||||||
|
@SET PSModulePath=
|
||||||
|
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
|
||||||
|
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
|
||||||
|
)
|
||||||
|
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
|
||||||
|
@SET __MVNW_PSMODULEP_SAVE=
|
||||||
|
@SET __MVNW_ARG0_NAME__=
|
||||||
|
@SET MVNW_USERNAME=
|
||||||
|
@SET MVNW_PASSWORD=
|
||||||
|
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
|
||||||
|
@echo Cannot start maven from wrapper >&2 && exit /b 1
|
||||||
|
@GOTO :EOF
|
||||||
|
: end batch / begin powershell #>
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
if ($env:MVNW_VERBOSE -eq "true") {
|
||||||
|
$VerbosePreference = "Continue"
|
||||||
|
}
|
||||||
|
|
||||||
|
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
|
||||||
|
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
|
||||||
|
if (!$distributionUrl) {
|
||||||
|
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
}
|
||||||
|
|
||||||
|
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
|
||||||
|
"maven-mvnd-*" {
|
||||||
|
$USE_MVND = $true
|
||||||
|
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
|
||||||
|
$MVN_CMD = "mvnd.cmd"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
$USE_MVND = $false
|
||||||
|
$MVN_CMD = $script -replace '^mvnw','mvn'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# apply MVNW_REPOURL and calculate MAVEN_HOME
|
||||||
|
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
|
||||||
|
if ($env:MVNW_REPOURL) {
|
||||||
|
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
|
||||||
|
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
|
||||||
|
}
|
||||||
|
$distributionUrlName = $distributionUrl -replace '^.*/',''
|
||||||
|
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
|
||||||
|
|
||||||
|
$MAVEN_M2_PATH = "$HOME/.m2"
|
||||||
|
if ($env:MAVEN_USER_HOME) {
|
||||||
|
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
|
||||||
|
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$MAVEN_WRAPPER_DISTS = $null
|
||||||
|
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
|
||||||
|
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
|
||||||
|
} else {
|
||||||
|
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
|
||||||
|
}
|
||||||
|
|
||||||
|
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
|
||||||
|
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
|
||||||
|
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
|
||||||
|
|
||||||
|
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
|
||||||
|
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
|
||||||
|
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||||
|
exit $?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
|
||||||
|
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
|
||||||
|
}
|
||||||
|
|
||||||
|
# prepare tmp dir
|
||||||
|
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
|
||||||
|
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
|
||||||
|
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
|
||||||
|
trap {
|
||||||
|
if ($TMP_DOWNLOAD_DIR.Exists) {
|
||||||
|
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||||
|
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
|
||||||
|
|
||||||
|
# Download and Install Apache Maven
|
||||||
|
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
|
||||||
|
Write-Verbose "Downloading from: $distributionUrl"
|
||||||
|
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
|
||||||
|
|
||||||
|
$webclient = New-Object System.Net.WebClient
|
||||||
|
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
|
||||||
|
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
|
||||||
|
}
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
|
||||||
|
|
||||||
|
# If specified, validate the SHA-256 sum of the Maven distribution zip file
|
||||||
|
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
|
||||||
|
if ($distributionSha256Sum) {
|
||||||
|
if ($USE_MVND) {
|
||||||
|
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
|
||||||
|
}
|
||||||
|
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
|
||||||
|
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
|
||||||
|
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# unzip and move
|
||||||
|
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
|
||||||
|
|
||||||
|
# Find the actual extracted directory name (handles snapshots where filename != directory name)
|
||||||
|
$actualDistributionDir = ""
|
||||||
|
|
||||||
|
# First try the expected directory name (for regular distributions)
|
||||||
|
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
|
||||||
|
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
|
||||||
|
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
|
||||||
|
$actualDistributionDir = $distributionUrlNameMain
|
||||||
|
}
|
||||||
|
|
||||||
|
# If not found, search for any directory with the Maven executable (for snapshots)
|
||||||
|
if (!$actualDistributionDir) {
|
||||||
|
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
|
||||||
|
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
|
||||||
|
if (Test-Path -Path $testPath -PathType Leaf) {
|
||||||
|
$actualDistributionDir = $_.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$actualDistributionDir) {
|
||||||
|
Write-Error "Could not find Maven distribution directory in extracted archive"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
|
||||||
|
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
|
||||||
|
try {
|
||||||
|
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
|
||||||
|
} catch {
|
||||||
|
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
|
||||||
|
Write-Error "fail to move MAVEN_HOME"
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
|
||||||
|
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 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>4.0.2</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>top.gtb520.java.pve_back_api.main</groupId>
|
||||||
|
<artifactId>pve-back-api</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>pve-back-api</name>
|
||||||
|
<description>pve-back-api</description>
|
||||||
|
<url/>
|
||||||
|
<licenses>
|
||||||
|
<license/>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer/>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection/>
|
||||||
|
<developerConnection/>
|
||||||
|
<tag/>
|
||||||
|
<url/>
|
||||||
|
</scm>
|
||||||
|
<properties>
|
||||||
|
<java.version>25</java.version>
|
||||||
|
<spring-shell.version>4.0.1</spring-shell.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webmvc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- YAML解析依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 日志依赖(可选,Spring Boot已包含) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-logging</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 连接后端PVE的依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>it.corsinvest.proxmoxve</groupId>
|
||||||
|
<artifactId>cv4pve-api-java</artifactId>
|
||||||
|
<version>9.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package top.gtb520.java.pve_back_api;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import top.gtb520.java.pve_back_api.config.AppConfig;
|
||||||
|
import top.gtb520.java.pve_back_api.config.ConfigManager;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("=== PVE后端API服务启动 ===");
|
||||||
|
|
||||||
|
// 初始化配置系统
|
||||||
|
initializeConfiguration();
|
||||||
|
|
||||||
|
// 执行初始化
|
||||||
|
Main main = new Main();
|
||||||
|
main.postInitialization();
|
||||||
|
|
||||||
|
// 启动Spring Boot应用
|
||||||
|
SpringApplication app = new SpringApplication(Main.class);
|
||||||
|
app.setDefaultProperties(Collections.singletonMap("server.port", AppConfig.HTTP_PORT));
|
||||||
|
app.run(args);
|
||||||
|
System.out.println("Spring框架加载完成!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化配置系统
|
||||||
|
*/
|
||||||
|
private static void initializeConfiguration() {
|
||||||
|
try {
|
||||||
|
String configPath = ConfigManager.initializeConfig();
|
||||||
|
if (configPath != null) {
|
||||||
|
System.out.println("配置系统初始化成功: " + configPath);
|
||||||
|
|
||||||
|
// 验证配置完整性
|
||||||
|
if (!AppConfig.validateRequiredConfig()) {
|
||||||
|
System.err.println("警告: 必要配置项不完整,请检查配置文件");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.err.println("配置系统初始化失败!");
|
||||||
|
// 使用默认配置继续运行
|
||||||
|
AppConfig.markAsLoaded();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("配置初始化异常: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
// 即使配置失败也继续启动应用
|
||||||
|
AppConfig.markAsLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用启动后的初始化工作
|
||||||
|
*/
|
||||||
|
public void postInitialization() {
|
||||||
|
System.out.println("=== 应用初始化 ===");
|
||||||
|
|
||||||
|
if (AppConfig.isConfigLoaded()) {
|
||||||
|
System.out.println("配置状态: 已加载");
|
||||||
|
|
||||||
|
// 显示关键配置信息
|
||||||
|
System.out.println("服务地址: " + AppConfig.HTTP_IP + ":" + AppConfig.HTTP_PORT);
|
||||||
|
System.out.println("PVE地址: " + AppConfig.PVE_URL);
|
||||||
|
|
||||||
|
// 可以在这里添加其他初始化逻辑
|
||||||
|
performAdditionalInitialization();
|
||||||
|
} else {
|
||||||
|
System.out.println("配置状态: 未加载,使用默认配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("应用初始化完成!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行额外的初始化任务
|
||||||
|
*/
|
||||||
|
private void performAdditionalInitialization() {
|
||||||
|
// 这里可以添加数据库连接测试、PVE连接验证等
|
||||||
|
try {
|
||||||
|
// 示例:测试数据库连接配置
|
||||||
|
if (AppConfig.MYSQL_JDBC != null && !AppConfig.MYSQL_JDBC.isEmpty()) {
|
||||||
|
System.out.println("数据库配置已设置");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 示例:测试PVE配置
|
||||||
|
if (AppConfig.PVE_URL != null && !AppConfig.PVE_URL.isEmpty()) {
|
||||||
|
System.out.println("PVE配置已设置");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("初始化检查时发生错误: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package top.gtb520.java.pve_back_api.config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局配置管理类
|
||||||
|
* 将配置文件中的配置项存储到全局静态变量中
|
||||||
|
*/
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
// 全局配置
|
||||||
|
public static volatile String HTTP_IP = "0.0.0.0";
|
||||||
|
public static volatile String HTTP_PORT = "8080";
|
||||||
|
|
||||||
|
// 数据库配置
|
||||||
|
public static volatile String MYSQL_JDBC = "";
|
||||||
|
public static volatile String MYSQL_USERNAME = "";
|
||||||
|
public static volatile String MYSQL_PASSWORD = "";
|
||||||
|
|
||||||
|
// PVE配置 - 保留原有URL并新增拆解配置
|
||||||
|
public static volatile String PVE_URL = "";
|
||||||
|
public static volatile String PVE_HOSTNAME_IP = "";
|
||||||
|
public static volatile String PVE_PORT = "8006";
|
||||||
|
public static volatile String PVE_PROTOCOL = "https";
|
||||||
|
public static volatile String PVE_API_TOKEN_NAME = "";
|
||||||
|
public static volatile String PVE_API_TOKEN_ID = "";
|
||||||
|
public static volatile String PVE_API_TOKEN_SECRET = "";
|
||||||
|
|
||||||
|
// 配置状态
|
||||||
|
private static volatile boolean isLoaded = false;
|
||||||
|
|
||||||
|
private AppConfig() {
|
||||||
|
// 私有构造函数,防止实例化
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标记配置已加载
|
||||||
|
*/
|
||||||
|
public static void markAsLoaded() {
|
||||||
|
isLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查配置是否已加载
|
||||||
|
*/
|
||||||
|
public static boolean isConfigLoaded() {
|
||||||
|
return isLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取完整的PVE URL(优先使用拆解后的配置构建)
|
||||||
|
*/
|
||||||
|
public static String getPveFullUrl() {
|
||||||
|
// 如果有拆解后的配置,优先使用它们构建URL
|
||||||
|
if (PVE_HOSTNAME_IP != null && !PVE_HOSTNAME_IP.isEmpty()) {
|
||||||
|
return PVE_PROTOCOL + "://" + PVE_HOSTNAME_IP + ":" + PVE_PORT + "/";
|
||||||
|
}
|
||||||
|
// 否则返回原始URL
|
||||||
|
return PVE_URL != null ? PVE_URL : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取完整的数据库连接URL(包含用户名和密码)
|
||||||
|
*/
|
||||||
|
public static String getFullJdbcUrl() {
|
||||||
|
if (MYSQL_JDBC == null || MYSQL_JDBC.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return MYSQL_JDBC + "?user=" + MYSQL_USERNAME + "&password=" + MYSQL_PASSWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证必要配置是否完整
|
||||||
|
*/
|
||||||
|
public static boolean validateRequiredConfig() {
|
||||||
|
return HTTP_IP != null && !HTTP_IP.isEmpty() &&
|
||||||
|
HTTP_PORT != null && !HTTP_PORT.isEmpty() &&
|
||||||
|
(PVE_URL != null && !PVE_URL.isEmpty()) ||
|
||||||
|
(PVE_HOSTNAME_IP != null && !PVE_HOSTNAME_IP.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印当前配置信息
|
||||||
|
*/
|
||||||
|
public static void printCurrentConfig() {
|
||||||
|
System.out.println("=== 应用配置信息 ===");
|
||||||
|
System.out.println("HTTP 监听地址: " + HTTP_IP + ":" + HTTP_PORT);
|
||||||
|
System.out.println("MySQL 连接: " + (MYSQL_JDBC != null ? "已配置" : "未配置"));
|
||||||
|
System.out.println("PVE 原始URL: " + (PVE_URL != null ? PVE_URL : "未配置"));
|
||||||
|
System.out.println("PVE 主机: " + (PVE_HOSTNAME_IP != null ? PVE_HOSTNAME_IP : "未配置"));
|
||||||
|
System.out.println("PVE 端口: " + PVE_PORT);
|
||||||
|
System.out.println("PVE 协议: " + PVE_PROTOCOL);
|
||||||
|
System.out.println("配置加载状态: " + (isLoaded ? "已完成" : "未完成"));
|
||||||
|
System.out.println("==================");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置配置到默认值
|
||||||
|
*/
|
||||||
|
public static void resetToDefaults() {
|
||||||
|
HTTP_IP = "0.0.0.0";
|
||||||
|
HTTP_PORT = "8080";
|
||||||
|
MYSQL_JDBC = "";
|
||||||
|
MYSQL_USERNAME = "";
|
||||||
|
MYSQL_PASSWORD = "";
|
||||||
|
PVE_URL = "";
|
||||||
|
PVE_HOSTNAME_IP = "";
|
||||||
|
PVE_PORT = "8006";
|
||||||
|
PVE_PROTOCOL = "https";
|
||||||
|
PVE_API_TOKEN_NAME = "";
|
||||||
|
PVE_API_TOKEN_ID = "";
|
||||||
|
PVE_API_TOKEN_SECRET = "";
|
||||||
|
isLoaded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,405 @@
|
|||||||
|
package top.gtb520.java.pve_back_api.config;
|
||||||
|
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置文件管理器
|
||||||
|
* 负责配置文件的检测、创建、加载和解析
|
||||||
|
*/
|
||||||
|
public class ConfigManager {
|
||||||
|
|
||||||
|
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
private static final String CONFIG_TEMPLATE_PATH = "config.yaml";
|
||||||
|
private static final String CONFIG_DIR_NAME = "conf";
|
||||||
|
private static final String CONFIG_FILE_NAME = "config.yaml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化配置系统
|
||||||
|
* @return 配置文件路径
|
||||||
|
*/
|
||||||
|
public static String initializeConfig() {
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
String jarDir = getApplicationDirectory();
|
||||||
|
Path configDir = Paths.get(jarDir, CONFIG_DIR_NAME);
|
||||||
|
Path configFile = configDir.resolve(CONFIG_FILE_NAME);
|
||||||
|
|
||||||
|
System.out.println("应用运行目录: " + jarDir);
|
||||||
|
|
||||||
|
// 确保配置目录存在
|
||||||
|
createConfigDirectory(configDir);
|
||||||
|
|
||||||
|
// 检查并创建配置文件
|
||||||
|
if (!Files.exists(configFile)) {
|
||||||
|
createDefaultConfigFile(configFile);
|
||||||
|
} else {
|
||||||
|
System.out.println("配置文件已存在: " + configFile.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载配置到全局变量
|
||||||
|
loadConfiguration(configFile.toString());
|
||||||
|
|
||||||
|
return configFile.toString();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("配置初始化失败: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用运行目录
|
||||||
|
*/
|
||||||
|
private static String getApplicationDirectory() {
|
||||||
|
try {
|
||||||
|
String classPath = ConfigManager.class.getProtectionDomain()
|
||||||
|
.getCodeSource().getLocation().getPath();
|
||||||
|
classPath = java.net.URLDecoder.decode(classPath, "UTF-8");
|
||||||
|
|
||||||
|
File classFile = new File(classPath);
|
||||||
|
|
||||||
|
if (classFile.isFile() && classPath.endsWith(".jar")) {
|
||||||
|
return classFile.getParent();
|
||||||
|
} else if (classFile.isDirectory()) {
|
||||||
|
String projectDir = classFile.getAbsolutePath();
|
||||||
|
if (projectDir.contains("target" + File.separator + "classes")) {
|
||||||
|
return projectDir.substring(0, projectDir.indexOf("target"));
|
||||||
|
}
|
||||||
|
return projectDir;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("获取应用目录失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return System.getProperty("user.dir");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建配置目录
|
||||||
|
*/
|
||||||
|
private static void createConfigDirectory(Path configDir) throws IOException {
|
||||||
|
if (!Files.exists(configDir)) {
|
||||||
|
Files.createDirectories(configDir);
|
||||||
|
System.out.println("创建配置目录: " + configDir.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建默认配置文件
|
||||||
|
*/
|
||||||
|
private static void createDefaultConfigFile(Path configFile) throws IOException {
|
||||||
|
System.out.println("创建默认配置文件: " + configFile.toString());
|
||||||
|
|
||||||
|
try (InputStream templateStream = getResourceAsStream(CONFIG_TEMPLATE_PATH);
|
||||||
|
OutputStream outputStream = Files.newOutputStream(configFile)) {
|
||||||
|
|
||||||
|
if (templateStream == null) {
|
||||||
|
createMinimalConfigFile(configFile);
|
||||||
|
} else {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int length;
|
||||||
|
while ((length = templateStream.read(buffer)) > 0) {
|
||||||
|
outputStream.write(buffer, 0, length);
|
||||||
|
}
|
||||||
|
System.out.println("从模板创建配置文件成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建最小化配置文件(当模板不可用时)
|
||||||
|
*/
|
||||||
|
private static void createMinimalConfigFile(Path configFile) throws IOException {
|
||||||
|
String minimalConfig = "# PVE后端API配置文件\n" +
|
||||||
|
"global:\n" +
|
||||||
|
" http_ip: \"0.0.0.0\"\n" +
|
||||||
|
" http_port: \"8080\"\n\n" +
|
||||||
|
"database:\n" +
|
||||||
|
" mysql_jdbc: \"\"\n" +
|
||||||
|
" mysql_username: \"\"\n" +
|
||||||
|
" mysql_password: \"\"\n\n" +
|
||||||
|
"pve:\n" +
|
||||||
|
" # 推荐使用拆分配置(优先级更高)\n" +
|
||||||
|
" hostname_ip: \"10.168.2.18\"\n" +
|
||||||
|
" port: \"8006\"\n" +
|
||||||
|
" protocol: \"https\"\n" +
|
||||||
|
" # 或者使用完整URL(向后兼容)\n" +
|
||||||
|
" url: \"https://10.168.2.18:8006/\"\n" +
|
||||||
|
" # API Token配置\n" +
|
||||||
|
" api_tocken_name: \"dev\"\n" +
|
||||||
|
" api_token_id: \"root@pam!dev\"\n" +
|
||||||
|
" api_token_secret: \"68e9dac5-3110-4f1b-b33a-feeaa4014f63\"\n";
|
||||||
|
|
||||||
|
Files.write(configFile, minimalConfig.getBytes("UTF-8"));
|
||||||
|
System.out.println("创建最小化配置文件成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从资源获取输入流
|
||||||
|
*/
|
||||||
|
private static InputStream getResourceAsStream(String resourcePath) {
|
||||||
|
// 首先尝试从类路径获取
|
||||||
|
InputStream stream = ConfigManager.class.getClassLoader().getResourceAsStream(resourcePath);
|
||||||
|
if (stream != null) {
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果类路径中没有,尝试从文件系统获取
|
||||||
|
try {
|
||||||
|
Path resourceFile = Paths.get(resourcePath);
|
||||||
|
if (Files.exists(resourceFile)) {
|
||||||
|
return Files.newInputStream(resourceFile);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// 忽略文件系统访问异常
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载配置文件到全局变量
|
||||||
|
* @param configFilePath 配置文件路径
|
||||||
|
*/
|
||||||
|
private static void loadConfiguration(String configFilePath) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> configData = loadYamlConfig(configFilePath);
|
||||||
|
|
||||||
|
if (configData == null) {
|
||||||
|
handleEmptyConfig();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析并设置配置值
|
||||||
|
parseAndSetConfig(configData);
|
||||||
|
AppConfig.markAsLoaded();
|
||||||
|
|
||||||
|
System.out.println("✅ 配置加载成功!");
|
||||||
|
AppConfig.printCurrentConfig();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
handleConfigLoadError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载YAML配置文件
|
||||||
|
*/
|
||||||
|
private static Map<String, Object> loadYamlConfig(String configFilePath) throws IOException {
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
try (InputStream inputStream = Files.newInputStream(Paths.get(configFilePath))) {
|
||||||
|
return yaml.load(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理空配置情况
|
||||||
|
*/
|
||||||
|
private static void handleEmptyConfig() {
|
||||||
|
System.err.println("❌ 配置文件为空或格式错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理配置加载错误
|
||||||
|
*/
|
||||||
|
private static void handleConfigLoadError(Exception e) {
|
||||||
|
System.err.println("❌ 加载配置文件失败: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析配置数据并设置到全局变量
|
||||||
|
* @param data 配置数据映射
|
||||||
|
*/
|
||||||
|
private static void parseAndSetConfig(Map<String, Object> data) {
|
||||||
|
try {
|
||||||
|
parseGlobalSection(data);
|
||||||
|
parseDatabaseSection(data);
|
||||||
|
parsePveSection(data);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("❌ 解析配置数据时发生错误: " + e.getMessage());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析全局配置部分
|
||||||
|
*/
|
||||||
|
private static void parseGlobalSection(Map<String, Object> data) {
|
||||||
|
if (!data.containsKey("global")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> global = (Map<String, Object>) data.get("global");
|
||||||
|
AppConfig.HTTP_IP = getStringValue(global, "http_ip", AppConfig.HTTP_IP);
|
||||||
|
AppConfig.HTTP_PORT = getStringValue(global, "http_port", AppConfig.HTTP_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析数据库配置部分
|
||||||
|
*/
|
||||||
|
private static void parseDatabaseSection(Map<String, Object> data) {
|
||||||
|
if (!data.containsKey("database")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> database = (Map<String, Object>) data.get("database");
|
||||||
|
AppConfig.MYSQL_JDBC = getStringValue(database, "mysql_jdbc", AppConfig.MYSQL_JDBC);
|
||||||
|
AppConfig.MYSQL_USERNAME = getStringValue(database, "mysql_username", AppConfig.MYSQL_USERNAME);
|
||||||
|
AppConfig.MYSQL_PASSWORD = getStringValue(database, "mysql_password", AppConfig.MYSQL_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析PVE配置部分
|
||||||
|
*/
|
||||||
|
private static void parsePveSection(Map<String, Object> data) {
|
||||||
|
if (!data.containsKey("pve")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> pve = (Map<String, Object>) data.get("pve");
|
||||||
|
processPveUrlConfig(pve);
|
||||||
|
processPveApiTokens(pve);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理PVE URL相关配置
|
||||||
|
*/
|
||||||
|
private static void processPveUrlConfig(Map<String, Object> pve) {
|
||||||
|
// 保留原始URL配置
|
||||||
|
AppConfig.PVE_URL = getStringValue(pve, "url", AppConfig.PVE_URL);
|
||||||
|
|
||||||
|
// 解析拆分后的PVE配置(优先级更高)
|
||||||
|
AppConfig.PVE_HOSTNAME_IP = getStringValue(pve, "hostname_ip", AppConfig.PVE_HOSTNAME_IP);
|
||||||
|
AppConfig.PVE_PORT = getStringValue(pve, "port", AppConfig.PVE_PORT);
|
||||||
|
AppConfig.PVE_PROTOCOL = getStringValue(pve, "protocol", AppConfig.PVE_PROTOCOL);
|
||||||
|
|
||||||
|
// 如果提供了拆分配置,同时更新URL
|
||||||
|
if (hasValidHostname()) {
|
||||||
|
AppConfig.PVE_URL = buildPveUrl();
|
||||||
|
}
|
||||||
|
// 如果只有URL而没有拆分配置,则解析URL
|
||||||
|
else if (hasValidUrl()) {
|
||||||
|
parsePveUrl(AppConfig.PVE_URL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理PVE API令牌配置
|
||||||
|
*/
|
||||||
|
private static void processPveApiTokens(Map<String, Object> pve) {
|
||||||
|
AppConfig.PVE_API_TOKEN_NAME = getStringValue(pve, "api_tocken_name", AppConfig.PVE_API_TOKEN_NAME);
|
||||||
|
AppConfig.PVE_API_TOKEN_ID = getStringValue(pve, "api_token_id", AppConfig.PVE_API_TOKEN_ID);
|
||||||
|
AppConfig.PVE_API_TOKEN_SECRET = getStringValue(pve, "api_token_secret", AppConfig.PVE_API_TOKEN_SECRET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否有有效的主机名配置
|
||||||
|
*/
|
||||||
|
private static boolean hasValidHostname() {
|
||||||
|
return AppConfig.PVE_HOSTNAME_IP != null && !AppConfig.PVE_HOSTNAME_IP.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否有有效的URL配置
|
||||||
|
*/
|
||||||
|
private static boolean hasValidUrl() {
|
||||||
|
return AppConfig.PVE_URL != null && !AppConfig.PVE_URL.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建PVE完整URL
|
||||||
|
*/
|
||||||
|
private static String buildPveUrl() {
|
||||||
|
return AppConfig.PVE_PROTOCOL + "://" + AppConfig.PVE_HOSTNAME_IP + ":" + AppConfig.PVE_PORT + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从完整URL解析PVE主机和端口信息
|
||||||
|
*/
|
||||||
|
private static void parsePveUrl(String url) {
|
||||||
|
try {
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除末尾的斜杠
|
||||||
|
if (url.endsWith("/")) {
|
||||||
|
url = url.substring(0, url.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析协议
|
||||||
|
if (url.startsWith("https://")) {
|
||||||
|
AppConfig.PVE_PROTOCOL = "https";
|
||||||
|
url = url.substring(8);
|
||||||
|
} else if (url.startsWith("http://")) {
|
||||||
|
AppConfig.PVE_PROTOCOL = "http";
|
||||||
|
url = url.substring(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析主机和端口
|
||||||
|
int portIndex = url.lastIndexOf(":");
|
||||||
|
if (portIndex > 0) {
|
||||||
|
AppConfig.PVE_HOSTNAME_IP = url.substring(0, portIndex);
|
||||||
|
String portStr = url.substring(portIndex + 1);
|
||||||
|
if (!portStr.isEmpty()) {
|
||||||
|
AppConfig.PVE_PORT = portStr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AppConfig.PVE_HOSTNAME_IP = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("解析PVE URL时发生错误: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全获取字符串值
|
||||||
|
*/
|
||||||
|
private static String getStringValue(Map<String, Object> map, String key, String defaultValue) {
|
||||||
|
if (map.containsKey(key)) {
|
||||||
|
Object value = map.get(key);
|
||||||
|
return value != null ? value.toString() : defaultValue;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新加载配置
|
||||||
|
*/
|
||||||
|
public static boolean reloadConfiguration() {
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
String jarDir = getApplicationDirectory();
|
||||||
|
Path configFile = Paths.get(jarDir, CONFIG_DIR_NAME, CONFIG_FILE_NAME);
|
||||||
|
|
||||||
|
if (Files.exists(configFile)) {
|
||||||
|
AppConfig.resetToDefaults();
|
||||||
|
loadConfiguration(configFile.toString());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
System.err.println("配置文件不存在,无法重新加载");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("重新加载配置失败: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package top.gtb520.java.pve_back_api.config;
|
||||||
|
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局配置类
|
||||||
|
* 存储所有配置项的全局变量
|
||||||
|
*/
|
||||||
|
public class GlobalConfig {
|
||||||
|
|
||||||
|
// 全局配置
|
||||||
|
public static String HTTP_IP = "0.0.0.0";
|
||||||
|
public static String HTTP_PORT = "8080";
|
||||||
|
|
||||||
|
// 数据库配置
|
||||||
|
public static String MYSQL_JDBC = "";
|
||||||
|
public static String MYSQL_USERNAME = "";
|
||||||
|
public static String MYSQL_PASSWORD = "";
|
||||||
|
|
||||||
|
// PVE配置
|
||||||
|
public static String PVE_URL = "";
|
||||||
|
public static String PVE_API_TOKEN_NAME = "";
|
||||||
|
public static String PVE_API_TOKEN_ID = "";
|
||||||
|
public static String PVE_API_TOKEN_SECRET = "";
|
||||||
|
|
||||||
|
// 私有构造函数,防止实例化
|
||||||
|
private GlobalConfig() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印所有配置信息(用于调试)
|
||||||
|
*/
|
||||||
|
public static void printConfig() {
|
||||||
|
System.out.println("=== 当前配置信息 ===");
|
||||||
|
System.out.println("HTTP IP: " + HTTP_IP);
|
||||||
|
System.out.println("HTTP PORT: " + HTTP_PORT);
|
||||||
|
System.out.println("MYSQL JDBC: " + MYSQL_JDBC);
|
||||||
|
System.out.println("MYSQL USERNAME: " + MYSQL_USERNAME);
|
||||||
|
System.out.println("PVE URL: " + PVE_URL);
|
||||||
|
System.out.println("PVE API TOKEN NAME: " + PVE_API_TOKEN_NAME);
|
||||||
|
System.out.println("PVE API TOKEN ID: " + PVE_API_TOKEN_ID);
|
||||||
|
System.out.println("===================");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package top.gtb520.java.pve_back_api.config;
|
||||||
|
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* YAML配置文件解析器
|
||||||
|
* 负责从不同来源加载和解析YAML配置文件
|
||||||
|
*/
|
||||||
|
public class YamlConfigLoader {
|
||||||
|
|
||||||
|
private static final String GLOBAL_SECTION = "global";
|
||||||
|
private static final String DATABASE_SECTION = "database";
|
||||||
|
private static final String PVE_SECTION = "pve";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从资源文件加载配置
|
||||||
|
* @param resourcePath 资源文件路径
|
||||||
|
*/
|
||||||
|
public static void loadConfigFromResource(String resourcePath) {
|
||||||
|
try {
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
InputStream inputStream = YamlConfigLoader.class.getClassLoader().getResourceAsStream(resourcePath);
|
||||||
|
|
||||||
|
if (inputStream == null) {
|
||||||
|
handleResourceNotFound(resourcePath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> data = yaml.load(inputStream);
|
||||||
|
parseConfig(data);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
handleLoadException("资源", resourcePath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件路径加载配置
|
||||||
|
* @param filePath 文件路径
|
||||||
|
*/
|
||||||
|
public static void loadConfigFromFile(String filePath) {
|
||||||
|
try {
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
InputStream inputStream = java.nio.file.Files.newInputStream(java.nio.file.Paths.get(filePath));
|
||||||
|
|
||||||
|
Map<String, Object> data = yaml.load(inputStream);
|
||||||
|
parseConfig(data);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
handleLoadException("文件", filePath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析配置数据并设置到全局变量
|
||||||
|
* @param data 配置数据映射
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static void parseConfig(Map<String, Object> data) {
|
||||||
|
try {
|
||||||
|
parseGlobalConfig(data);
|
||||||
|
parseDatabaseConfig(data);
|
||||||
|
parsePveConfig(data);
|
||||||
|
|
||||||
|
System.out.println("配置加载成功!");
|
||||||
|
GlobalConfig.printConfig();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("解析配置数据时发生错误: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析全局配置部分
|
||||||
|
*/
|
||||||
|
private static void parseGlobalConfig(Map<String, Object> data) {
|
||||||
|
if (!data.containsKey(GLOBAL_SECTION)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> global = (Map<String, Object>) data.get(GLOBAL_SECTION);
|
||||||
|
GlobalConfig.HTTP_IP = getStringValue(global, "http_ip", GlobalConfig.HTTP_IP);
|
||||||
|
GlobalConfig.HTTP_PORT = getStringValue(global, "http_port", GlobalConfig.HTTP_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析数据库配置部分
|
||||||
|
*/
|
||||||
|
private static void parseDatabaseConfig(Map<String, Object> data) {
|
||||||
|
if (!data.containsKey(DATABASE_SECTION)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> database = (Map<String, Object>) data.get(DATABASE_SECTION);
|
||||||
|
GlobalConfig.MYSQL_JDBC = getStringValue(database, "mysql_jdbc", GlobalConfig.MYSQL_JDBC);
|
||||||
|
GlobalConfig.MYSQL_USERNAME = getStringValue(database, "mysql_username", GlobalConfig.MYSQL_USERNAME);
|
||||||
|
GlobalConfig.MYSQL_PASSWORD = getStringValue(database, "mysql_password", GlobalConfig.MYSQL_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析PVE配置部分
|
||||||
|
*/
|
||||||
|
private static void parsePveConfig(Map<String, Object> data) {
|
||||||
|
if (!data.containsKey(PVE_SECTION)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> pve = (Map<String, Object>) data.get(PVE_SECTION);
|
||||||
|
GlobalConfig.PVE_URL = getStringValue(pve, "url", GlobalConfig.PVE_URL);
|
||||||
|
GlobalConfig.PVE_API_TOKEN_NAME = getStringValue(pve, "api_tocken_name", GlobalConfig.PVE_API_TOKEN_NAME);
|
||||||
|
GlobalConfig.PVE_API_TOKEN_ID = getStringValue(pve, "api_token_id", GlobalConfig.PVE_API_TOKEN_ID);
|
||||||
|
GlobalConfig.PVE_API_TOKEN_SECRET = getStringValue(pve, "api_token_secret", GlobalConfig.PVE_API_TOKEN_SECRET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全获取字符串值
|
||||||
|
*/
|
||||||
|
private static String getStringValue(Map<String, Object> map, String key, String defaultValue) {
|
||||||
|
if (map.containsKey(key)) {
|
||||||
|
Object value = map.get(key);
|
||||||
|
return value != null ? value.toString() : defaultValue;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理资源未找到的情况
|
||||||
|
*/
|
||||||
|
private static void handleResourceNotFound(String resourcePath) {
|
||||||
|
System.err.println("❌ 无法找到资源配置文件: " + resourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理加载异常
|
||||||
|
*/
|
||||||
|
private static void handleLoadException(String type, String path, Exception e) {
|
||||||
|
System.err.println("❌ 解析" + type + "配置文件失败: " + path);
|
||||||
|
System.err.println("错误详情: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
package top.gtb520.java.pve_back_api.route.pve;
|
||||||
|
|
||||||
|
import it.corsinvest.proxmoxve.api.*;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
// 导入配置变量
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static top.gtb520.java.pve_back_api.config.AppConfig.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PVE状态相关路由处理器
|
||||||
|
* 提供与Proxmox VE服务器通信的客户端创建功能和状态查询
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class status {
|
||||||
|
|
||||||
|
private static final int DEFAULT_TIMEOUT = 120000; // 2分钟超时时间
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API:/api/pve/status
|
||||||
|
* 类型:GET
|
||||||
|
* 获取PVE集群状态信息,包括节点、虚拟机、容器等资源状态
|
||||||
|
*
|
||||||
|
* @return 包含集群状态信息的列表
|
||||||
|
* @throws Exception 当获取状态失败时抛出
|
||||||
|
*/
|
||||||
|
@GetMapping("/api/pve/status")
|
||||||
|
public List<Map<String, Object>> GetPveStatus() throws Exception {
|
||||||
|
System.out.println("开始获取PVE状态信息...");
|
||||||
|
List<Map<String, Object>> pveStatus = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建PVE客户端
|
||||||
|
PveClient client = createClient();
|
||||||
|
|
||||||
|
// 获取集群资源信息
|
||||||
|
var resourcesResult = client.getCluster().getResources().resources();
|
||||||
|
|
||||||
|
if (resourcesResult.isSuccessStatusCode()) {
|
||||||
|
JsonNode resources = resourcesResult.getResponse().get("data");
|
||||||
|
|
||||||
|
// 统计各类资源
|
||||||
|
int nodeCount = 0, vmCount = 0, ctCount = 0;
|
||||||
|
int runningNodes = 0, runningVms = 0, runningCts = 0;
|
||||||
|
|
||||||
|
// 处理每个资源
|
||||||
|
for (JsonNode resource : resources) {
|
||||||
|
String type = resource.get("type").asText();
|
||||||
|
String status = resource.get("status").asText();
|
||||||
|
|
||||||
|
Map<String, Object> resourceInfo = new HashMap<>();
|
||||||
|
resourceInfo.put("type", type);
|
||||||
|
resourceInfo.put("status", status);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "node":
|
||||||
|
nodeCount++;
|
||||||
|
if ("online".equals(status)) runningNodes++;
|
||||||
|
resourceInfo.put("name", resource.get("node").asText());
|
||||||
|
resourceInfo.put("cpu_usage", String.format("%.2f%%",
|
||||||
|
resource.get("cpu").asDouble() * 100));
|
||||||
|
resourceInfo.put("memory_usage", String.format("%.2f%%",
|
||||||
|
(resource.get("mem").asDouble() / resource.get("maxmem").asDouble()) * 100));
|
||||||
|
resourceInfo.put("uptime", formatUptime(resource.get("uptime").asInt()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "qemu":
|
||||||
|
vmCount++;
|
||||||
|
if ("running".equals(status)) runningVms++;
|
||||||
|
resourceInfo.put("vmid", resource.get("vmid").asInt());
|
||||||
|
resourceInfo.put("name", resource.get("name").asText());
|
||||||
|
resourceInfo.put("node", resource.get("node").asText());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "lxc":
|
||||||
|
ctCount++;
|
||||||
|
if ("running".equals(status)) runningCts++;
|
||||||
|
resourceInfo.put("vmid", resource.get("vmid").asInt());
|
||||||
|
resourceInfo.put("name", resource.get("name").asText());
|
||||||
|
resourceInfo.put("node", resource.get("node").asText());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pveStatus.add(resourceInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加统计信息
|
||||||
|
Map<String, Object> summary = new HashMap<>();
|
||||||
|
summary.put("summary", true);
|
||||||
|
summary.put("total_nodes", nodeCount);
|
||||||
|
summary.put("running_nodes", runningNodes);
|
||||||
|
summary.put("total_vms", vmCount);
|
||||||
|
summary.put("running_vms", runningVms);
|
||||||
|
summary.put("total_containers", ctCount);
|
||||||
|
summary.put("running_containers", runningCts);
|
||||||
|
summary.put("timestamp", System.currentTimeMillis());
|
||||||
|
pveStatus.add(summary);
|
||||||
|
|
||||||
|
System.out.println("✅ 成功获取PVE状态信息");
|
||||||
|
System.out.printf("📊 统计: 节点%d(%d运行), VM%d(%d运行), 容器%d(%d运行)%n",
|
||||||
|
nodeCount, runningNodes, vmCount, runningVms, ctCount, runningCts);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 更安全的错误处理
|
||||||
|
String errorMsg = "未知错误";
|
||||||
|
try {
|
||||||
|
if (resourcesResult != null) {
|
||||||
|
errorMsg = resourcesResult.getError();
|
||||||
|
} else {
|
||||||
|
errorMsg = "API调用返回null结果";
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorMsg = "错误处理异常: " + e.getClass().getSimpleName() + " - " + e.getMessage();
|
||||||
|
}
|
||||||
|
throw new Exception("获取集群资源失败: " + errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("❌ 获取PVE状态失败: " + e.getMessage());
|
||||||
|
throw new Exception("获取PVE状态失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pveStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化运行时间
|
||||||
|
*/
|
||||||
|
private static String formatUptime(int seconds) {
|
||||||
|
int days = seconds / 86400;
|
||||||
|
int hours = (seconds % 86400) / 3600;
|
||||||
|
int minutes = (seconds % 3600) / 60;
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (days > 0) sb.append(days).append("天 ");
|
||||||
|
if (hours > 0) sb.append(hours).append("小时 ");
|
||||||
|
if (minutes > 0) sb.append(minutes).append("分钟");
|
||||||
|
|
||||||
|
return sb.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建PVE客户端实例
|
||||||
|
* 支持API令牌认证和传统登录认证两种方式
|
||||||
|
*
|
||||||
|
* @return 配置好的PveClient实例
|
||||||
|
* @throws RuntimeException 当客户端创建失败时抛出
|
||||||
|
*/
|
||||||
|
public static PveClient createClient() throws RuntimeException {
|
||||||
|
// 构建API_TOKEN字符串
|
||||||
|
String[] api_token_list = PVE_API_TOKEN_ID.split("!");
|
||||||
|
String api_token = api_token_list[0] + ":" + api_token_list[1] + "@" + "token=" + PVE_API_TOKEN_SECRET;
|
||||||
|
System.out.println("API_TOKEN: " + api_token);
|
||||||
|
|
||||||
|
// 创建PVE客户端实例
|
||||||
|
var client = new PveClient(PVE_HOSTNAME_IP, Integer.parseInt(PVE_PORT));
|
||||||
|
client.setValidateCertificate(false); // SSL证书验证
|
||||||
|
client.setTimeout(DEFAULT_TIMEOUT); // 设置请求超时时间
|
||||||
|
client.setApiToken(api_token);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package top.gtb520.java.pve_back_api.route;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class test {
|
||||||
|
@GetMapping("/test")
|
||||||
|
public String test() {
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
spring.application.name=pve-back-api
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# 全局配置
|
||||||
|
global:
|
||||||
|
http_ip: "0.0.0.0"
|
||||||
|
http_port: "8080"
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
database:
|
||||||
|
mysql_jdbc: "jdbc:mysql://10.168.2.2:3306/pve_monitor?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrlInLocalInfile=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&allowLoadLocalInfile=true&allowUrlInLocalInfile=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&allowLoadLocalInfile=true&allowUrlInLocal"
|
||||||
|
mysql_username: "root"
|
||||||
|
mysql_password: "Password"
|
||||||
|
|
||||||
|
# PVE配置
|
||||||
|
pve:
|
||||||
|
# PVE后端地址,示例:https://192.168.1.1:8006/ (协议HTTPS,带结尾的“/”,不保留结尾其他参数)
|
||||||
|
url: "https://10.168.2.18:8006/"
|
||||||
|
api_tocken_name: "dev"
|
||||||
|
api_token_id: "root@pam!dev"
|
||||||
|
api_token_secret: "68e9dac5-3110-4f1b-b33a-feeaa4014f63"
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package top.gtb520.java.pve_back_api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import top.gtb520.java.pve_back_api.config.AppConfig;
|
||||||
|
import top.gtb520.java.pve_back_api.config.ConfigManager;
|
||||||
|
import top.gtb520.java.pve_back_api.config.YamlConfigLoader;
|
||||||
|
import top.gtb520.java.pve_back_api.route.pve.status;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class MainTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAppConfigInitialization() {
|
||||||
|
// 测试配置类的基本功能
|
||||||
|
assertNotNull(AppConfig.HTTP_IP);
|
||||||
|
assertNotNull(AppConfig.HTTP_PORT);
|
||||||
|
assertFalse(AppConfig.isConfigLoaded());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConfigManagerMethodsExist() {
|
||||||
|
// 测试ConfigManager类的方法是否存在
|
||||||
|
assertTrue(ConfigManager.class.getDeclaredMethods().length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testYamlConfigLoaderMethodsExist() {
|
||||||
|
// 测试YamlConfigLoader类的方法是否存在
|
||||||
|
assertTrue(YamlConfigLoader.class.getDeclaredMethods().length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testStatusClassExists() {
|
||||||
|
// 测试status类是否存在createClient方法
|
||||||
|
assertNotNull(status.class.getDeclaredMethods());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPveUrlBuilding() {
|
||||||
|
// 测试PVE URL构建逻辑
|
||||||
|
AppConfig.PVE_PROTOCOL = "https";
|
||||||
|
AppConfig.PVE_HOSTNAME_IP = "192.168.1.100";
|
||||||
|
AppConfig.PVE_PORT = "8006";
|
||||||
|
|
||||||
|
String expectedUrl = "https://192.168.1.100:8006/";
|
||||||
|
assertEquals(expectedUrl, AppConfig.getPveFullUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package top.gtb520.java.pve_back_api;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||||
|
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||||
|
import reactor.netty.http.client.HttpClient;
|
||||||
|
import reactor.netty.tcp.TcpClient;
|
||||||
|
|
||||||
|
public class ResourcesResultTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建忽略SSL证书验证的WebClient实例
|
||||||
|
* 用于测试环境或自签名证书场景
|
||||||
|
*/
|
||||||
|
private static WebClient createInsecureWebClient() {
|
||||||
|
try {
|
||||||
|
// 使用Netty内置的不安全信任管理器工厂
|
||||||
|
TcpClient tcpClient = TcpClient.create()
|
||||||
|
.secure(sslContextSpec -> {
|
||||||
|
try {
|
||||||
|
sslContextSpec.sslContext(
|
||||||
|
io.netty.handler.ssl.SslContextBuilder.forClient()
|
||||||
|
.trustManager(io.netty.handler.ssl.util.InsecureTrustManagerFactory.INSTANCE)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("SSL配置失败", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建HttpClient和连接器
|
||||||
|
HttpClient httpClient = HttpClient.from(tcpClient);
|
||||||
|
ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
|
||||||
|
|
||||||
|
// 构建并返回WebClient
|
||||||
|
return WebClient.builder()
|
||||||
|
.clientConnector(connector)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("创建WebClient失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testHttpsRequest() {
|
||||||
|
System.out.println("开始发送HTTPS请求...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建忽略证书验证的WebClient
|
||||||
|
WebClient client = createInsecureWebClient();
|
||||||
|
|
||||||
|
// 发送HTTPS GET请求
|
||||||
|
Mono<String> result = client.get()
|
||||||
|
.uri("https://10.168.2.2:8013/")
|
||||||
|
.retrieve()
|
||||||
|
.bodyToMono(String.class);
|
||||||
|
|
||||||
|
// 阻塞获取响应结果
|
||||||
|
String response = result.block();
|
||||||
|
System.out.println("✅ 请求成功!");
|
||||||
|
System.out.println("响应内容长度: " + (response != null ? response.length() : 0) + " 字符");
|
||||||
|
|
||||||
|
// 如果需要查看完整响应内容,取消下面的注释
|
||||||
|
// System.out.println("响应内容: " + response);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("❌ HTTPS请求失败: " + e.getMessage());
|
||||||
|
System.err.println("可能的原因:");
|
||||||
|
System.err.println("1. 目标服务器不可达");
|
||||||
|
System.err.println("2. 端口未开放");
|
||||||
|
System.err.println("3. 网络连接问题");
|
||||||
|
System.err.println("4. SSL配置问题");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
spring.application.name=pve-back-api
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# 全局配置
|
||||||
|
global:
|
||||||
|
http_ip: "0.0.0.0"
|
||||||
|
http_port: "8080"
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
database:
|
||||||
|
mysql_jdbc: "jdbc:mysql://10.168.2.2:3306/pve_monitor?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrlInLocalInfile=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&allowLoadLocalInfile=true&allowUrlInLocalInfile=true&allowPublicKeyRetrieval=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&allowLoadLocalInfile=true&allowUrlInLocal"
|
||||||
|
mysql_username: "root"
|
||||||
|
mysql_password: "Password"
|
||||||
|
|
||||||
|
# PVE配置
|
||||||
|
pve:
|
||||||
|
# PVE后端地址,示例:https://192.168.1.1:8006/ (协议HTTPS,带结尾的“/”,不保留结尾其他参数)
|
||||||
|
url: "https://10.168.2.18:8006/"
|
||||||
|
api_tocken_name: "dev"
|
||||||
|
api_token_id: "root@pam!dev"
|
||||||
|
api_token_secret: "68e9dac5-3110-4f1b-b33a-feeaa4014f63"
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,7 @@
|
|||||||
|
top\gtb520\java\pve_back_api\route\pve\status.class
|
||||||
|
top\gtb520\java\pve_back_api\config\ConfigManager.class
|
||||||
|
top\gtb520\java\pve_back_api\config\GlobalConfig.class
|
||||||
|
top\gtb520\java\pve_back_api\Main.class
|
||||||
|
top\gtb520\java\pve_back_api\config\AppConfig.class
|
||||||
|
top\gtb520\java\pve_back_api\config\YamlConfigLoader.class
|
||||||
|
top\gtb520\java\pve_back_api\route\test.class
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\config\AppConfig.java
|
||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\config\ConfigManager.java
|
||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\config\GlobalConfig.java
|
||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\config\YamlConfigLoader.java
|
||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\Main.java
|
||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\route\pve\status.java
|
||||||
|
G:\Project\Java\pve-back-api\src\main\java\top\gtb520\java\pve_back_api\route\test.java
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
top\gtb520\java\pve_back_api\MainTests.class
|
||||||
|
top\gtb520\java\pve_back_api\ResourcesResultTest.class
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
G:\Project\Java\pve-back-api\src\test\java\top\gtb520\java\pve_back_api\MainTests.java
|
||||||
|
G:\Project\Java\pve-back-api\src\test\java\top\gtb520\java\pve_back_api\ResourcesResultTest.java
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Created at 2026-02-04T18:14:51.799
|
||||||
|
Boot Manifest-JAR contains absolute paths in classpath 'G:\Project\Java\pve-back-api\target\test-classes'
|
||||||
|
Hint: <argLine>-Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
|
||||||
|
'other' has different root
|
||||||
|
|
||||||
@@ -0,0 +1,302 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" version="3.0.2" name="top.gtb520.java.pve_back_api.ResourcesResultTest" time="1.14" tests="1" errors="0" skipped="0" failures="0">
|
||||||
|
<properties>
|
||||||
|
<property name="java.specification.version" value="25"/>
|
||||||
|
<property name="sun.cpu.isalist" value="amd64"/>
|
||||||
|
<property name="sun.jnu.encoding" value="GBK"/>
|
||||||
|
<property name="java.class.path" value="G:\Project\Java\pve-back-api\target\test-classes;G:\Project\Java\pve-back-api\target\classes;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-webmvc\4.0.2\spring-boot-starter-webmvc-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-jackson\4.0.2\spring-boot-starter-jackson-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-jackson\4.0.2\spring-boot-jackson-4.0.2.jar;C:\Users\Administrator\.m2\repository\tools\jackson\core\jackson-databind\3.0.4\jackson-databind-3.0.4.jar;C:\Users\Administrator\.m2\repository\tools\jackson\core\jackson-core\3.0.4\jackson-core-3.0.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\4.0.2\spring-boot-starter-tomcat-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat-runtime\4.0.2\spring-boot-starter-tomcat-runtime-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\11.0.15\tomcat-embed-core-11.0.15.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\11.0.15\tomcat-embed-el-11.0.15.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\11.0.15\tomcat-embed-websocket-11.0.15.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-tomcat\4.0.2\spring-boot-tomcat-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-http-converter\4.0.2\spring-boot-http-converter-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot\4.0.2\spring-boot-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-context\7.0.3\spring-context-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-web\7.0.3\spring-web-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-beans\7.0.3\spring-beans-7.0.3.jar;C:\Users\Administrator\.m2\repository\io\micrometer\micrometer-observation\1.16.2\micrometer-observation-1.16.2.jar;C:\Users\Administrator\.m2\repository\io\micrometer\micrometer-commons\1.16.2\micrometer-commons-1.16.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-webmvc\4.0.2\spring-boot-webmvc-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-servlet\4.0.2\spring-boot-servlet-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-webmvc\7.0.3\spring-webmvc-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aop\7.0.3\spring-aop-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-expression\7.0.3\spring-expression-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter\4.0.2\spring-boot-starter-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\4.0.2\spring-boot-autoconfigure-4.0.2.jar;C:\Users\Administrator\.m2\repository\jakarta\annotation\jakarta.annotation-api\3.0.0\jakarta.annotation-api-3.0.0.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-test\4.0.2\spring-boot-starter-test-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-test\4.0.2\spring-boot-test-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\4.0.2\spring-boot-test-autoconfigure-4.0.2.jar;C:\Users\Administrator\.m2\repository\com\jayway\jsonpath\json-path\2.10.0\json-path-2.10.0.jar;C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\2.0.17\slf4j-api-2.0.17.jar;C:\Users\Administrator\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\4.0.4\jakarta.xml.bind-api-4.0.4.jar;C:\Users\Administrator\.m2\repository\jakarta\activation\jakarta.activation-api\2.1.4\jakarta.activation-api-2.1.4.jar;C:\Users\Administrator\.m2\repository\net\minidev\json-smart\2.6.0\json-smart-2.6.0.jar;C:\Users\Administrator\.m2\repository\net\minidev\accessors-smart\2.6.0\accessors-smart-2.6.0.jar;C:\Users\Administrator\.m2\repository\org\ow2\asm\asm\9.7.1\asm-9.7.1.jar;C:\Users\Administrator\.m2\repository\org\assertj\assertj-core\3.27.6\assertj-core-3.27.6.jar;C:\Users\Administrator\.m2\repository\net\bytebuddy\byte-buddy\1.17.8\byte-buddy-1.17.8.jar;C:\Users\Administrator\.m2\repository\org\awaitility\awaitility\4.3.0\awaitility-4.3.0.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest\3.0\hamcrest-3.0.jar;C:\Users\Administrator\.m2\repository\org\junit\jupiter\junit-jupiter\6.0.2\junit-jupiter-6.0.2.jar;C:\Users\Administrator\.m2\repository\org\junit\jupiter\junit-jupiter-api\6.0.2\junit-jupiter-api-6.0.2.jar;C:\Users\Administrator\.m2\repository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-commons\6.0.2\junit-platform-commons-6.0.2.jar;C:\ULine truncated
|
||||||
|
<property name="java.vm.vendor" value="Alibaba"/>
|
||||||
|
<property name="sun.arch.data.model" value="64"/>
|
||||||
|
<property name="user.variant" value=""/>
|
||||||
|
<property name="java.vendor.url" value="http://www.alibabagroup.com"/>
|
||||||
|
<property name="user.timezone" value="Asia/Shanghai"/>
|
||||||
|
<property name="os.name" value="Windows 10"/>
|
||||||
|
<property name="java.vm.specification.version" value="25"/>
|
||||||
|
<property name="sun.java.launcher" value="SUN_STANDARD"/>
|
||||||
|
<property name="user.country" value="CN"/>
|
||||||
|
<property name="sun.boot.library.path" value="C:\Program Files\Java\dragonwell-25.0.0.0.1+36-GA\bin"/>
|
||||||
|
<property name="sun.java.command" value="C:\Users\Administrator\AppData\Local\Temp\surefire6346205998026791008\surefirebooter-20260204181451769_3.jar C:\Users\Administrator\AppData\Local\Temp\surefire6346205998026791008 2026-02-04T18-14-48_524-jvmRun1 surefire-20260204181451769_1tmp surefire_0-20260204181451769_2tmp"/>
|
||||||
|
<property name="jdk.debug" value="release"/>
|
||||||
|
<property name="test" value="ResourcesResultTest"/>
|
||||||
|
<property name="surefire.test.class.path" value="G:\Project\Java\pve-back-api\target\test-classes;G:\Project\Java\pve-back-api\target\classes;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-webmvc\4.0.2\spring-boot-starter-webmvc-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-jackson\4.0.2\spring-boot-starter-jackson-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-jackson\4.0.2\spring-boot-jackson-4.0.2.jar;C:\Users\Administrator\.m2\repository\tools\jackson\core\jackson-databind\3.0.4\jackson-databind-3.0.4.jar;C:\Users\Administrator\.m2\repository\tools\jackson\core\jackson-core\3.0.4\jackson-core-3.0.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\4.0.2\spring-boot-starter-tomcat-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat-runtime\4.0.2\spring-boot-starter-tomcat-runtime-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\11.0.15\tomcat-embed-core-11.0.15.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\11.0.15\tomcat-embed-el-11.0.15.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\11.0.15\tomcat-embed-websocket-11.0.15.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-tomcat\4.0.2\spring-boot-tomcat-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-http-converter\4.0.2\spring-boot-http-converter-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot\4.0.2\spring-boot-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-context\7.0.3\spring-context-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-web\7.0.3\spring-web-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-beans\7.0.3\spring-beans-7.0.3.jar;C:\Users\Administrator\.m2\repository\io\micrometer\micrometer-observation\1.16.2\micrometer-observation-1.16.2.jar;C:\Users\Administrator\.m2\repository\io\micrometer\micrometer-commons\1.16.2\micrometer-commons-1.16.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-webmvc\4.0.2\spring-boot-webmvc-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-servlet\4.0.2\spring-boot-servlet-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-webmvc\7.0.3\spring-webmvc-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aop\7.0.3\spring-aop-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-expression\7.0.3\spring-expression-7.0.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter\4.0.2\spring-boot-starter-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\4.0.2\spring-boot-autoconfigure-4.0.2.jar;C:\Users\Administrator\.m2\repository\jakarta\annotation\jakarta.annotation-api\3.0.0\jakarta.annotation-api-3.0.0.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-test\4.0.2\spring-boot-starter-test-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-test\4.0.2\spring-boot-test-4.0.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\4.0.2\spring-boot-test-autoconfigure-4.0.2.jar;C:\Users\Administrator\.m2\repository\com\jayway\jsonpath\json-path\2.10.0\json-path-2.10.0.jar;C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\2.0.17\slf4j-api-2.0.17.jar;C:\Users\Administrator\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\4.0.4\jakarta.xml.bind-api-4.0.4.jar;C:\Users\Administrator\.m2\repository\jakarta\activation\jakarta.activation-api\2.1.4\jakarta.activation-api-2.1.4.jar;C:\Users\Administrator\.m2\repository\net\minidev\json-smart\2.6.0\json-smart-2.6.0.jar;C:\Users\Administrator\.m2\repository\net\minidev\accessors-smart\2.6.0\accessors-smart-2.6.0.jar;C:\Users\Administrator\.m2\repository\org\ow2\asm\asm\9.7.1\asm-9.7.1.jar;C:\Users\Administrator\.m2\repository\org\assertj\assertj-core\3.27.6\assertj-core-3.27.6.jar;C:\Users\Administrator\.m2\repository\net\bytebuddy\byte-buddy\1.17.8\byte-buddy-1.17.8.jar;C:\Users\Administrator\.m2\repository\org\awaitility\awaitility\4.3.0\awaitility-4.3.0.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest\3.0\hamcrest-3.0.jar;C:\Users\Administrator\.m2\repository\org\junit\jupiter\junit-jupiter\6.0.2\junit-jupiter-6.0.2.jar;C:\Users\Administrator\.m2\repository\org\junit\jupiter\junit-jupiter-api\6.0.2\junit-jupiter-api-6.0.2.jar;C:\Users\Administrator\.m2\repository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-commons\6.0.2\junit-platform-commons-6.0.2Line truncated
|
||||||
|
<property name="sun.cpu.endian" value="little"/>
|
||||||
|
<property name="user.home" value="C:\Users\Administrator"/>
|
||||||
|
<property name="user.language" value="zh"/>
|
||||||
|
<property name="java.specification.vendor" value="Oracle Corporation"/>
|
||||||
|
<property name="java.version.date" value="2025-09-24"/>
|
||||||
|
<property name="java.home" value="C:\Program Files\Java\dragonwell-25.0.0.0.1+36-GA"/>
|
||||||
|
<property name="file.separator" value="\"/>
|
||||||
|
<property name="basedir" value="G:\Project\Java\pve-back-api"/>
|
||||||
|
<property name="java.vm.compressedOopsMode" value="Zero based"/>
|
||||||
|
<property name="line.separator" value=" "/>
|
||||||
|
<property name="java.vm.specification.vendor" value="Oracle Corporation"/>
|
||||||
|
<property name="java.specification.name" value="Java Platform API Specification"/>
|
||||||
|
<property name="surefire.real.class.path" value="C:\Users\Administrator\AppData\Local\Temp\surefire6346205998026791008\surefirebooter-20260204181451769_3.jar"/>
|
||||||
|
<property name="user.script" value=""/>
|
||||||
|
<property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
|
||||||
|
<property name="java.runtime.version" value="25.0.0.0.1"/>
|
||||||
|
<property name="user.name" value="Administrator"/>
|
||||||
|
<property name="stdout.encoding" value="GBK"/>
|
||||||
|
<property name="path.separator" value=";"/>
|
||||||
|
<property name="os.version" value="10.0"/>
|
||||||
|
<property name="java.runtime.name" value="OpenJDK Runtime Environment"/>
|
||||||
|
<property name="file.encoding" value="UTF-8"/>
|
||||||
|
<property name="java.vm.name" value="OpenJDK 64-Bit Server VM"/>
|
||||||
|
<property name="java.vendor.version" value="(Alibaba Dragonwell Standard Edition)-25.0.0.0.1+36-GA"/>
|
||||||
|
<property name="localRepository" value="C:\Users\Administrator\.m2\repository"/>
|
||||||
|
<property name="java.vendor.url.bug" value="mailto:dragonwell_use@googlegroups.com"/>
|
||||||
|
<property name="java.io.tmpdir" value="C:\Users\ADMINI~1\AppData\Local\Temp\"/>
|
||||||
|
<property name="java.version" value="25.0.0.0.1"/>
|
||||||
|
<property name="user.dir" value="G:\Project\Java\pve-back-api"/>
|
||||||
|
<property name="os.arch" value="amd64"/>
|
||||||
|
<property name="java.vm.specification.name" value="Java Virtual Machine Specification"/>
|
||||||
|
<property name="sun.os.patch.level" value=""/>
|
||||||
|
<property name="native.encoding" value="GBK"/>
|
||||||
|
<property name="java.library.path" value="C:\Program Files\Java\dragonwell-25.0.0.0.1+36-GA\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;D:\phpEnv\php\php-7.4;C:\Program Files\OpenSSH\;C:\Program Files\Java\dragonwell-25.0.0.0.1+36-GA\bin;C:\Program Files (x86)\Common Files\Oracle\Java\java8path;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\MinGW\bin;C:\MinGW\msys\1.0\bin;C:\MinGW\mingw32\bin;D:\nodejs;C:\Python314\Scripts\;C:\Python314\;D:\Ruby34-x64\bin;C:\Program Files\dotnet\;C:\Program Files (x86)\Common Files\Intel\Shared Libraries\bin32;C:\Program Files (x86)\Common Files\Intel\Shared Libraries\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\libnvvp;G:\Project\Python_Interpreter\Python3.12.5\Scripts\;G:\Project\Python_Interpreter\Python3.12.5\;C:;Vmware\bin\;C:\Program Files (x86)\Common Files\Intel\Shared Libraries\redist\intel64\compiler;C:\Windows\System32\Wbem;C:\Windows\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;D:\Xshell\;D:\Xftp\;C:\Program Files\wget;C:\ProgramData\chocolatey\bin;C:\Program Files (x86)\Microsoft\Edge\Application\;C:\Program Files\Google\Chrome\Application;Program Files\Windows_Linux_Command;C:\Program Files\Go\bin;C:\Program Files\ossutil-v1.7.19-;D:\jvms\jvms_v2.1.7_amd64;C:\Program Files\NVIDIA Corporation\NVIDIA App\NvDLISR;D:\Gpg4win\..\GnuPG\bin;D:\Android\ADB\platform-tools;C:\Program Files\Git\cmd;D:\qemu;C:\Program Files\Docker\Docker\resources\bin;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;D:\Xoreax\IncrediBuild;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Users\Administrator\AppData\Local\pnpm;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;D:\Microsoft VS Code\bin;C:\Users\Administrator\.dotnet\tools;D:\JetBrains\IntelliJ IDEA Community Edition 2023.1.4\bin;D:\JetBrains\PyCharm2023.1.4\bin;D:\JetBrains\PhpStorm 2023.1.4\bin;C:\Program Files (x86)\Nmap;D:\JetBrains Gateway 2023.2\bin;D:\phpEnv\php\php-7.4\;D:\phpEnv\server\mysql\mysql-5.7\bin\;D:\phpEnv\tools\Composer\;D:\JetBrains\GoLand 2023.3.2\bin;C:\Users\Administrator\go\bin;C:\Users\Administrator\.dotnet\tools;C:\Users\Administrator\AppData\Local\JetBrains\Toolbox\scripts;D:\WebStorm 2024.1.2\bin;;D:\DataGrip 2024.1.3\bin;;C:\Users\Administrator\AppData\Local\GitHubDesktop\bin;D:\JetBrains\IntelliJ IDEA 2025.3.2\bin;D:\JetBrains\CLion 2024.2.1\bin;;C:\Windows\system32\config\systemprofile\.dotnet\tools;C:\Users\Administrator\AppData\Local\Microsoft\WinGet\Links;D:\JetBrains\PyCharm 2024.3.5\bin;;D:\JetBrains\PyCharm Community Edition 2024.3.5\bin;;D:\nvm;D:\nodejs;C:\Users\Administrator\AppData\Local\Programs\Rancher Desktop\resources\resources\win32\bin\;C:\Users\Administrator\AppData\Local\Programs\Rancher Desktop\resources\resources\win32\docker-cli-plugins\;C:\Users\Administrator\AppData\Local\Programs\Rancher Desktop\resources\resources\linux\bin\;C:\Users\Administrator\AppData\Local\Programs\Rancher Desktop\resources\resources\linux\docker-cli-plugins\;D:\Lens\resources\cli\bin;D:\JetBrains\RubyMine 2025.3\bin;C:\Users\Administrator\.dotnet\tools;."/>
|
||||||
|
<property name="java.vm.info" value="mixed mode, sharing"/>
|
||||||
|
<property name="stderr.encoding" value="GBK"/>
|
||||||
|
<property name="java.vendor" value="Alibaba"/>
|
||||||
|
<property name="java.vm.version" value="25.0.0.0.1"/>
|
||||||
|
<property name="stdin.encoding" value="GBK"/>
|
||||||
|
<property name="sun.io.unicode.encoding" value="UnicodeLittle"/>
|
||||||
|
<property name="java.class.version" value="69.0"/>
|
||||||
|
</properties>
|
||||||
|
<testcase name="testHttpsRequest" classname="top.gtb520.java.pve_back_api.ResourcesResultTest" time="1.117">
|
||||||
|
<system-out><![CDATA[开始发送HTTPS请求...
|
||||||
|
18:14:53.670 [reactor-tcp-nio-2] WARN reactor.netty.http.client.HttpClientConnect -- [995021fa, L:/10.168.2.110:50342 - R:/10.168.2.2:8013] The connection observed an error
|
||||||
|
io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 485454502f312e31203430302042616420526571756573740d0a5365727665723a206e67696e782f312e31362e310d0a446174653a205765642c2030342046656220323032362031303a31343a353020474d540d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a436f6e74656e742d4c656e6774683a20323232300d0a436f6e6e656374696f6e3a20636c6f73650d0a455461673a202235643665313261342d386163220d0a0d0a3c21444f43545950452068746d6c3e0d0a3c68746d6c206c616e673d227a682d434e223e0d0a3c686561643e0d0a20203c6d65746120636861727365743d227574662d38223e0d0a20203c7469746c653e34303020e99499e8afaf202d2070687073747564793c2f7469746c653e0d0a20203c6d657461206e616d653d226b6579776f7264732220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d226465736372697074696f6e2220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d2272656e64657265722220636f6e74656e743d227765626b6974223e0d0a20203c6d65746120687474702d65717569763d22582d55412d436f6d70617469626c652220636f6e74656e743d2249453d656467652c6368726f6d653d31223e0d0a20203c6d657461206e616d653d2276696577706f72742220636f6e74656e743d2277696474683d6465766963652d77696474682c20696e697469616c2d7363616c653d312c206d6178696d756d2d7363616c653d31223e0d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d7374617475732d6261722d7374796c652220636f6e74656e743d22626c61636b223e200d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d63617061626c652220636f6e74656e743d22796573223e0d0a20203c6d657461206e616d653d22666f726d61742d646574656374696f6e2220636f6e74656e743d2274656c6570686f6e653d6e6f223e0d0a20203c6d65746120485454502d45515549563d22707261676d612220434f4e54454e543d226e6f2d6361636865223e200d0a20203c6d65746120485454502d45515549563d2243616368652d436f6e74726f6c2220434f4e54454e543d226e6f2d73746f72652c206d7573742d726576616c6964617465223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d225765642c2032362046656220313939372030383a32313a353720474d54223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d2230223e0d0a20203c7374796c653e0d0a20202020626f64797b0d0a202020202020666f6e743a203136707820617269616c2c274d6963726f736f6674205961686569272c274869726167696e6f2053616e73204742272c73616e732d73657269663b0d0a202020207d0d0a2020202068317b0d0a2020202020206d617267696e3a20303b0d0a202020202020636f6c6f723a233361383761643b0d0a202020202020666f6e742d73697a653a20323670783b0d0a202020207d0d0a202020202e636f6e74656e747b0d0a20202020202077696474683a203435253b0d0a2020202020206d617267696e3a2030206175746f3b0d0a20202020200d0a202020207d0d0a202020202e636f6e74656e74203e6469767b0d0a2020202020206d617267696e2d746f703a2032303070783b0d0a20202020202070616464696e673a20323070783b0d0a2020202020206261636b67726f756e643a20236439656466373b20200d0a202020202020626f726465722d7261646975733a20313270783b0d0a202020207d0d0a202020202e636f6e74656e7420646c7b0d0a202020202020636f6c6f723a20233264366138383b0d0a2020202020206c696e652d6865696768743a20343070783b0d0a202020207d200d0a202020202e636f6e74656e742064697620646976207b0d0a20202020202070616464696e672d626f74746f6d3a20323070783b0d0a202020202020746578742d616c69676e3a63656e7465723b0d0a202020207d0d0a20203c2f7374796c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a20203c64697620636c6173733d22636f6e74656e74223e0d0a2020202020203c6469763e0d0a20202020202020202020203c68313e4854545020343030202d2042616420526571756573743c2f68313e0d0a20202020202020203c646c3e0d0a202020202020202020203c64743ee99499e8afafe8afb4e6988eefbc9ae59ba0e4b8bae99499e8afafe79a84e8afade6b395e5afbce887b4e69c8de58aa1e599a8e697a0e6b395e79086e8a7a3e8afb7e6b182e4bfa1e681afe380823c2f64743e0d0a202020202020202020203c64743ee58e9fe59ba031efbc9ae5aea2e688b7e7abafe58f91e8b5b7e79a84e8afb7e6b182e4b88de7aca6e59088e69c8de58aa1e599a8e5afb9e8afb7e6b182e79a84e69f90e4ba9be99990e588b6efbc8ce68896e88085e8afb7e6b182e69cace8baabe5ad98e59ca8e4b880e5ae9ae79a84e99499e8afafe380823c2f64743e0d0a090920203c64643ee8a7a3e586b3e58a9ee6b395efbc9a3c2f64643e0d0a202020202020202020203c64643ee993bee68ea5e4b8ade69c89e789b9e6ae8ae5ad97e7aca6e68896e88085e993bee68ea5e995bfe5baa6e8bf87e995bfe5afbce887b4efbc8ce8afb7e5afb9e5ba94e4bfaee694b92e3c2f64643e0d0a202020202020202020203c64743ee58e9fe59ba032
|
||||||
|
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1374)
|
||||||
|
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1449)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:545)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:484)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
|
||||||
|
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:172)
|
||||||
|
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.handle(AbstractNioChannel.java:445)
|
||||||
|
at io.netty.channel.nio.NioIoHandler$DefaultNioRegistration.handle(NioIoHandler.java:388)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKey(NioIoHandler.java:596)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeysPlain(NioIoHandler.java:541)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeys(NioIoHandler.java:514)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.run(NioIoHandler.java:484)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196)
|
||||||
|
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1195)
|
||||||
|
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
|
||||||
|
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
|
||||||
|
at java.base/java.lang.Thread.run(Thread.java:1474)
|
||||||
|
18:14:53.680 [reactor-tcp-nio-2] WARN reactor.netty.http.client.HttpClientConnect -- [995021fa, L:/10.168.2.110:50342 ! R:/10.168.2.2:8013] The connection observed an error
|
||||||
|
io.netty.handler.codec.DecoderException: io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 485454502f312e31203430302042616420526571756573740d0a5365727665723a206e67696e782f312e31362e310d0a446174653a205765642c2030342046656220323032362031303a31343a353020474d540d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a436f6e74656e742d4c656e6774683a20323232300d0a436f6e6e656374696f6e3a20636c6f73650d0a455461673a202235643665313261342d386163220d0a0d0a3c21444f43545950452068746d6c3e0d0a3c68746d6c206c616e673d227a682d434e223e0d0a3c686561643e0d0a20203c6d65746120636861727365743d227574662d38223e0d0a20203c7469746c653e34303020e99499e8afaf202d2070687073747564793c2f7469746c653e0d0a20203c6d657461206e616d653d226b6579776f7264732220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d226465736372697074696f6e2220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d2272656e64657265722220636f6e74656e743d227765626b6974223e0d0a20203c6d65746120687474702d65717569763d22582d55412d436f6d70617469626c652220636f6e74656e743d2249453d656467652c6368726f6d653d31223e0d0a20203c6d657461206e616d653d2276696577706f72742220636f6e74656e743d2277696474683d6465766963652d77696474682c20696e697469616c2d7363616c653d312c206d6178696d756d2d7363616c653d31223e0d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d7374617475732d6261722d7374796c652220636f6e74656e743d22626c61636b223e200d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d63617061626c652220636f6e74656e743d22796573223e0d0a20203c6d657461206e616d653d22666f726d61742d646574656374696f6e2220636f6e74656e743d2274656c6570686f6e653d6e6f223e0d0a20203c6d65746120485454502d45515549563d22707261676d612220434f4e54454e543d226e6f2d6361636865223e200d0a20203c6d65746120485454502d45515549563d2243616368652d436f6e74726f6c2220434f4e54454e543d226e6f2d73746f72652c206d7573742d726576616c6964617465223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d225765642c2032362046656220313939372030383a32313a353720474d54223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d2230223e0d0a20203c7374796c653e0d0a20202020626f64797b0d0a202020202020666f6e743a203136707820617269616c2c274d6963726f736f6674205961686569272c274869726167696e6f2053616e73204742272c73616e732d73657269663b0d0a202020207d0d0a2020202068317b0d0a2020202020206d617267696e3a20303b0d0a202020202020636f6c6f723a233361383761643b0d0a202020202020666f6e742d73697a653a20323670783b0d0a202020207d0d0a202020202e636f6e74656e747b0d0a20202020202077696474683a203435253b0d0a2020202020206d617267696e3a2030206175746f3b0d0a20202020200d0a202020207d0d0a202020202e636f6e74656e74203e6469767b0d0a2020202020206d617267696e2d746f703a2032303070783b0d0a20202020202070616464696e673a20323070783b0d0a2020202020206261636b67726f756e643a20236439656466373b20200d0a202020202020626f726465722d7261646975733a20313270783b0d0a202020207d0d0a202020202e636f6e74656e7420646c7b0d0a202020202020636f6c6f723a20233264366138383b0d0a2020202020206c696e652d6865696768743a20343070783b0d0a202020207d200d0a202020202e636f6e74656e742064697620646976207b0d0a20202020202070616464696e672d626f74746f6d3a20323070783b0d0a202020202020746578742d616c69676e3a63656e7465723b0d0a202020207d0d0a20203c2f7374796c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a20203c64697620636c6173733d22636f6e74656e74223e0d0a2020202020203c6469763e0d0a20202020202020202020203c68313e4854545020343030202d2042616420526571756573743c2f68313e0d0a20202020202020203c646c3e0d0a202020202020202020203c64743ee99499e8afafe8afb4e6988eefbc9ae59ba0e4b8bae99499e8afafe79a84e8afade6b395e5afbce887b4e69c8de58aa1e599a8e697a0e6b395e79086e8a7a3e8afb7e6b182e4bfa1e681afe380823c2f64743e0d0a202020202020202020203c64743ee58e9fe59ba031efbc9ae5aea2e688b7e7abafe58f91e8b5b7e79a84e8afb7e6b182e4b88de7aca6e59088e69c8de58aa1e599a8e5afb9e8afb7e6b182e79a84e69f90e4ba9be99990e588b6efbc8ce68896e88085e8afb7e6b182e69cace8baabe5ad98e59ca8e4b880e5ae9ae79a84e99499e8afafe380823c2f64743e0d0a090920203c64643ee8a7a3e586b3e58a9ee6b395efbc9a3c2f64643e0d0a202020202020202020203c64643ee993bee68ea5e4b8ade69c89e789b9e6ae8ae5ad97e7aca6e68896e88085e993bee68ea5e995bfe5baa6e8bf87e995bfe5afbce887b4efbc8ce8afb7e5afb9e5ba94e4bfaee694b92e3c2f64643e0d0a202020202020202020203c64743ee58e9fe59ba032
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:515)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
|
||||||
|
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:172)
|
||||||
|
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.handle(AbstractNioChannel.java:445)
|
||||||
|
at io.netty.channel.nio.NioIoHandler$DefaultNioRegistration.handle(NioIoHandler.java:388)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKey(NioIoHandler.java:596)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeysPlain(NioIoHandler.java:541)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeys(NioIoHandler.java:514)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.run(NioIoHandler.java:484)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196)
|
||||||
|
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1195)
|
||||||
|
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
|
||||||
|
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
|
||||||
|
at java.base/java.lang.Thread.run(Thread.java:1474)
|
||||||
|
Caused by: io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 485454502f312e31203430302042616420526571756573740d0a5365727665723a206e67696e782f312e31362e310d0a446174653a205765642c2030342046656220323032362031303a31343a353020474d540d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a436f6e74656e742d4c656e6774683a20323232300d0a436f6e6e656374696f6e3a20636c6f73650d0a455461673a202235643665313261342d386163220d0a0d0a3c21444f43545950452068746d6c3e0d0a3c68746d6c206c616e673d227a682d434e223e0d0a3c686561643e0d0a20203c6d65746120636861727365743d227574662d38223e0d0a20203c7469746c653e34303020e99499e8afaf202d2070687073747564793c2f7469746c653e0d0a20203c6d657461206e616d653d226b6579776f7264732220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d226465736372697074696f6e2220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d2272656e64657265722220636f6e74656e743d227765626b6974223e0d0a20203c6d65746120687474702d65717569763d22582d55412d436f6d70617469626c652220636f6e74656e743d2249453d656467652c6368726f6d653d31223e0d0a20203c6d657461206e616d653d2276696577706f72742220636f6e74656e743d2277696474683d6465766963652d77696474682c20696e697469616c2d7363616c653d312c206d6178696d756d2d7363616c653d31223e0d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d7374617475732d6261722d7374796c652220636f6e74656e743d22626c61636b223e200d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d63617061626c652220636f6e74656e743d22796573223e0d0a20203c6d657461206e616d653d22666f726d61742d646574656374696f6e2220636f6e74656e743d2274656c6570686f6e653d6e6f223e0d0a20203c6d65746120485454502d45515549563d22707261676d612220434f4e54454e543d226e6f2d6361636865223e200d0a20203c6d65746120485454502d45515549563d2243616368652d436f6e74726f6c2220434f4e54454e543d226e6f2d73746f72652c206d7573742d726576616c6964617465223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d225765642c2032362046656220313939372030383a32313a353720474d54223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d2230223e0d0a20203c7374796c653e0d0a20202020626f64797b0d0a202020202020666f6e743a203136707820617269616c2c274d6963726f736f6674205961686569272c274869726167696e6f2053616e73204742272c73616e732d73657269663b0d0a202020207d0d0a2020202068317b0d0a2020202020206d617267696e3a20303b0d0a202020202020636f6c6f723a233361383761643b0d0a202020202020666f6e742d73697a653a20323670783b0d0a202020207d0d0a202020202e636f6e74656e747b0d0a20202020202077696474683a203435253b0d0a2020202020206d617267696e3a2030206175746f3b0d0a20202020200d0a202020207d0d0a202020202e636f6e74656e74203e6469767b0d0a2020202020206d617267696e2d746f703a2032303070783b0d0a20202020202070616464696e673a20323070783b0d0a2020202020206261636b67726f756e643a20236439656466373b20200d0a202020202020626f726465722d7261646975733a20313270783b0d0a202020207d0d0a202020202e636f6e74656e7420646c7b0d0a202020202020636f6c6f723a20233264366138383b0d0a2020202020206c696e652d6865696768743a20343070783b0d0a202020207d200d0a202020202e636f6e74656e742064697620646976207b0d0a20202020202070616464696e672d626f74746f6d3a20323070783b0d0a202020202020746578742d616c69676e3a63656e7465723b0d0a202020207d0d0a20203c2f7374796c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a20203c64697620636c6173733d22636f6e74656e74223e0d0a2020202020203c6469763e0d0a20202020202020202020203c68313e4854545020343030202d2042616420526571756573743c2f68313e0d0a20202020202020203c646c3e0d0a202020202020202020203c64743ee99499e8afafe8afb4e6988eefbc9ae59ba0e4b8bae99499e8afafe79a84e8afade6b395e5afbce887b4e69c8de58aa1e599a8e697a0e6b395e79086e8a7a3e8afb7e6b182e4bfa1e681afe380823c2f64743e0d0a202020202020202020203c64743ee58e9fe59ba031efbc9ae5aea2e688b7e7abafe58f91e8b5b7e79a84e8afb7e6b182e4b88de7aca6e59088e69c8de58aa1e599a8e5afb9e8afb7e6b182e79a84e69f90e4ba9be99990e588b6efbc8ce68896e88085e8afb7e6b182e69cace8baabe5ad98e59ca8e4b880e5ae9ae79a84e99499e8afafe380823c2f64743e0d0a090920203c64643ee8a7a3e586b3e58a9ee6b395efbc9a3c2f64643e0d0a202020202020202020203c64643ee993bee68ea5e4b8ade69c89e789b9e6ae8ae5ad97e7aca6e68896e88085e993bee68ea5e995bfe5baa6e8bf87e995bfe5afbce887b4efbc8ce8afb7e5afb9e5ba94e4bfaee694b92e3c2f64643e0d0a202020202020202020203c64743ee58e9fe59ba032
|
||||||
|
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1374)
|
||||||
|
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1449)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:545)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:484)
|
||||||
|
... 17 common frames omitted
|
||||||
|
]]></system-out>
|
||||||
|
<system-err><![CDATA[❌ HTTPS请求失败: not an SSL/TLS record: 485454502f312e31203430302042616420526571756573740d0a5365727665723a206e67696e782f312e31362e310d0a446174653a205765642c2030342046656220323032362031303a31343a353020474d540d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a436f6e74656e742d4c656e6774683a20323232300d0a436f6e6e656374696f6e3a20636c6f73650d0a455461673a202235643665313261342d386163220d0a0d0a3c21444f43545950452068746d6c3e0d0a3c68746d6c206c616e673d227a682d434e223e0d0a3c686561643e0d0a20203c6d65746120636861727365743d227574662d38223e0d0a20203c7469746c653e34303020e99499e8afaf202d2070687073747564793c2f7469746c653e0d0a20203c6d657461206e616d653d226b6579776f7264732220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d226465736372697074696f6e2220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d2272656e64657265722220636f6e74656e743d227765626b6974223e0d0a20203c6d65746120687474702d65717569763d22582d55412d436f6d70617469626c652220636f6e74656e743d2249453d656467652c6368726f6d653d31223e0d0a20203c6d657461206e616d653d2276696577706f72742220636f6e74656e743d2277696474683d6465766963652d77696474682c20696e697469616c2d7363616c653d312c206d6178696d756d2d7363616c653d31223e0d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d7374617475732d6261722d7374796c652220636f6e74656e743d22626c61636b223e200d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d63617061626c652220636f6e74656e743d22796573223e0d0a20203c6d657461206e616d653d22666f726d61742d646574656374696f6e2220636f6e74656e743d2274656c6570686f6e653d6e6f223e0d0a20203c6d65746120485454502d45515549563d22707261676d612220434f4e54454e543d226e6f2d6361636865223e200d0a20203c6d65746120485454502d45515549563d2243616368652d436f6e74726f6c2220434f4e54454e543d226e6f2d73746f72652c206d7573742d726576616c6964617465223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d225765642c2032362046656220313939372030383a32313a353720474d54223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d2230223e0d0a20203c7374796c653e0d0a20202020626f64797b0d0a202020202020666f6e743a203136707820617269616c2c274d6963726f736f6674205961686569272c274869726167696e6f2053616e73204742272c73616e732d73657269663b0d0a202020207d0d0a2020202068317b0d0a2020202020206d617267696e3a20303b0d0a202020202020636f6c6f723a233361383761643b0d0a202020202020666f6e742d73697a653a20323670783b0d0a202020207d0d0a202020202e636f6e74656e747b0d0a20202020202077696474683a203435253b0d0a2020202020206d617267696e3a2030206175746f3b0d0a20202020200d0a202020207d0d0a202020202e636f6e74656e74203e6469767b0d0a2020202020206d617267696e2d746f703a2032303070783b0d0a20202020202070616464696e673a20323070783b0d0a2020202020206261636b67726f756e643a20236439656466373b20200d0a202020202020626f726465722d7261646975733a20313270783b0d0a202020207d0d0a202020202e636f6e74656e7420646c7b0d0a202020202020636f6c6f723a20233264366138383b0d0a2020202020206c696e652d6865696768743a20343070783b0d0a202020207d200d0a202020202e636f6e74656e742064697620646976207b0d0a20202020202070616464696e672d626f74746f6d3a20323070783b0d0a202020202020746578742d616c69676e3a63656e7465723b0d0a202020207d0d0a20203c2f7374796c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a20203c64697620636c6173733d22636f6e74656e74223e0d0a2020202020203c6469763e0d0a20202020202020202020203c68313e4854545020343030202d2042616420526571756573743c2f68313e0d0a20202020202020203c646c3e0d0a202020202020202020203c64743ee99499e8afafe8afb4e6988eefbc9ae59ba0e4b8bae99499e8afafe79a84e8afade6b395e5afbce887b4e69c8de58aa1e599a8e697a0e6b395e79086e8a7a3e8afb7e6b182e4bfa1e681afe380823c2f64743e0d0a202020202020202020203c64743ee58e9fe59ba031efbc9ae5aea2e688b7e7abafe58f91e8b5b7e79a84e8afb7e6b182e4b88de7aca6e59088e69c8de58aa1e599a8e5afb9e8afb7e6b182e79a84e69f90e4ba9be99990e588b6efbc8ce68896e88085e8afb7e6b182e69cace8baabe5ad98e59ca8e4b880e5ae9ae79a84e99499e8afafe380823c2f64743e0d0a090920203c64643ee8a7a3e586b3e58a9ee6b395efbc9a3c2f64643e0d0a202020202020202020203c64643ee993bee68ea5e4b8ade69c89e789b9e6ae8ae5ad97e7aca6e68896e88085e993bee68ea5e995bfe5baa6e8bf87e995bfe5afbce887b4efbc8ce8afb7e5afb9e5ba94e4bfaee694b92e3c2f64643e0d0a202020202020202020203c64743ee58e9fe59ba032
|
||||||
|
可能的原因:
|
||||||
|
1. 目标服务器不可达
|
||||||
|
2. 端口未开放
|
||||||
|
3. 网络连接问题
|
||||||
|
4. SSL配置问题
|
||||||
|
org.springframework.web.reactive.function.client.WebClientRequestException: not an SSL/TLS record: 485454502f312e31203430302042616420526571756573740d0a5365727665723a206e67696e782f312e31362e310d0a446174653a205765642c2030342046656220323032362031303a31343a353020474d540d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a436f6e74656e742d4c656e6774683a20323232300d0a436f6e6e656374696f6e3a20636c6f73650d0a455461673a202235643665313261342d386163220d0a0d0a3c21444f43545950452068746d6c3e0d0a3c68746d6c206c616e673d227a682d434e223e0d0a3c686561643e0d0a20203c6d65746120636861727365743d227574662d38223e0d0a20203c7469746c653e34303020e99499e8afaf202d2070687073747564793c2f7469746c653e0d0a20203c6d657461206e616d653d226b6579776f7264732220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d226465736372697074696f6e2220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d2272656e64657265722220636f6e74656e743d227765626b6974223e0d0a20203c6d65746120687474702d65717569763d22582d55412d436f6d70617469626c652220636f6e74656e743d2249453d656467652c6368726f6d653d31223e0d0a20203c6d657461206e616d653d2276696577706f72742220636f6e74656e743d2277696474683d6465766963652d77696474682c20696e697469616c2d7363616c653d312c206d6178696d756d2d7363616c653d31223e0d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d7374617475732d6261722d7374796c652220636f6e74656e743d22626c61636b223e200d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d63617061626c652220636f6e74656e743d22796573223e0d0a20203c6d657461206e616d653d22666f726d61742d646574656374696f6e2220636f6e74656e743d2274656c6570686f6e653d6e6f223e0d0a20203c6d65746120485454502d45515549563d22707261676d612220434f4e54454e543d226e6f2d6361636865223e200d0a20203c6d65746120485454502d45515549563d2243616368652d436f6e74726f6c2220434f4e54454e543d226e6f2d73746f72652c206d7573742d726576616c6964617465223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d225765642c2032362046656220313939372030383a32313a353720474d54223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d2230223e0d0a20203c7374796c653e0d0a20202020626f64797b0d0a202020202020666f6e743a203136707820617269616c2c274d6963726f736f6674205961686569272c274869726167696e6f2053616e73204742272c73616e732d73657269663b0d0a202020207d0d0a2020202068317b0d0a2020202020206d617267696e3a20303b0d0a202020202020636f6c6f723a233361383761643b0d0a202020202020666f6e742d73697a653a20323670783b0d0a202020207d0d0a202020202e636f6e74656e747b0d0a20202020202077696474683a203435253b0d0a2020202020206d617267696e3a2030206175746f3b0d0a20202020200d0a202020207d0d0a202020202e636f6e74656e74203e6469767b0d0a2020202020206d617267696e2d746f703a2032303070783b0d0a20202020202070616464696e673a20323070783b0d0a2020202020206261636b67726f756e643a20236439656466373b20200d0a202020202020626f726465722d7261646975733a20313270783b0d0a202020207d0d0a202020202e636f6e74656e7420646c7b0d0a202020202020636f6c6f723a20233264366138383b0d0a2020202020206c696e652d6865696768743a20343070783b0d0a202020207d200d0a202020202e636f6e74656e742064697620646976207b0d0a20202020202070616464696e672d626f74746f6d3a20323070783b0d0a202020202020746578742d616c69676e3a63656e7465723b0d0a202020207d0d0a20203c2f7374796c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a20203c64697620636c6173733d22636f6e74656e74223e0d0a2020202020203c6469763e0d0a20202020202020202020203c68313e4854545020343030202d2042616420526571756573743c2f68313e0d0a20202020202020203c646c3e0d0a202020202020202020203c64743ee99499e8afafe8afb4e6988eefbc9ae59ba0e4b8bae99499e8afafe79a84e8afade6b395e5afbce887b4e69c8de58aa1e599a8e697a0e6b395e79086e8a7a3e8afb7e6b182e4bfa1e681afe380823c2f64743e0d0a202020202020202020203c64743ee58e9fe59ba031efbc9ae5aea2e688b7e7abafe58f91e8b5b7e79a84e8afb7e6b182e4b88de7aca6e59088e69c8de58aa1e599a8e5afb9e8afb7e6b182e79a84e69f90e4ba9be99990e588b6efbc8ce68896e88085e8afb7e6b182e69cace8baabe5ad98e59ca8e4b880e5ae9ae79a84e99499e8afafe380823c2f64743e0d0a090920203c64643ee8a7a3e586b3e58a9ee6b395efbc9a3c2f64643e0d0a202020202020202020203c64643ee993bee68ea5e4b8ade69c89e789b9e6ae8ae5ad97e7aca6e68896e88085e993bee68ea5e995bfe5baa6e8bf87e995bfe5afbce887b4efbc8ce8afb7e5afb9e5ba94e4bfaee694b92e3c2f64643e0d0a202020202020202020203c64743ee58e9fe59ba032
|
||||||
|
at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$0(ExchangeFunctions.java:137)
|
||||||
|
Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:
|
||||||
|
Error has been observed at the following site(s):
|
||||||
|
*__checkpoint ⇢ Request to GET https://10.168.2.2:8013/ [DefaultWebClient]
|
||||||
|
Original Stack Trace:
|
||||||
|
at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$0(ExchangeFunctions.java:137)
|
||||||
|
at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:56)
|
||||||
|
at reactor.core.publisher.Mono.subscribe(Mono.java:4569)
|
||||||
|
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:104)
|
||||||
|
at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:225)
|
||||||
|
at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:225)
|
||||||
|
at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:225)
|
||||||
|
at reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:94)
|
||||||
|
at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onError(MonoFlatMapMany.java:207)
|
||||||
|
at reactor.core.publisher.SerializedSubscriber.onError(SerializedSubscriber.java:125)
|
||||||
|
at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.whenError(FluxRetryWhen.java:230)
|
||||||
|
at reactor.core.publisher.FluxRetryWhen$RetryWhenOtherSubscriber.onError(FluxRetryWhen.java:282)
|
||||||
|
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:123)
|
||||||
|
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.maybeOnError(FluxConcatMapNoPrefetch.java:327)
|
||||||
|
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.onNext(FluxConcatMapNoPrefetch.java:212)
|
||||||
|
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:109)
|
||||||
|
at reactor.core.publisher.SinkManyEmitterProcessor.drain(SinkManyEmitterProcessor.java:483)
|
||||||
|
at reactor.core.publisher.SinkManyEmitterProcessor$EmitterInner.drainParent(SinkManyEmitterProcessor.java:627)
|
||||||
|
at reactor.core.publisher.FluxPublish$PubSubInner.request(FluxPublish.java:881)
|
||||||
|
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:138)
|
||||||
|
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.request(FluxConcatMapNoPrefetch.java:337)
|
||||||
|
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:138)
|
||||||
|
at reactor.core.publisher.Operators$DeferredSubscription.request(Operators.java:1740)
|
||||||
|
at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onError(FluxRetryWhen.java:197)
|
||||||
|
at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:208)
|
||||||
|
at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect$ClientTransportSubscriber.onError(HttpClientConnect.java:336)
|
||||||
|
at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:208)
|
||||||
|
at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onUncaughtException(DefaultPooledConnectionProvider.java:232)
|
||||||
|
at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onUncaughtException(DefaultPooledConnectionProvider.java:487)
|
||||||
|
at reactor.netty.channel.ChannelOperationsHandler.exceptionCaught(ChannelOperationsHandler.java:156)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:289)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:271)
|
||||||
|
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireExceptionCaught(CombinedChannelDuplexHandler.java:422)
|
||||||
|
at io.netty.channel.ChannelHandlerAdapter.exceptionCaught(ChannelHandlerAdapter.java:92)
|
||||||
|
at io.netty.channel.CombinedChannelDuplexHandler$1.fireExceptionCaught(CombinedChannelDuplexHandler.java:144)
|
||||||
|
at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:143)
|
||||||
|
at io.netty.channel.CombinedChannelDuplexHandler.exceptionCaught(CombinedChannelDuplexHandler.java:229)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:289)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:271)
|
||||||
|
at reactor.netty.tcp.SslProvider$SslReadHandler.userEventTriggered(SslProvider.java:725)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:323)
|
||||||
|
at io.netty.handler.ssl.SslUtils.handleHandshakeFailure(SslUtils.java:543)
|
||||||
|
at io.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:2062)
|
||||||
|
at io.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:2031)
|
||||||
|
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1379)
|
||||||
|
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1449)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:545)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:484)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
|
||||||
|
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:172)
|
||||||
|
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.handle(AbstractNioChannel.java:445)
|
||||||
|
at io.netty.channel.nio.NioIoHandler$DefaultNioRegistration.handle(NioIoHandler.java:388)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKey(NioIoHandler.java:596)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeysPlain(NioIoHandler.java:541)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeys(NioIoHandler.java:514)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.run(NioIoHandler.java:484)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196)
|
||||||
|
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1195)
|
||||||
|
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
|
||||||
|
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
|
||||||
|
at java.base/java.lang.Thread.run(Thread.java:1474)
|
||||||
|
Suppressed: java.lang.Exception: #block terminated with an error
|
||||||
|
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:104)
|
||||||
|
at reactor.core.publisher.Mono.block(Mono.java:1773)
|
||||||
|
at top.gtb520.java.pve_back_api.ResourcesResultTest.testHttpsRequest(ResourcesResultTest.java:62)
|
||||||
|
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
|
||||||
|
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:701)
|
||||||
|
at org.junit.platform.commons.support.ReflectionSupport.invokeMethod(ReflectionSupport.java:502)
|
||||||
|
at org.junit.jupiter.engine.support.MethodReflectionUtils.invoke(MethodReflectionUtils.java:45)
|
||||||
|
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:61)
|
||||||
|
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:124)
|
||||||
|
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:163)
|
||||||
|
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:148)
|
||||||
|
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
|
||||||
|
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:123)
|
||||||
|
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:105)
|
||||||
|
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:99)
|
||||||
|
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:66)
|
||||||
|
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:47)
|
||||||
|
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:39)
|
||||||
|
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:104)
|
||||||
|
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:98)
|
||||||
|
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invokeVoid(InterceptingExecutableInvoker.java:71)
|
||||||
|
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$0(TestMethodTestDescriptor.java:219)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:215)
|
||||||
|
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:157)
|
||||||
|
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:70)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:176)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
|
||||||
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:42)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:180)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
|
||||||
|
at java.base/java.util.ArrayList.forEach(ArrayList.java:1604)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:42)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:180)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:36)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:52)
|
||||||
|
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:58)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:246)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:218)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:179)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:66)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:157)
|
||||||
|
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:65)
|
||||||
|
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:125)
|
||||||
|
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
|
||||||
|
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:58)
|
||||||
|
at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$2(InterceptingLauncher.java:57)
|
||||||
|
at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25)
|
||||||
|
at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:56)
|
||||||
|
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:58)
|
||||||
|
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
|
||||||
|
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
|
||||||
|
at org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:125)
|
||||||
|
at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithCancellationToken(LauncherAdapter.java:68)
|
||||||
|
at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:54)
|
||||||
|
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203)
|
||||||
|
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168)
|
||||||
|
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136)
|
||||||
|
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
|
||||||
|
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
|
||||||
|
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
|
||||||
|
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
|
||||||
|
Caused by: io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 485454502f312e31203430302042616420526571756573740d0a5365727665723a206e67696e782f312e31362e310d0a446174653a205765642c2030342046656220323032362031303a31343a353020474d540d0a436f6e74656e742d547970653a20746578742f68746d6c0d0a436f6e74656e742d4c656e6774683a20323232300d0a436f6e6e656374696f6e3a20636c6f73650d0a455461673a202235643665313261342d386163220d0a0d0a3c21444f43545950452068746d6c3e0d0a3c68746d6c206c616e673d227a682d434e223e0d0a3c686561643e0d0a20203c6d65746120636861727365743d227574662d38223e0d0a20203c7469746c653e34303020e99499e8afaf202d2070687073747564793c2f7469746c653e0d0a20203c6d657461206e616d653d226b6579776f7264732220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d226465736372697074696f6e2220636f6e74656e743d22223e0d0a20203c6d657461206e616d653d2272656e64657265722220636f6e74656e743d227765626b6974223e0d0a20203c6d65746120687474702d65717569763d22582d55412d436f6d70617469626c652220636f6e74656e743d2249453d656467652c6368726f6d653d31223e0d0a20203c6d657461206e616d653d2276696577706f72742220636f6e74656e743d2277696474683d6465766963652d77696474682c20696e697469616c2d7363616c653d312c206d6178696d756d2d7363616c653d31223e0d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d7374617475732d6261722d7374796c652220636f6e74656e743d22626c61636b223e200d0a20203c6d657461206e616d653d226170706c652d6d6f62696c652d7765622d6170702d63617061626c652220636f6e74656e743d22796573223e0d0a20203c6d657461206e616d653d22666f726d61742d646574656374696f6e2220636f6e74656e743d2274656c6570686f6e653d6e6f223e0d0a20203c6d65746120485454502d45515549563d22707261676d612220434f4e54454e543d226e6f2d6361636865223e200d0a20203c6d65746120485454502d45515549563d2243616368652d436f6e74726f6c2220434f4e54454e543d226e6f2d73746f72652c206d7573742d726576616c6964617465223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d225765642c2032362046656220313939372030383a32313a353720474d54223e200d0a20203c6d65746120485454502d45515549563d22657870697265732220434f4e54454e543d2230223e0d0a20203c7374796c653e0d0a20202020626f64797b0d0a202020202020666f6e743a203136707820617269616c2c274d6963726f736f6674205961686569272c274869726167696e6f2053616e73204742272c73616e732d73657269663b0d0a202020207d0d0a2020202068317b0d0a2020202020206d617267696e3a20303b0d0a202020202020636f6c6f723a233361383761643b0d0a202020202020666f6e742d73697a653a20323670783b0d0a202020207d0d0a202020202e636f6e74656e747b0d0a20202020202077696474683a203435253b0d0a2020202020206d617267696e3a2030206175746f3b0d0a20202020200d0a202020207d0d0a202020202e636f6e74656e74203e6469767b0d0a2020202020206d617267696e2d746f703a2032303070783b0d0a20202020202070616464696e673a20323070783b0d0a2020202020206261636b67726f756e643a20236439656466373b20200d0a202020202020626f726465722d7261646975733a20313270783b0d0a202020207d0d0a202020202e636f6e74656e7420646c7b0d0a202020202020636f6c6f723a20233264366138383b0d0a2020202020206c696e652d6865696768743a20343070783b0d0a202020207d200d0a202020202e636f6e74656e742064697620646976207b0d0a20202020202070616464696e672d626f74746f6d3a20323070783b0d0a202020202020746578742d616c69676e3a63656e7465723b0d0a202020207d0d0a20203c2f7374796c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a20203c64697620636c6173733d22636f6e74656e74223e0d0a2020202020203c6469763e0d0a20202020202020202020203c68313e4854545020343030202d2042616420526571756573743c2f68313e0d0a20202020202020203c646c3e0d0a202020202020202020203c64743ee99499e8afafe8afb4e6988eefbc9ae59ba0e4b8bae99499e8afafe79a84e8afade6b395e5afbce887b4e69c8de58aa1e599a8e697a0e6b395e79086e8a7a3e8afb7e6b182e4bfa1e681afe380823c2f64743e0d0a202020202020202020203c64743ee58e9fe59ba031efbc9ae5aea2e688b7e7abafe58f91e8b5b7e79a84e8afb7e6b182e4b88de7aca6e59088e69c8de58aa1e599a8e5afb9e8afb7e6b182e79a84e69f90e4ba9be99990e588b6efbc8ce68896e88085e8afb7e6b182e69cace8baabe5ad98e59ca8e4b880e5ae9ae79a84e99499e8afafe380823c2f64743e0d0a090920203c64643ee8a7a3e586b3e58a9ee6b395efbc9a3c2f64643e0d0a202020202020202020203c64643ee993bee68ea5e4b8ade69c89e789b9e6ae8ae5ad97e7aca6e68896e88085e993bee68ea5e995bfe5baa6e8bf87e995bfe5afbce887b4efbc8ce8afb7e5afb9e5ba94e4bfaee694b92e3c2f64643e0d0a202020202020202020203c64743ee58e9fe59ba032
|
||||||
|
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1374)
|
||||||
|
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1449)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:545)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:484)
|
||||||
|
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
|
||||||
|
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429)
|
||||||
|
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
|
||||||
|
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:172)
|
||||||
|
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.handle(AbstractNioChannel.java:445)
|
||||||
|
at io.netty.channel.nio.NioIoHandler$DefaultNioRegistration.handle(NioIoHandler.java:388)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKey(NioIoHandler.java:596)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeysPlain(NioIoHandler.java:541)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.processSelectedKeys(NioIoHandler.java:514)
|
||||||
|
at io.netty.channel.nio.NioIoHandler.run(NioIoHandler.java:484)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225)
|
||||||
|
at io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196)
|
||||||
|
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1195)
|
||||||
|
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
|
||||||
|
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
|
||||||
|
at java.base/java.lang.Thread.run(Thread.java:1474)
|
||||||
|
]]></system-err>
|
||||||
|
</testcase>
|
||||||
|
</testsuite>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Test set: top.gtb520.java.pve_back_api.ResourcesResultTest
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.140 s -- in top.gtb520.java.pve_back_api.ResourcesResultTest
|
||||||
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user