diff --git a/README.md b/README.md index 9755253..30ca7ab 100644 --- a/README.md +++ b/README.md @@ -1 +1,245 @@ -### adds API +# adds API + +### swagger + +[API URL](http://localhost:8081/swagger-ui.html) + +### API 결과 수신 + +* 정상 수신 + +```java + +@Schema(name = "ApiBaseResponse", description = "Api 결과 DTO") +@Data +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@JsonRootName("result") +//@JsonInclude(JsonInclude.Include.NON_NULL) +public class ApiBaseResponse { + @Schema(requiredMode = REQUIRED, title = "결과 코드", description = "결과 코드", example = "200") + private Integer code = ResultCode.SUCCESS.getStatusCode(); + + @Schema(requiredMode = REQUIRED, title = "결과 메세지", description = "결과 메세제-에러인 경우 필수", example = " ") + private String message = ResultCode.SUCCESS.getMessage(); + + @Schema(requiredMode = REQUIRED, title = "API 실행 결과", description = "정상 실행시 결과 값", example = " ") + private T data; + + @Schema(requiredMode = REQUIRED, title = "실행 결과 건수", description = "실행 결과 건수", example = " ") + private int totalCount; + + @Schema(requiredMode = REQUIRED, title = "API 실행 성공 or 실패", description = "API 실행 성공(true) or 실패(false)", example = " ") + private Boolean success = Objects.equals(code, ResultCode.SUCCESS.getStatusCode()); + + @Schema(requiredMode = REQUIRED, title = "API 실행 시간", description = "API 실행 시간", example = " ") + @Builder.Default + private String responseTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + public static ApiBaseResponse of() { + return new ApiBaseResponse<>(); + } + + public static ApiBaseResponse of(T data) { + return new ApiBaseResponse<>(data); + } + + public static ApiBaseResponse empty() { + return new ApiBaseResponse<>(null, ResultCode.NO_CONTENT); + } + + private ApiBaseResponse(T data) { + + if (ObjectUtils.isEmpty(data)) { + this.code = ResultCode.NO_CONTENT.getStatusCode(); + this.message = ResultCode.NO_CONTENT.getMessage(); + this.data = null; + } else { + this.code = ResultCode.SUCCESS.getStatusCode(); + this.message = ResultCode.findByStatusCode(code).getMessage(); + this.data = data; + } + } + + private ApiBaseResponse(T data, ResultCode resultCode) { + this.success = true; + this.code = resultCode.getStatusCode(); + this.message = resultCode.getMessage(); + this.data = null; + } + + public ApiBaseResponse(Integer code, String message) { + this.code = code; + this.message = message; + } + + public ApiBaseResponse(Integer code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + public int getTotalCount() { + if (data == null) { + this.totalCount = 0; + + } else { + + if (Collection.class.isAssignableFrom(data.getClass())) { + this.totalCount = ((Collection)data).size(); + + } else { + this.totalCount = 1; + } + } + return totalCount; + } +} +``` + +* 정상 수신 + +```json +{ + "success": true, + "code": 200, + "message": "성공", + "data": { + "token_status": "USED", + "token_expires_at": 1624344762, + "token_used_at": 0, + "doc_box_sent_at": 0, + "doc_box_received_at": 0, + "authenticated_at": 0, + "user_notified_at": 0, + "payload": "payload 파라미터 입니다.", + "signed_at": 0 + }, + "totalCount": 1, + "responseTime": null +} +``` + +* 에러 수신 + +```json +{ + "success": false, + "code": 400, + "data": null, + "message": "로그인 정보가 올바르지 않습니다.", + "totalCount": 0, + "responseTime": "2024-05-20 09:34:20" +} +``` + +* API 호출 결과가 서버등(네트웍장애)의 장애인 경우를 제외 하고 + 예외로 return 되는 경우는 없다(발생시 공통팀에 반드시 알려 줄 것) + +```js + $.ajax({ + url: url, + type: method, + contentType: "application/json; charset=utf-8", + dataType: "json", + data: JSON.stringify(data), + beforeSend: (xhr) => { + //xhr.setRequestHeader(header, token); + $("#loading").show(); + + }, + success: function (res, textStatus) { + console.log(JSON.stringify(res)); + if (res.success) { + //정상 응답 + $("#resData").text(res.data) + } else { + //에러 응답 + $("#errData").text(JSON.stringify(res)); + } + }, + error: function (data) { + // 여기로 오는 경우 공통팀에 알려 주세요 + alert("점검필요-error로 return", data.responseText); + }, + complete: () => { + $("#loading").hide(); + } +}); +``` + +### API(Restful call) validation + +* Controller 단에서 @Validated 사용으로 처리 가능 +* But, 이경우 API 로그를 남기기 위해 Service 단에서 체크 하도록 컨트롤러 단에서는 유효성 체크 skip + +### spring validation + +```text +@Valid는 Java, @Validated는 Spring에서 지원하는 어노테이션 +@Validated는 @Valid의 기능을 포함하고, 유효성을 검토할 그룹을 지정할 수 있는 기능이 추가됨 +``` + +```java +@Null // null만 혀용 +@NotNull // null을 허용하지 않습니다. "", " "는 허용 +@NotEmpty // null, ""을 허용하지 않습니다. " "는 허용 +@NotBlank // null, "", " " 모두 허용하지 않습니다. + +@Email // 이메일 형식을 검사합니다. 다만 ""의 경우를 통과 시킵니다 +@Pattern(regexp =) // 정규식을 검사할 때 사용됩니다. +@Size(min =, max =) // 길이를 제한할 때 사용됩니다. + +@Max(value =) // value 이하의 값을 받을 때 사용됩니다. +@Min(value =) // value 이상의 값을 받을 때 사용됩니다. + +@Positive // 값을 양수로 제한합니다. +@PositiveOrZero // 값을 양수와 0만 가능하도록 제한합니다. + +@Negative // 값을 음수로 제한합니다. +@NegativeOrZero // 값을 음수와 0만 가능하도록 제한합니다. + +@Future // 현재보다 미래 +@Past // 현재보다 과거 + +@AssertFalse // false 여부, null은 체크하지 않습니다. +@AssertTrue // true 여부, null은 체크하지 않습니다. +``` + +### intellij devtools 활성 + +```text +1. IntelliJ - Preferencs… +2. 컴파일러 - build project automatically(프로젝트 자동 빌드) 체크 +3. Advanced Settings > Compiler + Allow auto-make to start even if developed application is current running + (개발된 애플리케이션이 현재 실행 중인 경우에도 auto-make가 시작되도록 허용) 체크 +# 1 ~ 3항 까지 설정후 에도 안되는 경우만 4번 설정 +4. 서버설정 : Edit Configurations... + Modfy Options > On Update Action > Update Resources + +``` + +### ens-api 배포 및 run : profile에 따라 local|dev|prod + +```shell +# jdk : azul-17.0.1 +# 프로젝트 root 폴더로 이동 : adds-api +# 패키지 생성 : local|dev|prod +$ mvnw clean package -P local + +# 실행 : 프로젝트폴더//target에 생성된 jar파일 실행 +$ c:\tools\java\azul-17.0.1\java -jar -Dspring.profiles.active=local .\adds-api.jar + +# mvn 명령어 설명 +# -pl [모듈명] : 모듈명의 프로젝트만 빌드 +# -am : 의존성 있는 프로젝트 함께 빌드 - C가 A를 디펜던시로 가지고 있으며 C를 빌드하면 A -> C 순으로 빌드 +$ mvnw clean package -pl mens-api -am -P local +# -amd : 의존성 있는 타 프로젝트 빌드 - C가 A를 디펜던시로 가지고 있는 경우 A를 빌드 하면 A -> C 순으로 빌드 +$ mvnw clean package -pl mens-core -amd -P local + +mvn clean package -pl mens-batch -am -P prod + +``` + diff --git a/pom.xml b/pom.xml index a0e195d..26357d6 100644 --- a/pom.xml +++ b/pom.xml @@ -9,10 +9,10 @@ cokr.xit - adds - 0.0.1-SNAPSHOT - adds - xit adds system + adds-api + 0.0.1 + adds-api + xit adds api system 17 @@ -205,6 +205,9 @@ + install + ${basedir}/target + ${project.name} org.springframework.boot @@ -229,4 +232,39 @@ + + + + local + + local + + + true + + + + + + dev + + dev + + + false + + + + + + prod + + prod + + + false + + + + diff --git a/shell/backupApi.sh b/shell/backupApi.sh new file mode 100644 index 0000000..e5691e5 --- /dev/null +++ b/shell/backupApi.sh @@ -0,0 +1,22 @@ +#!/bin/sh +if [ $# -ne 1 ]; then + echo "-----------------------------------" + echo " Undefined parameter" + echo "./backupApi.sh [application name]" + echo "-----------------------------------" + exit 1 +fi + +if [ ! -f "../$1.jar" ]; then + echo "===================================" + echo " $1.jar file not exist" + echo "===================================" + exit 1 +fi + +source /applications/adds/bin/stopApi.sh $1 + +echo "-----------------------------------" +echo " $1 application backup success!" +echo "-----------------------------------" +mv /applications/adds/$1.jar /applications/adds/$1.jar_backup diff --git a/shell/deployApi.sh b/shell/deployApi.sh new file mode 100644 index 0000000..dbc0f25 --- /dev/null +++ b/shell/deployApi.sh @@ -0,0 +1,18 @@ +#!/bin/sh +if [ $# -ne 1 ]; then + echo "-----------------------------------" + echo " Undefined parameter" + echo "./deployApi.sh [application name]" + echo "-----------------------------------" + exit 1 +fi + +if [ ! -f "../$1.jar" ]; then + echo "===================================" + echo " $1.jar file not exist" + echo "===================================" + exit 1 +fi + +mv /applications/adds/$1.jar /applications/adds/$1.jar_backup +cp /var/lib/jenkins/workspace/ADDS-API/adds-api/target/$1.jar /applications/adds/$1.jar diff --git a/shell/startApi.sh b/shell/startApi.sh new file mode 100644 index 0000000..b270fd5 --- /dev/null +++ b/shell/startApi.sh @@ -0,0 +1,22 @@ +#!/bin/sh +if [ $# -ne 1 ]; then + echo "-----------------------------------" + echo " Undefined parameter" + echo "./startApi.sh [application name]" + echo "-----------------------------------" + exit 1 +fi + +if [ ! -f "../$1.jar" ]; then + echo "===================================" + echo " $1.jar file not exist" + echo "===================================" + exit 1 +fi + +echo "================================" +echo " $1 application start" +echo "================================" +JAVA_HOME=/lib/jvm/java-17-openjdk +export JAVA_HOME +nohup $JAVA_HOME/bin/java -Dspring.profiles.active=prod -jar /applications/adds/$1.jar > /dev/null & diff --git a/shell/stopApi.sh b/shell/stopApi.sh new file mode 100644 index 0000000..43b3f0b --- /dev/null +++ b/shell/stopApi.sh @@ -0,0 +1,22 @@ +#!/bin/sh +if [ $# -ne 1 ]; then + echo "-----------------------------------" + echo " Undefined parameter" + echo "./stopApi.sh [application name]" + echo "-----------------------------------" + exit 1 +fi + +PID=`ps -ef | grep java | grep $1 | awk '{print $2}'` +echo "Process ID: $PID" +if [ -z $PID ]; then + echo "==============================" + echo " No $1 deamon is running" + echo "==============================" +else + echo "Kill $1[$PID] process" + kill $PID + echo "===============================" + echo " $1[$PID] application stop" + echo "===============================" +fi diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 86315bf..014a0e5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -22,7 +22,7 @@ server: spring: application: - name: xit-adds + name: adds-api profiles: active: '@springProfilesActive@' include: