Compare commits

...

No commits in common. "main" and "master" have entirely different histories.
main ... master

24 changed files with 1348 additions and 3 deletions

358
.gitignore vendored Normal file
View File

@ -0,0 +1,358 @@
# Created by https://www.toptal.com/developers/gitignore/api/windows,macos,git,java,maven,eclipse,intellij,gradle,netbeans,visualstudiocode
# Edit at https://www.toptal.com/developers/gitignore?templates=windows,macos,git,java,maven,eclipse,intellij,gradle,netbeans,visualstudiocode
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
/src/main/generated
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
.idea/**/azureSettings.xml
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# Eclipse m2e generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
### NetBeans ###
**/nbproject/private/
**/nbproject/Makefile-*.mk
**/nbproject/Package-*.bash
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### Gradle ###
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
# JDT-specific (Eclipse Java Development Tools)
### Gradle Patch ###
# Java heap dump
*.hprof
# End of https://www.toptal.com/developers/gitignore/api/windows,macos,git,java,maven,eclipse,intellij,gradle,netbeans,visualstudiocode

26
.idea/compiler.xml Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="wms_cache_main" target="1.7" />
<module name="wms_cache_test" target="1.7" />
</bytecodeTargetLevel>
</component>
</project>

View File

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

57
.idea/misc.xml Normal file
View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ClientPropertiesManager">
<properties class="javax.swing.AbstractButton">
<property name="hideActionText" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JComponent">
<property name="html.disable" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JEditorPane">
<property name="JEditorPane.w3cLengthUnits" class="java.lang.Boolean" />
<property name="JEditorPane.honorDisplayProperties" class="java.lang.Boolean" />
<property name="charset" class="java.lang.String" />
</properties>
<properties class="javax.swing.JList">
<property name="List.isFileList" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JPasswordField">
<property name="JPasswordField.cutCopyAllowed" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JSlider">
<property name="Slider.paintThumbArrowShape" class="java.lang.Boolean" />
<property name="JSlider.isFilled" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JTable">
<property name="Table.isFileList" class="java.lang.Boolean" />
<property name="JTable.autoStartsEdit" class="java.lang.Boolean" />
<property name="terminateEditOnFocusLost" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JToolBar">
<property name="JToolBar.isRollover" class="java.lang.Boolean" />
</properties>
<properties class="javax.swing.JTree">
<property name="JTree.lineStyle" class="java.lang.String" />
</properties>
<properties class="javax.swing.text.JTextComponent">
<property name="caretAspectRatio" class="java.lang.Double" />
<property name="caretWidth" class="java.lang.Integer" />
</properties>
</component>
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="false" assert-keyword="false" jdk-15="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
</project>

