HANTE 6 månader sedan
förälder
incheckning
2afa77c65d

+ 8 - 7
pom.xml

@@ -32,7 +32,8 @@
         <maven.compiler.target>1.8</maven.compiler.target>
         <!--main 함수가 있는 class 경로-->
         <start-class>com.sig.api.SigOpenApiServerApplication</start-class>
-        <webapp.lib>C:\DEV\ITS\01.WINDOWS\22.06.UTIC\JAVA\repository</webapp.lib>
+<!--        <webapp.lib>C:\DEV\ITS\01.WINDOWS\22.06.UTIC\JAVA\repository</webapp.lib>-->
+        <webapp.lib>C:/java/repository</webapp.lib>
         <maven.test.skip>true</maven.test.skip>
     </properties>
 
@@ -52,14 +53,14 @@
         <dependency>
             <groupId>com.oracle</groupId>
             <artifactId>ojdbc7</artifactId>
-            <version>12.1.0.2</version>
+            <version>12.2.0.1</version>
         </dependency>
 
-        <dependency>
-            <groupId>com.tibero</groupId>
-            <artifactId>tibero6-jdbc</artifactId>
-            <version>14</version>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.tibero</groupId>-->
+<!--            <artifactId>tibero6-jdbc</artifactId>-->
+<!--            <version>14</version>-->
+<!--        </dependency>-->
 
         <dependency>
             <groupId>commons-io</groupId>

+ 18 - 1
src/main/java/com/sig/api/SigOpenApiServerApplication.java

@@ -21,6 +21,10 @@ import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.web.bind.annotation.CrossOrigin;
 
 import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
 
 @Slf4j
@@ -73,13 +77,26 @@ public class SigOpenApiServerApplication extends SpringBootServletInitializer im
         authService.loadApiAuthInfo();
 
         processConfig.setStartSchedule(true);
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            log.error("on shutdown hook.");
+            terminateApplication();
+        }));
+    }
+    public void terminateApplication() {
+        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        log.error("Application terminateApplication: {}.", sdfDate.format(new Date()));
     }
 
     @Override
     public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
         // shutdown.....
         SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        log.error("Application Terminated: {}, {}", sdfDate.format(new Date()), contextClosedEvent.toString());
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(contextClosedEvent.getTimestamp()), ZoneId.systemDefault());
+        String formattedDateTime = dateTime.format(formatter);
+        log.error("ContextClosedEvent Application Terminated: {}, {}", sdfDate.format(new Date()), contextClosedEvent);
+        log.error("ContextClosedEvent Source: " + contextClosedEvent.getSource());
+        log.error("ContextClosedEvent Timestamp: " + formattedDateTime);
     }
 
     @Override

+ 5 - 6
src/main/java/com/sig/api/global/SigOpenApiAuthManager.java

@@ -4,6 +4,7 @@ import com.sig.api.dto.sig.TbApiAuthDto;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -40,13 +41,11 @@ public class SigOpenApiAuthManager {
         return this.authMap.size();
     }
 
