核心SDK提交

This commit is contained in:
ZZX9599
2025-09-08 17:06:22 +08:00
commit 7964ce1569
57 changed files with 2060 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

0
.idea/.gitignore generated vendored Normal file
View File

6
.idea/encodings.xml generated Normal file
View File

@ -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>

13
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,13 @@
<?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>
<option name="workspaceImportForciblyTurnedOn" value="true" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK" />
</project>

124
.idea/uiDesigner.xml generated Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

216
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,216 @@
<?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="414d0304-fefe-46ab-b37b-a838c6ff92b3" name="Changes" comment="去除无效部分">
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/SdkApp.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/controller/CltController.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/service/CltService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/vo/CltDetailVo.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/utils/JacksonUtil.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/utils/PositionUtil.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/controller/MbtilesController.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/service/MbtilesService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/controller/PakController.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/service/PakService.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/vo/PakIndexVo.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pom.xml" beforeDir="false" afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/App.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/clt/controller/CltController.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/clt/domain/CltInfos.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/domain/CltInfos.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/clt/domain/CltTiles.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/domain/CltTiles.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/clt/mapper/CltInfosMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/mapper/CltInfosMapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/clt/mapper/CltTilesMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/clt/mapper/CltTilesMapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/config/CustomCorsFilter.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/config/CustomCorsFilter.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/config/ServerConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/config/ServerConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/config/SwaggerConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/config/SwaggerConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/config/WebConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/config/WebConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/controller/SourceMapController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/controller/SourceMapController.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/ds/DataSourceConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/ds/DataSourceConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/ds/DynamicDataSourceContextHolder.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/ds/DynamicDataSourceContextHolder.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/ds/DynamicDataSourceManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/ds/DynamicDataSourceManager.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/ds/DynamicRoutingDataSource.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/ds/DynamicRoutingDataSource.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/generator/CodeGenerator.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/generator/CodeGenerator.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/handler/BlobTypeHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/handler/BlobTypeHandler.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/map/MapDto.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/map/MapDto.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/map/SourceMap.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/map/SourceMap.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/map/SourceTypeMap.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/map/SourceTypeMap.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/utils/DecompressionUtil.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/utils/DecompressionUtil.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/utils/GlobalResponse.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/utils/GzipDecompressorUtil.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/utils/GzipDecompressorUtil.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/utils/MD5HashUtil.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/utils/MD5HashUtil.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/common/utils/PakTableName.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/common/utils/PakTableName.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/mbtiles/controller/MbtilesController.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/mbtiles/domain/MbtilesMetaData.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/domain/MbtilesMetaData.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/mbtiles/domain/MbtilesTiles.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/domain/MbtilesTiles.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/mbtiles/mapper/MbtilesMetaDataMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/mapper/MbtilesMetaDataMapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/mbtiles/mapper/MbtilesTilesMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/mapper/MbtilesTilesMapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/mbtiles/vo/MbtilesIndexVo.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/vo/MbtilesIndexVo.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/pak/controller/PakController.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/pak/domain/PakBlocks.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/domain/PakBlocks.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/pak/domain/PakInfos.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/domain/PakInfos.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/pak/mapper/PakBlocksMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/mapper/PakBlocksMapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/pak/mapper/PakInfosMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/yjdsj/pak/mapper/PakInfosMapper.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/pak/vo/PakIndexVo.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/poi/controller/TblPoisController.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/poi/domain/TblPois.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/xzjm/poi/mapper/TblPoisMapper.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/application.yml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/application.yml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/CltInfosMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/mapper/CltInfosMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/CltTilesMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/mapper/CltTilesMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/MbtilesMetaDataMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/mapper/MbtilesMetaDataMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/MbtilesTilesMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/mapper/MbtilesTilesMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/PakBlocksMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/mapper/PakBlocksMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/PakInfosMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/mapper/PakInfosMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/mapper/TblPoisMapper.xml" beforeDir="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="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="HighlightingSettingsPerFile">
<setting file="file://$PROJECT_DIR$/pom.xml" root0="SKIP_INSPECTION" />
<setting file="file://$PROJECT_DIR$/src/main/java/com/yjdsj/clt/controller/CltController.java" root0="SKIP_INSPECTION" />
<setting file="file://$PROJECT_DIR$/src/main/java/com/yjdsj/clt/service/CltService.java" root0="SKIP_INSPECTION" />
<setting file="file://$PROJECT_DIR$/src/main/java/com/yjdsj/mbtiles/service/MbtilesService.java" root0="SKIP_INSPECTION" />
<setting file="file://$PROJECT_DIR$/src/main/java/com/yjdsj/pak/service/PakService.java" root0="SKIP_INSPECTION" />
</component>
<component name="MavenImportPreferences">
<option name="generalSettings">
<MavenGeneralSettings>
<option name="localRepository" value="D:\study\Repository" />
<option name="mavenHome" value="D:\study\Maven\apache-maven-3.9.6" />
<option name="userSettingsFile" value="D:\study\Maven\apache-maven-3.9.6\conf\settings.xml" />
</MavenGeneralSettings>
</option>
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 3
}</component>
<component name="ProjectId" id="2v6gdLEDX9Itw57NT0G6qRfVkMD" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="2" id="Add" />
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Maven.geographysdk [clean].executor": "Run",
"Maven.geographysdk [package].executor": "Run",
"RequestMappingsPanelOrder0": "0",
"RequestMappingsPanelOrder1": "1",
"RequestMappingsPanelWidth0": "75",
"RequestMappingsPanelWidth1": "75",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"Spring Boot.App.executor": "Run",
"Spring Boot.SdkApp.executor": "Run",
"git-widget-placeholder": "master",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "D:/geographysdk/src/main/java/com/yjdsj",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "MavenSettings",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="RecentsManager">
<key name="CreateClassDialog.RecentsKey">
<recent name="com.xzjm.clt.service" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="D:\geographysdk\src\main\java\com\yjdsj" />
<recent name="D:\geographysdk\src\main\java\com\yjdsj\common\config" />
</key>
<key name="CopyClassDialog.RECENTS_KEY">
<recent name="com.yjdsj.common.utils" />
</key>
</component>
<component name="RunManager">
<configuration name="SdkApp" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" temporary="true" nameIsGenerated="true">
<module name="geographysdk" />
<option name="SPRING_BOOT_MAIN_CLASS" value="com.yjdsj.SdkApp" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.yjdsj.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<recent_temporary>
<list>
<item itemvalue="Spring Boot.SdkApp" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="414d0304-fefe-46ab-b37b-a838c6ff92b3" name="Changes" comment="" />
<created>1743471024061</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1743471024061</updated>
<workItem from="1743471025089" duration="310000" />
<workItem from="1743471894653" duration="904000" />
<workItem from="1756181938956" duration="5196000" />
<workItem from="1756258884017" duration="108000" />
<workItem from="1756259648649" duration="8000" />
<workItem from="1756275647764" duration="5000" />
<workItem from="1757295670775" duration="109000" />
<workItem from="1757295852768" duration="1319000" />
<workItem from="1757300022870" duration="15000" />
<workItem from="1757300075439" duration="2000" />
<workItem from="1757300132550" duration="10371000" />
</task>
<task id="LOCAL-00001" summary="去除无效部分">
<option name="closed" value="true" />
<created>1743472791450</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1743472791450</updated>
</task>
<option name="localTasksCounter" value="2" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State />
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="去除无效部分" />
<option name="LAST_COMMIT_MESSAGE" value="去除无效部分" />
</component>
</project>

