release: 2026-03-31 (40건 커밋) #118
@ -84,23 +84,27 @@ public class BypassCodeGenerator {
|
||||
StringBuilder fieldLines = new StringBuilder();
|
||||
for (BypassApiField field : fields) {
|
||||
String jsonProp = field.getJsonProperty() != null ? field.getJsonProperty() : field.getFieldName();
|
||||
fieldLines.append(" @JsonProperty(\"%s\")\n".formatted(jsonProp));
|
||||
fieldLines.append(" private %s %s;\n\n".formatted(field.getFieldType(), field.getFieldName()));
|
||||
fieldLines.append(" @JsonProperty(\"").append(jsonProp).append("\")\n");
|
||||
fieldLines.append(" private ").append(field.getFieldType()).append(" ").append(field.getFieldName()).append(";\n\n");
|
||||
}
|
||||
|
||||
return """
|
||||
package %s;
|
||||
package {{PACKAGE}};
|
||||
|
||||
%s
|
||||
{{IMPORTS}}
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class %sBypassDto {
|
||||
public class {{CLASS_NAME}} {
|
||||
|
||||
%s}
|
||||
""".formatted(packageName, imports, domainCap, fieldLines);
|
||||
{{FIELDS}}}
|
||||
"""
|
||||
.replace("{{PACKAGE}}", packageName)
|
||||
.replace("{{IMPORTS}}", imports.toString())
|
||||
.replace("{{CLASS_NAME}}", domainCap + "BypassDto")
|
||||
.replace("{{FIELDS}}", fieldLines.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,7 +119,7 @@ public class BypassCodeGenerator {
|
||||
boolean isList = "LIST".equalsIgnoreCase(config.getResponseType());
|
||||
boolean isPost = "POST".equalsIgnoreCase(config.getHttpMethod());
|
||||
|
||||
String returnType = isList ? "List<%s>".formatted(dtoClass) : dtoClass;
|
||||
String returnType = isList ? "List<" + dtoClass + ">" : dtoClass;
|
||||
String methodName = "get" + domainCap + "Data";
|
||||
String fetchMethod = buildFetchMethodCall(config, params, isList, isPost);
|
||||
String methodParams = buildMethodParams(params);
|
||||
@ -123,52 +127,51 @@ public class BypassCodeGenerator {
|
||||
String listImport = isList ? "import java.util.List;\n" : "";
|
||||
|
||||
return """
|
||||
package %s;
|
||||
package {{PACKAGE}};
|
||||
|
||||
import %s.%s;
|
||||
import {{DTO_IMPORT}};
|
||||
import com.snp.batch.common.web.service.BaseBypassService;
|
||||
%simport org.springframework.beans.factory.annotation.Qualifier;
|
||||
{{LIST_IMPORT}}import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* %s bypass 서비스
|
||||
* {{DISPLAY_NAME}} bypass 서비스
|
||||
* 외부 Maritime API에서 데이터를 실시간 조회하여 그대로 반환
|
||||
*/
|
||||
@Service
|
||||
public class %sBypassService extends BaseBypassService<%s> {
|
||||
public class {{DOMAIN_CAP}}BypassService extends BaseBypassService<{{DTO_CLASS}}> {
|
||||
|
||||
public %sBypassService(
|
||||
@Qualifier("%s") WebClient webClient) {
|
||||
super(webClient, "%s", "%s",
|
||||
public {{DOMAIN_CAP}}BypassService(
|
||||
@Qualifier("{{WEBCLIENT_BEAN}}") WebClient webClient) {
|
||||
super(webClient, "{{DISPLAY_NAME}}", "{{EXTERNAL_PATH}}",
|
||||
new ParameterizedTypeReference<>() {},
|
||||
new ParameterizedTypeReference<>() {});
|
||||
}
|
||||
|
||||
/**
|
||||
* %s 데이터를 조회합니다.
|
||||
* {{DISPLAY_NAME}} 데이터를 조회합니다.
|
||||
*
|
||||
* @return %s
|
||||
* @return {{DISPLAY_NAME}}
|
||||
*/
|
||||
public %s %s(%s) {
|
||||
%s
|
||||
public {{RETURN_TYPE}} {{METHOD_NAME}}({{METHOD_PARAMS}}) {
|
||||
{{FETCH_METHOD}}
|
||||
}
|
||||
}
|
||||
""".formatted(
|
||||
packageName,
|
||||
dtoPackage, dtoClass,
|
||||
listImport,
|
||||
config.getDisplayName(),
|
||||
domainCap, dtoClass,
|
||||
domainCap,
|
||||
config.getWebclientBean(),
|
||||
config.getExternalPath(),
|
||||
config.getDisplayName(),
|
||||
config.getDisplayName(),
|
||||
returnType, methodName, methodParams,
|
||||
fetchMethod
|
||||
);
|
||||
"""
|
||||
.replace("{{PACKAGE}}", packageName)
|
||||
.replace("{{DTO_IMPORT}}", dtoPackage + "." + dtoClass)
|
||||
.replace("{{LIST_IMPORT}}", listImport)
|
||||
.replace("{{DISPLAY_NAME}}", config.getDisplayName())
|
||||
.replace("{{DOMAIN_CAP}}", domainCap)
|
||||
.replace("{{DTO_CLASS}}", dtoClass)
|
||||
.replace("{{WEBCLIENT_BEAN}}", config.getWebclientBean())
|
||||
.replace("{{EXTERNAL_PATH}}", config.getExternalPath())
|
||||
.replace("{{RETURN_TYPE}}", returnType)
|
||||
.replace("{{METHOD_NAME}}", methodName)
|
||||
.replace("{{METHOD_PARAMS}}", methodParams)
|
||||
.replace("{{FETCH_METHOD}}", fetchMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,7 +190,7 @@ public class BypassCodeGenerator {
|
||||
boolean isList = "LIST".equalsIgnoreCase(config.getResponseType());
|
||||
boolean isPost = "POST".equalsIgnoreCase(config.getHttpMethod());
|
||||
|
||||
String responseGeneric = isList ? "List<%s>".formatted(dtoClass) : dtoClass;
|
||||
String responseGeneric = isList ? "List<" + dtoClass + ">" : dtoClass;
|
||||
String mappingAnnotation = isPost ? "@PostMapping" : "@GetMapping";
|
||||
String listImport = isList ? "import java.util.List;\n" : "";
|
||||
|
||||
@ -205,59 +208,58 @@ public class BypassCodeGenerator {
|
||||
String requestMappingPath = "/api/" + domain;
|
||||
|
||||
return """
|
||||
package %s;
|
||||
package {{PACKAGE}};
|
||||
|
||||
import %s.%s;
|
||||
import %s.%s;
|
||||
import {{DTO_IMPORT}};
|
||||
import {{SERVICE_IMPORT}};
|
||||
import com.snp.batch.common.web.ApiResponse;
|
||||
import com.snp.batch.common.web.controller.BaseBypassController;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
%simport lombok.RequiredArgsConstructor;
|
||||
{{LIST_IMPORT}}import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
%s%s%s%s
|
||||
{{PATH_VARIABLE_IMPORT}}{{REQUEST_PARAM_IMPORT}}{{REQUEST_BODY_IMPORT}}
|
||||
/**
|
||||
* %s bypass API
|
||||
* {{DISPLAY_NAME}} bypass API
|
||||
* S&P Maritime API에서 데이터를 실시간 조회하여 그대로 반환
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("%s")
|
||||
@RequestMapping("{{REQUEST_MAPPING_PATH}}")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "%s", description = "%s bypass API")
|
||||
public class %sController extends BaseBypassController {
|
||||
@Tag(name = "{{DOMAIN_CAP}}", description = "{{DISPLAY_NAME}} bypass API")
|
||||
public class {{DOMAIN_CAP}}Controller extends BaseBypassController {
|
||||
|
||||
private final %s %s;
|
||||
private final {{SERVICE_CLASS}} {{SERVICE_FIELD}};
|
||||
|
||||
@Operation(
|
||||
summary = "%s 조회",
|
||||
description = "S&P API에서 %s 데이터를 요청하고 응답을 그대로 반환합니다."
|
||||
summary = "{{DISPLAY_NAME}} 조회",
|
||||
description = "S&P API에서 {{DISPLAY_NAME}} 데이터를 요청하고 응답을 그대로 반환합니다."
|
||||
)
|
||||
%s
|
||||
public ResponseEntity<ApiResponse<%s>> get%sData(%s) {
|
||||
return execute(() -> %s.get%sData(%s));
|
||||
{{MAPPING_ANNOTATION}}
|
||||
public ResponseEntity<ApiResponse<{{RESPONSE_GENERIC}}>> get{{DOMAIN_CAP}}Data({{PARAM_ANNOTATIONS}}) {
|
||||
return execute(() -> {{SERVICE_FIELD}}.get{{DOMAIN_CAP}}Data({{SERVICE_CALL_ARGS}}));
|
||||
}
|
||||
}
|
||||
""".formatted(
|
||||
packageName,
|
||||
dtoPackage, dtoClass,
|
||||
servicePackage, serviceClass,
|
||||
listImport,
|
||||
pathVariableImport, requestParamImport, requestBodyImport,
|
||||
mappingAnnotation.equals("@PostMapping") ? "" : "",
|
||||
config.getDisplayName(),
|
||||
requestMappingPath,
|
||||
domainCap, config.getDisplayName(),
|
||||
domainCap,
|
||||
serviceClass, serviceField,
|
||||
config.getDisplayName(), config.getDisplayName(),
|
||||
mappingAnnotation + mappingPath,
|
||||
responseGeneric, domainCap,
|
||||
paramAnnotations.isEmpty() ? "" : paramAnnotations,
|
||||
serviceField, domainCap, serviceCallArgs
|
||||
);
|
||||
"""
|
||||
.replace("{{PACKAGE}}", packageName)
|
||||
.replace("{{DTO_IMPORT}}", dtoPackage + "." + dtoClass)
|
||||
.replace("{{SERVICE_IMPORT}}", servicePackage + "." + serviceClass)
|
||||
.replace("{{LIST_IMPORT}}", listImport)
|
||||
.replace("{{PATH_VARIABLE_IMPORT}}", pathVariableImport)
|
||||
.replace("{{REQUEST_PARAM_IMPORT}}", requestParamImport)
|
||||
.replace("{{REQUEST_BODY_IMPORT}}", requestBodyImport)
|
||||
.replace("{{DISPLAY_NAME}}", config.getDisplayName())
|
||||
.replace("{{DOMAIN_CAP}}", domainCap)
|
||||
.replace("{{REQUEST_MAPPING_PATH}}", requestMappingPath)
|
||||
.replace("{{SERVICE_CLASS}}", serviceClass)
|
||||
.replace("{{SERVICE_FIELD}}", serviceField)
|
||||
.replace("{{MAPPING_ANNOTATION}}", mappingAnnotation + mappingPath)
|
||||
.replace("{{RESPONSE_GENERIC}}", responseGeneric)
|
||||
.replace("{{PARAM_ANNOTATIONS}}", paramAnnotations.isEmpty() ? "" : paramAnnotations)
|
||||
.replace("{{SERVICE_CALL_ARGS}}", serviceCallArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,10 +267,6 @@ public class BypassCodeGenerator {
|
||||
*/
|
||||
private String buildFetchMethodCall(BypassApiConfig config, List<BypassApiParam> params,
|
||||
boolean isList, boolean isPost) {
|
||||
List<BypassApiParam> pathParams = params.stream()
|
||||
.filter(p -> "PATH".equalsIgnoreCase(p.getParamIn()))
|
||||
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
||||
.toList();
|
||||
List<BypassApiParam> queryParams = params.stream()
|
||||
.filter(p -> "QUERY".equalsIgnoreCase(p.getParamIn()))
|
||||
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
||||
@ -276,12 +274,9 @@ public class BypassCodeGenerator {
|
||||
|
||||
StringBuilder uriBuilder = new StringBuilder();
|
||||
uriBuilder.append("uri -> uri.path(getApiPath())");
|
||||
for (BypassApiParam p : pathParams) {
|
||||
// PATH 파라미터는 path()에 직접 치환되므로 별도 처리 불필요
|
||||
}
|
||||
for (BypassApiParam p : queryParams) {
|
||||
uriBuilder.append("\n .queryParam(\"%s\", %s)"
|
||||
.formatted(p.getParamName(), p.getParamName()));
|
||||
uriBuilder.append("\n .queryParam(\"")
|
||||
.append(p.getParamName()).append("\", ").append(p.getParamName()).append(")");
|
||||
}
|
||||
uriBuilder.append("\n .build()");
|
||||
|
||||
@ -292,10 +287,10 @@ public class BypassCodeGenerator {
|
||||
.filter(p -> "BODY".equalsIgnoreCase(p.getParamIn()))
|
||||
.findFirst().orElse(null);
|
||||
String bodyArg = bodyParam != null ? bodyParam.getParamName() : "null";
|
||||
return "return %s(%s, %s);".formatted(fetchName, bodyArg, uriBuilder);
|
||||
return "return " + fetchName + "(" + bodyArg + ", " + uriBuilder + ");";
|
||||
} else {
|
||||
fetchName = isList ? "fetchGetList" : "fetchGetOne";
|
||||
return "return %s(%s);".formatted(fetchName, uriBuilder);
|
||||
return "return " + fetchName + "(" + uriBuilder + ");";
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,24 +324,20 @@ public class BypassCodeGenerator {
|
||||
return params.stream()
|
||||
.sorted((a, b) -> Integer.compare(a.getSortOrder(), b.getSortOrder()))
|
||||
.map(p -> {
|
||||
String annotation;
|
||||
String description = p.getDescription() != null ? p.getDescription() : p.getParamName();
|
||||
switch (p.getParamIn().toUpperCase()) {
|
||||
case "PATH" -> annotation = """
|
||||
@Parameter(description = "%s")
|
||||
@PathVariable %s %s""".formatted(description, toJavaType(p.getParamType()), p.getParamName());
|
||||
case "BODY" -> annotation = """
|
||||
@Parameter(description = "%s")
|
||||
@RequestBody %s %s""".formatted(description, toJavaType(p.getParamType()), p.getParamName());
|
||||
String javaType = toJavaType(p.getParamType());
|
||||
String paramName = p.getParamName();
|
||||
return switch (p.getParamIn().toUpperCase()) {
|
||||
case "PATH" -> "@Parameter(description = \"" + description + "\")\n"
|
||||
+ " @PathVariable " + javaType + " " + paramName;
|
||||
case "BODY" -> "@Parameter(description = \"" + description + "\")\n"
|
||||
+ " @RequestBody " + javaType + " " + paramName;
|
||||
default -> {
|
||||
String required = Boolean.TRUE.equals(p.getRequired()) ? "true" : "false";
|
||||
annotation = """
|
||||
@Parameter(description = "%s")
|
||||
@RequestParam(required = %s) %s %s""".formatted(
|
||||
description, required, toJavaType(p.getParamType()), p.getParamName());
|
||||
yield "@Parameter(description = \"" + description + "\")\n"
|
||||
+ " @RequestParam(required = " + required + ") " + javaType + " " + paramName;
|
||||
}
|
||||
}
|
||||
return annotation;
|
||||
};
|
||||
})
|
||||
.collect(Collectors.joining(",\n "));
|
||||
}
|
||||
@ -365,7 +356,7 @@ public class BypassCodeGenerator {
|
||||
String path = pathParams.stream()
|
||||
.map(p -> "{" + p.getParamName() + "}")
|
||||
.collect(Collectors.joining("/", "/", ""));
|
||||
return "(\"%s\")".formatted(path);
|
||||
return "(\"" + path + "\")";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
불러오는 중...
Reference in New Issue
Block a user