api sample

This commit is contained in:
2025-11-17 09:39:18 +09:00
parent 74e1c6bb9c
commit 7d64ee897d
29 changed files with 918 additions and 126 deletions

View File

@@ -1,6 +1,5 @@
package com.kamco.cd.kamcoback.config;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import lombok.RequiredArgsConstructor;
@@ -15,85 +14,85 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class StartupLogger {
private final Environment environment;
private final DataSource dataSource;
private final Environment environment;
private final DataSource dataSource;
@EventListener(ApplicationReadyEvent.class)
public void logStartupInfo() {
String[] activeProfiles = environment.getActiveProfiles();
String profileInfo =
activeProfiles.length > 0 ? String.join(", ", activeProfiles) : "default";
@EventListener(ApplicationReadyEvent.class)
public void logStartupInfo() {
String[] activeProfiles = environment.getActiveProfiles();
String profileInfo =
activeProfiles.length > 0 ? String.join(", ", activeProfiles) : "default";
// Database connection information
String dbUrl = environment.getProperty("spring.datasource.url");
String dbUsername = environment.getProperty("spring.datasource.username");
String dbDriver = environment.getProperty("spring.datasource.driver-class-name");
// Database connection information
String dbUrl = environment.getProperty("spring.datasource.url");
String dbUsername = environment.getProperty("spring.datasource.username");
String dbDriver = environment.getProperty("spring.datasource.driver-class-name");
// HikariCP pool settings
String poolInfo = "";
if (dataSource instanceof HikariDataSource hikariDs) {
poolInfo =
String.format(
"""
│ Pool Size : min=%d, max=%d
│ Connection Timeout: %dms
│ Idle Timeout : %dms
│ Max Lifetime : %dms""",
hikariDs.getMinimumIdle(),
hikariDs.getMaximumPoolSize(),
hikariDs.getConnectionTimeout(),
hikariDs.getIdleTimeout(),
hikariDs.getMaxLifetime());
}
// HikariCP pool settings
String poolInfo = "";
if (dataSource instanceof HikariDataSource hikariDs) {
poolInfo =
String.format(
"""
│ Pool Size : min=%d, max=%d
│ Connection Timeout: %dms
│ Idle Timeout : %dms
│ Max Lifetime : %dms""",
hikariDs.getMinimumIdle(),
hikariDs.getMaximumPoolSize(),
hikariDs.getConnectionTimeout(),
hikariDs.getIdleTimeout(),
hikariDs.getMaxLifetime());
}
// JPA/Hibernate settings
String showSql = environment.getProperty("spring.jpa.show-sql", "false");
String ddlAuto = environment.getProperty("spring.jpa.hibernate.ddl-auto", "none");
String batchSize =
environment.getProperty("spring.jpa.properties.hibernate.jdbc.batch_size", "N/A");
String batchFetchSize =
environment.getProperty(
"spring.jpa.properties.hibernate.default_batch_fetch_size", "N/A");
// JPA/Hibernate settings
String showSql = environment.getProperty("spring.jpa.show-sql", "false");
String ddlAuto = environment.getProperty("spring.jpa.hibernate.ddl-auto", "none");
String batchSize =
environment.getProperty("spring.jpa.properties.hibernate.jdbc.batch_size", "N/A");
String batchFetchSize =
environment.getProperty(
"spring.jpa.properties.hibernate.default_batch_fetch_size", "N/A");
String startupMessage =
String.format(
"""
String startupMessage =
String.format(
"""
╔════════════════════════════════════════════════════════════════════════════════╗
║ 🚀 APPLICATION STARTUP INFORMATION ║
╠════════════════════════════════════════════════════════════════════════════════╣
║ PROFILE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Active Profile(s): %s
╠════════════════════════════════════════════════════════════════════════════════╣
║ DATABASE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Database URL : %s
│ Username : %s
│ Driver : %s
╠════════════════════════════════════════════════════════════════════════════════╣
║ HIKARICP CONNECTION POOL ║
╠────────────────────────────────────────────────────────────────────────────────╣
%s
╠════════════════════════════════════════════════════════════════════════════════╣
║ JPA/HIBERNATE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Show SQL : %s
│ DDL Auto : %s
│ JDBC Batch Size : %s
│ Fetch Batch Size : %s
╚════════════════════════════════════════════════════════════════════════════════╝
""",
profileInfo,
dbUrl != null ? dbUrl : "N/A",
dbUsername != null ? dbUsername : "N/A",
dbDriver != null ? dbDriver : "PostgreSQL JDBC Driver (auto-detected)",
poolInfo,
showSql,
ddlAuto,
batchSize,
batchFetchSize);
╔════════════════════════════════════════════════════════════════════════════════╗
║ 🚀 APPLICATION STARTUP INFORMATION ║
╠════════════════════════════════════════════════════════════════════════════════╣
║ PROFILE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Active Profile(s): %s
╠════════════════════════════════════════════════════════════════════════════════╣
║ DATABASE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Database URL : %s
│ Username : %s
│ Driver : %s
╠════════════════════════════════════════════════════════════════════════════════╣
║ HIKARICP CONNECTION POOL ║
╠────────────────────────────────────────────────────────────────────────────────╣
%s
╠════════════════════════════════════════════════════════════════════════════════╣
║ JPA/HIBERNATE CONFIGURATION ║
╠────────────────────────────────────────────────────────────────────────────────╣
│ Show SQL : %s
│ DDL Auto : %s
│ JDBC Batch Size : %s
│ Fetch Batch Size : %s
╚════════════════════════════════════════════════════════════════════════════════╝
""",
profileInfo,
dbUrl != null ? dbUrl : "N/A",
dbUsername != null ? dbUsername : "N/A",
dbDriver != null ? dbDriver : "PostgreSQL JDBC Driver (auto-detected)",
poolInfo,
showSql,
ddlAuto,
batchSize,
batchFetchSize);
log.info(startupMessage);
}
log.info(startupMessage);
}
}