-    public boolean containsKey(long key) {
-        return this.authMap.containsKey(key);
-    }
-
-    public void beforeLoading() {
+    public void beforeLoading(HashSet<String> authSet) {
         for (Map.Entry<String, TbApiAuthDto> obj : this.authMap.entrySet()) {
-            obj.getValue().setValid(false);
+            if (!authSet.contains(obj.getKey())) {
+                obj.getValue().setValid(false);
+            }
         }
     }
 

+ 1 - 0
src/main/java/com/sig/api/scheduler/SigOpenApiScheduler.java

@@ -29,6 +29,7 @@ public class SigOpenApiScheduler {
     @Scheduled(cron = "10 0/5 * * * *")  // 5분주기 작업 실행
     public void scheduleApiAuthLoading() {
         if (!this.processConfig.isStartSchedule()) {
+            log.info("scheduleApiAuthLoading: start schedule false. {}", Thread.currentThread().getName());
             return;
         }
         StopWatch stopWatch = new StopWatch();

+ 10 - 12
src/main/java/com/sig/api/service/sig/SigOpenApiAuthService.java

@@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.HashSet;
 import java.util.List;
 
 @Slf4j
@@ -21,10 +22,15 @@ public class SigOpenApiAuthService {
 
     public int loadApiAuthInfo() {
 
-        SigOpenApiAuthManager.getInstance().beforeLoading();
+        // 20250204: 순간적으로 valid==false 가 될때 처리되는 서비스가
+        // 20: SERVICE_ACCESS_DENIED_ERROR 로 처리되는 문제가 있음.
+        // 이를 방지하기 위해 beforeLoading, afterLoading 처리 변경
 
+        HashSet<String> authSet = new HashSet<>();
         List<TbApiAuth> authLists = this.mapper.selectApiAuthInfo();
         for (TbApiAuth obj : authLists) {
+            authSet.add(obj.getSERVICE_KEY());
+
             TbApiAuthDto dto = SigOpenApiAuthManager.getInstance().get(obj.getSERVICE_KEY());
             if (dto != null) {
                 dto.setValid(true);
@@ -36,17 +42,8 @@ public class SigOpenApiAuthService {
             }
         }
 
-//        authLists.forEach(obj -> {
-//            TbApiAuthDto dto = SigOpenApiAuthManager.getInstance().get(obj.getSERVICE_KEY());
-//            if (dto != null) {
-//                dto.setValid(true);
-//                dto.setREAL_IP(obj.getREAL_IP());
-//                dto.setUSER_IP(obj.getUSER_IP());
-//            }
-//            else {
-//                SigOpenApiAuthManager.getInstance().put(obj.getSERVICE_KEY(), obj.toDto());
-//            }
-//        });
+        // valid check
+        SigOpenApiAuthManager.getInstance().beforeLoading(authSet);
 
         String adminKey = "A515753C425C4B579BCC1F2E0ED50374";
         TbApiAuthDto dto = SigOpenApiAuthManager.getInstance().get(adminKey);
@@ -62,6 +59,7 @@ public class SigOpenApiAuthService {
             dto.setValid(true);
         }
 
+        // invalid data delete
         SigOpenApiAuthManager.getInstance().afterLoading();
         return authLists.size();
     }

+ 3 - 3
src/main/java/com/sig/utils/ApiUtils.java

@@ -12,17 +12,17 @@ public class ApiUtils {
         String ipAddr = request.getHeader("X-FORWARDED-FOR");
 
         // proxy 환경일 경우
-        if (ipAddr == null || ipAddr.length() == 0) {
+        if (ipAddr == null || ipAddr.isEmpty()) {
             ipAddr = request.getHeader("Proxy-Client-IP");
         }
 
         // 웹로직 서버일 경우
-        if (ipAddr == null || ipAddr.length() == 0) {
+        if (ipAddr == null || ipAddr.isEmpty()) {
             ipAddr = request.getHeader("WL-Proxy-Client-IP");
         }
 
         // 기타
-        if (ipAddr == null || ipAddr.length() == 0) {
+        if (ipAddr == null || ipAddr.isEmpty()) {
             ipAddr = request.getRemoteAddr() ;
         }
 

+ 40 - 33
src/main/resources/logback-spring.xml

@@ -6,17 +6,23 @@
     <property name="ROOT_LOG_LEVEL"  value="INFO"/>
     <property name="LOG_CHARSET"     value="UTF-8" />
     <property name="LOG_ENCODING"    value="UTF-8"/>
-    <property name="LOG_PATH"        value="${user.dir}/logs/${PROJECT_NAME}/"/>
-    <property name="LOG_BACKUP_PATH" value="${user.dir}/logs/${PROJECT_NAME}/backup/"/>
+    <property name="LOG_PATH"        value="${user.home}/logs/"/>
+    <property name="LOG_BACKUP_PATH" value="${user.home}/logs/backup/"/>
 
     <property name="LOG_FILE_NAME"             value="${PROJECT_NAME}.log"/>
-    <property name="LOG_FILE_NAME_ERROR"       value="${PROJECT_NAME}.err.log"/>
+    <property name="LOG_FILE_NAME_ERROR"       value="${PROJECT_NAME}-err.log"/>
     <property name="LOG_FILE_NAME_PATTERN"     value="%d{yyyyMMdd}_%i.log.gz"/>
-    <property name="LOG_FILE_NAME_SESSION"     value="${PROJECT_NAME}-session.log"/>
-    <property name="LOG_FILE_NAME_CENTER_COMM" value="${PROJECT_NAME}-center-comm.log"/>
-    <property name="LOG_FILE_NAME_SQL"         value="${PROJECT_NAME}-sql.log"/>
+<!--    <property name="LOG_FILE_NAME_SESSION"     value="${PROJECT_NAME}-session.log"/>-->
+<!--    <property name="LOG_FILE_NAME_CENTER_COMM" value="${PROJECT_NAME}-center-comm.log"/>-->
+<!--    <property name="LOG_FILE_NAME_SQL"         value="${PROJECT_NAME}-sql.log"/>-->
     <property name="LOG_FILE_NAME_SCHEDULE"    value="${PROJECT_NAME}-schedule.log"/>
-    <property name="LOG_FILE_NAME_STATISTICS"  value="${PROJECT_NAME}-statistics.log"/>
+<!--    <property name="LOG_FILE_NAME_STATISTICS"  value="${PROJECT_NAME}-statistics.log"/>-->
+    <property name="LOG_PATTERN_FILE"        value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
+    <property name="LOG_PATTERN_ERROR"       value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
+    <property name="LOG_PATTERN_SCHEDULE"    value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>\
+
+    <property name="MAX_FILESIZE" value="50MB"/>
+    <property name="MAX_HISTORY"  value="30"/>
 
     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
         <withJansi>true</withJansi>
@@ -26,60 +32,61 @@
         </encoder>
     </appender>
 
-    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <file>./logs/sig-api-server.log</file>
+    <appender name="FILE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_PATH}${LOG_FILE_NAME}</file>
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <charset>UTF-8</charset>
-            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n</pattern>
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_FILE}</pattern>
         </encoder>
         <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-            <fileNamePattern>./logs/backup/sig-api-server.%d{yyyy-MM-dd}_%i.log.gz</fileNamePattern>
-            <maxFileSize>500MB</maxFileSize>
-            <maxHistory>30</maxHistory>
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME}.${LOG_FILE_NAME_PATTERN}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
         </rollingPolicy>
     </appender>
 
-    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <filter class="ch.qos.logback.classic.filter.LevelFilter">
             <level>error</level>
             <onMatch>ACCEPT</onMatch>
             <onMismatch>DENY</onMismatch>
         </filter>
-        <file>./logs/sig-api-server.err.log</file>
+        <file>${LOG_PATH}${LOG_FILE_NAME_ERROR}</file>
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <charset>UTF-8</charset>
-            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger{35}.%M.%L - %msg%n</pattern>
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_ERROR}</pattern>
         </encoder>
         <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-            <fileNamePattern>./logs/backup/sig-api-server-error.%d{yyyy-MM-dd}_%i.log.gz</fileNamePattern>
-            <maxFileSize>500MB</maxFileSize>
-            <maxHistory>30</maxHistory>
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME_ERROR}.${LOG_FILE_NAME_PATTERN}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
         </rollingPolicy>
     </appender>
 
     <appender name="FILE_SCHEDULE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <file>./logs/sig-api-server-schedule.log</file>
+        <file>${LOG_PATH}${LOG_FILE_NAME_SCHEDULE}</file>
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <charset>UTF-8</charset>
-            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n</pattern>
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_SCHEDULE}</pattern>
         </encoder>
         <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-            <fileNamePattern>./logs/backup/sig-api-server-schedule.%d{yyyy-MM-dd}_%i.log.gz</fileNamePattern>
-            <maxFileSize>500MB</maxFileSize>
-            <maxHistory>30</maxHistory>
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME_SCHEDULE}.${LOG_FILE_NAME_PATTERN}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
         </rollingPolicy>
     </appender>
 
-    <root level="${ROOT_LOG_LEVEL}">
-        <appender-ref ref="CONSOLE"/>
-        <appender-ref ref="FILE"/>
-        <appender-ref ref="ERROR"/>
+    <root level="INFO">
+<!--        <appender-ref ref="CONSOLE"/>-->
+        <appender-ref ref="FILE_LOG"/>
+        <appender-ref ref="FILE_ERROR"/>
     </root>
 
     <logger name="com.sig.api.scheduler" level="INFO" additivity="false">
-        <appender-ref ref="CONSOLE"/>
+<!--        <appender-ref ref="CONSOLE"/>-->
         <appender-ref ref="FILE_SCHEDULE"/>
-        <appender-ref ref="ERROR"/>
+        <appender-ref ref="FILE_LOG"/>
+        <appender-ref ref="FILE_ERROR"/>
     </logger>
 
 </configuration>