10
.idea/modules.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/modules/wms_cache.iml" filepath="$PROJECT_DIR$/.idea/modules/wms_cache.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/wms_cache_main.iml" filepath="$PROJECT_DIR$/.idea/modules/wms_cache_main.iml" group="wms_cache" />
<module fileurl="file://$PROJECT_DIR$/.idea/modules/wms_cache_test.iml" filepath="$PROJECT_DIR$/.idea/modules/wms_cache_test.iml" group="wms_cache" />
</modules>
</component>
</project>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="wms_cache" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/../..">
<excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
<excludeFolder url="file://$MODULE_DIR$/../../build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="wms_cache:main" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="" external.system.module.type="sourceSet" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/../../build/classes/main" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../src/main">
<sourceFolder url="file://$MODULE_DIR$/../../src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../src/main/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: org.springframework:spring-webmvc:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-orm:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate:hibernate-core:4.3.11.Final" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate:hibernate-entitymanager:4.3.11.Final" level="project" />
<orderEntry type="library" name="Gradle: cglib:cglib-nodep:2.2.2" level="project" />
<orderEntry type="library" name="Gradle: javax.servlet:jstl:1.2" level="project" />
<orderEntry type="library" name="Gradle: org.apache.httpcomponents:httpclient:4.3.4" level="project" />
<orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.9" level="project" />
<orderEntry type="library" name="Gradle: org.postgresql:postgresql:42.7.3" level="project" />
<orderEntry type="library" name="Gradle: c3p0:c3p0:0.9.1.2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Gradle: javax.servlet:servlet-api:2.5" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Gradle: javax.servlet.jsp:jsp-api:2.1" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-asm:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-beans:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-context:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-context-support:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-core:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-expression:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-web:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-jdbc:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-tx:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.jboss.logging:jboss-logging:3.1.3.GA" level="project" />
<orderEntry type="library" name="Gradle: org.jboss.logging:jboss-logging-annotations:1.2.0.Beta1" level="project" />
<orderEntry type="library" name="Gradle: org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final" level="project" />
<orderEntry type="library" name="Gradle: dom4j:dom4j:1.6.1" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate.common:hibernate-commons-annotations:4.0.5.Final" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final" level="project" />
<orderEntry type="library" name="Gradle: org.javassist:javassist:3.18.1-GA" level="project" />
<orderEntry type="library" name="Gradle: antlr:antlr:2.7.7" level="project" />
<orderEntry type="library" name="Gradle: org.jboss:jandex:1.1.0.Final" level="project" />
<orderEntry type="library" name="Gradle: org.apache.httpcomponents:httpcore:4.3.2" level="project" />
<orderEntry type="library" name="Gradle: commons-logging:commons-logging:1.1.3" level="project" />
<orderEntry type="library" name="Gradle: org.checkerframework:checker-qual:3.42.0" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-aop:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: aopalliance:aopalliance:1.0" level="project" />
<orderEntry type="library" name="Gradle: xml-apis:xml-apis:1.0.b2" level="project" />
</component>
</module>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="wms_cache:test" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="" external.system.module.type="sourceSet" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output-test url="file://$MODULE_DIR$/../../build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../src/test">
<sourceFolder url="file://$MODULE_DIR$/../../src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/../../src/test/resources" type="java-test-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="wms_cache_main" />
<orderEntry type="library" name="Gradle: org.springframework:spring-webmvc:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-orm:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate:hibernate-core:4.3.11.Final" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate:hibernate-entitymanager:4.3.11.Final" level="project" />
<orderEntry type="library" name="Gradle: cglib:cglib-nodep:2.2.2" level="project" />
<orderEntry type="library" name="Gradle: javax.servlet:jstl:1.2" level="project" />
<orderEntry type="library" name="Gradle: org.apache.httpcomponents:httpclient:4.3.4" level="project" />
<orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.9" level="project" />
<orderEntry type="library" name="Gradle: org.postgresql:postgresql:42.7.3" level="project" />
<orderEntry type="library" name="Gradle: c3p0:c3p0:0.9.1.2" level="project" />
<orderEntry type="library" name="Gradle: javax.servlet:servlet-api:2.5" level="project" />
<orderEntry type="library" name="Gradle: javax.servlet.jsp:jsp-api:2.1" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-asm:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-beans:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-context:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-context-support:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-core:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-expression:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-web:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-jdbc:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-tx:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: org.jboss.logging:jboss-logging:3.1.3.GA" level="project" />
<orderEntry type="library" name="Gradle: org.jboss.logging:jboss-logging-annotations:1.2.0.Beta1" level="project" />
<orderEntry type="library" name="Gradle: org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Final" level="project" />
<orderEntry type="library" name="Gradle: dom4j:dom4j:1.6.1" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate.common:hibernate-commons-annotations:4.0.5.Final" level="project" />
<orderEntry type="library" name="Gradle: org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final" level="project" />
<orderEntry type="library" name="Gradle: org.javassist:javassist:3.18.1-GA" level="project" />
<orderEntry type="library" name="Gradle: antlr:antlr:2.7.7" level="project" />
<orderEntry type="library" name="Gradle: org.jboss:jandex:1.1.0.Final" level="project" />
<orderEntry type="library" name="Gradle: org.apache.httpcomponents:httpcore:4.3.2" level="project" />
<orderEntry type="library" name="Gradle: commons-logging:commons-logging:1.1.3" level="project" />
<orderEntry type="library" name="Gradle: org.checkerframework:checker-qual:3.42.0" level="project" />
<orderEntry type="library" name="Gradle: org.springframework:spring-aop:3.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Gradle: aopalliance:aopalliance:1.0" level="project" />
<orderEntry type="library" name="Gradle: xml-apis:xml-apis:1.0.b2" level="project" />
</component>
<component name="TestModuleProperties" production-module="wms_cache_main" />
</module>