View File

@@ -26,8 +26,6 @@ public class WebConfig {
module.addSerializer(Point.class, new GeometrySerializer<>(Point.class));
module.addDeserializer(Point.class, new GeometryDeserializer<>(Point.class));
return Jackson2ObjectMapperBuilder.json()
.modulesToInstall(module)
.build();
return Jackson2ObjectMapperBuilder.json().modulesToInstall(module).build();
}
}

View File

@@ -1,4 +1,120 @@
package com.kamco.cd.kamcoback.config.api;
public class ApiResponseDto {
import com.fasterxml.jackson.annotation.JsonInclude;
import com.kamco.cd.kamcoback.config.enums.EnumType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
@Getter
@ToString
public class ApiResponseDto<T> {
private T data;
@JsonInclude(JsonInclude.Include.NON_NULL)
private Error error;
@JsonInclude(JsonInclude.Include.NON_NULL)
private T errorData;
public ApiResponseDto(T data) {
this.data = data;
}
public ApiResponseDto(ApiResponseCode code) {
this.error = new Error(code.getId(), code.getMessage());
}
public ApiResponseDto(ApiResponseCode code, String message) {
this.error = new Error(code.getId(), message);
}
public ApiResponseDto(ApiResponseCode code, String message, T errorData) {
this.error = new Error(code.getId(), message);
this.errorData = errorData;
}
public static <T> ApiResponseDto<T> createOK(T data) {
return new ApiResponseDto<>(data);
}
public static ApiResponseDto<String> createException(ApiResponseCode code) {
return new ApiResponseDto<>(code);
}
public static ApiResponseDto<String> createException(ApiResponseCode code, String message) {
return new ApiResponseDto<>(code, message);
}
public static <T> ApiResponseDto<T> createException(
ApiResponseCode code, String message, T data) {
return new ApiResponseDto<>(code, message, data);
}
@Getter
public static class Error {
private final String code;
private final String message;
public Error(String code, String message) {
this.code = code;
this.message = message;
}
}
@Getter
@RequiredArgsConstructor
public enum ApiResponseCode implements EnumType {
// @formatter:off
OK("요청이 성공하였습니다."),
BAD_REQUEST("요청 파라미터가 잘못되었습니다."),
ALREADY_EXIST_MALL("이미 등록된 쇼핑센터입니다."),
NOT_FOUND_MAP("지도를 찾을 수 없습니다."),
UNAUTHORIZED("권한이 없습니다."),
CONFLICT("이미 등록된 컨텐츠입니다."),
NOT_FOUND("Resource를 찾을 수 없습니다."),
NOT_FOUND_DATA("데이터를 찾을 수 없습니다."),
NOT_FOUND_WEATHER_DATA("날씨 데이터를 찾을 수 없습니다."),
FAIL_SEND_MESSAGE("메시지를 전송하지 못했습니다."),
TOO_MANY_CONNECTED_MACHINES("연결된 기기가 너무 많습니다."),
UNAUTHENTICATED("인증에 실패하였습니다."),
INVALID_TOKEN("잘못된 토큰입니다."),
EXPIRED_TOKEN("만료된 토큰입니다."),
INTERNAL_SERVER_ERROR("서버에 문제가 발생 하였습니다."),
FORBIDDEN("권한을 확인해주세요."),
INVALID_PASSWORD("잘못된 비밀번호 입니다."),
NOT_FOUND_CAR_IN("입차정보가 없습니다."),
WRONG_STATUS("잘못된 상태입니다."),
FAIL_VERIFICATION("인증에 실패하였습니다."),
INVALID_EMAIL("잘못된 형식의 이메일입니다."),
REQUIRED_EMAIL("이메일은 필수 항목입니다."),
WRONG_PASSWORD("잘못된 패스워드입니다.."),
DUPLICATE_EMAIL("이미 가입된 이메일입니다."),
DUPLICATE_DATA("이미 등록되여 있습니다."),
DATA_INTEGRITY_ERROR("요청을 처리할수 없습니다."),
FOREIGN_KEY_ERROR("참조 중인 데이터가 있어 삭제할 수 없습니다."),
DUPLICATE_EMPLOYEEID("이미 가입된 사번입니다."),
NOT_FOUND_USER_FOR_EMAIL("이메일로 유저를 찾을 수 없습니다."),
NOT_FOUND_USER("사용자를 찾을 수 없습니다."),
INVALID_EMAIL_TOKEN(
"You can only reset your password within 24 hours from when the email was sent.\n"
+ "To reset your password again, please submit a new request through \"Forgot"
+ " Password.\""),
;
// @formatter:on
private final String message;
@Override
public String getId() {
return name();
}
@Override
public String getText() {
return message;
}
}
}

View File

@@ -1,4 +1,8 @@
package com.kamco.cd.kamcoback.config.api;
package com.kamco.cd.kamcoback.config.enums;
public interface EnumType {
String getId();
String getText();
}