107
pom.xml Normal file
View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 项目 GAV -->
<groupId>com.yjdsj</groupId>
<artifactId>geographysdk</artifactId>
<version>1.0.0</version>
<!-- 项目统一配置 -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
</parent>
<dependencies>
<!-- Web 起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MybtaisPlus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!-- MybatisPlus 分页 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 模板引擎依赖 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!-- Lombok 依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- SqlLite 依赖 -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.7</version>
</dependency>
<!-- Hutool工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.8</version>
</dependency>
</dependencies>
<build>
<finalName>geographysdk</finalName>
<plugins>
<plugin>
<!-- SpringBoot 插件 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,11 @@
package com.yjdsj;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SdkApp {
public static void main(String[] args) {
SpringApplication.run(SdkApp.class, args);
}
}

View File

@ -0,0 +1,66 @@
package com.yjdsj.clt.controller;
import com.yjdsj.clt.domain.CltTiles;
import com.yjdsj.clt.service.CltService;
import com.yjdsj.common.map.SourceMap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Slf4j
@RestController
@Api(tags = "倾斜模型资源")
@RequestMapping("/data/clt")
public class CltController {
@Resource
private CltService cltService;
@Resource
private SourceMap sourceMap;
@ApiOperation(value = "获取倾斜模型资源列表")
@GetMapping("/list")
public Object list() {
return sourceMap.getCltSourceList();
}
@ApiOperation(value = "获取倾斜模型资源的详情")
@GetMapping("/detail/{mark}")
public Object detail(@PathVariable @ApiParam(value = "资源标识") String mark) {
return cltService.detail(mark);
}
@GetMapping("/{mark}/{path:.*}")
public ResponseEntity<?> getData(@PathVariable @ApiParam(value = "资源标识") String mark, @PathVariable String path, HttpServletRequest request) {
try {
// 查询对应的 CltTiles 数据
CltTiles cltTiles = cltService.getTileData(mark, path);
if (cltTiles == null) {
return ResponseEntity.notFound().build();
}
// 获取是否需要压缩
boolean isZip = cltService.checkIsZip(mark);
// 处理解压数据并返回
Object responseData = cltService.handleDecompressedData(cltTiles, isZip);
return ResponseEntity.ok(responseData);
} catch (IOException e) {
log.error("处理瓦片数据失败", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}

View File

@ -0,0 +1,8 @@
package com.yjdsj.clt.domain;
import lombok.Data;
@Data
public class CltInfos {
private String params;
}

View File

@ -0,0 +1,10 @@
package com.yjdsj.clt.domain;
import lombok.Data;
@Data
public class CltTiles {
private String md5;
private String path;
private byte[] tile;
private String type;
}

View File

@ -0,0 +1,8 @@
package com.yjdsj.clt.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CltInfosMapper {
String selectParams();
}

View File

@ -0,0 +1,9 @@
package com.yjdsj.clt.mapper;
import com.yjdsj.clt.domain.CltTiles;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CltTilesMapper {
CltTiles selectTileByMd5(String md5);
}

View File

@ -0,0 +1,120 @@
package com.yjdsj.clt.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.yjdsj.clt.domain.CltTiles;
import com.yjdsj.clt.mapper.CltInfosMapper;
import com.yjdsj.clt.mapper.CltTilesMapper;
import com.yjdsj.clt.vo.CltDetailVo;
import com.yjdsj.common.ds.DynamicDataSourceContextHolder;
import com.yjdsj.common.map.SourceMap;
import com.yjdsj.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@Slf4j
@Service
public class CltService {
@Resource
private CltInfosMapper cltInfosMapper;
@Resource
private CltTilesMapper cltTilesMapper;
@Resource
private SourceMap sourceMap;
// 是否需要压缩缓存
private final ConcurrentMap<String, Boolean> zipCache = new ConcurrentHashMap<>();
public Map<String, String> getCltSourceList() {
return sourceMap.getCltSourceList();
}
public CltDetailVo detail(String mark) {
CltDetailVo result = new CltDetailVo();
try {
// 读取 JSON 文件
String json = DecompressionUtil.decompressAndConvertToString(getTileData(mark, "tileset.json").getTile());
// 读取JSON字符串为根节点
ObjectNode rootNode = (ObjectNode) JacksonUtil.mapper.readTree(json);
// 逐层定位到 root 节点 → 再定位到 transform 节点
ObjectNode rootChildNode = (ObjectNode) rootNode.get("root");
ArrayNode transformArrayNode = (ArrayNode) rootChildNode.get("transform");
// 将 ArrayNode 转换为 double[] 数组
double[] transform = new double[transformArrayNode.size()];
for (int i = 0; i < transformArrayNode.size(); i++) {
transform[i] = transformArrayNode.get(i).asDouble();
}
PositionUtil.BlhResult blhResult = PositionUtil.xyz2Blh(transform[12], transform[13], transform[14]);
// 设置 URL
result.setUrl(String.format("/data/clt/%s/tileset.json", mark));
// 设置 3D 旋转参数
CltDetailVo.Orientation orientation = new CltDetailVo.Orientation(0, 0, 0);
result.setOrientation(orientation);
// 设置位置
CltDetailVo.Position position = new CltDetailVo.Position(
blhResult.lon,
blhResult.lat,
blhResult.alt
);
result.setPosition(position);
result.setFileType("tileset");
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
return result;
}
public CltTiles getTileData(String mark, String path) {
// 设置数据源
DynamicDataSourceContextHolder.setDataSourceKey(mark);
try {
// 查询对应的 CltTiles 数据
return cltTilesMapper.selectTileByMd5(MD5HashUtil.toMD5(path));
} finally {
// 清理数据源设置
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
public boolean checkIsZip(String mark) {
// 设置数据源
DynamicDataSourceContextHolder.setDataSourceKey(mark);
String paramsJson = cltInfosMapper.selectParams();
try {
JsonNode rootNode = JacksonUtil.mapper.readTree(paramsJson);
return rootNode.path("zip").asBoolean(false);
} catch (IOException e) {
return false;
} finally {
// 清理数据源设置
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
public Object handleDecompressedData(CltTiles cltTiles, boolean isZip) throws IOException {
if (isZip) {
if ("tileset.json".equals(cltTiles.getPath())) {
// 解压缩并返回字符串
return DecompressionUtil.decompressAndConvertToString(cltTiles.getTile());
} else {
// 解压缩并返回字节数组
return GzipDecompressorUtil.decompress(cltTiles.getTile());
}
}
// 不需要解压则直接返回对应的数据
return cltTiles.getTile();
}
}

View File

@ -0,0 +1,28 @@
package com.yjdsj.clt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
public class CltDetailVo {
private String url;
private Orientation orientation;
private Position position;
private String fileType;
@Data
@AllArgsConstructor
public static class Orientation {
private double heading;
private double roll;
private double pitch;
}
@Data
@AllArgsConstructor
public static class Position {
private double lon;
private double lat;
private double alt;
}
}

View File

@ -0,0 +1,23 @@
package com.yjdsj.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CustomCorsFilter {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

View File

@ -0,0 +1,15 @@
package com.yjdsj.common.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class ServerConfig {
@Value("${server.port}")
private int port;
@Value("${server.host}")
private String host;
}

View File

@ -0,0 +1,34 @@
package com.yjdsj.common.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class SwaggerConfig {
@Bean
public Docket webApiConfig() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("对接API")
.description("对接相关接口")
.version("1.0")
.build();
}
}

View File

@ -0,0 +1,18 @@
package com.yjdsj.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*") // 允许所有来源
.allowedMethods("*") // 允许所有方法GET, POST, PUT, DELETE 等)
.allowedHeaders("*") // 允许所有头
.allowCredentials(true) // 允许发送凭证cookies 等)
.maxAge(3600); // 预检请求的缓存时间(单位:秒)
}
}

View File

@ -0,0 +1,33 @@
package com.yjdsj.common.controller;
import com.yjdsj.common.map.SourceMap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Api(tags = "资源管理")
@Slf4j
@RestController
@RequestMapping("/sourceMap")
public class SourceMapController {
@Resource
private SourceMap sourceMap;
// 添加资源映射关系
@PostMapping("/add")
@ApiOperation(value = "添加资源映射关系")
public Object addSourceMapping(@RequestParam String filePath) {
return sourceMap.addSourceMapping(filePath);
}
// 移除资源映射关系
@DeleteMapping("/remove")
@ApiOperation(value = "移除资源映射关系")
public void removeSourceMapping(@RequestParam String filePath) {
sourceMap.removeSourceMapping(filePath);
}
}

View File

@ -0,0 +1,38 @@
package com.yjdsj.common.ds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Resource
private DynamicDataSourceManager dynamicDataSourceManager;
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource(dynamicDataSourceManager);
return dynamicRoutingDataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Autowired DataSource dynamicDataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dynamicDataSource);
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
return sessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(@Autowired SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

View File

@ -0,0 +1,18 @@
package com.yjdsj.common.ds;
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
public static void setDataSourceKey(String key) {
CONTEXT_HOLDER.set(key);
}
public static String getDataSourceKey() {
return CONTEXT_HOLDER.get();
}
public static void clearDataSourceKey() {
CONTEXT_HOLDER.remove();
}
}

View File

@ -0,0 +1,46 @@
package com.yjdsj.common.ds;
import com.yjdsj.common.map.SourceMap;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Component
public class DynamicDataSourceManager {
private final Map<String, DataSource> dataSourceCache = new HashMap<>();
private final SourceMap sourceMap;
@Autowired
public DynamicDataSourceManager(SourceMap sourceMap) {
this.sourceMap = sourceMap;
}
public DataSource getDataSource(String dbName) {
// 检查缓存中是否已有数据源
if (dataSourceCache.containsKey(dbName)) {
return dataSourceCache.get(dbName);
} else {
// 动态创建数据源
String dbPath = sourceMap.getSourceMapping(dbName);
if (dbPath != null) {
DataSource dataSource = createDataSource(dbPath);
dataSourceCache.put(dbName, dataSource);
return dataSource;
} else {
throw new IllegalArgumentException("Data source not found for name: " + dbName);
}
}
}
private DataSource createDataSource(String dbPath) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:sqlite:" + dbPath);
dataSource.setDriverClassName("org.sqlite.JDBC");
return dataSource;
}
}

View File

@ -0,0 +1,28 @@
package com.yjdsj.common.ds;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
private final DynamicDataSourceManager dataSourceManager;
public DynamicRoutingDataSource(DynamicDataSourceManager dataSourceManager) {
this.dataSourceManager = dataSourceManager;
this.setTargetDataSources(new HashMap<>());
this.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceKey();
}
@Override
protected DataSource determineTargetDataSource() {
String dataSourceKey = (String) determineCurrentLookupKey();
return dataSourceManager.getDataSource(dataSourceKey);
}
}

View File

@ -0,0 +1,61 @@
package com.yjdsj.common.generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.Collections;
/**
*
* @date 2024/6/26 14:42
*/
public class CodeGenerator {
private static String databasePath = "D:\\DJ\\source\\广西提供poi.poi"; // SQLite 数据库文件路径
private static String author = "周志雄";
public static void main(String[] args) {
Generation(databasePath, "tbl_pois"); // 生成指定表的代码,这里以 "users" 表为例
}
public static void Generation(String databasePath, String... tableName) {
FastAutoGenerator.create("jdbc:sqlite:" + databasePath, "", "")
.globalConfig(builder -> {
builder.author(author) // 设置作者名
.enableSwagger() // 启用Swagger
.outputDir(System.getProperty("user.dir") + "/src/main/java"); // 指定输出目录
})
.packageConfig(builder -> {
builder.entity("domain") // 实体类包名
.parent("com.xzjm.poi") // 父包名
.controller("controller") // 控制层包名
.mapper("mapper") // mapper 层包名
.service("service") // service 层包名
.serviceImpl("service.impl") // service 实现类包名
// 自定义 mapper.xml 文件输出目录
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
builder.addInclude(tableName) // 设置要生成的表名
.addTablePrefix("t_") // 设置表前缀过滤(如果没有,可以去掉)
.entityBuilder()
.enableLombok() // 启用 Lombok
.naming(NamingStrategy.underline_to_camel) // 表名映射为实体类驼峰命名
.columnNaming(NamingStrategy.underline_to_camel) // 字段映射为驼峰命名
.mapperBuilder()
.enableMapperAnnotation() // 启用 @Mapper 注解
.enableBaseResultMap() // 启用 BaseResultMap 生成
.enableBaseColumnList() // 启用 BaseColumnList 生成
.formatMapperFileName("%sMapper") // 格式化 Mapper 文件名称
.formatXmlFileName("%sMapper") // 格式化 XML 文件名称
.serviceBuilder()
.formatServiceFileName("%sService") // 格式化 Service 接口文件名称
.formatServiceImplFileName("%sServiceImpl") // 格式化 Service 实现类文件名称
.controllerBuilder()
.enableRestStyle() // 启用 Restful 风格
.formatFileName("%sController") // 格式化 Controller 文件名称
.enableHyphenStyle(); // 启用驼峰转连字符
}).execute();
}
}

View File

@ -0,0 +1,36 @@
package com.yjdsj.common.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
*
* @date 2024/8/20 11:46
*/
public class BlobTypeHandler extends BaseTypeHandler<byte[]> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, byte[] parameter, JdbcType jdbcType) throws SQLException {
ps.setBytes(i, parameter);
}
@Override
public byte[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getBytes(columnName);
}
@Override
public byte[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getBytes(columnIndex);
}
@Override
public byte[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getBytes(columnIndex);
}
}

View File

@ -0,0 +1,9 @@
package com.yjdsj.common.map;
import lombok.Data;
@Data
public class MapDto {
private String filePath;
private Integer userId;
}

View File

@ -0,0 +1,91 @@
package com.yjdsj.common.map;
import com.yjdsj.common.utils.MD5HashUtil;
import org.springframework.stereotype.Component;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class SourceMap {
private Map<String, String> sourceMap = new ConcurrentHashMap<>();
// 添加资源映射关系
public String addSourceMapping(String filePath) {
sourceMap.put(MD5HashUtil.toMD5(filePath), filePath);
return MD5HashUtil.toMD5(filePath);
}
// 移除资源映射关系
public void removeSourceMapping(String filePath) {
sourceMap.remove(MD5HashUtil.toMD5(filePath));
}
// 获取资源映射关系
public String getSourceMapping(String mark) {
return sourceMap.get(mark);
}
// 获取倾斜模型资源列表
public Map<String, String> getCltSourceList() {
Map<String, String> sourceList = new HashMap<>();
for (Map.Entry<String, String> entry : sourceMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (value.endsWith(".clt")) {
String fileName = getFileNameWithExtension(value);
sourceList.put(key, fileName);
}
}
return sourceList;
}
// 获取图层资源列表
public Map<String, String> getMBTilesSourceList() {
Map<String, String> sourceList = new HashMap<>();
for (Map.Entry<String, String> entry : sourceMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (value.endsWith(".mbtiles")) {
String fileName = getFileNameWithExtension(value);
sourceList.put(key, fileName);
}
}
return sourceList;
}
// 获取地形资源列表
public Map<String, String> getPakSourceList() {
Map<String, String> sourceList = new HashMap<>();
for (Map.Entry<String, String> entry : sourceMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (value.endsWith(".pak")) {
String fileName = getFileNameWithExtension(value);
sourceList.put(key, fileName);
}
}
return sourceList;
}
/**
* 获取文件名和后缀
*/
public static String getFileNameWithExtension(String filePath) {
Path path = Paths.get(filePath); // 获取路径
return path.getFileName().toString(); // 返回文件名和后缀
}
/**
* 遍历数据并打印内容、无参
*/
public void printSourceMap() {
for (Map.Entry<String, String> entry : sourceMap.entrySet()) {
System.out.println("MD5 Key: " + entry.getKey() + ", File Path: " + entry.getValue());
}
}
}

View File

@ -0,0 +1,27 @@
package com.yjdsj.common.map;
import java.util.HashMap;
import java.util.Map;
/**
*
* @date 2024/8/20 11:04
*/
public class SourceTypeMap {
/**
* 文件类型映射
*/
private static Map<String, String> SourceType = new HashMap<>();
/**
* 初始化
*/
static {
SourceType.put("clt", "tileset");
}
// 获取资源对应的类型
public static String getSourceType(String fileExtension) {
return SourceType.get(fileExtension);
}
}

View File

@ -0,0 +1,23 @@
package com.yjdsj.common.utils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class DecompressionUtil {
/**
* 将压缩数据解压并转换为字符串
*
* @param compressedData
* @return
*/
public static String decompressAndConvertToString(byte[] compressedData) {
try {
byte[] decompressedData = GzipDecompressorUtil.decompress(compressedData);
return new String(decompressedData, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
return "Failed to decompress data: " + e.getMessage();
}
}
}

View File

@ -0,0 +1,30 @@
package com.yjdsj.common.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
public class GzipDecompressorUtil {
/**
* 解压数据
*
* @param compressedData
* @return
* @throws IOException
*/
public static byte[] decompress(byte[] compressedData) throws IOException {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(compressedData);
GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int len;
while ((len = gzipInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
return byteArrayOutputStream.toByteArray();
}
}
}

View File

@ -0,0 +1,7 @@
package com.yjdsj.common.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonUtil {
public static final ObjectMapper mapper = new ObjectMapper();
}

View File

@ -0,0 +1,36 @@
package com.yjdsj.common.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5HashUtil {
/**
* 将输入字符串转换为MD5哈希值
*
* @param input 要转换的字符串
* @return 转换后的MD5哈希值
*/
public static String toMD5(String input) {
try {
// 获取MD5算法实例
MessageDigest md = MessageDigest.getInstance("MD5");
// 将输入字符串转换为字节数组
byte[] messageDigest = md.digest(input.getBytes());
// 将字节数组转换为十六进制字符串
StringBuilder hexString = new StringBuilder();
for (byte b : messageDigest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
// 返回MD5哈希值
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MD5算法不存在", e);
}
}
}

View File

@ -0,0 +1,21 @@
package com.yjdsj.common.utils;
public class PakTableName {
/**
* 根据坐标动态计算获取表名
*
* @param z
* @param x
* @param y
* @return
*/
public static String getTableName(int z, int x, int y) {
if (z < 10) {
return "blocks";
} else {
double tx = Math.floorDiv(x, 512);
double ty = Math.floorDiv(y, 512);
return "blocks_" + Integer.toString(z) + "_" + Integer.toString((int) tx) + "_" + Integer.toString((int) ty);
}
}
}

View File

@ -0,0 +1,51 @@
package com.yjdsj.common.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
public class PositionUtil {
// 定义所需的常量,这些值需要根据实际应用场景设置
private static final double a = 6378137.0; // 椭球长半轴
private static final double e = 0.0818191908426; // 第一偏心率
private static final double epsilon = 1e-8; // 迭代精度
private static final double r2d = 180.0 / Math.PI; // 弧度转角度
/**
* 存储 BLH 转换结果的内部类
*/
@Data
@AllArgsConstructor
public static class BlhResult {
public double lon; // 经度
public double lat; // 纬度
public double alt; // 高度
}
/**
* 将XYZ坐标转换为BLH坐标
*/
public static BlhResult xyz2Blh(double x, double y, double z) {
double tmpX = x;
double tmpY = y;
double tmpZ = z;
double curB = 0.0;
double N = 0.0;
double calB = Math.atan2(tmpZ, Math.sqrt(tmpX * tmpX + tmpY * tmpY));
int counter = 0;
while (Math.abs(curB - calB) * r2d > epsilon && counter < 25) {
curB = calB;
N = a / Math.sqrt(1 - e * e * Math.sin(curB) * Math.sin(curB));
calB = Math.atan2(tmpZ + N * e * e * Math.sin(curB),
Math.sqrt(tmpX * tmpX + tmpY * tmpY));
counter++;
}
double longitude = Math.atan2(tmpY, tmpX) * r2d;
double latitude = curB * r2d;
double height = tmpZ / Math.sin(curB) - N * (1 - e * e);
return new BlhResult(longitude, latitude, height);
}
}

View File

@ -0,0 +1,59 @@
package com.yjdsj.mbtiles.controller;
import com.yjdsj.mbtiles.domain.MbtilesTiles;
import com.yjdsj.mbtiles.service.MbtilesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Slf4j
@RestController
@Api(tags = "图层文件相关")
@RequestMapping("/data/mbtiles")
public class MbtilesController {
@Resource
private MbtilesService mbtilesService;
@ApiOperation(value = "获取图层资源列表")
@GetMapping("/list")
public Object list() {
return mbtilesService.getMbtilesSourceList();
}
@ApiOperation(value = "获取图层资源的详情")
@GetMapping("/detail/{mark}")
public Object detail(@PathVariable @ApiParam(value = "资源标识") String mark) {
return mbtilesService.detail(mark);
}
@GetMapping("/{mark}/{z}/{x}/{y}.{format}")
public ResponseEntity getData(
@PathVariable @ApiParam(value = "资源标识") String mark,
@PathVariable("z") int z,
@PathVariable("x") int x,
@PathVariable("y") int y,
@PathVariable("format") String format) {
MbtilesTiles mbtilesTiles = mbtilesService.getTileData(mark, z, x, y);
if (mbtilesTiles == null) {
return ResponseEntity.notFound().build();
}
// 获取响应媒体类型
String contentType = mbtilesService.getContentTypeByFormat(format);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.body(mbtilesTiles.getTileData());
}
}

View File

@ -0,0 +1,9 @@
package com.yjdsj.mbtiles.domain;
import lombok.Data;
@Data
public class MbtilesMetaData {
private String name;
private String value;
}

View File

@ -0,0 +1,12 @@
package com.yjdsj.mbtiles.domain;
import lombok.Data;
@Data
public class MbtilesTiles {
private String zoomLevel;
private String tileColumn;
private String tileRow;
private byte[] tileData;
}

View File

@ -0,0 +1,11 @@
package com.yjdsj.mbtiles.mapper;
import com.yjdsj.mbtiles.domain.MbtilesMetaData;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MbtilesMetaDataMapper {
List<MbtilesMetaData> selectList();
}

View File

@ -0,0 +1,11 @@
package com.yjdsj.mbtiles.mapper;
import com.yjdsj.mbtiles.domain.MbtilesTiles;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface MbtilesTilesMapper {
MbtilesTiles selectByCondition(@Param("z") int z, @Param("x") int x, @Param("y") int y);
int selectByZoomLevel(@Param("zoomLevel") int zoomLevel);
}

View File

@ -0,0 +1,132 @@
package com.yjdsj.mbtiles.service;
import com.yjdsj.common.ds.DynamicDataSourceContextHolder;
import com.yjdsj.common.map.SourceMap;
import com.yjdsj.mbtiles.domain.MbtilesMetaData;
import com.yjdsj.mbtiles.domain.MbtilesTiles;
import com.yjdsj.mbtiles.mapper.MbtilesMetaDataMapper;
import com.yjdsj.mbtiles.mapper.MbtilesTilesMapper;
import com.yjdsj.mbtiles.vo.MbtilesIndexVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class MbtilesService {
@Resource
private MbtilesMetaDataMapper mbtilesMetaDataMapper;
@Resource
private MbtilesTilesMapper mbtilesTilesMapper;
@Resource
private SourceMap sourceMap;
/**
* 获取图层资源列表
*/
public Map<String, String> getMbtilesSourceList() {
return sourceMap.getMBTilesSourceList();
}
/**
* 构建图层资源索引信息
*/
public MbtilesIndexVo detail(String mark) {
String XYZ = "xyz";
String WEBMERCATORTILINGSCHEME = "WebMercatorTilingScheme";
String GEOGRAPHICTILINGSCHEME = "GeographicTilingScheme";
MbtilesIndexVo mbtilesIndexVo = new MbtilesIndexVo();
DynamicDataSourceContextHolder.setDataSourceKey(mark);
try {
// 获取元数据并转换为Map
List<MbtilesMetaData> mbtilesMetaDataList = mbtilesMetaDataMapper.selectList();
Map<String, String> metaDataMap = new HashMap<>(mbtilesMetaDataList.size());
for (MbtilesMetaData meta : mbtilesMetaDataList) {
metaDataMap.put(meta.getName(), meta.getValue());
}
// 处理边界信息
String[] boundsArray = metaDataMap.get("bounds").split(",");
// 处理缩放级别
Map<Integer, Integer> zoomLevelCounts = new HashMap<>(31);
for (int i = 0; i <= 30; i++) {
zoomLevelCounts.put(i, mbtilesTilesMapper.selectByZoomLevel(i));
}
// 计算最大最小 zoomLevel
int minZoomLevel = zoomLevelCounts.entrySet().stream()
.filter(entry -> entry.getValue() > 0)
.map(Map.Entry::getKey)
.min(Integer::compare)
.orElse(Integer.MAX_VALUE);
int maxZoomLevel = zoomLevelCounts.entrySet().stream()
.filter(entry -> entry.getValue() > 0)
.map(Map.Entry::getKey)
.max(Integer::compare)
.orElse(Integer.MIN_VALUE);
// 构建URL
String format = metaDataMap.getOrDefault("format", "png");
String url = String.format("/data/mbtiles/%s/{z}/{x}/{y}.%s", mark, format);
// 设置返回对象属性
mbtilesIndexVo.setUrl(url);
mbtilesIndexVo.setMinZoom(minZoomLevel);
mbtilesIndexVo.setMaxZoom(maxZoomLevel);
mbtilesIndexVo.setWest(boundsArray[0]);
mbtilesIndexVo.setSouth(boundsArray[1]);
mbtilesIndexVo.setEast(boundsArray[2]);
mbtilesIndexVo.setNorth(boundsArray[3]);
// 处理加载方式
mbtilesIndexVo.setLoadMethod(metaDataMap.getOrDefault("load_method", XYZ));
// 处理投影名称(优先级: profile 包含 longlat > schema_name > 默认)
String schemaName = metaDataMap.getOrDefault("schema_name", WEBMERCATORTILINGSCHEME);
if (metaDataMap.containsKey("profile") && metaDataMap.get("profile").contains("+proj=longlat")) {
schemaName = GEOGRAPHICTILINGSCHEME;
}
mbtilesIndexVo.setSchemaName(schemaName);
mbtilesIndexVo.setFileType("layer");
return mbtilesIndexVo;
} finally {
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
/**
* 获取瓦片数据
*/
public MbtilesTiles getTileData(String mark, int z, int x, int y) {
// 坐标翻转
int flippedY = (int) (Math.pow(2, z) - 1 - y);
// 获取数据源
DynamicDataSourceContextHolder.setDataSourceKey(mark);
try {
return mbtilesTilesMapper.selectByCondition(z, x, flippedY);
} finally {
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
/**
* 根据格式获取对应的媒体类型
*/
public String getContentTypeByFormat(String format) {
if ("png".equals(format)) {
return "image/png";
} else if ("jpg".equals(format) || "jpeg".equals(format)) {
return "image/jpeg";
} else {
return "application/octet-stream";
}
}
}

View File

@ -0,0 +1,19 @@
package com.yjdsj.mbtiles.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class MbtilesIndexVo {
private String url;
private Integer minZoom;
private Integer maxZoom;
private String west;
private String south;
private String east;
private String north;
private String loadMethod;
private String schemaName;
private String fileType;
}

View File

@ -0,0 +1,73 @@
package com.yjdsj.pak.controller;
import com.yjdsj.pak.service.PakService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
@Slf4j
@RestController
@Api(tags = "地形资源相关")
@RequestMapping("/data/pak")
public class PakController {
@Resource
private PakService pakService;
@ApiOperation(value = "获取地形资源列表")
@GetMapping("/list")
public Object list() {
return pakService.getPakSourceList();
}
@ApiOperation(value = "获取地形资源的详情")
@GetMapping("/detail/{mark}")
public Object cltIndex(@PathVariable @ApiParam(value = "资源标识") String mark) {
return pakService.buildPakIndex(mark);
}
@ApiOperation(value = "获取JSON数据")
@GetMapping("/{mark}/layer.json")
public ResponseEntity jsonBySourceIdAndParam(@PathVariable("mark") @ApiParam(value = "资源标识") String mark) {
String layerJson = pakService.getCachedLayerJson(mark);
return layerJson != null ? ResponseEntity.ok(layerJson) : ResponseEntity.notFound().build();
}
@ApiOperation(value = "获取地形瓦片数据")
@GetMapping("/{mark}/{z}/{x}/{y}.{suffix}")
public ResponseEntity<?> data(
@PathVariable("mark") @ApiParam(value = "资源标识") String mark,
@PathVariable("z") @ApiParam(value = "缩放级别") int z,
@PathVariable("x") @ApiParam(value = "X轴坐标") int x,
@PathVariable("y") @ApiParam(value = "Y轴坐标") int y,
@PathVariable("suffix") @ApiParam(value = "文件后缀") String suffix) {
try {
// 调用 Service 获取处理后的瓦片数据
byte[] tileData = pakService.getTileData(mark, z, x, y);
if (tileData == null) {
return ResponseEntity.notFound().build();
}
// 根据文件后缀设置正确的Content-Type
MediaType mediaType = "png".equalsIgnoreCase(suffix) ?
MediaType.IMAGE_PNG : MediaType.IMAGE_JPEG;
return ResponseEntity.ok()
.contentType(mediaType)
.body(tileData);
} catch (IOException e) {
return ResponseEntity.status(500).body("瓦片数据处理失败: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,11 @@
package com.yjdsj.pak.domain;
import lombok.Data;
@Data
public class PakBlocks {
private String z;
private String x;
private String y;
private byte[] tile;
}

View File

@ -0,0 +1,22 @@
package com.yjdsj.pak.domain;
import lombok.Data;
@Data
public class PakInfos {
private String minX;
private String minY;
private String maxX;
private String maxY;
private String minLevel;
private String maxLevel;
private String source;
private String type;
private String tiletrans;
private String zip;
private String curLevel;
private String curX;
private String curY;
private byte[] layerJson;
private String contentType;
private Integer proj;
}

View File

@ -0,0 +1,9 @@
package com.yjdsj.pak.mapper;
import com.yjdsj.pak.domain.PakBlocks;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PakBlocksMapper {
PakBlocks selectByCondition(String tableName, int z, int x, int y);
}

View File

@ -0,0 +1,9 @@
package com.yjdsj.pak.mapper;
import com.yjdsj.pak.domain.PakInfos;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PakInfosMapper {
PakInfos selectInfo();
}

View File

@ -0,0 +1,134 @@
package com.yjdsj.pak.service;
import com.yjdsj.common.ds.DynamicDataSourceContextHolder;
import com.yjdsj.common.map.SourceMap;
import com.yjdsj.common.utils.GzipDecompressorUtil;
import com.yjdsj.common.utils.PakTableName;
import com.yjdsj.pak.domain.PakBlocks;
import com.yjdsj.pak.domain.PakInfos;
import com.yjdsj.pak.mapper.PakBlocksMapper;
import com.yjdsj.pak.mapper.PakInfosMapper;
import com.yjdsj.pak.vo.PakIndexVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
public class PakService {
@Resource
private SourceMap sourceMap;
@Resource
private PakInfosMapper pakInfosMapper;
@Resource
private PakBlocksMapper pakBlocksMapper;
// 资源压缩状态缓存
private final Map<String, Boolean> isZipCache = new HashMap<>();
// JSON数据缓存
private final Map<String, String> jsonCache = new HashMap<>();
/**
* 获取地形资源列表
*/
public Map<String, String> getPakSourceList() {
return sourceMap.getPakSourceList();
}
/**
* 构建地形资源索引信息含URL、元数据并更新缓存
*/
public PakIndexVo buildPakIndex(String mark) {
final String XYZ = "xyz";
final String TMS = "tms";
final String TERRAIN_TYPE = "terrain";
final String WEBMERCATORTILINGSCHEME = "WebMercatorTilingScheme";
final String GEOGRAPHICTILINGSCHEME = "GeographicTilingScheme";
final int PROJ_4326 = 4326;
DynamicDataSourceContextHolder.setDataSourceKey(mark);
try {
// 查询资源元数据并校验
PakInfos pakInfos = pakInfosMapper.selectInfo();
if (pakInfos == null) {
return null;
}
// 复制属性并初始化VO
PakIndexVo pakIndexVo = new PakIndexVo();
BeanUtils.copyProperties(pakInfos, pakIndexVo);
// 设置地理坐标范围
pakIndexVo.setWest(pakInfos.getMinX());
pakIndexVo.setSouth(pakInfos.getMinY());
pakIndexVo.setEast(pakInfos.getMaxX());
pakIndexVo.setNorth(pakInfos.getMaxY());
// 设置加载方式
String tiletrans = pakInfos.getTiletrans();
pakIndexVo.setLoadMethod(TMS.equals(tiletrans) ? TMS : XYZ);
// 优化投影名称设置
pakIndexVo.setSchemaName(WEBMERCATORTILINGSCHEME);
Integer proj = pakInfos.getProj();
if (proj != null && proj == PROJ_4326) {
pakIndexVo.setSchemaName(GEOGRAPHICTILINGSCHEME);
}
// 构建资源访问URL
String baseUrl = String.format("/data/pak/%s", mark);
if (TERRAIN_TYPE.equals(pakInfos.getType())) {
pakIndexVo.setUrl(baseUrl);
pakIndexVo.setFileType("terrain");
} else {
// 安全处理 contentType 解析
String contentType = pakInfos.getContentType();
String suffix = "unknown";
if (contentType != null && contentType.contains("/")) {
String[] typeParts = contentType.split("/");
if (typeParts.length > 1) {
suffix = typeParts[1];
}
}
pakIndexVo.setUrl(baseUrl + "/{z}/{x}/{y}." + suffix);
pakIndexVo.setFileType("layer");
}
// 缓存更新
String zipFlag = pakInfos.getZip();
isZipCache.put(mark, zipFlag != null && Integer.parseInt(zipFlag) > 0);
jsonCache.put(mark, new String(pakInfos.getLayerJson() != null ? pakInfos.getLayerJson() : new byte[0]));
return pakIndexVo;
} finally {
// 确保数据源清理
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
/**
* 获取缓存的 layer.json 数据
*/
public String getCachedLayerJson(String mark) {
return jsonCache.get(mark);
}
/**
* 根据坐标获取瓦片数据(含压缩处理)
*/
public byte[] getTileData(String mark, int z, int x, int y) throws IOException {
DynamicDataSourceContextHolder.setDataSourceKey(mark);
try {
// 确定目标表名(通过工具类计算)
String tableName = PakTableName.getTableName(z, x, y);
// 查询瓦片数据
PakBlocks pakBlocks = pakBlocksMapper.selectByCondition(tableName, z, x, y);
if (pakBlocks == null) {
return null;
}
// 处理压缩数据(根据缓存的压缩状态)
Boolean isZip = isZipCache.getOrDefault(mark, false);
return isZip ? GzipDecompressorUtil.decompress(pakBlocks.getTile()) : pakBlocks.getTile();
} finally {
DynamicDataSourceContextHolder.clearDataSourceKey();
}
}
}

View File

@ -0,0 +1,19 @@
package com.yjdsj.pak.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class PakIndexVo {
private String west;
private String south;
private String east;
private String north;
private String minLevel;
private String maxLevel;
private String url;
private String type;
private String loadMethod;
private String schemaName;
private String fileType;
}

View File

@ -0,0 +1,3 @@
server:
host: 127.0.0.1
port: 8080

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjdsj.clt.mapper.CltInfosMapper">
<select id="selectParams" resultType="java.lang.String">
select params from infos limit 1
</select>
</mapper>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjdsj.clt.mapper.CltTilesMapper">
<resultMap id="CltTilesResultMap" type="com.yjdsj.clt.domain.CltTiles">
<result property="md5" column="md5"/>
<result property="path" column="path"/>
<result property="tile" column="tile" typeHandler="com.yjdsj.common.handler.BlobTypeHandler"/>
<result property="type" column="type"/>
</resultMap>
<select id="selectTileByMd5" resultMap="CltTilesResultMap">
select *
from tiles
where md5 = #{md5}
</select>
</mapper>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjdsj.mbtiles.mapper.MbtilesMetaDataMapper">
<select id="selectParams" resultType="java.lang.String">
select params from infos limit 1
</select>
<!-- 查询元数据列表 -->
<select id="selectList" resultType="com.yjdsj.mbtiles.domain.MbtilesMetaData">
select *
from metadata
</select>
</mapper>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjdsj.mbtiles.mapper.MbtilesTilesMapper">
<resultMap id="BaseResultMap" type="com.yjdsj.mbtiles.domain.MbtilesTiles">
<result property="zoomLevel" column="zoom_level"/>
<result property="tileColumn" column="tile_column"/>
<result property="tileRow" column="tile_row"/>
<result property="tileData" column="tile_data" typeHandler="com.yjdsj.common.handler.BlobTypeHandler"/>
</resultMap>
<select id="selectByZoomLevel" resultType="java.lang.Integer">
select count(*)
from tiles
where zoom_level = #{zoomLevel} limit 1
</select>
<select id="selectByCondition" resultMap="BaseResultMap">
select *
from tiles
where zoom_level = #{z}
and tile_column = #{x}
and tile_row = #{y}
</select>
</mapper>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjdsj.pak.mapper.PakBlocksMapper">
<resultMap id="BaseResultMap" type="com.yjdsj.pak.domain.PakBlocks">
<id column="z" jdbcType="INTEGER" property="z"/>
<id column="x" jdbcType="INTEGER" property="x"/>
<id column="y" jdbcType="INTEGER" property="y"/>
<result property="tile" column="tile" typeHandler="com.yjdsj.common.handler.BlobTypeHandler"/>
</resultMap>
<select id="selectByCondition" resultMap="BaseResultMap">
SELECT *
FROM ${tableName}
WHERE z = #{z}
AND x = #{x}
AND y = #{y}
</select>
</mapper>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yjdsj.pak.mapper.PakInfosMapper">
<resultMap id="BaseResultMap" type="com.yjdsj.pak.domain.PakInfos">
<result column="minx" property="minX"/>
<result column="miny" property="minY"/>
<result column="maxx" property="maxX"/>
<result column="maxy" property="maxY"/>
<result column="minlevel" property="minLevel"/>
<result column="maxlevel" property="maxLevel"/>
<result column="source" property="source"/>
<result column="type" property="type"/>
<result column="tiletrans" property="tiletrans"/>
<result column="zip" property="zip"/>
<result column="cur_level" property="curLevel"/>
<result column="cur_x" property="curX"/>
<result column="cur_y" property="curY"/>
<result column="layerjson" property="layerJson"/>
<result column="contenttype" property="contentType"/>
</resultMap>
<select id="selectInfo" resultMap="BaseResultMap">
select *
from infos;
</select>
</mapper>