View File

@ -1,3 +0,0 @@
# wms_cache
WMS(Web Map Service) 캐시 서버

54
build.gradle Normal file
View File

@ -0,0 +1,54 @@
// Java (WAR)
apply plugin: 'java'
apply plugin: 'war'
// (jetty)
apply plugin: 'jetty'
// Java 1.7
sourceCompatibility = 1.7
targetCompatibility = 1.7
// UTF-8
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
//
repositories {
mavenCentral()
}
// ()
dependencies {
// 1. Spring Framework 3.1.4
compile 'org.springframework:spring-webmvc:3.1.4.RELEASE'
compile 'org.springframework:spring-orm:3.1.4.RELEASE'
// 2. Hibernate
compile 'org.hibernate:hibernate-core:4.3.11.Final'
compile 'org.hibernate:hibernate-entitymanager:4.3.11.Final'
// @Transactional CGLIB
compile 'cglib:cglib-nodep:2.2.2'
// JSP Servlet API ( )
providedCompile 'javax.servlet:servlet-api:2.5'
providedCompile 'javax.servlet.jsp:jsp-api:2.1'
// JSTL (JSP )
compile 'javax.servlet:jstl:1.2'
// HTTP Apache HttpClient
compile 'org.apache.httpcomponents:httpclient:4.3.4'
// SHA-256 Apache Commons Codec
compile 'commons-codec:commons-codec:1.9'
// PostgreSQL 14+ JDBC
compile 'org.postgresql:postgresql:42.7.3'
// C3P0
compile 'c3p0:c3p0:0.9.1.2'
// ----------------------------
}
// Jetty 8080
httpPort = 8083

View File

@ -0,0 +1,41 @@
package kr.co.dbnt.wms.cache;
import kr.co.dbnt.wms.cache.entity.TestTable;
import kr.co.dbnt.wms.cache.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Controller
public class MainController {
@Autowired
private TestService testService; // TestService 주입
// 웹 브라우저에서 최상위 주소("/")로 GET 요청이 오면 이 메서드를 실행
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model) {
return "index";
}
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testDatabase(Model model) {
// 1. Insert -> Select -> Update 실행
testService.runCrudTest();
// 2. 전체 데이터 조회해서 View로 전달
List<TestTable> testDataList = testService.getAllData();
model.addAttribute("message", "DB CRUD Test Completed! Check the Console Log.");
model.addAttribute("testDataList", testDataList);
return "test_db"; // 결과를 hello.jsp에서 보여줌
}
}

View File

