From 7f94b721e2b54ed9fa77226d3086744db3ce18f4 Mon Sep 17 00:00:00 2001 From: An-JiYun <81212388+An-JiYun@users.noreply.github.com> Date: Mon, 10 Apr 2023 16:37:59 +0900 Subject: [PATCH 1/2] Update deployment.yml --- .github/workflows/deployment.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 2be1220..51ce10a 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -46,10 +46,10 @@ jobs: - name: Send jar to remote server uses: appleboy/scp-action@master with: - host: {나의 public ip} - username: {나의 userName} + host: 34.64.50.6 + username: agy0512 source: "real_coding_server-0.0.1-SNAPSHOT.jar" - target: "/home/{나의 userName}" + target: "/home/agy0512" key: ${{ secrets.PRIVATE_KEY }} run-app: @@ -61,16 +61,16 @@ jobs: - name: Move deploy.sh uses: appleboy/scp-action@master with: - host: {나의 public ip} - username: {나의 userName} + host: 34.64.50.6 + username: agy0512 source: "deploy.sh" - target: "/home/{나의 userName}" + target: "/home/agy0512" key: ${{ secrets.PRIVATE_KEY }} - name: Execute script uses: appleboy/ssh-action@master with: - username: {나의 userName} - host: {나의 public ip} + username: agy0512 + host: 34.64.50.6 key: ${{ secrets.PRIVATE_KEY }} script_stop: true - script: cd /home/{나의 userName} && chmod +x deploy.sh && ./deploy.sh + script: cd /home/agy0512 && chmod +x deploy.sh && ./deploy.sh From 8d788a7e164b6a135b3f92bc7a44cb033175fe90 Mon Sep 17 00:00:00 2001 From: An-JiYun Date: Mon, 17 Apr 2023 19:46:36 +0900 Subject: [PATCH 2/2] test --- ad/.gitignore | 42 +++++++++++++++ ad/build.gradle | 8 +++ ad/src/main/java/com/cnu/ad/Main.java | 12 +++++ .../com/cnu/ad/controller/AdController.java | 18 +++++++ .../java/com/cnu/ad/model/Advertisement.java | 9 ++++ .../java/com/cnu/ad/service/AdService.java | 22 ++++++++ ad/src/main/resources/application.yml | 2 + build.gradle | 39 ++++++++------ post/.gitignore | 42 +++++++++++++++ post/build.gradle | 18 +++++++ post/src/main/java/com/cnu/post/Main.java | 10 ++++ .../cnu/post/client/AdvertisementClient.java | 29 ++++++++++ .../com/cnu/post/config/WebMVCConfig.java | 16 ++++++ .../cnu/post/controller/PostController.java | 41 ++++++++++++++ .../post/controller/ProjectController.java | 46 ++++++++++++++++ .../java/com/cnu/post/entity/BaseEntity.java | 24 +++++++++ .../main/java/com/cnu/post/entity/Post.java | 33 ++++++++++++ .../java/com/cnu/post/entity/Project.java | 54 +++++++++++++++++++ .../com/cnu/post/model/Advertisement.java | 9 ++++ .../cnu/post/model/request/PostRequest.java | 24 +++++++++ .../post/model/request/ProjectRequest.java | 32 +++++++++++ .../cnu/post/model/response/PostResponse.java | 10 ++++ .../java/com/cnu/post/model/type/Tag.java | 8 +++ .../cnu/post/repository/PostRepository.java | 13 +++++ .../post/repository/ProjectRepository.java | 13 +++++ .../com/cnu/post/service/PostService.java | 48 +++++++++++++++++ .../com/cnu/post/service/ProjectService.java | 49 +++++++++++++++++ post/src/main/resources/application.yml | 31 +++++++++++ settings.gradle.kts | 2 + 29 files changed, 687 insertions(+), 17 deletions(-) create mode 100644 ad/.gitignore create mode 100644 ad/build.gradle create mode 100644 ad/src/main/java/com/cnu/ad/Main.java create mode 100644 ad/src/main/java/com/cnu/ad/controller/AdController.java create mode 100644 ad/src/main/java/com/cnu/ad/model/Advertisement.java create mode 100644 ad/src/main/java/com/cnu/ad/service/AdService.java create mode 100644 ad/src/main/resources/application.yml create mode 100644 post/.gitignore create mode 100644 post/build.gradle create mode 100644 post/src/main/java/com/cnu/post/Main.java create mode 100644 post/src/main/java/com/cnu/post/client/AdvertisementClient.java create mode 100644 post/src/main/java/com/cnu/post/config/WebMVCConfig.java create mode 100644 post/src/main/java/com/cnu/post/controller/PostController.java create mode 100644 post/src/main/java/com/cnu/post/controller/ProjectController.java create mode 100644 post/src/main/java/com/cnu/post/entity/BaseEntity.java create mode 100644 post/src/main/java/com/cnu/post/entity/Post.java create mode 100644 post/src/main/java/com/cnu/post/entity/Project.java create mode 100644 post/src/main/java/com/cnu/post/model/Advertisement.java create mode 100644 post/src/main/java/com/cnu/post/model/request/PostRequest.java create mode 100644 post/src/main/java/com/cnu/post/model/request/ProjectRequest.java create mode 100644 post/src/main/java/com/cnu/post/model/response/PostResponse.java create mode 100644 post/src/main/java/com/cnu/post/model/type/Tag.java create mode 100644 post/src/main/java/com/cnu/post/repository/PostRepository.java create mode 100644 post/src/main/java/com/cnu/post/repository/ProjectRepository.java create mode 100644 post/src/main/java/com/cnu/post/service/PostService.java create mode 100644 post/src/main/java/com/cnu/post/service/ProjectService.java create mode 100644 post/src/main/resources/application.yml diff --git a/ad/.gitignore b/ad/.gitignore new file mode 100644 index 0000000..b63da45 --- /dev/null +++ b/ad/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/ad/build.gradle b/ad/build.gradle new file mode 100644 index 0000000..0df9ab3 --- /dev/null +++ b/ad/build.gradle @@ -0,0 +1,8 @@ +bootJar { + enabled = true +} +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} \ No newline at end of file diff --git a/ad/src/main/java/com/cnu/ad/Main.java b/ad/src/main/java/com/cnu/ad/Main.java new file mode 100644 index 0000000..b4ece29 --- /dev/null +++ b/ad/src/main/java/com/cnu/ad/Main.java @@ -0,0 +1,12 @@ +package com.cnu.ad; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} \ No newline at end of file diff --git a/ad/src/main/java/com/cnu/ad/controller/AdController.java b/ad/src/main/java/com/cnu/ad/controller/AdController.java new file mode 100644 index 0000000..856e983 --- /dev/null +++ b/ad/src/main/java/com/cnu/ad/controller/AdController.java @@ -0,0 +1,18 @@ +package com.cnu.ad.controller; + +import com.cnu.ad.model.Advertisement; +import com.cnu.ad.service.AdService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/ads") +@RequiredArgsConstructor +public class AdController { + + private final AdService adService; + @GetMapping + public Advertisement getAd(){return adService.getAd();} +} \ No newline at end of file diff --git a/ad/src/main/java/com/cnu/ad/model/Advertisement.java b/ad/src/main/java/com/cnu/ad/model/Advertisement.java new file mode 100644 index 0000000..311efc2 --- /dev/null +++ b/ad/src/main/java/com/cnu/ad/model/Advertisement.java @@ -0,0 +1,9 @@ +package com.cnu.ad.model; + +public record Advertisement( + String title, + String description, + String imageUrl, + String siteUrl +) { +} \ No newline at end of file diff --git a/ad/src/main/java/com/cnu/ad/service/AdService.java b/ad/src/main/java/com/cnu/ad/service/AdService.java new file mode 100644 index 0000000..f36587e --- /dev/null +++ b/ad/src/main/java/com/cnu/ad/service/AdService.java @@ -0,0 +1,22 @@ +package com.cnu.ad.service; + +import com.cnu.ad.model.Advertisement; +import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Random; + +@Service +public class AdService { + private final List ads = List.of( + new Advertisement("구글 개발자 채용", "구글코리아에서 우수한 인재들을 모집합니다", "https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", "https://www.google.com"), + new Advertisement("나이키 멤버십 빅 세일", "오직 나이키 멤버십을 위한 단 3일! 새학기 설레는 마음을 조던과 함께", "https://www.google.com/imgres?imgurl=https%3A%2F%2Fcdn.eyesmag.com%2Fcontent%2Fuploads%2FsliderImages%2F2020%2F12%2F24%2Fair-jordan-1-ko-chicago-01-406abe1e-0ef2-4b71-b479-7716fdb60630.jpg&tbnid=QyvBKpDwO_UoBM&vet=12ahUKEwjA0KXhva7-AhXnplYBHaWYA2cQMygAegUIARCMAg..i&imgrefurl=https%3A%2F%2Fwww.eyesmag.com%2Fposts%2F133372%2Fair-jordan-1-ko-chicago&docid=sYwmVvloa4MEMM&w=903&h=600&q=%EC%A1%B0%EB%8D%98&ved=2ahUKEwjA0KXhva7-AhXnplYBHaWYA2cQMygAegUIARCMAg", "https://www.nike.com/kr"), + new Advertisement("충남대학교 컴퓨터공학 대학원생 상반기 모집", "충남대학교 컴퓨터공학 대학원생 상반기 모집을 시작합니다. 자세한 사항은 홈페이지를 참고해주세요.", "https://www.google.com/imgres?imgurl=https%3A%2F%2Fplus.cnu.ac.kr%2FUpl%2F_board%2Fsub07_0703%2Fsub07_0703_0_1625820900.jpg&tbnid=25yHUTidQqon-M&vet=12ahUKEwinxujGva7-AhVVplYBHfSXBE4QMygDegUIARDMAQ..i&imgrefurl=https%3A%2F%2Fplus.cnu.ac.kr%2F_prog%2F_board%2F%3Fmode%3DV%26no%3D2480211%26code%3Dsub07_0703%26site_dvs_cd%3Dkr%26menu_dvs_cd%3D0703%26skey%3D%26sval%3D%26site_dvs%3D%26ntt_tag%3D%26GotoPage%3D&docid=nUktNpfW-pncMM&w=2048&h=1215&q=%EC%B6%A9%EB%82%A8%EB%8C%80%ED%95%99%EA%B5%90&ved=2ahUKEwinxujGva7-AhVVplYBHfSXBE4QMygDegUIARDMAQ", "https://plus.cnu.ac.kr/html/kr/"), + new Advertisement("쿠팡 와우회원 1만원 할인", "오직 쿠팡 와우회원에게만 주어지는 마지막 기회! 1만원 할인 쿠폰을 받아보세요.", "https://www.google.com/imgres?imgurl=https%3A%2F%2Fimage10.coupangcdn.com%2Fimage%2Fmobile%2Fv3%2Fimg_fb_like.png&tbnid=9tak8zDG-dGaMM&vet=12ahUKEwip6-2Rvq7-AhVflFYBHRiADfwQMygAegUIARDbAQ..i&imgrefurl=https%3A%2F%2Fwww.coupang.com%2F&docid=Qqxdvidhpoqf-M&w=512&h=512&itg=1&q=%EC%BF%A0%ED%8C%A1&ved=2ahUKEwip6-2Rvq7-AhVflFYBHRiADfwQMygAegUIARDbAQ", "https://www.coupang.com/"), + new Advertisement("네이버 쇼핑에서 후기쓰고 포인트 적립하자~", "믿고보는 네이버 쇼핑 후기! 후기쓰고 포인트 적립하자~", "https://www.google.com/imgres?imgurl=https%3A%2F%2Fcenter.shopping.naver.com%2Fimg%2Fimg_main_carousel.jpg&tbnid=4w-j7Xc4PzwJ5M&vet=12ahUKEwjw--fKvq7-AhV9klYBHQ8QAZYQMygAegUIARCIAQ..i&imgrefurl=https%3A%2F%2Fcenter.shopping.naver.com%2F&docid=oZ5oXq3Zhw_iFM&w=2050&h=1478&q=%EB%84%A4%EC%9D%B4%EB%B2%84%20%EC%87%BC%ED%95%91&ved=2ahUKEwjw--fKvq7-AhV9klYBHQ8QAZYQMygAegUIARCIAQ", "https://www.naver.com/"), + new Advertisement("시험기간 이벤트 참여하고 간식받자!", "공부하기도 힘든데 배는 고프지 말아야지! 시험기간 이벤트 참여하고 간식받자!", "https://www.google.com/imgres?imgurl=https%3A%2F%2Fcenter.shopping.naver.com%2Fimg%2Fimg_main_carousel.jpg&tbnid=4w-j7Xc4PzwJ5M&vet=12ahUKEwjw--fKvq7-AhV9klYBHQ8QAZYQMygAegUIARCIAQ..i&imgrefurl=https%3A%2F%2Fcenter.shopping.naver.com%2F&docid=oZ5oXq3Zhw_iFM&w=2050&h=1478&q=%EB%84%A4%EC%9D%B4%EB%B2%84%20%EC%87%BC%ED%95%91&ved=2ahUKEwjw--fKvq7-AhV9klYBHQ8QAZYQMygAegUIARCIAQ", "https://www.naver.com/") + ); + public Advertisement getAd(){ + int randomIndex = new Random().nextInt(ads.size()); + return ads.get(randomIndex); + } +} \ No newline at end of file diff --git a/ad/src/main/resources/application.yml b/ad/src/main/resources/application.yml new file mode 100644 index 0000000..5503e49 --- /dev/null +++ b/ad/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 9090 diff --git a/build.gradle b/build.gradle index 4619d59..84d60e2 100644 --- a/build.gradle +++ b/build.gradle @@ -14,25 +14,30 @@ configurations { } } -repositories { - mavenCentral() +allprojects { + repositories { + mavenCentral() + } } -dependencies { - implementation 'org.springframework.boot:spring-boot-starter' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' //TODO: annotation build 활성화 언급하기 - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' - implementation 'org.springframework.boot:spring-boot-starter-validation:3.0.5' +subprojects { + apply plugin: 'java' + apply plugin: 'org.springframework.boot' + apply plugin: 'io.spring.dependency-management' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'com.h2database:h2' + group = 'com.cnu' + version = '0.0.1-SNAPSHOT' + sourceCompatibility = '17' - testImplementation 'org.springframework.boot:spring-boot-starter-test' -} + dependencies { + // lombok + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' //TODO: annotation build 활성화 언급하기 -tasks.named('test') { - useJUnitPlatform() -} + // test + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation('org.springframework.boot:spring-boot-starter-test') { + exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' + } + } +} \ No newline at end of file diff --git a/post/.gitignore b/post/.gitignore new file mode 100644 index 0000000..b63da45 --- /dev/null +++ b/post/.gitignore @@ -0,0 +1,42 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/post/build.gradle b/post/build.gradle new file mode 100644 index 0000000..3a0f255 --- /dev/null +++ b/post/build.gradle @@ -0,0 +1,18 @@ +bootJar { + enabled = true +} +dependencies { + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + + // db + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'com.h2database:h2' + + // Resilience4j + implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.0.2' + implementation 'org.springframework.boot:spring-boot-starter-aop' + implementation project(path: ':') + implementation project(path: ':') +} \ No newline at end of file diff --git a/post/src/main/java/com/cnu/post/Main.java b/post/src/main/java/com/cnu/post/Main.java new file mode 100644 index 0000000..2c4001f --- /dev/null +++ b/post/src/main/java/com/cnu/post/Main.java @@ -0,0 +1,10 @@ +package com.cnu.post; + +import org.springframework.boot.SpringApplication; + +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + + } +} \ No newline at end of file diff --git a/post/src/main/java/com/cnu/post/client/AdvertisementClient.java b/post/src/main/java/com/cnu/post/client/AdvertisementClient.java new file mode 100644 index 0000000..5dd741d --- /dev/null +++ b/post/src/main/java/com/cnu/post/client/AdvertisementClient.java @@ -0,0 +1,29 @@ +package com.cnu.post.client; + +import com.cnu.post.model.Advertisement; +import io.github.resilience4j.circuitbreaker.CallNotPermittedException; +import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component + +public class AdvertisementClient { + RestTemplate restTemplate = new RestTemplate(); + private static final Advertisement AD_FALLBACK = new Advertisement( + "Devblog로 개발 블로그를 만들어보자", + "Devblog는 개발자들을 위한 블로그 플랫폼입니다. Devblog로 개발 블로그를 만들어보세요!", + "https://devblog.com/images/og-image.png", + "https://devblog.com" + ); + + + @CircuitBreaker(name = "ad",fallbackMethod = "fallback") + public Advertisement getAd() { + return restTemplate.getForObject("http://localhost:9090/ads", Advertisement.class); + } + + private Advertisement fallback(CallNotPermittedException e) { + return AD_FALLBACK; + } +} \ No newline at end of file diff --git a/post/src/main/java/com/cnu/post/config/WebMVCConfig.java b/post/src/main/java/com/cnu/post/config/WebMVCConfig.java new file mode 100644 index 0000000..1f38c1e --- /dev/null +++ b/post/src/main/java/com/cnu/post/config/WebMVCConfig.java @@ -0,0 +1,16 @@ +package com.cnu.post.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebMVCConfig implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowCredentials(true) + .allowedMethods("*") + .allowedOriginPatterns("*"); + } +} diff --git a/post/src/main/java/com/cnu/post/controller/PostController.java b/post/src/main/java/com/cnu/post/controller/PostController.java new file mode 100644 index 0000000..9f74a3c --- /dev/null +++ b/post/src/main/java/com/cnu/post/controller/PostController.java @@ -0,0 +1,41 @@ +package com.cnu.post.controller; + +import com.cnu.post.entity.Post; +import com.cnu.post.model.request.PostRequest; +import com.cnu.post.model.response.PostResponse; +import com.cnu.post.service.PostService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/posts") +@RequiredArgsConstructor +public class PostController { + + private final PostService postService; + @PostMapping + public ResponseEntity createPost(@RequestBody PostRequest postRequest){ + return ResponseEntity.ok(postService.createPost(postRequest)); + } + @GetMapping + public ResponseEntity> getPosts(){ + return ResponseEntity.ok(postService.getPosts()); + } + @GetMapping("/{postId}") + public ResponseEntity getPost(@PathVariable("postId") Integer postId){ + return ResponseEntity.ok(postService.getPost(postId).orElse(null)); + } + @PutMapping("/{postId}") + public ResponseEntity updatePost(@PathVariable("postId") Integer postId,@RequestBody PostRequest postRequest){ + return ResponseEntity.ok(postService.updatePost(postId, postRequest).orElse(null)); + } + + @DeleteMapping("/{postId}") + public ResponseEntity deletePost(@PathVariable("postId") Integer postId){ + postService.deletePost(postId); + return ResponseEntity.noContent().build(); + } +} \ No newline at end of file diff --git a/post/src/main/java/com/cnu/post/controller/ProjectController.java b/post/src/main/java/com/cnu/post/controller/ProjectController.java new file mode 100644 index 0000000..f25358b --- /dev/null +++ b/post/src/main/java/com/cnu/post/controller/ProjectController.java @@ -0,0 +1,46 @@ +package com.cnu.post.controller; + +import com.cnu.post.entity.Project; +import com.cnu.post.model.request.ProjectRequest; +//import com.cnu.post.model.response.ProjectResponse; +import com.cnu.post.service.ProjectService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/projects") +@RequiredArgsConstructor +public class ProjectController { + private final ProjectService projectService; + + @PostMapping + public ResponseEntity createProject(@RequestBody ProjectRequest projectRequest) { + return ResponseEntity.ok(projectService.createProject(projectRequest)); + } + + @GetMapping + public ResponseEntity> getProjects() { + return ResponseEntity.ok(projectService.getProjects()); + } + + @GetMapping("/{projectId}") + public ResponseEntity getProject(@PathVariable("projectId") Integer projectId) { + return ResponseEntity.ok(projectService.getProject(projectId).orElse(null)); + } + + @PutMapping("/{projectId}") + public ResponseEntity updatePost(@PathVariable("projectId")Integer projectId, + @RequestBody ProjectRequest projectRequest) { + return ResponseEntity.ok(projectService.updateProject(projectId, projectRequest).orElse(null)); + } + + @DeleteMapping("/{projecttId}") + public ResponseEntity deleteProject(@PathVariable("projectId") Integer projectId) { + projectService.deleteProject(projectId); + + return ResponseEntity.noContent().build(); + } +} \ No newline at end of file diff --git a/post/src/main/java/com/cnu/post/entity/BaseEntity.java b/post/src/main/java/com/cnu/post/entity/BaseEntity.java new file mode 100644 index 0000000..db34549 --- /dev/null +++ b/post/src/main/java/com/cnu/post/entity/BaseEntity.java @@ -0,0 +1,24 @@ +package com.cnu.post.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public class BaseEntity { + @Column + @CreatedDate + private LocalDateTime createdAt; + + @Column + @LastModifiedDate + private LocalDateTime updatedAt; +} diff --git a/post/src/main/java/com/cnu/post/entity/Post.java b/post/src/main/java/com/cnu/post/entity/Post.java new file mode 100644 index 0000000..d023c2a --- /dev/null +++ b/post/src/main/java/com/cnu/post/entity/Post.java @@ -0,0 +1,33 @@ +package com.cnu.post.entity; + +import com.cnu.post.model.type.Tag; +import jakarta.persistence.*; +import lombok.*; + +@Getter +@Entity(name = "posts") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Post extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + @Setter + private String title; + + @Column + @Setter + private String contents; + + @Setter + @Enumerated(EnumType.STRING) + private Tag tag; + + @Builder + public Post(String title, String contents, Tag tag) { + this.title = title; + this.contents = contents; + this.tag = tag; + } +} diff --git a/post/src/main/java/com/cnu/post/entity/Project.java b/post/src/main/java/com/cnu/post/entity/Project.java new file mode 100644 index 0000000..918cfb6 --- /dev/null +++ b/post/src/main/java/com/cnu/post/entity/Project.java @@ -0,0 +1,54 @@ +package com.cnu.post.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDateTime; + +@Getter +@Entity(name = "projects") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Project extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column + @Setter + private String title; + + @Column + @Setter + private String summary; + + @Column + @Setter + private String description; + + @Column + @Setter + private LocalDateTime startDate; + + @Column + @Setter + private LocalDateTime endDate; + + @Column + @Setter + private Boolean isInProgress; + + @Builder + private Project(String title, + String summary, + String description, + LocalDateTime startDate, + LocalDateTime endDate, + Boolean isInProgress) { + this.title = title; + this.summary = summary; + this.description = description; + this.startDate = startDate; + this.endDate = endDate; + this.isInProgress = isInProgress; + } +} diff --git a/post/src/main/java/com/cnu/post/model/Advertisement.java b/post/src/main/java/com/cnu/post/model/Advertisement.java new file mode 100644 index 0000000..78ff031 --- /dev/null +++ b/post/src/main/java/com/cnu/post/model/Advertisement.java @@ -0,0 +1,9 @@ +package com.cnu.post.model; + +public record Advertisement( + String title, + String description, + String imageUrl, + String siteUrl +) { +} diff --git a/post/src/main/java/com/cnu/post/model/request/PostRequest.java b/post/src/main/java/com/cnu/post/model/request/PostRequest.java new file mode 100644 index 0000000..c738cd3 --- /dev/null +++ b/post/src/main/java/com/cnu/post/model/request/PostRequest.java @@ -0,0 +1,24 @@ +package com.cnu.post.model.request; + + +import com.cnu.post.entity.Post; +import com.cnu.post.model.type.Tag; +import jakarta.validation.Valid; +import lombok.Getter; + +@Getter +public class PostRequest { + @Valid + private String title; + private String contents; + + private Tag tag; + + public Post toEntity() { + return Post.builder() + .title(title) + .contents(contents) + .tag(tag) + .build(); + } +} diff --git a/post/src/main/java/com/cnu/post/model/request/ProjectRequest.java b/post/src/main/java/com/cnu/post/model/request/ProjectRequest.java new file mode 100644 index 0000000..697ec4f --- /dev/null +++ b/post/src/main/java/com/cnu/post/model/request/ProjectRequest.java @@ -0,0 +1,32 @@ +package com.cnu.post.model.request; + +import com.cnu.post.entity.Project; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +public class ProjectRequest { + private String title; + + private String summary; + + private String description; + + private LocalDateTime startDate; + + private LocalDateTime endDate; + + private Boolean isInProgress; + + public Project toEntity() { + return Project.builder() + .title(title) + .summary(summary) + .description(description) + .startDate(startDate) + .endDate(endDate) + .isInProgress(isInProgress) + .build(); + } +} diff --git a/post/src/main/java/com/cnu/post/model/response/PostResponse.java b/post/src/main/java/com/cnu/post/model/response/PostResponse.java new file mode 100644 index 0000000..afd6fb6 --- /dev/null +++ b/post/src/main/java/com/cnu/post/model/response/PostResponse.java @@ -0,0 +1,10 @@ +package com.cnu.post.model.response; + +import com.cnu.post.entity.Post; +import com.cnu.post.model.Advertisement; + +public record PostResponse( + Post post, + Advertisement advertisement +) { +} diff --git a/post/src/main/java/com/cnu/post/model/type/Tag.java b/post/src/main/java/com/cnu/post/model/type/Tag.java new file mode 100644 index 0000000..8d48a79 --- /dev/null +++ b/post/src/main/java/com/cnu/post/model/type/Tag.java @@ -0,0 +1,8 @@ +package com.cnu.post.model.type; + +public enum Tag { + JAVA, + SPRINGBOOT, + REACT, + DB +} diff --git a/post/src/main/java/com/cnu/post/repository/PostRepository.java b/post/src/main/java/com/cnu/post/repository/PostRepository.java new file mode 100644 index 0000000..ae97e85 --- /dev/null +++ b/post/src/main/java/com/cnu/post/repository/PostRepository.java @@ -0,0 +1,13 @@ +package com.cnu.post.repository; + +import com.cnu.post.entity.Post; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PostRepository extends JpaRepository { +// Post save(Post p21ost); +// List findAll(); +// Optional findById(Integer postId); +// void delete(Post post); +} diff --git a/post/src/main/java/com/cnu/post/repository/ProjectRepository.java b/post/src/main/java/com/cnu/post/repository/ProjectRepository.java new file mode 100644 index 0000000..5be57a1 --- /dev/null +++ b/post/src/main/java/com/cnu/post/repository/ProjectRepository.java @@ -0,0 +1,13 @@ +package com.cnu.post.repository; + +import com.cnu.post.entity.Project; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProjectRepository extends JpaRepository { +// Project save(Project post); +// List findAll(); +// Optional findById(Integer projectId); +// void delete(Project projectId); +} diff --git a/post/src/main/java/com/cnu/post/service/PostService.java b/post/src/main/java/com/cnu/post/service/PostService.java new file mode 100644 index 0000000..59429dd --- /dev/null +++ b/post/src/main/java/com/cnu/post/service/PostService.java @@ -0,0 +1,48 @@ +package com.cnu.post.service; + +import com.cnu.post.client.AdvertisementClient; +import com.cnu.post.entity.Post; +import com.cnu.post.model.request.PostRequest; +import com.cnu.post.model.response.PostResponse; +import com.cnu.post.repository.PostRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class PostService { + + private final PostRepository postRepository; + private final AdvertisementClient advertisementClient; + + public Post createPost(PostRequest postRequest) { + return postRepository.save(postRequest.toEntity()); + } + + public List getPosts() { + return postRepository.findAll(); + } + + public Optional getPost(Integer postId) { + return postRepository.findById(postId) + .map(post -> new PostResponse(post, advertisementClient.getAd())); + } + + public Optional updatePost(Integer postId, PostRequest postRequest) { + return postRepository.findById(postId) + .map(post -> { + post.setTitle(postRequest.getTitle()); + post.setContents(postRequest.getContents()); + post.setTag(postRequest.getTag()); + return postRepository.save(post); + }); + } + + public void deletePost(Integer postId) { + postRepository.findById(postId) + .ifPresent(postRepository::delete); + } +} diff --git a/post/src/main/java/com/cnu/post/service/ProjectService.java b/post/src/main/java/com/cnu/post/service/ProjectService.java new file mode 100644 index 0000000..31a451b --- /dev/null +++ b/post/src/main/java/com/cnu/post/service/ProjectService.java @@ -0,0 +1,49 @@ +package com.cnu.post.service; + +import com.cnu.post.client.AdvertisementClient; +import com.cnu.post.entity.Project; +import com.cnu.post.model.request.ProjectRequest; +//import com.cnu.post.model.response.ProjectResponse; +import com.cnu.post.repository.ProjectRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class ProjectService { + + private final ProjectRepository projectRepository; + private final AdvertisementClient advertisementClient; + + public Project createProject(ProjectRequest projectRequest) { + return projectRepository.save(projectRequest.toEntity()); + } + + public List getProjects() { + return projectRepository.findAll(); + } + + public Optional getProject(Integer projectId) { + return projectRepository.findById(projectId); + } + + public Optional updateProject(Integer projectId, ProjectRequest projectRequest) { + return projectRepository.findById(projectId) + .map(project -> { + project.setTitle(projectRequest.getTitle()); + project.setSummary(projectRequest.getSummary()); + project.setDescription(projectRequest.getDescription()); + project.setStartDate(projectRequest.getStartDate()); + project.setEndDate(projectRequest.getEndDate()); + return projectRepository.save(project); + }); + } + + public void deleteProject(Integer projectId) { + projectRepository.findById(projectId) + .ifPresent(projectRepository::delete); + } +} diff --git a/post/src/main/resources/application.yml b/post/src/main/resources/application.yml new file mode 100644 index 0000000..786cb4e --- /dev/null +++ b/post/src/main/resources/application.yml @@ -0,0 +1,31 @@ +# H2 Setting Info (H2 Console? ???? ?? ???? ??) +h2: + console: + enabled: true # H2 Console? ???? ?? (H2 Console? H2 Database? UI? ????? ??) + path: /h2-console # H2 Console? Path +# Database Setting Info (Database? H2? ???? ?? H2?? ?? ??) +datasource: + driver-class-name: org.h2.Driver # Database? H2? ?????. + url: jdbc:h2:mem:devblog # H2 ?? ?? + username: sa # H2 ?? ? ??? username ?? (??? ??? ??) + password: # H2 ?? ? ??? password ?? (??? ??? ??) + +jpa: + hibernate: + ddl-auto: create # ??????? ??? ? ??????? ????? ?? ??? ?? + properties: + hibernate: + format_sql: true # ???? query? ??? + +resilience4j: + circuitbreaker: + instances: + ad: + slidingWindowType: COUNT_BASED + slidingWindowSize: 5 + failureRateThreshold: 50 # 에러 비율로 해당 값 이상으로 에러 발생시 서킷이 open + slowCallRateThreshold: 100 + minimumNumberOfCalls: 3 # circuitbreaker가 에러비율 또는 slow call 비율을 계산하기 전에 요구되는 최소 호출 횟수 + +logging.level: + org.hibernate.SQL: debug \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 85d9125..a7ea2d7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1 +1,3 @@ rootProject.name = "real_coding_server" +include("post") +include("ad")