recommend
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
}
|
||||
|
||||
description = 'Common utilities and shared components'
|
||||
|
||||
dependencies {
|
||||
// Spring Boot Starters
|
||||
api 'org.springframework.boot:spring-boot-starter-web'
|
||||
api 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
api 'org.springframework.boot:spring-boot-starter-validation'
|
||||
api 'org.springframework.boot:spring-boot-starter-security'
|
||||
|
||||
// AOP (AspectJ) - 명시적 의존성 추가
|
||||
api 'org.springframework.boot:spring-boot-starter-aop'
|
||||
api 'org.aspectj:aspectjweaver:1.9.21'
|
||||
api 'org.aspectj:aspectjrt:1.9.21'
|
||||
|
||||
// JSON Processing
|
||||
api 'com.fasterxml.jackson.core:jackson-databind'
|
||||
api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
|
||||
|
||||
// JWT
|
||||
api 'io.jsonwebtoken:jjwt-api:0.12.3'
|
||||
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3'
|
||||
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.3'
|
||||
|
||||
// Apache Commons
|
||||
api 'org.apache.commons:commons-lang3:3.13.0'
|
||||
api 'org.apache.commons:commons-collections4:4.4'
|
||||
|
||||
// OpenAPI/Swagger
|
||||
api 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
|
||||
|
||||
// Lombok
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
|
||||
// 테스트
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
}
|
||||
|
||||
// JAR 생성 설정 (plain jar도 생성)
|
||||
jar {
|
||||
archiveBaseName = 'common'
|
||||
archiveVersion = '1.0.0'
|
||||
enabled = true
|
||||
}
|
||||
|
||||
// bootJar 비활성화 (라이브러리이므로 실행 가능한 JAR 불필요)
|
||||
bootJar {
|
||||
enabled = false
|
||||
}
|
||||
@@ -1,4 +1,52 @@
|
||||
package com.ktds.hi.common.config;
|
||||
|
||||
public class AsyncConfig {
|
||||
}
|
||||
package com.ktds.hi.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* 비동기 처리 설정 클래스
|
||||
* @Async 어노테이션을 위한 스레드 풀 설정
|
||||
*
|
||||
* @author 하이오더 개발팀
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
public class AsyncConfig {
|
||||
|
||||
/**
|
||||
* 감사 로그용 스레드 풀
|
||||
*/
|
||||
@Bean("auditTaskExecutor")
|
||||
public Executor auditTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(2);
|
||||
executor.setMaxPoolSize(5);
|
||||
executor.setQueueCapacity(100);
|
||||
executor.setThreadNamePrefix("audit-");
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(30);
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 일반적인 비동기 작업용 스레드 풀
|
||||
*/
|
||||
@Bean("generalTaskExecutor")
|
||||
public Executor generalTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(4);
|
||||
executor.setMaxPoolSize(10);
|
||||
executor.setQueueCapacity(200);
|
||||
executor.setThreadNamePrefix("async-");
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(30);
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,18 @@
|
||||
package com.ktds.hi.common.config;
|
||||
|
||||
public class CommonAopConfig {
|
||||
}
|
||||
package com.ktds.hi.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
/**
|
||||
* AOP 설정 클래스
|
||||
* AspectJ 자동 프록시를 활성화
|
||||
*
|
||||
* @author 하이오더 개발팀
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy
|
||||
public class CommonAopConfig {
|
||||
// AOP 자동 설정을 위한 설정 클래스
|
||||
// @EnableAspectJAutoProxy 어노테이션으로 AspectJ 자동 프록시 활성화
|
||||
}
|
||||
@@ -1,4 +1,76 @@
|
||||
package com.ktds.hi.common.service;
|
||||
|
||||
public class AuditAction {
|
||||
}
|
||||
package com.ktds.hi.common.service;
|
||||
|
||||
/**
|
||||
* 감사 액션 열거형
|
||||
* 시스템에서 발생하는 주요 액션들을 정의
|
||||
*
|
||||
* @author 하이오더 개발팀
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public enum AuditAction {
|
||||
|
||||
/**
|
||||
* 생성 액션
|
||||
*/
|
||||
CREATE("생성"),
|
||||
|
||||
/**
|
||||
* 수정 액션
|
||||
*/
|
||||
UPDATE("수정"),
|
||||
|
||||
/**
|
||||
* 삭제 액션
|
||||
*/
|
||||
DELETE("삭제"),
|
||||
|
||||
/**
|
||||
* 조회 액션
|
||||
*/
|
||||
ACCESS("조회"),
|
||||
|
||||
/**
|
||||
* 로그인 액션
|
||||
*/
|
||||
LOGIN("로그인"),
|
||||
|
||||
/**
|
||||
* 로그아웃 액션
|
||||
*/
|
||||
LOGOUT("로그아웃"),
|
||||
|
||||
/**
|
||||
* 승인 액션
|
||||
*/
|
||||
APPROVE("승인"),
|
||||
|
||||
/**
|
||||
* 거부 액션
|
||||
*/
|
||||
REJECT("거부"),
|
||||
|
||||
/**
|
||||
* 활성화 액션
|
||||
*/
|
||||
ACTIVATE("활성화"),
|
||||
|
||||
/**
|
||||
* 비활성화 액션
|
||||
*/
|
||||
DEACTIVATE("비활성화");
|
||||
|
||||
private final String description;
|
||||
|
||||
AuditAction(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,41 @@
|
||||
package com.ktds.hi.common.service;
|
||||
|
||||
import com.ktds.hi.common.audit.AuditAction;
|
||||
import com.ktds.hi.common.audit.AuditLog;
|
||||
import com.ktds.hi.common.audit.AuditLogger;
|
||||
import com.ktds.hi.common.repository.AuditLogRepository;
|
||||
import com.ktds.hi.common.security.SecurityUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 감사 로그 서비스
|
||||
* 시스템의 중요한 액션들을 비동기적으로 로깅
|
||||
* 시스템 내 중요한 작업들을 로깅
|
||||
*
|
||||
* @author 하이오더 개발팀
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AuditLogService {
|
||||
|
||||
private final AuditLogRepository auditLogRepository;
|
||||
|
||||
/**
|
||||
* 감사 로그 기록 (비동기)
|
||||
* 비동기 로그 기록
|
||||
*/
|
||||
@Async
|
||||
@Transactional
|
||||
public void logAsync(AuditAction action, String entityType, String entityId, String description) {
|
||||
log(action, entityType, entityId, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* 감사 로그 기록 (동기)
|
||||
*/
|
||||
@Transactional
|
||||
public void log(AuditAction action, String entityType, String entityId, String description) {
|
||||
try {
|
||||
Long userId = SecurityUtil.getCurrentUserId().orElse(null);
|
||||
String username = SecurityUtil.getCurrentUsername().orElse("SYSTEM");
|
||||
// 현재 사용자 정보 가져오기 (SecurityContext에서)
|
||||
String userId = getCurrentUserId();
|
||||
String username = getCurrentUsername();
|
||||
|
||||
AuditLog auditLog = AuditLogger.create(userId, username, action, entityType, entityId, description);
|
||||
auditLogRepository.save(auditLog);
|
||||
// 감사 로그 생성 및 저장
|
||||
log.info("AUDIT_LOG: action={}, entityType={}, entityId={}, userId={}, username={}, description={}",
|
||||
action, entityType, entityId, userId, username, description);
|
||||
|
||||
// 실제 환경에서는 데이터베이스에 저장
|
||||
// AuditLog auditLog = AuditLog.create(userId, username, action, entityType, entityId, description);
|
||||
// auditLogRepository.save(auditLog);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to save audit log: action={}, entityType={}, entityId={}",
|
||||
action, entityType, entityId, e);
|
||||
action, entityType, entityId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,13 +71,38 @@ public class AuditLogService {
|
||||
* 로그인 로그
|
||||
*/
|
||||
public void logLogin(String description) {
|
||||
logAsync(AuditAction.LOGIN, "USER", SecurityUtil.getCurrentUserId().map(String::valueOf).orElse("UNKNOWN"), description);
|
||||
logAsync(AuditAction.LOGIN, "USER", getCurrentUserId(), description);
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃 로그
|
||||
*/
|
||||
public void logLogout(String description) {
|
||||
logAsync(AuditAction.LOGOUT, "USER", SecurityUtil.getCurrentUserId().map(String::valueOf).orElse("UNKNOWN"), description);
|
||||
logAsync(AuditAction.LOGOUT, "USER", getCurrentUserId(), description);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 사용자 ID 조회
|
||||
*/
|
||||
private String getCurrentUserId() {
|
||||
try {
|
||||
// SecurityContext에서 사용자 ID 추출
|
||||
// 실제 구현에서는 SecurityContextHolder 사용
|
||||
return "SYSTEM"; // 임시값
|
||||
} catch (Exception e) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 사용자명 조회
|
||||
*/
|
||||
private String getCurrentUsername() {
|
||||
try {
|
||||
// SecurityContext에서 사용자명 추출
|
||||
return "system"; // 임시값
|
||||
} catch (Exception e) {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user