@ -0,0 +1,59 @@
package kr.co.dbnt.wms.cache.controller;
import kr.co.dbnt.wms.cache.service.WmsCacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Controller
public class WmsController {
@Autowired
private WmsCacheService wmsCacheService;
@RequestMapping(value = "/openapi/wms", method = RequestMethod.GET)
public void getWmsImage(HttpServletRequest request, HttpServletResponse response) {
try {
String queryString = request.getQueryString();
if (queryString == null || queryString.isEmpty()) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Query parameters are required.");
return;
}
File imageFile = wmsCacheService.getImage(queryString);
response.setContentType("image/png");
response.setContentLength((int) imageFile.length());
// try-with-resources 구문으로 InputStream을 안전하게 엽니다.
try (InputStream inputStream = new FileInputStream(imageFile)) {
// InputStream의 내용을 OutputStream으로 직접 복사합니다.
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
response.getOutputStream().write(buffer, 0, bytesRead);
}
}
} catch (IOException e) {
e.printStackTrace();
try {
// 에러 발생 시 서버 에러 응답
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to process WMS request.");
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,43 @@
package kr.co.dbnt.wms.cache.dao;
import kr.co.dbnt.wms.cache.entity.TestTable;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Repository
public class TestDao {
@PersistenceContext
private EntityManager em;
// 데이터 삽입 (Insert)
public void save(TestTable testTable) {
em.persist(testTable);
}
// ID로 한 건 조회 (Select by ID)
public TestTable findById(Long id) {
return em.find(TestTable.class, id);
}
// 전체 조회 (Select All)
public List<TestTable> findAll() {
return em.createQuery("SELECT t FROM TestTable t", TestTable.class)
.getResultList();
}
// 영속성 컨텍스트의 변경 내용을 데이터베이스에 강제로 반영합니다.
public void flush() {
em.flush();
}
// 데이터 수정 (Update)
// 참고: Service 레이어의 @Transactional에 의해 자동으로 DB에 반영됩니다.
// 별도의 update 메서드 없이, find로 가져온 객체의 값을 변경하면 됩니다.
}

View File

@ -0,0 +1,39 @@
package kr.co.dbnt.wms.cache.dao;
import kr.co.dbnt.wms.cache.entity.WmsCache;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.List;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Repository
public class WmsCacheDao {
@PersistenceContext
private EntityManager em;
public void save(WmsCache wmsCache) {
em.persist(wmsCache);
}
/**
* 1 .
* @param requestHash SHA-256
* @return WmsCache ( null)
*/
public WmsCache findLatestByHash(String requestHash) {
// 'status'가 'SUCCESS'인 데이터만 조회하도록 조건을 추가합니다.
String jpql = "SELECT wc FROM WmsCache wc WHERE wc.requestHash = :hash AND wc.status = 'SUCCESS' ORDER BY wc.createdAt DESC";
TypedQuery<WmsCache> query = em.createQuery(jpql, WmsCache.class);
query.setParameter("hash", requestHash);
query.setMaxResults(1); // 가장 최신 1건만 가져옴
List<WmsCache> results = query.getResultList();
return results.isEmpty() ? null : results.get(0);
}
}

View File

@ -0,0 +1,55 @@
package kr.co.dbnt.wms.cache.entity;
import javax.persistence.*;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Entity
@Table(name = "test")
public class TestTable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "test_id_seq_generator")
@SequenceGenerator(
name = "test_id_seq_generator",
sequenceName = "test_id_seq",
allocationSize = 1
)
private Long id;
@Column(name = "name", length = 100)
private String name;
// JPA는 기본 생성자를 필요로 합니다.
public TestTable() {
}
public TestTable(String name) {
this.name = name;
}
// --- Getter and Setter ---
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TestTable{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

View File

@ -0,0 +1,102 @@
package kr.co.dbnt.wms.cache.entity;
import javax.persistence.*;
import java.util.Date;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Entity
@Table(name = "wms_cache")
public class WmsCache {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "wms_cache_id_seq_generator")
@SequenceGenerator(
name = "wms_cache_id_seq_generator",
sequenceName = "wms_cache_id_seq", // PostgreSQL이 자동으로 생성하는 시퀀스 이름
allocationSize = 1
)
private Long id;
@Column(name = "request_hash", length = 64, nullable = false)
private String requestHash;
@Column(name = "request_params", columnDefinition = "TEXT")
private String requestParams;
@Column(name = "file_path", length = 255, nullable = true)
private String filePath;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at", nullable = false)
private Date createdAt;
@Column(name = "status", length = 20)
private String status;
@Column(name = "error_message", columnDefinition = "TEXT")
private String errorMessage;
// --- Constructors, Getters, Setters ---
public WmsCache() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRequestHash() {
return requestHash;
}
public void setRequestHash(String requestHash) {
this.requestHash = requestHash;
}
public String getRequestParams() {
return requestParams;
}
public void setRequestParams(String requestParams) {
this.requestParams = requestParams;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

View File

@ -0,0 +1,49 @@
package kr.co.dbnt.wms.cache.service;
import kr.co.dbnt.wms.cache.dao.TestDao;
import kr.co.dbnt.wms.cache.entity.TestTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Service
@Transactional // 이 클래스의 모든 public 메서드는 하나의 트랜잭션으로 묶입니다.
public class TestService {
@Autowired
private TestDao testDao;
public void runCrudTest() {
// 1. Insert
System.out.println("--- Inserting new data ---");
TestTable newData = new TestTable("First Data");
testDao.save(newData);
testDao.flush(); // DB에 즉시 반영
System.out.println("Saved data: " + newData);
// 2. Select (방금 넣은 데이터 확인)
System.out.println("\n--- Finding data by ID ---");
TestTable foundData = testDao.findById(newData.getId());
System.out.println("Found data: " + foundData);
// 3. Update
System.out.println("\n--- Updating data ---");
foundData.setName("Updated Data");
System.out.println("Data updated in memory. Transaction commit will save it to DB.");
}
@Transactional(readOnly = true) // 조회 전용 트랜잭션 (성능에 유리)
public List<TestTable> getAllData() {
System.out.println("\n--- Finding all data ---");
List<TestTable> allData = testDao.findAll();
System.out.println("All data in DB: " + allData);
return allData;
}
}

View File

@ -0,0 +1,152 @@
package kr.co.dbnt.wms.cache.service;
import kr.co.dbnt.wms.cache.dao.WmsCacheDao;
import kr.co.dbnt.wms.cache.entity.WmsCache;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import javax.net.ssl.SSLContext;
import java.security.cert.X509Certificate;
/**
* Created by kimtheho on 25. 10. 15.
*/
@Service
@Transactional
public class WmsCacheService {
@Autowired
private WmsCacheDao wmsCacheDao;
@Value("${wms.cache.directory}")
private String cacheDir;
@Value("${wms.upstream.url}")
private String upstreamWmsUrl;
@Value("${wms.upstream.apikey}")
private String upstreamApiKey;
/**
* WMS
* @param queryString (API )
* @return
* @throws IOException
*/
public File getImage(String queryString) throws IOException {
String requestHash = DigestUtils.sha256Hex(queryString);
WmsCache latestCache = wmsCacheDao.findLatestByHash(requestHash);
// 1. 유효한 캐시가 있는지 확인 (100일 이내)
if (latestCache != null) {
long diff = new Date().getTime() - latestCache.getCreatedAt().getTime();
long days = TimeUnit.MILLISECONDS.toDays(diff);
if (days <= 100) {
System.out.println(">>> Cache HIT! Returning file: " + latestCache.getFilePath());
File cachedFile = new File(latestCache.getFilePath());
if (cachedFile.exists()) {
return cachedFile;
}
}
}
// 2. 유효한 캐시가 없으면 새로 요청하여 저장 (Cache Miss)
System.out.println(">>> Cache MISS! Fetching new image...");
return fetchAndCacheImage(queryString, requestHash);
}
/**
* WMS DB .
*/
private File fetchAndCacheImage(String queryString, String requestHash) throws IOException {
// --- 수정된 부분 ---
// 외부 서버로 요청할 URL을 생성할 때, 원본 queryString에 API 키를 추가합니다.
// WMS 표준에서는 파라미터 순서가 중요하지 않으므로, 가장 간단하고 안전하게 맨 뒤에 추가합니다.
String queryStringWithKey = queryString + "&key=" + upstreamApiKey;
String requestUrl = upstreamWmsUrl + "?" + queryStringWithKey;
System.out.println(">>> Requesting to upstream: " + requestUrl);
// ------------------
try {
// SSL 인증서를 무시하는 SSLContext 생성
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) {
return true; // 모든 인증서를 신뢰함
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
// SSL 설정을 적용한 HttpClient 생성
try (CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
CloseableHttpResponse response = httpClient.execute(new HttpGet(requestUrl))) {
HttpEntity entity = response.getEntity();
if (response.getStatusLine().getStatusCode() != 200 || entity == null) {
// HTTP 에러 발생 시 예외를 던짐
throw new IOException("Failed to fetch image from upstream server: " + response.getStatusLine());
}
String fileName = UUID.randomUUID().toString() + ".png";
File imageFile = new File(cacheDir, fileName);
imageFile.getParentFile().mkdirs();
try (InputStream inputStream = entity.getContent();
FileOutputStream outputStream = new FileOutputStream(imageFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
// 성공 정보를 DB에 저장 (이때는 API 키가 없는 원본 queryString을 저장)
WmsCache newCache = new WmsCache();
newCache.setStatus("SUCCESS"); // 성공 상태 기록
newCache.setRequestHash(requestHash);
newCache.setRequestParams(queryString);
newCache.setFilePath(imageFile.getAbsolutePath());
newCache.setCreatedAt(new Date());
wmsCacheDao.save(newCache);
System.out.println(">>> New image cached at: " + imageFile.getAbsolutePath());
return imageFile;
}
} catch (Exception e) {
System.err.println("!!! Failed to fetch image. Logging error to DB. Reason: " + e.getMessage());
// 실패 정보를 DB에 저장 (이때도 API 키가 없는 원본 queryString을 저장)
WmsCache errorCache = new WmsCache();
errorCache.setStatus("ERROR"); // 에러 상태 기록
errorCache.setRequestHash(requestHash);
errorCache.setRequestParams(queryString);
errorCache.setErrorMessage(e.toString()); // 에러 메시지 기록
errorCache.setCreatedAt(new Date());
wmsCacheDao.save(errorCache);
// 원래 발생했던 예외를 다시 던져서 Controller가 알 수 있도록 함
throw new IOException("Failed to create SSL context or execute HTTP request", e);
}
}
}

View File

@ -0,0 +1,22 @@
db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://localhost:5432/wms_cache
db.username=postgres
db.password=geoinfo
# Hibernate 설정
hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
hibernate.show_sql=true
hibernate.format_sql=true
#hibernate.hbm2ddl.auto=create 옵션은 애플리케이션이 시작될 때마다 기존 테이블을 삭제하고 새로 만들기 때문에 테이블의 모든 데이터가 사라집니다.
#개발 단계: 테이블 구조를 자주 바꿀 때 매우 편리합니다.
#운영 단계: 데이터가 모두 삭제되므로 절대로 create나 update를 사용하면 안 됩니다. 운영 시에는 validate 또는 none으로 변경해야 합니다.
hibernate.hbm2ddl.auto=update
# WMS Cache Server Settings
# 외부 WMS 서버 기본 URL
wms.upstream.url=https://data.kigam.re.kr/openapi/wms
# 외부 WMS 서버 API 키( https://data.kigam.re.kr/my-openapi/request/2213 )
wms.upstream.apikey=4n4YdSOGgluWg8KEqxPYQfsxQB8Iqo
# 캐시 이미지를 저장할 서버 내부 경로
wms.cache.directory=/opt/wms_cache/wms_cache_images/

View File

@ -0,0 +1,10 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring 3.1 Test</title>
</head>
<body>
<h1>It works</h1>
</body>
</html>

View File

@ -0,0 +1,34 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring 3.1 Test</title>
</head>
<body>
<h1>${message}</h1>
<hr/>
<h3>Data in 'test' table:</h3>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<c:forEach items="${testDataList}" var="item">
<tr>
<td>${item.id}</td>
<td>${item.name}</td>
</tr>
</c:forEach>
<c:if test="${empty testDataList}">
<tr>
<td colspan="2">No data found.</td>
</tr>
</c:if>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="kr.co.dbnt.wms.cache">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:property-placeholder location="classpath:application.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${db.driver}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="user" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="kr.co.dbnt.wms.cache.entity"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="kr.co.dbnt.wms.cache">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>MySpringProject</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>