diff --git a/.travis.yml b/.travis.yml index 3f92c5d..ca260f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: java jdk: - openjdk11 -#branches: -# only: -# - main +branches: + only: + - main # travis CI 서버 home cache: diff --git a/src/main/java/myblog/blog/article/controller/ArticleController.java b/src/main/java/myblog/blog/article/adapter/incomming/web/ArticleController.java similarity index 52% rename from src/main/java/myblog/blog/article/controller/ArticleController.java rename to src/main/java/myblog/blog/article/adapter/incomming/web/ArticleController.java index fff93d2..4e5cfe6 100644 --- a/src/main/java/myblog/blog/article/controller/ArticleController.java +++ b/src/main/java/myblog/blog/article/adapter/incomming/web/ArticleController.java @@ -1,20 +1,24 @@ -package myblog.blog.article.controller; +package myblog.blog.article.adapter.incomming.web; import lombok.RequiredArgsConstructor; -import myblog.blog.article.domain.Article; -import myblog.blog.article.service.*; -import myblog.blog.article.dto.*; +import myblog.blog.article.application.port.incomming.ArticleUseCase; +import myblog.blog.article.application.port.incomming.TempArticleUseCase; +import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase; +import myblog.blog.article.application.port.incomming.TagsQueriesUseCase; +import myblog.blog.article.application.port.request.ArticleCreateRequest; +import myblog.blog.article.application.port.request.ArticleEditRequest; +import myblog.blog.article.application.port.response.ArticleResponseByCategory; +import myblog.blog.article.application.port.response.ArticleResponseForCardBox; +import myblog.blog.article.application.port.response.ArticleResponseForDetail; +import myblog.blog.article.application.port.response.ArticleResponseForEdit; import myblog.blog.category.service.CategoryService; import myblog.blog.category.dto.*; import myblog.blog.member.auth.PrincipalDetails; -import myblog.blog.member.dto.MemberDto; -import myblog.blog.tags.queries.TagsQueries; -import myblog.blog.tags.service.TagsService; +import myblog.blog.member.dto.MemberVo; import myblog.blog.shared.queries.LayoutRenderingQueries; import org.jsoup.Jsoup; - import org.modelmapper.ModelMapper; import org.springframework.data.domain.*; @@ -38,24 +42,19 @@ import static myblog.blog.shared.utils.MarkdownUtils.*; @RequiredArgsConstructor public class ArticleController { - private final ArticleService articleService; - private final TagsService tagsService; + private final ArticleUseCase articleUseCase; + private final ArticleQueriesUseCase articleQueriesUseCase; + private final TempArticleUseCase tempArticleUseCase; + private final TagsQueriesUseCase tagsQueriesUseCase; private final CategoryService categoryService; - private final TempArticleService tempArticleService; - - private final TagsQueries tagsQueries; private final LayoutRenderingQueries layoutRenderingQueries; - private final ModelMapper modelMapper; - /* - - 아티클 작성 폼 조회 - */ @GetMapping("article/write") - public String getWriteArticleForm(Model model) { + String getArticleWriteForm(Model model) { layoutRenderingQueries.AddLayoutTo(model); model.addAttribute("categoryInput", getCategoryDtosForForm()); - model.addAttribute("tagsInput", tagsQueries.findAllTagDtos()); + model.addAttribute("tagsInput", tagsQueriesUseCase.findAllTagDtos()); model.addAttribute("articleDto", new ArticleForm()); return "article/articleWriteForm"; } @@ -64,35 +63,26 @@ public class ArticleController { */ @PostMapping("article/write") @Transactional - public String writeArticle(@Validated ArticleForm articleForm, + String writeArticle(@Validated ArticleForm articleForm, @AuthenticationPrincipal PrincipalDetails principal, Errors errors, Model model) { if (errors.hasErrors()) { - getWriteArticleForm(model); + getArticleWriteForm(model); } - Long articleId = articleService.writeArticle(articleForm, principal.getMember()); - articleService.pushArticleToGithub(articleId); - tempArticleService.deleteTemp(); + Long articleId = articleUseCase.writeArticle(ArticleCreateRequest.from(articleForm,principal.getMemberId())); + articleUseCase.backupArticle(articleId); + tempArticleUseCase.deleteTemp(); return "redirect:/article/view?articleId=" + articleId; } /* - 아티클 수정 폼 조회 */ @GetMapping("/article/edit") - public String updateArticle(@RequestParam Long articleId, - Model model) { - // 기존 아티클 DTO 전처리 - Article article = articleService.readArticle(articleId); - ArticleDtoForEdit articleDto = modelMapper.map(article, ArticleDtoForEdit.class); - List articleTagStrings = article.getArticleTagLists() - .stream() - .map(articleTag -> articleTag.getTags().getName()) - .collect(Collectors.toList()); - articleDto.setArticleTagList(articleTagStrings); - // + String updateArticle(@RequestParam Long articleId, Model model) { + ArticleResponseForEdit articleDto = articleQueriesUseCase.getArticleForEdit(articleId); layoutRenderingQueries.AddLayoutTo(model); model.addAttribute("categoryInput", getCategoryDtosForForm()); - model.addAttribute("tagsInput", tagsQueries.findAllTagDtos()); + model.addAttribute("tagsInput", tagsQueriesUseCase.findAllTagDtos()); model.addAttribute("articleDto", articleDto); return "article/articleEditForm"; } @@ -102,9 +92,9 @@ public class ArticleController { */ @PostMapping("/article/edit") @Transactional - public String editArticle(@RequestParam Long articleId, - @ModelAttribute ArticleForm articleForm) { - articleService.editArticle(articleId, articleForm); + String editArticle(@RequestParam Long articleId, + @ModelAttribute ArticleForm articleForm) { + articleUseCase.editArticle(ArticleEditRequest.from(articleId, articleForm)); return "redirect:/article/view?articleId=" + articleId; } @@ -113,8 +103,8 @@ public class ArticleController { */ @PostMapping("/article/delete") @Transactional - public String deleteArticle(@RequestParam Long articleId) { - articleService.deleteArticle(articleId); + String deleteArticle(@RequestParam Long articleId) { + articleUseCase.deleteArticle(articleId); return "redirect:/"; } @@ -123,25 +113,22 @@ public class ArticleController { */ @Transactional @GetMapping("article/list") - public String getArticlesListByCategory(@RequestParam String category, - @RequestParam Integer tier, - @RequestParam Integer page, - Model model) { - // DTO 매핑 전처리 - PagingBoxDto pagingBoxDto = - PagingBoxDto.createOf(page, getTotalArticleCntByCategory(category, categoryService.getCategoryForView())); + String getArticlesListByCategory(@RequestParam String category, + @RequestParam Integer tier, + @RequestParam Integer page, + Model model) { + PagingBoxHandler pagingBoxHandler = + PagingBoxHandler.createOf(page, getTotalArticleCntByCategory(category, categoryService.getCategoryForView())); - Slice articleDtoList = - articleService.getArticlesByCategory(category, tier, pagingBoxDto.getCurPageNum()) - .map(article -> modelMapper.map(article, ArticleDtoForCardBox.class)); - // + Slice articleDtoList = + articleQueriesUseCase.getArticlesByCategory(category, tier, pagingBoxHandler.getCurPageNum()); - for(ArticleDtoForCardBox articleDto : articleDtoList){ + for(ArticleResponseForCardBox articleDto : articleDtoList){ articleDto.setContent(Jsoup.parse(getHtmlRenderer().render(getParser().parse(articleDto.getContent()))).text()); } layoutRenderingQueries.AddLayoutTo(model); - model.addAttribute("pagingBox", pagingBoxDto); + model.addAttribute("pagingBox", pagingBoxHandler); model.addAttribute("articleList", articleDtoList); return "article/articleList"; @@ -152,25 +139,22 @@ public class ArticleController { */ @Transactional @GetMapping("article/list/tag/") - public String getArticlesListByTag(@RequestParam Integer page, - @RequestParam String tagName, - Model model) { - // DTO 매핑 전처리 - Page articleList = - articleService.getArticlesByTag(tagName, page) - .map(article -> - modelMapper.map(article, ArticleDtoForCardBox.class)); + String getArticlesListByTag(@RequestParam Integer page, + @RequestParam String tagName, + Model model) { + Page articleList = + articleQueriesUseCase.getArticlesByTag(tagName, page); - for(ArticleDtoForCardBox article : articleList){ + for(ArticleResponseForCardBox article : articleList){ article.setContent(Jsoup.parse(getHtmlRenderer().render(getParser().parse(article.getContent()))).text()); } - PagingBoxDto pagingBoxDto = - PagingBoxDto.createOf(page, (int)articleList.getTotalElements()); + PagingBoxHandler pagingBoxHandler = + PagingBoxHandler.createOf(page, (int)articleList.getTotalElements()); layoutRenderingQueries.AddLayoutTo(model); model.addAttribute("articleList", articleList); - model.addAttribute("pagingBox", pagingBoxDto); + model.addAttribute("pagingBox", pagingBoxHandler); return "article/articleListByTag"; } @@ -180,25 +164,22 @@ public class ArticleController { */ @Transactional @GetMapping("article/list/search/") - public String getArticlesListByKeyword(@RequestParam Integer page, - @RequestParam String keyword, - Model model) { - // DTO 매핑 전처리 - Page articleList = - articleService.getArticlesByKeyword(keyword, page) - .map(article -> - modelMapper.map(article, ArticleDtoForCardBox.class)); + String getArticlesListByKeyword(@RequestParam Integer page, + @RequestParam String keyword, + Model model) { + Page articleList = + articleQueriesUseCase.getArticlesByKeyword(keyword, page); - for(ArticleDtoForCardBox article : articleList){ + for(ArticleResponseForCardBox article : articleList){ article.setContent(Jsoup.parse(getHtmlRenderer().render(getParser().parse(article.getContent()))).text()); } - PagingBoxDto pagingBoxDto = - PagingBoxDto.createOf(page, (int)articleList.getTotalElements()); + PagingBoxHandler pagingBoxHandler = + PagingBoxHandler.createOf(page, (int)articleList.getTotalElements()); layoutRenderingQueries.AddLayoutTo(model); model.addAttribute("articleList", articleList); - model.addAttribute("pagingBox", pagingBoxDto); + model.addAttribute("pagingBox", pagingBoxHandler); return "article/articleListByKeyword"; @@ -214,81 +195,65 @@ public class ArticleController { */ @Transactional @GetMapping("/article/view") - public String readArticle(@RequestParam Long articleId, - @AuthenticationPrincipal PrincipalDetails principal, - @CookieValue(required = false, name = "view") String cookie, - HttpServletResponse response, - Model model) { + String readArticle(@RequestParam Long articleId, + @AuthenticationPrincipal PrincipalDetails principal, + @CookieValue(required = false, name = "view") String cookie, + HttpServletResponse response, + Model model) { // 1. 로그인 여부에 따라 뷰단에 회원정보 출력 여부 결정 if (principal != null) { - model.addAttribute("member", modelMapper.map(principal.getMember(), MemberDto.class)); + model.addAttribute("member", MemberVo.from(principal.getMember())); } else { model.addAttribute("member", null); } /* - DTO 매핑 전처리 - 2. 게시물 상세조회용 + 2.화면단을 위한 처리 */ - Article article = articleService.readArticle(articleId); + ArticleResponseForDetail articleResponseForDetail = articleQueriesUseCase.getArticleForDetail(articleId); + articleResponseForDetail.setContent(getHtmlRenderer().render(getParser().parse(articleResponseForDetail.getContent()))); - ArticleDtoForDetail articleDtoForDetail = - modelMapper.map(article, ArticleDtoForDetail.class); - - List tags = - article.getArticleTagLists() - .stream() - .map(tag -> tag.getTags().getName()) - .collect(Collectors.toList()); - - articleDtoForDetail.setTags(tags); - articleDtoForDetail.setContent(getHtmlRenderer().render(getParser().parse(article.getContent()))); - - List articleTitlesSortByCategory = - articleService - .getArticlesByCategoryForDetailView(article.getCategory()) - .stream() - .map(article1 -> modelMapper.map(article1, ArticleDtoByCategory.class)) - .collect(Collectors.toList()); + List articleTitlesSortByCategory = + articleQueriesUseCase + .getArticlesByCategoryForDetailView(articleResponseForDetail.getCategory()); // 3. 메타 태그용 Dto 전처리 StringBuilder metaTags = new StringBuilder(); - for (String tag : tags) { + for (String tag : articleResponseForDetail.getTags()) { metaTags.append(tag).append(", "); } String substringContents = null; - if(articleDtoForDetail.getContent().length()>200) { - substringContents = articleDtoForDetail.getContent().substring(0, 200); + if(articleResponseForDetail.getContent().length()>200) { + substringContents = articleResponseForDetail.getContent().substring(0, 200); } - else substringContents = articleDtoForDetail.getContent(); + else substringContents = articleResponseForDetail.getContent(); // 4. 모델 담기 layoutRenderingQueries.AddLayoutTo(model); - model.addAttribute("article", articleDtoForDetail); + model.addAttribute("article", articleResponseForDetail); model.addAttribute("metaTags",metaTags); model.addAttribute("metaContents",Jsoup.parse(substringContents).text()); model.addAttribute("articlesSortBycategory", articleTitlesSortByCategory); - // 5. 조회수 증가 검토 - addHitWithCookie(article, cookie, response); + // 5. 조회수 증가 검토 및 증가 + if(needToAddHitThroughCheckingCookie(articleId, cookie, response)) articleUseCase.addHit(articleId); return "article/articleView"; } - /* - 쿠키 추가 / 조회수 증가 검토 */ - private void addHitWithCookie(Article article, String cookie, HttpServletResponse response) { - Long articleId = article.getId(); + private boolean needToAddHitThroughCheckingCookie(Long articleId, String cookie, HttpServletResponse response) { if (cookie == null) { Cookie viewCookie = new Cookie("view", articleId + "/"); viewCookie.setComment("게시물 조회 확인용"); viewCookie.setMaxAge(60 * 60); - articleService.addHit(article); response.addCookie(viewCookie); + return true; } else { + boolean addHitAvailable = false; boolean isRead = false; String[] viewCookieList = cookie.split("/"); for (String alreadyRead : viewCookieList) { @@ -299,9 +264,10 @@ public class ArticleController { } if (!isRead) { cookie += articleId + "/"; - article.addHit(); + addHitAvailable = true; } response.addCookie(new Cookie("view", cookie)); + return addHitAvailable; } } @@ -329,11 +295,11 @@ public class ArticleController { /* - 아티클 폼에 필요한 카테고리 dtos */ - private List getCategoryDtosForForm() { + private List getCategoryDtosForForm() { return categoryService .findCategoryByTier(2) .stream() - .map(category -> modelMapper.map(category, CategoryNormalDto.class)) + .map(category -> modelMapper.map(category, CategorySimpleView.class)) .collect(Collectors.toList()); } } diff --git a/src/main/java/myblog/blog/article/dto/ArticleForm.java b/src/main/java/myblog/blog/article/adapter/incomming/web/ArticleForm.java similarity index 84% rename from src/main/java/myblog/blog/article/dto/ArticleForm.java rename to src/main/java/myblog/blog/article/adapter/incomming/web/ArticleForm.java index d864499..df5fa77 100644 --- a/src/main/java/myblog/blog/article/dto/ArticleForm.java +++ b/src/main/java/myblog/blog/article/adapter/incomming/web/ArticleForm.java @@ -1,11 +1,9 @@ -package myblog.blog.article.dto; +package myblog.blog.article.adapter.incomming.web; import lombok.Getter; import lombok.Setter; -import myblog.blog.article.domain.Article; import javax.validation.constraints.NotBlank; -import java.util.Objects; @Setter @Getter diff --git a/src/main/java/myblog/blog/main/MainController.java b/src/main/java/myblog/blog/article/adapter/incomming/web/MainController.java similarity index 56% rename from src/main/java/myblog/blog/main/MainController.java rename to src/main/java/myblog/blog/article/adapter/incomming/web/MainController.java index 707f396..196c010 100644 --- a/src/main/java/myblog/blog/main/MainController.java +++ b/src/main/java/myblog/blog/article/adapter/incomming/web/MainController.java @@ -1,28 +1,24 @@ -package myblog.blog.main; +package myblog.blog.article.adapter.incomming.web; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import myblog.blog.article.dto.ArticleDtoForCardBox; -import myblog.blog.article.service.ArticleService; + +import myblog.blog.article.application.port.response.ArticleResponseForCardBox; +import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase; import myblog.blog.shared.queries.LayoutRenderingQueries; import org.jsoup.Jsoup; -import org.modelmapper.ModelMapper; + import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; - import java.util.List; -import java.util.stream.Collectors; import static myblog.blog.shared.utils.MarkdownUtils.*; @Controller @RequiredArgsConstructor -@Slf4j public class MainController { - private final ArticleService articleService; - private final ModelMapper modelMapper; + private final ArticleQueriesUseCase articleQueriesUseCase; private final LayoutRenderingQueries layoutRenderingQueries; /* - 메인 화면 제어용 컨트롤러 @@ -30,10 +26,7 @@ public class MainController { @GetMapping("/") public String main(Model model) { // Dto 전처리 - List popularArticles = articleService.getPopularArticles() - .stream() - .map(article -> modelMapper.map(article, ArticleDtoForCardBox.class)) - .collect(Collectors.toList()); + List popularArticles = articleQueriesUseCase.getPopularArticles(); // layoutRenderingQueries.AddLayoutTo(model); model.addAttribute("popularArticles", popularArticles); @@ -45,17 +38,14 @@ public class MainController { */ @GetMapping("/main/article/{lastArticleId}") public @ResponseBody - List mainNextPage(@PathVariable(required = false) Long lastArticleId) { + List mainNextPage(@PathVariable(required = false) Long lastArticleId) { // Entity to Dto - List articles = articleService.getRecentArticles(lastArticleId) - .stream() - .map(article -> modelMapper.map(article, ArticleDtoForCardBox.class)) - .collect(Collectors.toList()); + List articles = articleQueriesUseCase.getRecentArticles(lastArticleId); // 화면렌더링을 위한 파싱 - for(ArticleDtoForCardBox article : articles){ + for(ArticleResponseForCardBox article : articles){ String content = Jsoup.parse(getHtmlRenderer().render(getParser().parse(article.getContent()))).text(); if(content.length()>300) { content = content.substring(0, 300); diff --git a/src/main/java/myblog/blog/article/dto/PagingBoxDto.java b/src/main/java/myblog/blog/article/adapter/incomming/web/PagingBoxHandler.java similarity index 86% rename from src/main/java/myblog/blog/article/dto/PagingBoxDto.java rename to src/main/java/myblog/blog/article/adapter/incomming/web/PagingBoxHandler.java index 45c4097..900976e 100644 --- a/src/main/java/myblog/blog/article/dto/PagingBoxDto.java +++ b/src/main/java/myblog/blog/article/adapter/incomming/web/PagingBoxHandler.java @@ -1,14 +1,13 @@ -package myblog.blog.article.dto; +package myblog.blog.article.adapter.incomming.web; import lombok.Getter; import lombok.Setter; -import org.springframework.data.domain.Page; /* - 뷰단 페이징 박스 처리를 위한 핸들러 */ @Getter @Setter -public class PagingBoxDto { +public class PagingBoxHandler { private int curPageNum; private int lastPageNum; @@ -20,9 +19,9 @@ public class PagingBoxDto { private final int displayArticlePerPage = 5; // 스태틱 생성 메소드 - public static PagingBoxDto createOf(int page, int totalArticles) { + public static PagingBoxHandler createOf(int page, int totalArticles) { - PagingBoxDto box = new PagingBoxDto(); + PagingBoxHandler box = new PagingBoxHandler(); box.curPageNum = page; box.lastPageNum = (int) (Math.ceil(totalArticles / (double) box.displayArticlePerPage)); diff --git a/src/main/java/myblog/blog/article/controller/TempArticleController.java b/src/main/java/myblog/blog/article/adapter/incomming/web/TempArticleController.java similarity index 52% rename from src/main/java/myblog/blog/article/controller/TempArticleController.java rename to src/main/java/myblog/blog/article/adapter/incomming/web/TempArticleController.java index e594539..b56c68f 100644 --- a/src/main/java/myblog/blog/article/controller/TempArticleController.java +++ b/src/main/java/myblog/blog/article/adapter/incomming/web/TempArticleController.java @@ -1,9 +1,9 @@ -package myblog.blog.article.controller; +package myblog.blog.article.adapter.incomming.web; import lombok.RequiredArgsConstructor; import myblog.blog.article.domain.TempArticle; -import myblog.blog.article.service.TempArticleService; -import myblog.blog.article.dto.TempArticleDto; +import myblog.blog.article.application.TempArticleService; +import myblog.blog.article.application.port.response.TempArticleResponse; import org.springframework.web.bind.annotation.*; import java.util.Optional; @@ -21,9 +21,9 @@ public class TempArticleController { - 임시 아티클 저장 요청 */ @PostMapping("/article/temp/autoSave") - public String autoSaveTemp(@RequestBody TempArticleDto tempArticleDto){ + public String autoSaveTemp(@RequestBody TempArticleResponse tempArticleResponse){ - tempArticleService.saveTemp(new TempArticle(tempArticleDto.getContent())); + tempArticleService.saveTemp(new TempArticle(tempArticleResponse.getContent())); return "저장성공"; } @@ -32,13 +32,14 @@ public class TempArticleController { - 임시 아티클 조회 */ @GetMapping("/article/temp/getTemp") - public @ResponseBody TempArticleDto getTempArticle(){ + public @ResponseBody + TempArticleResponse getTempArticle(){ Optional tempArticle = tempArticleService.getTempArticle(); - TempArticleDto tempArticleDto = new TempArticleDto(); - tempArticleDto.setContent(tempArticle.orElse(new TempArticle()).getContent()); + TempArticleResponse tempArticleResponse = new TempArticleResponse(); + tempArticleResponse.setContent(tempArticle.orElse(new TempArticle()).getContent()); - return tempArticleDto; + return tempArticleResponse; } } diff --git a/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleBackupRepositoryAdapter.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleBackupRepositoryAdapter.java new file mode 100644 index 0000000..8ca7cd5 --- /dev/null +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleBackupRepositoryAdapter.java @@ -0,0 +1,16 @@ +package myblog.blog.article.adapter.outgoing.persistence; + +import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.outgoing.ArticleBackupRepositoryPort; +import myblog.blog.article.domain.Article; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class ArticleBackupRepositoryAdapter implements ArticleBackupRepositoryPort { + + private final GithubRepoArticleRepository githubRepoArticleRepository; + + @Override + public void backup(Article article) {githubRepoArticleRepository.pushArticleToGithub(article);} +} diff --git a/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleRepositoryAdapter.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleRepositoryAdapter.java new file mode 100644 index 0000000..5006dc1 --- /dev/null +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleRepositoryAdapter.java @@ -0,0 +1,92 @@ +package myblog.blog.article.adapter.outgoing.persistence; + +import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.outgoing.ArticleBackupRepositoryPort; +import myblog.blog.article.application.port.outgoing.ArticleRepositoryPort; +import myblog.blog.article.domain.Article; +import myblog.blog.category.domain.Category; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; + +@RequiredArgsConstructor +@Component +public class ArticleRepositoryAdapter implements ArticleRepositoryPort { + + private final JpaArticleRepository jpaArticleRepository; + private final MybatisArticleRepository mybatisArticleRepository; + + @Override + public List
findTop6ByOrderByHitDesc() { + return jpaArticleRepository.findTop6ByOrderByHitDesc(); + } + + @Override + public List
findTop6ByCategoryOrderByIdDesc(Category category) { + return jpaArticleRepository.findTop6ByCategoryOrderByIdDesc(category); + } + + @Override + public Slice
findByOrderByIdDesc(Pageable pageable) { + return jpaArticleRepository.findByOrderByIdDesc(pageable); + } + + @Override + public List
findByOrderByIdDescWithList(Pageable pageable) { + return jpaArticleRepository.findByOrderByIdDescWithList(pageable); + } + + @Override + public List
findByOrderByIdDesc(Long articleId, Pageable pageable) { + return jpaArticleRepository.findByOrderByIdDesc(articleId, pageable); + } + + @Override + public Slice
findBySubCategoryOrderByIdDesc(Pageable pageable, String category) { + return jpaArticleRepository.findBySubCategoryOrderByIdDesc(pageable,category); + } + + @Override + public Slice
findBySupCategoryOrderByIdDesc(Pageable pageable, String category) { + return jpaArticleRepository.findBySupCategoryOrderByIdDesc(pageable,category); + } + + @Override + public Article findArticleByIdFetchCategoryAndTags(Long articleId) { + return jpaArticleRepository.findArticleByIdFetchCategoryAndTags(articleId); + } + + @Override + public Page
findAllByArticleTagsOrderById(Pageable pageable, String tag) { + return jpaArticleRepository.findAllByArticleTagsOrderById(pageable,tag); + } + + @Override + public Page
findAllByKeywordOrderById(Pageable pageable, String keyword) { + return jpaArticleRepository.findAllByArticleTagsOrderById(pageable, keyword); + } + + @Override + public List
findAllByOrderByIdDesc() { + return jpaArticleRepository.findAllByOrderByIdDesc(); + } + + @Override + public Optional
findById(Long articleId) { + return jpaArticleRepository.findById(articleId); + } + + @Override + public void save(Article newArticle) { + jpaArticleRepository.save(newArticle); + } + + @Override + public void deleteArticle(Long articleId) { + mybatisArticleRepository.deleteArticle(articleId); + } +} diff --git a/src/main/java/myblog/blog/tags/repository/ArticleTagListsRepository.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleTagListsRepository.java similarity index 88% rename from src/main/java/myblog/blog/tags/repository/ArticleTagListsRepository.java rename to src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleTagListsRepository.java index 4a02108..846248a 100644 --- a/src/main/java/myblog/blog/tags/repository/ArticleTagListsRepository.java +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/ArticleTagListsRepository.java @@ -1,7 +1,7 @@ -package myblog.blog.tags.repository; +package myblog.blog.article.adapter.outgoing.persistence; import myblog.blog.article.domain.Article; -import myblog.blog.tags.domain.ArticleTagList; +import myblog.blog.article.domain.ArticleTagList; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/myblog/blog/article/adapter/outgoing/persistence/GithubRepoArticleRepository.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/GithubRepoArticleRepository.java new file mode 100644 index 0000000..218bf36 --- /dev/null +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/GithubRepoArticleRepository.java @@ -0,0 +1,35 @@ +package myblog.blog.article.adapter.outgoing.persistence; + +import myblog.blog.article.domain.Article; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GitHub; +import org.kohsuke.github.GitHubBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +public class GithubRepoArticleRepository { + + @Value("${git.gitToken}") + private String gitToken; + @Value("${git.repo}") + private String gitRepo; + + void pushArticleToGithub(Article article) { + try { + GitHub gitHub = new GitHubBuilder().withOAuthToken(gitToken).build(); + GHRepository repository = gitHub.getRepository(gitRepo); + repository.createContent() + .path(article.getCategory().getParents().getTitle()+"/"+ article.getCategory().getTitle()+"/"+ article.getTitle()+".md") + .content(article.getContent()) + .message("test") + .branch("main") + .commit(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/myblog/blog/article/repository/ArticleRepository.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaArticleRepository.java similarity index 96% rename from src/main/java/myblog/blog/article/repository/ArticleRepository.java rename to src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaArticleRepository.java index e46280e..241620b 100644 --- a/src/main/java/myblog/blog/article/repository/ArticleRepository.java +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaArticleRepository.java @@ -1,4 +1,4 @@ -package myblog.blog.article.repository; +package myblog.blog.article.adapter.outgoing.persistence; import myblog.blog.article.domain.Article; import myblog.blog.category.domain.Category; @@ -11,7 +11,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; -public interface ArticleRepository extends JpaRepository { +public interface JpaArticleRepository extends JpaRepository { /* - 최대 6개까지 조회수가 높은 게시물 가져오기 diff --git a/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaTagsRepository.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaTagsRepository.java new file mode 100644 index 0000000..b691cc3 --- /dev/null +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaTagsRepository.java @@ -0,0 +1,10 @@ +package myblog.blog.article.adapter.outgoing.persistence; + +import myblog.blog.article.domain.Tags; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface JpaTagsRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/src/main/java/myblog/blog/article/repository/TempArticleRepository.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaTempArticleRepository.java similarity index 50% rename from src/main/java/myblog/blog/article/repository/TempArticleRepository.java rename to src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaTempArticleRepository.java index b81732d..30b27bd 100644 --- a/src/main/java/myblog/blog/article/repository/TempArticleRepository.java +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/JpaTempArticleRepository.java @@ -1,8 +1,8 @@ -package myblog.blog.article.repository; +package myblog.blog.article.adapter.outgoing.persistence; import myblog.blog.article.domain.TempArticle; import org.springframework.data.jpa.repository.JpaRepository; // 기본 JPA 메소드 사용 -public interface TempArticleRepository extends JpaRepository { +public interface JpaTempArticleRepository extends JpaRepository { } diff --git a/src/main/java/myblog/blog/article/repository/NaArticleRepository.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/MybatisArticleRepository.java similarity index 77% rename from src/main/java/myblog/blog/article/repository/NaArticleRepository.java rename to src/main/java/myblog/blog/article/adapter/outgoing/persistence/MybatisArticleRepository.java index 15ae74a..60972a1 100644 --- a/src/main/java/myblog/blog/article/repository/NaArticleRepository.java +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/MybatisArticleRepository.java @@ -1,10 +1,10 @@ -package myblog.blog.article.repository; +package myblog.blog.article.adapter.outgoing.persistence; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Mapper; @Mapper -public interface NaArticleRepository { +public interface MybatisArticleRepository { /* - 삭제처리시 불필요한 조회방지 위해 네이티브 쿼리 사용 cascade delete 처리 diff --git a/src/main/java/myblog/blog/article/adapter/outgoing/persistence/TagRepositoryAdapter.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/TagRepositoryAdapter.java new file mode 100644 index 0000000..c0ef9c2 --- /dev/null +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/TagRepositoryAdapter.java @@ -0,0 +1,20 @@ +package myblog.blog.article.adapter.outgoing.persistence; + +import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.outgoing.TagRepositoryPort; +import myblog.blog.article.domain.Tags; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@RequiredArgsConstructor +public class TagRepositoryAdapter implements TagRepositoryPort { + + private final JpaTagsRepository jpaTagsRepository; + + @Override + public List findAll() { + return jpaTagsRepository.findAll(); + } +} diff --git a/src/main/java/myblog/blog/article/adapter/outgoing/persistence/TempArticleRepositoryAdapter.java b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/TempArticleRepositoryAdapter.java new file mode 100644 index 0000000..e31f481 --- /dev/null +++ b/src/main/java/myblog/blog/article/adapter/outgoing/persistence/TempArticleRepositoryAdapter.java @@ -0,0 +1,30 @@ +package myblog.blog.article.adapter.outgoing.persistence; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import myblog.blog.article.application.port.outgoing.TempArticleRepositoryPort; +import myblog.blog.article.domain.TempArticle; + +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class TempArticleRepositoryAdapter implements TempArticleRepositoryPort { + + private final JpaTempArticleRepository jpaTempArticleRepository; + + @Override + public void save(TempArticle tempArticle) { + jpaTempArticleRepository.save(tempArticle); + } + + @Override + public Optional findById(long id) { + return jpaTempArticleRepository.findById(id); + } + + @Override + public void delete(TempArticle tempArticle) { + jpaTempArticleRepository.delete(tempArticle); + } +} diff --git a/src/main/java/myblog/blog/article/application/ArticleQueries.java b/src/main/java/myblog/blog/article/application/ArticleQueries.java new file mode 100644 index 0000000..fc06125 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/ArticleQueries.java @@ -0,0 +1,162 @@ +package myblog.blog.article.application; + +import lombok.RequiredArgsConstructor; + +import myblog.blog.article.application.port.response.ArticleResponseForCardBox; +import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase; +import myblog.blog.article.application.port.outgoing.ArticleRepositoryPort; + +import myblog.blog.article.domain.Article; +import myblog.blog.category.domain.Category; +import myblog.blog.article.application.port.response.ArticleResponseByCategory; +import myblog.blog.article.application.port.response.ArticleResponseForDetail; +import myblog.blog.article.application.port.response.ArticleResponseForEdit; + +import myblog.blog.category.service.CategoryService; +import org.modelmapper.ModelMapper; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; +import org.springframework.stereotype.Component; +import java.util.List; +import java.util.stream.Collectors; + +@Component +@RequiredArgsConstructor +public class ArticleQueries implements ArticleQueriesUseCase { + + private final ArticleRepositoryPort articleRepositoryPort; + private final CategoryService categoryService; + private final ModelMapper modelMapper; + + /* + - 메인화면 위한 인기 아티클 6개 목록 가져오기 + - 레이아웃 렌더링 성능 향상을 위해 캐싱작업 + 카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화 + DTO 매핑 로직 서비스단에서 처리 + */ + @Override + @Cacheable(value = "layoutCaching", key = "1") + public List getPopularArticles() { + return articleRepositoryPort.findTop6ByOrderByHitDesc() + .stream() + .map(article -> modelMapper.map(article, ArticleResponseForCardBox.class)) + .collect(Collectors.toList()); + } + /* + - 메인화면 위한 최신 아티클 커서 페이징해서 가져오기 + - 레이아웃 렌더링 성능 향상을 위해 캐싱작업 + 카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화 + */ + @Override + @Cacheable(value = "layoutRecentArticleCaching", key = "#lastArticleId") + public List getRecentArticles(Long lastArticleId) { + List
articles = lastArticleId.equals(0L) ? + articleRepositoryPort + .findByOrderByIdDescWithList(PageRequest.of(0, 5)) + : + articleRepositoryPort + .findByOrderByIdDesc(lastArticleId, PageRequest.of(0, 5)); + return articles + .stream() + .map(article -> modelMapper.map(article, ArticleResponseForCardBox.class)) + .collect(Collectors.toList()); + } + /* + - 카테고리별 게시물 페이징 처리해서 가져오기 + */ + @Override + public Slice getArticlesByCategory(String category, Integer tier, Integer page) { + Slice
articles; + + if (tier.equals(0)) { + articles = articleRepositoryPort + .findByOrderByIdDesc( + PageRequest.of(pageResolve(page), 5)); + } + else { + articles = articleRepositoryPort + .findBySupCategoryOrderByIdDesc( + PageRequest.of(pageResolve(page), 5), category); + + } + + if(articles == null) throw new IllegalArgumentException("NotFoundArticleException"); + + return articles.map(article -> modelMapper.map(article, ArticleResponseForCardBox.class)); + } + + /* + - 아티클 수정을 위한 반환 + */ + @Override + public ArticleResponseForEdit getArticleForEdit(Long id){ + Article article = articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id); + ArticleResponseForEdit articleDto = modelMapper.map(article, ArticleResponseForEdit.class); + List articleTagStrings = article.getArticleTagLists() + .stream() + .map(articleTag -> articleTag.getTags().getName()) + .collect(Collectors.toList()); + articleDto.setArticleTagList(articleTagStrings); + return articleDto; + } + /* + * - 아티클 상세 조회를 위한 쿼리 + * */ + @Override + public ArticleResponseForDetail getArticleForDetail(Long id){ + Article article = articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id); + ArticleResponseForDetail articleResponseForDetail = + modelMapper.map(article, ArticleResponseForDetail.class); + + List tags = + article.getArticleTagLists() + .stream() + .map(tag -> tag.getTags().getName()) + .collect(Collectors.toList()); + + articleResponseForDetail.setTags(tags); + return articleResponseForDetail; + } + + /* + - 카테고리별 최신게시물 6개만 아티클 상세뷰 위해 가져오는로직 + */ + @Override + public List getArticlesByCategoryForDetailView(String categoryName){ + Category category = categoryService.findCategory(categoryName); + return articleRepositoryPort.findTop6ByCategoryOrderByIdDesc(category) + .stream() + .map(article -> modelMapper.map(article, ArticleResponseByCategory.class)) + .collect(Collectors.toList()); + } + /* + - 태그별 게시물 페이징 처리해서 가져오기 + */ + @Override + public Page getArticlesByTag(String tag, Integer page) { + return articleRepositoryPort + .findAllByArticleTagsOrderById(PageRequest.of(pageResolve(page), 5), tag) + .map(article -> + modelMapper.map(article, ArticleResponseForCardBox.class)); + } + /* + - 검색어별 게시물 페이징 처리해서 가져오기 + */ + @Override + public Page getArticlesByKeyword(String keyword, Integer page) { + return articleRepositoryPort + .findAllByKeywordOrderById(PageRequest.of(pageResolve(page),5), keyword) + .map(article -> + modelMapper.map(article, ArticleResponseForCardBox.class)); + } + /* + - 페이지 시작점 0~1변경 메서드 + */ + private int pageResolve(Integer rawPage) { + if (rawPage == null || rawPage == 1) { + return 0; + } else return rawPage - 1; + } +} diff --git a/src/main/java/myblog/blog/article/application/ArticleService.java b/src/main/java/myblog/blog/article/application/ArticleService.java new file mode 100644 index 0000000..d106b96 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/ArticleService.java @@ -0,0 +1,100 @@ +package myblog.blog.article.application; + +import lombok.RequiredArgsConstructor; + +import myblog.blog.article.application.port.request.ArticleCreateRequest; +import myblog.blog.article.application.port.request.ArticleEditRequest; +import myblog.blog.article.application.port.incomming.ArticleUseCase; +import myblog.blog.article.application.port.incomming.TagUseCase; +import myblog.blog.article.application.port.outgoing.ArticleBackupRepositoryPort; +import myblog.blog.article.application.port.outgoing.ArticleRepositoryPort; + +import myblog.blog.article.domain.Article; +import myblog.blog.category.domain.Category; +import myblog.blog.member.doamin.Member; + +import myblog.blog.category.service.CategoryService; +import myblog.blog.member.service.Oauth2MemberService; + +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class ArticleService implements ArticleUseCase { + + private final TagUseCase tagUseCase; + private final CategoryService categoryService; + private final Oauth2MemberService memberService; + private final ArticleRepositoryPort articleRepositoryPort; + private final ArticleBackupRepositoryPort articleBackupRepositoryPort; + + @Override + @CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true) + public Long writeArticle(ArticleCreateRequest articleCreateRequest) { + Member writer = memberService.findById(articleCreateRequest.getMemberId()); + Category category = categoryService.findCategory(articleCreateRequest.getCategory()); + Article newArticle = new Article(articleCreateRequest.getTitle(), + articleCreateRequest.getContent(), + articleCreateRequest.getToc(), + writer, + articleCreateRequest.getThumbnailUrl(), + category); + articleRepositoryPort.save(newArticle); + tagUseCase.createNewTagsAndArticleTagList(articleCreateRequest.getTags(), newArticle); + return newArticle.getId(); + } + + @Override + @CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true) + public void editArticle(ArticleEditRequest articleEditRequest) { + Article article = articleRepositoryPort.findById(articleEditRequest.getArticleId()) + .orElseThrow(() -> new IllegalArgumentException("NotFoundArticleException")); + Category category = categoryService.findCategory(articleEditRequest.getCategoryName()); + tagUseCase.deleteAllTagsWith(article); + tagUseCase.createNewTagsAndArticleTagList(articleEditRequest.getTags(), article); + article.edit(articleEditRequest.getContent(), + articleEditRequest.getTitle(), + articleEditRequest.getToc(), + articleEditRequest.getThumbnailUrl(), category); + } + + @Override + @CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true) + public void deleteArticle(Long articleId) { + articleRepositoryPort.deleteArticle(articleId); + } + + @Override + public void backupArticle(Long articleId) { + Article article = articleRepositoryPort.findById(articleId) + .orElseThrow(() -> new IllegalArgumentException("NotFoundArticle")); + articleBackupRepositoryPort.backup(article); + } + + @Override + public void addHit(Long articleId) { + Article article = articleRepositoryPort.findById(articleId) + .orElseThrow(() -> new IllegalArgumentException("NotFoundArticleException")); + article.addHit(); + } + + /* + - 아티클 도메인으로 반환 + */ + @Override + public Article getArticle(Long id){ + return articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id); + } + /* + - 모든 아티클 도메인으로 반환 + */ + @Override + public List
getTotalArticle(){ + return articleRepositoryPort.findAllByOrderByIdDesc(); + } +} diff --git a/src/main/java/myblog/blog/article/application/TagsQueries.java b/src/main/java/myblog/blog/article/application/TagsQueries.java new file mode 100644 index 0000000..ef9a180 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/TagsQueries.java @@ -0,0 +1,27 @@ +package myblog.blog.article.application; + +import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.outgoing.TagRepositoryPort; +import myblog.blog.article.domain.Tags; +import myblog.blog.article.application.port.incomming.TagsQueriesUseCase; +import myblog.blog.shared.utils.MapperUtils; +import myblog.blog.article.application.port.response.TagsResponse; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@Transactional +@RequiredArgsConstructor +public class TagsQueries implements TagsQueriesUseCase { + private final TagRepositoryPort tagRepositoryPort; + + public List findAllTagDtos(){ + List tags = tagRepositoryPort.findAll(); + return tags.stream() + .map(tag -> MapperUtils.getModelMapper().map(tag, TagsResponse.class)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/myblog/blog/tags/service/TagsService.java b/src/main/java/myblog/blog/article/application/TagsService.java similarity index 66% rename from src/main/java/myblog/blog/tags/service/TagsService.java rename to src/main/java/myblog/blog/article/application/TagsService.java index e8ea5f7..332c0ea 100644 --- a/src/main/java/myblog/blog/tags/service/TagsService.java +++ b/src/main/java/myblog/blog/article/application/TagsService.java @@ -1,25 +1,27 @@ -package myblog.blog.tags.service; +package myblog.blog.article.application; import lombok.RequiredArgsConstructor; +import myblog.blog.article.adapter.outgoing.persistence.ArticleTagListsRepository; +import myblog.blog.article.adapter.outgoing.persistence.JpaTagsRepository; +import myblog.blog.article.application.port.incomming.TagUseCase; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import myblog.blog.article.domain.*; -import myblog.blog.tags.domain.*; import myblog.blog.shared.utils.MapperUtils; -import myblog.blog.tags.repository.*; import java.util.*; @Service @Transactional @RequiredArgsConstructor -public class TagsService { - private final TagsRepository tagsRepository; +public class TagsService implements TagUseCase { + private final JpaTagsRepository jpaTagsRepository; private final ArticleTagListsRepository articleTagListsRepository; /* - Json 객체로 넘어온 태그들을 파싱해서 신규 태그인경우 저장 */ + @Override public void createNewTagsAndArticleTagList(String names, Article article) { List> tagsDtoArrayList = MapperUtils.getGson().fromJson(names, ArrayList.class); for (var tagDto : tagsDtoArrayList) { @@ -29,10 +31,11 @@ public class TagsService { } private Tags findOrCreateTagFrom(Map tags) { - return tagsRepository.findByName(tags.get("value")) - .orElseGet(() -> tagsRepository.save(new Tags(tags.get("value")))); + return jpaTagsRepository.findByName(tags.get("value")) + .orElseGet(() -> jpaTagsRepository.save(new Tags(tags.get("value")))); } + @Override public void deleteAllTagsWith(Article article){ articleTagListsRepository.deleteByArticle(article); } diff --git a/src/main/java/myblog/blog/article/service/TempArticleService.java b/src/main/java/myblog/blog/article/application/TempArticleService.java similarity index 57% rename from src/main/java/myblog/blog/article/service/TempArticleService.java rename to src/main/java/myblog/blog/article/application/TempArticleService.java index 4ca0ed9..9b0afb6 100644 --- a/src/main/java/myblog/blog/article/service/TempArticleService.java +++ b/src/main/java/myblog/blog/article/application/TempArticleService.java @@ -1,8 +1,9 @@ -package myblog.blog.article.service; +package myblog.blog.article.application; import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.incomming.TempArticleUseCase; +import myblog.blog.article.application.port.outgoing.TempArticleRepositoryPort; import myblog.blog.article.domain.TempArticle; -import myblog.blog.article.repository.TempArticleRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,31 +12,31 @@ import java.util.Optional; @Service @Transactional @RequiredArgsConstructor -public class TempArticleService { +public class TempArticleService implements TempArticleUseCase { - private final TempArticleRepository tempArticleRepository; + private final TempArticleRepositoryPort tempArticleRepositoryPort; /* - 자동 저장 로직 - ID값 고정으로 머지를 작동시켜 임시글 DB에 1개 유지 */ public void saveTemp(TempArticle tempArticle){ - tempArticleRepository.save(tempArticle); + tempArticleRepositoryPort.save(tempArticle); } /* - 임시글 가져오기 */ public Optional getTempArticle(){ - return tempArticleRepository.findById(1L); + return tempArticleRepositoryPort.findById(1L); } /* - 임시글 삭제 */ public void deleteTemp(){ - Optional deleteArticle = tempArticleRepository.findById(1L); - deleteArticle.ifPresent(tempArticleRepository::delete); + Optional deleteArticle = tempArticleRepositoryPort.findById(1L); + deleteArticle.ifPresent(tempArticleRepositoryPort::delete); } } diff --git a/src/main/java/myblog/blog/article/application/port/incomming/ArticleQueriesUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/ArticleQueriesUseCase.java new file mode 100644 index 0000000..d1da141 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/ArticleQueriesUseCase.java @@ -0,0 +1,21 @@ +package myblog.blog.article.application.port.incomming; + +import myblog.blog.article.application.port.response.ArticleResponseForCardBox; +import myblog.blog.article.application.port.response.ArticleResponseByCategory; +import myblog.blog.article.application.port.response.ArticleResponseForDetail; +import myblog.blog.article.application.port.response.ArticleResponseForEdit; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Slice; + +import java.util.List; + +public interface ArticleQueriesUseCase { + List getPopularArticles(); + List getRecentArticles(Long lastArticleId); + Slice getArticlesByCategory(String category, Integer tier, Integer page); + ArticleResponseForEdit getArticleForEdit(Long id); + ArticleResponseForDetail getArticleForDetail(Long id); + List getArticlesByCategoryForDetailView(String category); + Page getArticlesByTag(String tag, Integer page); + Page getArticlesByKeyword(String keyword, Integer page); +} diff --git a/src/main/java/myblog/blog/article/application/port/incomming/ArticleUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/ArticleUseCase.java new file mode 100644 index 0000000..194a2a0 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/ArticleUseCase.java @@ -0,0 +1,17 @@ +package myblog.blog.article.application.port.incomming; + +import myblog.blog.article.application.port.request.ArticleCreateRequest; +import myblog.blog.article.application.port.request.ArticleEditRequest; +import myblog.blog.article.domain.Article; + +import java.util.List; + +public interface ArticleUseCase { + Long writeArticle(ArticleCreateRequest articleCreateRequest); + void editArticle(ArticleEditRequest articleEditRequest); + void deleteArticle(Long articleId); + void addHit(Long articleId); + void backupArticle(Long articleId); + Article getArticle(Long id); + List
getTotalArticle(); +} diff --git a/src/main/java/myblog/blog/article/application/port/incomming/RssUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/RssUseCase.java new file mode 100644 index 0000000..1901ad6 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/RssUseCase.java @@ -0,0 +1,5 @@ +package myblog.blog.article.application.port.incomming; + +public interface RssUseCase { + String getRssFeed(); +} diff --git a/src/main/java/myblog/blog/article/application/port/incomming/SiteMapUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/SiteMapUseCase.java new file mode 100644 index 0000000..d648a3e --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/SiteMapUseCase.java @@ -0,0 +1,5 @@ +package myblog.blog.article.application.port.incomming; + +public interface SiteMapUseCase { + String getSiteMap(); +} diff --git a/src/main/java/myblog/blog/article/application/port/incomming/TagUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/TagUseCase.java new file mode 100644 index 0000000..99d21d2 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/TagUseCase.java @@ -0,0 +1,8 @@ +package myblog.blog.article.application.port.incomming; + +import myblog.blog.article.domain.Article; + +public interface TagUseCase { + void createNewTagsAndArticleTagList(String names, Article article); + void deleteAllTagsWith(Article article); +} diff --git a/src/main/java/myblog/blog/article/application/port/incomming/TagsQueriesUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/TagsQueriesUseCase.java new file mode 100644 index 0000000..b0fe6ff --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/TagsQueriesUseCase.java @@ -0,0 +1,9 @@ +package myblog.blog.article.application.port.incomming; + +import myblog.blog.article.application.port.response.TagsResponse; + +import java.util.List; + +public interface TagsQueriesUseCase { + List findAllTagDtos(); +} diff --git a/src/main/java/myblog/blog/article/application/port/incomming/TempArticleUseCase.java b/src/main/java/myblog/blog/article/application/port/incomming/TempArticleUseCase.java new file mode 100644 index 0000000..ecfc976 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/incomming/TempArticleUseCase.java @@ -0,0 +1,11 @@ +package myblog.blog.article.application.port.incomming; + +import myblog.blog.article.domain.TempArticle; + +import java.util.Optional; + +public interface TempArticleUseCase { + void saveTemp(TempArticle tempArticle); + Optional getTempArticle(); + void deleteTemp(); +} diff --git a/src/main/java/myblog/blog/article/application/port/outgoing/ArticleBackupRepositoryPort.java b/src/main/java/myblog/blog/article/application/port/outgoing/ArticleBackupRepositoryPort.java new file mode 100644 index 0000000..29c4fa2 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/outgoing/ArticleBackupRepositoryPort.java @@ -0,0 +1,7 @@ +package myblog.blog.article.application.port.outgoing; + +import myblog.blog.article.domain.Article; + +public interface ArticleBackupRepositoryPort { + public void backup(Article article); +} diff --git a/src/main/java/myblog/blog/article/application/port/outgoing/ArticleRepositoryPort.java b/src/main/java/myblog/blog/article/application/port/outgoing/ArticleRepositoryPort.java new file mode 100644 index 0000000..8f240a6 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/outgoing/ArticleRepositoryPort.java @@ -0,0 +1,27 @@ +package myblog.blog.article.application.port.outgoing; + +import myblog.blog.article.domain.Article; +import myblog.blog.category.domain.Category; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +import java.util.List; +import java.util.Optional; + +public interface ArticleRepositoryPort { + List
findTop6ByOrderByHitDesc(); + List
findTop6ByCategoryOrderByIdDesc(Category category); + Slice
findByOrderByIdDesc(Pageable pageable); + List
findByOrderByIdDescWithList(Pageable pageable); + List
findByOrderByIdDesc(Long articleId, Pageable pageable); + Slice
findBySubCategoryOrderByIdDesc(Pageable pageable, String category); + Slice
findBySupCategoryOrderByIdDesc(Pageable pageable, String category); + Article findArticleByIdFetchCategoryAndTags(Long articleId); + Page
findAllByArticleTagsOrderById(Pageable pageable, String tag); + Page
findAllByKeywordOrderById(Pageable pageable, String keyword); + List
findAllByOrderByIdDesc(); + Optional
findById(Long articleId); + void save(Article newArticle); + void deleteArticle(Long articleId); +} diff --git a/src/main/java/myblog/blog/article/application/port/outgoing/TagRepositoryPort.java b/src/main/java/myblog/blog/article/application/port/outgoing/TagRepositoryPort.java new file mode 100644 index 0000000..912ebd6 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/outgoing/TagRepositoryPort.java @@ -0,0 +1,9 @@ +package myblog.blog.article.application.port.outgoing; + +import myblog.blog.article.domain.Tags; + +import java.util.List; + +public interface TagRepositoryPort { + List findAll(); +} diff --git a/src/main/java/myblog/blog/article/application/port/outgoing/TempArticleRepositoryPort.java b/src/main/java/myblog/blog/article/application/port/outgoing/TempArticleRepositoryPort.java new file mode 100644 index 0000000..30e71b7 --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/outgoing/TempArticleRepositoryPort.java @@ -0,0 +1,11 @@ +package myblog.blog.article.application.port.outgoing; + +import myblog.blog.article.domain.TempArticle; + +import java.util.Optional; + +public interface TempArticleRepositoryPort { + void save(TempArticle tempArticle); + Optional findById(long l); + void delete(TempArticle tempArticle); +} diff --git a/src/main/java/myblog/blog/article/application/port/request/ArticleCreateRequest.java b/src/main/java/myblog/blog/article/application/port/request/ArticleCreateRequest.java new file mode 100644 index 0000000..dd2168a --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/request/ArticleCreateRequest.java @@ -0,0 +1,27 @@ +package myblog.blog.article.application.port.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import myblog.blog.article.adapter.incomming.web.ArticleForm; + +@Getter +@AllArgsConstructor +public class ArticleCreateRequest { + private Long memberId; + private String title; + private String content; + private String toc; + private String thumbnailUrl; + private String category; + private String tags; + + static public ArticleCreateRequest from(ArticleForm articleForm, Long memberId){ + return new ArticleCreateRequest(memberId, + articleForm.getTitle(), + articleForm.getContent(), + articleForm.getToc(), + articleForm.getThumbnailUrl(), + articleForm.getCategory(), + articleForm.getTags()); + } +} diff --git a/src/main/java/myblog/blog/article/application/port/request/ArticleEditRequest.java b/src/main/java/myblog/blog/article/application/port/request/ArticleEditRequest.java new file mode 100644 index 0000000..a45e4ec --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/request/ArticleEditRequest.java @@ -0,0 +1,29 @@ +package myblog.blog.article.application.port.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import myblog.blog.article.adapter.incomming.web.ArticleForm; + +@Getter +@AllArgsConstructor +public class ArticleEditRequest { + + private Long articleId; + private String title; + private String content; + private String toc; + private String thumbnailUrl; + private String categoryName; + private String tags; + + static public ArticleEditRequest from(Long articleId, ArticleForm articleForm){ + return new ArticleEditRequest(articleId, + articleForm.getTitle(), + articleForm.getContent(), + articleForm.getToc(), + articleForm.getThumbnailUrl(), + articleForm.getCategory(), + articleForm.getTags()); + } + +} diff --git a/src/main/java/myblog/blog/article/dto/ArticleDtoByCategory.java b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseByCategory.java similarity index 62% rename from src/main/java/myblog/blog/article/dto/ArticleDtoByCategory.java rename to src/main/java/myblog/blog/article/application/port/response/ArticleResponseByCategory.java index 0d89a44..019d952 100644 --- a/src/main/java/myblog/blog/article/dto/ArticleDtoByCategory.java +++ b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseByCategory.java @@ -1,4 +1,4 @@ -package myblog.blog.article.dto; +package myblog.blog.article.application.port.response; import lombok.Getter; import lombok.Setter; @@ -7,7 +7,7 @@ import lombok.Setter; - 카테고리별 게시물 표시용 DTO */ @Getter @Setter -public class ArticleDtoByCategory { +public class ArticleResponseByCategory { private String title; private Long id; } diff --git a/src/main/java/myblog/blog/article/dto/ArticleDtoForCardBox.java b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseForCardBox.java similarity index 63% rename from src/main/java/myblog/blog/article/dto/ArticleDtoForCardBox.java rename to src/main/java/myblog/blog/article/application/port/response/ArticleResponseForCardBox.java index 9914ad1..98f64c9 100644 --- a/src/main/java/myblog/blog/article/dto/ArticleDtoForCardBox.java +++ b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseForCardBox.java @@ -1,4 +1,4 @@ -package myblog.blog.article.dto; +package myblog.blog.article.application.port.response; import lombok.Getter; import lombok.Setter; @@ -6,11 +6,11 @@ import lombok.Setter; import java.time.LocalDateTime; /* - - 메인 화면 출력용 아티클 DTO + - 메인 화면 렌더링용 아티클 DTO */ @Getter @Setter -public class ArticleDtoForCardBox { +public class ArticleResponseForCardBox { private Long id; private String title; private String content; diff --git a/src/main/java/myblog/blog/article/dto/ArticleDtoForDetail.java b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseForDetail.java similarity index 78% rename from src/main/java/myblog/blog/article/dto/ArticleDtoForDetail.java rename to src/main/java/myblog/blog/article/application/port/response/ArticleResponseForDetail.java index 4bb00dc..a0d072e 100644 --- a/src/main/java/myblog/blog/article/dto/ArticleDtoForDetail.java +++ b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseForDetail.java @@ -1,9 +1,8 @@ -package myblog.blog.article.dto; +package myblog.blog.article.application.port.response; import lombok.Getter; import lombok.Setter; -import javax.validation.constraints.NotBlank; import java.time.LocalDateTime; import java.util.List; @@ -11,7 +10,7 @@ import java.util.List; - 아티클 상세조회용 DTO */ @Getter @Setter -public class ArticleDtoForDetail { +public class ArticleResponseForDetail { private Long id; private String title; diff --git a/src/main/java/myblog/blog/article/dto/ArticleDtoForEdit.java b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseForEdit.java similarity index 74% rename from src/main/java/myblog/blog/article/dto/ArticleDtoForEdit.java rename to src/main/java/myblog/blog/article/application/port/response/ArticleResponseForEdit.java index bb8ca41..f73500e 100644 --- a/src/main/java/myblog/blog/article/dto/ArticleDtoForEdit.java +++ b/src/main/java/myblog/blog/article/application/port/response/ArticleResponseForEdit.java @@ -1,10 +1,8 @@ -package myblog.blog.article.dto; +package myblog.blog.article.application.port.response; import lombok.Getter; import lombok.Setter; import myblog.blog.category.domain.Category; -import myblog.blog.tags.domain.ArticleTagList; -import myblog.blog.tags.dto.TagsDto; import java.util.ArrayList; import java.util.List; @@ -13,7 +11,7 @@ import java.util.List; - 아티클 수정 폼을 위한 DTO */ @Getter @Setter -public class ArticleDtoForEdit { +public class ArticleResponseForEdit { private Long id; private String title; diff --git a/src/main/java/myblog/blog/article/application/port/response/TagsResponse.java b/src/main/java/myblog/blog/article/application/port/response/TagsResponse.java new file mode 100644 index 0000000..c4449ef --- /dev/null +++ b/src/main/java/myblog/blog/article/application/port/response/TagsResponse.java @@ -0,0 +1,15 @@ +package myblog.blog.article.application.port.response; + +import lombok.Data; + + /* + - 뷰단 사용을 위한 DTO + */ +@Data +public class TagsResponse { + private String name; + public TagsResponse(){} + public TagsResponse(String name) { + this.name = name; + } +} diff --git a/src/main/java/myblog/blog/article/dto/TempArticleDto.java b/src/main/java/myblog/blog/article/application/port/response/TempArticleResponse.java similarity index 61% rename from src/main/java/myblog/blog/article/dto/TempArticleDto.java rename to src/main/java/myblog/blog/article/application/port/response/TempArticleResponse.java index 8c9996c..5869ef9 100644 --- a/src/main/java/myblog/blog/article/dto/TempArticleDto.java +++ b/src/main/java/myblog/blog/article/application/port/response/TempArticleResponse.java @@ -1,4 +1,4 @@ -package myblog.blog.article.dto; +package myblog.blog.article.application.port.response; import lombok.Getter; import lombok.Setter; @@ -7,6 +7,6 @@ import lombok.Setter; */ @Getter @Setter -public class TempArticleDto { +public class TempArticleResponse { private String content; } diff --git a/src/main/java/myblog/blog/article/domain/Article.java b/src/main/java/myblog/blog/article/domain/Article.java index 59cbff8..4f49504 100644 --- a/src/main/java/myblog/blog/article/domain/Article.java +++ b/src/main/java/myblog/blog/article/domain/Article.java @@ -1,20 +1,17 @@ package myblog.blog.article.domain; -import lombok.Builder; -import lombok.Getter; -import myblog.blog.article.dto.ArticleForm; import myblog.blog.shared.BasicEntity; import myblog.blog.category.domain.Category; import myblog.blog.comment.domain.Comment; import myblog.blog.member.doamin.Member; -import myblog.blog.tags.domain.ArticleTagList; + +import lombok.Builder; +import lombok.Getter; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; - import javax.persistence.*; import java.util.*; - /* - 아티클 Entity - toc 추후 개발 예정 @@ -89,14 +86,13 @@ public class Article extends BasicEntity { /* - 아티클 수정을 위한 로직 */ - public void isEditedFrom(ArticleForm articleForm, Category category){ - this.content = articleForm.getContent(); - this.title = articleForm.getTitle(); - this.toc = articleForm.getToc(); + public void edit(String content, String title, String toc, String thumbnailUrl, Category category){ + this.content = content; + this.title = title; + this.toc = toc; this.category = category; - - if(articleForm.getThumbnailUrl() != null){ - this.thumbnailUrl = articleForm.getThumbnailUrl(); + if(thumbnailUrl != null){ + this.thumbnailUrl = getThumbnailUrl(); } } /* diff --git a/src/main/java/myblog/blog/tags/domain/ArticleTagList.java b/src/main/java/myblog/blog/article/domain/ArticleTagList.java similarity index 84% rename from src/main/java/myblog/blog/tags/domain/ArticleTagList.java rename to src/main/java/myblog/blog/article/domain/ArticleTagList.java index f1b8791..2f68411 100644 --- a/src/main/java/myblog/blog/tags/domain/ArticleTagList.java +++ b/src/main/java/myblog/blog/article/domain/ArticleTagList.java @@ -1,14 +1,13 @@ -package myblog.blog.tags.domain; +package myblog.blog.article.domain; -import lombok.*; -import myblog.blog.article.domain.Article; +import lombok.Getter; import myblog.blog.shared.BasicEntity; import javax.persistence.*; /* - - 다 대 다 연관관계 해소 엔티티 -*/ + - 다 대 다 연관관계 해소 엔티티 + */ @Entity @Getter @SequenceGenerator( diff --git a/src/main/java/myblog/blog/tags/domain/Tags.java b/src/main/java/myblog/blog/article/domain/Tags.java similarity index 86% rename from src/main/java/myblog/blog/tags/domain/Tags.java rename to src/main/java/myblog/blog/article/domain/Tags.java index b1c6303..7ade06e 100644 --- a/src/main/java/myblog/blog/tags/domain/Tags.java +++ b/src/main/java/myblog/blog/article/domain/Tags.java @@ -1,10 +1,11 @@ -package myblog.blog.tags.domain; +package myblog.blog.article.domain; -import lombok.*; +import lombok.Getter; import myblog.blog.shared.BasicEntity; import javax.persistence.*; -import java.util.*; +import java.util.ArrayList; +import java.util.List; @Entity @SequenceGenerator( @@ -30,4 +31,4 @@ public class Tags extends BasicEntity { public Tags(String name) { this.name = name; } -} +} \ No newline at end of file diff --git a/src/main/java/myblog/blog/article/domain/TempArticle.java b/src/main/java/myblog/blog/article/domain/TempArticle.java index 4badcbe..1632f81 100644 --- a/src/main/java/myblog/blog/article/domain/TempArticle.java +++ b/src/main/java/myblog/blog/article/domain/TempArticle.java @@ -4,6 +4,8 @@ import lombok.Getter; import myblog.blog.shared.BasicEntity; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; /* - 임시 아티클 저장 Entity diff --git a/src/main/java/myblog/blog/article/service/ArticleService.java b/src/main/java/myblog/blog/article/service/ArticleService.java deleted file mode 100644 index 9d65b0f..0000000 --- a/src/main/java/myblog/blog/article/service/ArticleService.java +++ /dev/null @@ -1,219 +0,0 @@ -package myblog.blog.article.service; - -import lombok.RequiredArgsConstructor; -import myblog.blog.article.domain.Article; -import myblog.blog.category.domain.Category; -import myblog.blog.member.doamin.Member; -import myblog.blog.article.dto.ArticleForm; -import myblog.blog.article.repository.ArticleRepository; -import myblog.blog.article.repository.NaArticleRepository; -import myblog.blog.category.service.CategoryService; -import myblog.blog.tags.service.TagsService; -import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GitHub; -import org.kohsuke.github.GitHubBuilder; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Slice; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.beans.factory.annotation.Value; -import java.io.IOException; -import java.util.List; - -@Service -@Transactional -@RequiredArgsConstructor -public class ArticleService { - - @Value("${git.gitToken}") - private String gitToken; - @Value("${git.repo}") - private String gitRepo; - - private final TagsService tagsService; - private final CategoryService categoryService; - private final ArticleRepository articleRepository; - private final NaArticleRepository naArticleRepository; - - /* - - 아티클 작성 로직 - - 글작성시 아티클 캐싱 초기화 - */ - @CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true) - public Long writeArticle(ArticleForm articleDto, Member writer) { - Article newArticle = articleFrom(articleDto, writer); - articleRepository.save(newArticle); - tagsService.createNewTagsAndArticleTagList(articleDto.getTags(), newArticle); - return newArticle.getId(); - } - - /* - - 아티클 수정 로직 - - 글 수정시 아티클 캐싱 초기화 - */ - @CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true) - public void editArticle(Long articleId, ArticleForm articleForm) { - Article article = articleRepository.findById(articleId).get(); - Category category = categoryService.findCategory(articleForm.getCategory()); - tagsService.deleteAllTagsWith(article); - tagsService.createNewTagsAndArticleTagList(articleForm.getTags(), article); - article.isEditedFrom(articleForm,category); - } - - /* - - 아티클 삭제 로직 - - 글 삭제시 아티클 캐싱 초기화 - */ - @CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true) - public void deleteArticle(Long articleId) { - naArticleRepository.deleteArticle(articleId); - } - - /* - - 메인화면 위한 인기 아티클 6개 목록 가져오기 - - 레이아웃 렌더링 성능 향상을 위해 캐싱작업 - 카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화 - DTO 매핑 로직 서비스단에서 처리 - */ - @Cacheable(value = "layoutCaching", key = "1") - public List
getPopularArticles() { - return articleRepository.findTop6ByOrderByHitDesc(); - } - - /* - - 메인화면 위한 최신 아티클 커서 페이징해서 가져오기 - - 레이아웃 렌더링 성능 향상을 위해 캐싱작업 - 카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화 - */ - @Cacheable(value = "layoutRecentArticleCaching", key = "#lastArticleId") - public List
getRecentArticles(Long lastArticleId) { - return lastArticleId.equals(0L)? - articleRepository - .findByOrderByIdDescWithList(PageRequest.of(0, 5)) - : - articleRepository - .findByOrderByIdDesc(lastArticleId, PageRequest.of(0, 5)); - - } - - /* - - 카테고리별 게시물 페이징 처리해서 가져오기 - */ - public Slice
getArticlesByCategory(String category, Integer tier, Integer page) { - Slice
articles = null; - - if (tier.equals(0)) { - articles = articleRepository - .findByOrderByIdDesc( - PageRequest.of(pageResolve(page), 5)); - } - - if (tier.equals(1)) { - articles = articleRepository - .findBySupCategoryOrderByIdDesc( - PageRequest.of(pageResolve(page), 5), category); - - } - - if (tier.equals(2)) { - articles = articleRepository - .findBySubCategoryOrderByIdDesc( - PageRequest.of(pageResolve(page), 5), category); - } - - return articles; - } - - /* - - 아티클 읽기 위한 페치로 전체 가져오기 - */ - public Article readArticle(Long id){ - return articleRepository.findArticleByIdFetchCategoryAndTags(id); - } - - /* - - 모든 게시물 조회 - */ - public List
getTotalArticle(){ - return articleRepository.findAllByOrderByIdDesc(); - } - - /* - - 카테고리별 최신게시물 6개만 아티클 상세뷰 위해 가져오는로직 - */ - public List
getArticlesByCategoryForDetailView(Category category){ - return articleRepository.findTop6ByCategoryOrderByIdDesc(category); - } - - /* - - 태그별 게시물 페이징 처리해서 가져오기 - */ - public Page
getArticlesByTag(String tag, Integer page) { - return articleRepository - .findAllByArticleTagsOrderById(PageRequest.of(pageResolve(page), 5), tag); - } - - /* - - 검색어별 게시물 페이징 처리해서 가져오기 - */ - public Page
getArticlesByKeyword(String keyword, Integer page) { - return articleRepository - .findAllByKeywordOrderById(PageRequest.of(pageResolve(page),5), keyword); - } - - /* - - 아티클 조회수 추가 - */ - public void addHit(Article article) { - article.addHit(); - } - - /* - - 깃헙에 아티클 푸시하기 - */ - public void pushArticleToGithub(Long articleId) { - articleRepository.findById(articleId).ifPresent(this::pushArticleToGithub); - } - - private void pushArticleToGithub(Article article) { - try { - GitHub gitHub = new GitHubBuilder().withOAuthToken(gitToken).build(); - GHRepository repository = gitHub.getRepository(gitRepo); - repository.createContent() - .path(article.getCategory().getParents().getTitle()+"/"+ article.getCategory().getTitle()+"/"+ article.getTitle()+".md") - .content(article.getContent()) - .message("test") - .branch("main") - .commit(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /* - - 페이지 시작점 0~1변경 메서드 - */ - private int pageResolve(Integer rawPage) { - if (rawPage == null || rawPage == 1) { - return 0; - } else return rawPage - 1; - } - - /* - - 새로운 아티클 도메인 생성 메서드 - */ - private Article articleFrom(ArticleForm articleDto, Member writer) { - return Article.builder() - .title(articleDto.getTitle()) - .content(articleDto.getContent()) - .toc(articleDto.getToc()) - .member(writer) - .thumbnailUrl(articleDto.getThumbnailUrl()) - .category(categoryService.findCategory(articleDto.getCategory())) - .build(); - } - -} diff --git a/src/main/java/myblog/blog/category/controller/CategoryController.java b/src/main/java/myblog/blog/category/controller/CategoryController.java index 820e042..1e87203 100644 --- a/src/main/java/myblog/blog/category/controller/CategoryController.java +++ b/src/main/java/myblog/blog/category/controller/CategoryController.java @@ -4,7 +4,7 @@ import lombok.RequiredArgsConstructor; import myblog.blog.shared.exception.CustomFormException; import myblog.blog.shared.exception.ListValidator; import myblog.blog.category.dto.CategoryForView; -import myblog.blog.category.dto.CategoryNormalDto; +import myblog.blog.category.dto.CategorySimpleView; import myblog.blog.category.service.CategoryService; import myblog.blog.comment.dto.CommentDtoForLayout; import myblog.blog.comment.service.CommentService; @@ -37,8 +37,8 @@ public class CategoryController { public String editCategoryForm(Model model) { // DTO 매핑 전처리 - List categoryList = categoryService.getCategorytCountList(); - List copyList = cloneList(categoryList); + List categoryList = categoryService.getCategorytCountList(); + List copyList = cloneList(categoryList); copyList.remove(0); CategoryForView categoryForView = CategoryForView.createCategory(categoryList); List comments = commentService.recentCommentList(); @@ -56,7 +56,7 @@ public class CategoryController { */ @PostMapping("/category/edit") public @ResponseBody - String editCategory(@RequestBody List categoryList, Errors errors) { + String editCategory(@RequestBody List categoryList, Errors errors) { // List DTO 검증을 위한 커스텀 validator listValidator.validate(categoryList, errors); // 유효성 검사 @@ -67,11 +67,11 @@ public class CategoryController { categoryService.changeCategory(categoryList); return "변경 성공"; } - private List cloneList(List categoryList) { + private List cloneList(List categoryList) { return categoryList .stream() .map(categoryNormalDto -> - modelMapper.map(categoryNormalDto, CategoryNormalDto.class)) + modelMapper.map(categoryNormalDto, CategorySimpleView.class)) .collect(Collectors.toList()); } } diff --git a/src/main/java/myblog/blog/category/dto/CategoryForView.java b/src/main/java/myblog/blog/category/dto/CategoryForView.java index c0eb41e..8424b62 100644 --- a/src/main/java/myblog/blog/category/dto/CategoryForView.java +++ b/src/main/java/myblog/blog/category/dto/CategoryForView.java @@ -4,7 +4,6 @@ import lombok.Getter; import lombok.Setter; import java.util.ArrayList; -import java.util.Collections; import java.util.List; /* @@ -25,7 +24,7 @@ public class CategoryForView { /* - 스태틱 생성 메서드 */ - public static CategoryForView createCategory(List crList) { + public static CategoryForView createCategory(List crList) { return recursiveBuildFromCategoryDto(0, crList); } @@ -35,12 +34,12 @@ public class CategoryForView { 2. Depth 변화시 재귀 호출 / 재귀 탈출 3. 탈출시 상위 카테고리 list로 삽입하여 트리구조 작성 */ - private static CategoryForView recursiveBuildFromCategoryDto(int tier, List source) { + private static CategoryForView recursiveBuildFromCategoryDto(int tier, List source) { CategoryForView categoryForView = new CategoryForView(); while (!source.isEmpty()) { - CategoryNormalDto cSource = source.get(0); + CategorySimpleView cSource = source.get(0); if (cSource.getTier() == tier) { if(categoryForView.getTitle() != null diff --git a/src/main/java/myblog/blog/category/dto/CategoryNormalDto.java b/src/main/java/myblog/blog/category/dto/CategorySimpleView.java similarity index 92% rename from src/main/java/myblog/blog/category/dto/CategoryNormalDto.java rename to src/main/java/myblog/blog/category/dto/CategorySimpleView.java index 70949d4..e7d5c83 100644 --- a/src/main/java/myblog/blog/category/dto/CategoryNormalDto.java +++ b/src/main/java/myblog/blog/category/dto/CategorySimpleView.java @@ -12,7 +12,7 @@ import javax.validation.constraints.NotBlank; @Getter @Setter @ToString -public class CategoryNormalDto { +public class CategorySimpleView { private Long id; @NotBlank(message = "카테고리명은 공백일 수 없습니다.") diff --git a/src/main/java/myblog/blog/category/repository/CategoryRepository.java b/src/main/java/myblog/blog/category/repository/CategoryRepository.java index cb14902..0877564 100644 --- a/src/main/java/myblog/blog/category/repository/CategoryRepository.java +++ b/src/main/java/myblog/blog/category/repository/CategoryRepository.java @@ -5,13 +5,14 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import java.util.List; +import java.util.Optional; public interface CategoryRepository extends JpaRepository { /* - 카테고리 이름으로 카테고리 찾기 */ - Category findByTitle(String title); + Optional findByTitle(String title); /* - 티어별 카테고리들 가져오기 diff --git a/src/main/java/myblog/blog/category/repository/NaCategoryRepository.java b/src/main/java/myblog/blog/category/repository/NaCategoryRepository.java index 9ddb376..42393d0 100644 --- a/src/main/java/myblog/blog/category/repository/NaCategoryRepository.java +++ b/src/main/java/myblog/blog/category/repository/NaCategoryRepository.java @@ -1,6 +1,6 @@ package myblog.blog.category.repository; -import myblog.blog.category.dto.CategoryNormalDto; +import myblog.blog.category.dto.CategorySimpleView; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.springframework.stereotype.Repository; @@ -23,6 +23,6 @@ public interface NaCategoryRepository { " group by c.title, b.title with rollup) e\n" + " right join category f on (e.title = f.title)\n" + " order by pOrder, cOrder ") - List getCategoryCount(); + List getCategoryCount(); } diff --git a/src/main/java/myblog/blog/category/service/CategoryService.java b/src/main/java/myblog/blog/category/service/CategoryService.java index ae38fad..5e14b6e 100644 --- a/src/main/java/myblog/blog/category/service/CategoryService.java +++ b/src/main/java/myblog/blog/category/service/CategoryService.java @@ -2,17 +2,15 @@ package myblog.blog.category.service; import lombok.RequiredArgsConstructor; import myblog.blog.category.domain.Category; -import myblog.blog.category.dto.CategoryNormalDto; +import myblog.blog.category.dto.CategorySimpleView; import myblog.blog.category.dto.CategoryForView; import myblog.blog.category.repository.CategoryRepository; import myblog.blog.category.repository.NaCategoryRepository; -import myblog.blog.member.doamin.Role; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.annotation.PostConstruct; import java.util.List; import java.util.Optional; @@ -28,7 +26,8 @@ public class CategoryService { - 카테고리 이름으로 카테고리 찾기 */ public Category findCategory(String title) { - return categoryRepository.findByTitle(title); + return categoryRepository.findByTitle(title) + .orElseThrow(() -> new IllegalArgumentException("NotFoundCategoryException")); } /* @@ -41,7 +40,7 @@ public class CategoryService { /* - 카테고리와 카테고리별 아티클 수 찾기 */ - public List getCategorytCountList() { + public List getCategorytCountList() { return naCategoryRepository.getCategoryCount(); } @@ -74,7 +73,7 @@ public class CategoryService { */ @Transactional @CacheEvict(value = {"layoutCaching", "seoCaching"}, allEntries = true) - public void changeCategory(List categoryList) { + public void changeCategory(List categoryList) { // 1.카테고리 리스트 순서 작성 sortingOrder(categoryList); @@ -83,62 +82,62 @@ public class CategoryService { // 3. 카테고리 변경 루프 while (!categoryList.isEmpty()) { - CategoryNormalDto categoryNormalDto = categoryList.get(0); + CategorySimpleView categorySimpleView = categoryList.get(0); categoryList.remove(0); // 부모카테고리인경우 - if (categoryNormalDto.getTier() == 1) { + if (categorySimpleView.getTier() == 1) { Category pCategory = null; // 부모카테고리가 기존에 존재 x - if (categoryNormalDto.getId() == null) { - pCategory = createNewCategory(categoryNormalDto, null); + if (categorySimpleView.getId() == null) { + pCategory = createNewCategory(categorySimpleView, null); } // 부모카테고리가 기존에 존재 o else { for (int i = 0; i < categoryListFromDb.size(); i++) { - if (categoryListFromDb.get(i).getId().equals(categoryNormalDto.getId())) { + if (categoryListFromDb.get(i).getId().equals(categorySimpleView.getId())) { pCategory = categoryListFromDb.get(i); categoryListFromDb.remove(i); break; } } pCategory.updateCategory( - categoryNormalDto.getTitle(), - categoryNormalDto.getTier(), - categoryNormalDto.getPOrder(), - categoryNormalDto.getCOrder(), + categorySimpleView.getTitle(), + categorySimpleView.getTier(), + categorySimpleView.getPOrder(), + categorySimpleView.getCOrder(), null ); } while (!categoryList.isEmpty()) { - CategoryNormalDto subCategoryNormalDto = categoryList.get(0); - if (subCategoryNormalDto.getTier() == 1) break; + CategorySimpleView subCategorySimpleView = categoryList.get(0); + if (subCategorySimpleView.getTier() == 1) break; categoryList.remove(0); // 자식 카테고리인경우 Category cCategory = null; // 카테고리가 기존에 존재 x - if (subCategoryNormalDto.getId() == null) { - cCategory = createNewCategory(subCategoryNormalDto, pCategory.getTitle()); + if (subCategorySimpleView.getId() == null) { + cCategory = createNewCategory(subCategorySimpleView, pCategory.getTitle()); } // 카테고리가 기존에 존재 o else { for (int i = 0; i < categoryListFromDb.size(); i++) { - if (categoryListFromDb.get(i).getId().equals(subCategoryNormalDto.getId())) { + if (categoryListFromDb.get(i).getId().equals(subCategorySimpleView.getId())) { cCategory = categoryListFromDb.get(i); categoryListFromDb.remove(i); break; } } cCategory.updateCategory( - subCategoryNormalDto.getTitle(), - subCategoryNormalDto.getTier(), - subCategoryNormalDto.getPOrder(), - subCategoryNormalDto.getCOrder(), + subCategorySimpleView.getTitle(), + subCategorySimpleView.getTier(), + subCategorySimpleView.getPOrder(), + subCategorySimpleView.getCOrder(), pCategory); } } @@ -152,17 +151,18 @@ public class CategoryService { - 새로운 카테고리 생성하기 - 상위 카테고리 존재 유무 분기 */ - private Category createNewCategory(CategoryNormalDto categoryNormalDto, String parent) { + private Category createNewCategory(CategorySimpleView categorySimpleView, String parent) { Category parentCategory = null; if (parent != null) { - parentCategory = categoryRepository.findByTitle(parent); + parentCategory = categoryRepository.findByTitle(parent) + .orElseThrow(() -> new IllegalArgumentException("NotFoundCategoryException")); } Category category = Category.builder() - .title(categoryNormalDto.getTitle()) - .pSortNum(categoryNormalDto.getPOrder()) - .cSortNum(categoryNormalDto.getCOrder()) - .tier(categoryNormalDto.getTier()) + .title(categorySimpleView.getTitle()) + .pSortNum(categorySimpleView.getPOrder()) + .cSortNum(categorySimpleView.getCOrder()) + .tier(categorySimpleView.getTier()) .parents(parentCategory) .build(); categoryRepository.save(category); @@ -172,12 +172,12 @@ public class CategoryService { /* - 카테고리 변경을 위해 카테고리의 순번을 작성하는 로직 */ - private void sortingOrder(List categoryList) { + private void sortingOrder(List categoryList) { int pOrderIndex = 0; int cOrderIndex = 0; //티어별 트리구조로 순서 작성 로직 - for (CategoryNormalDto categoryDto : categoryList) { + for (CategorySimpleView categoryDto : categoryList) { if (categoryDto.getTier() == 1) { cOrderIndex = 0; diff --git a/src/main/java/myblog/blog/comment/controller/CommentController.java b/src/main/java/myblog/blog/comment/controller/CommentController.java index fa16c8d..6c7cdba 100644 --- a/src/main/java/myblog/blog/comment/controller/CommentController.java +++ b/src/main/java/myblog/blog/comment/controller/CommentController.java @@ -1,8 +1,9 @@ package myblog.blog.comment.controller; import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase; import myblog.blog.article.domain.Article; -import myblog.blog.article.service.ArticleService; +import myblog.blog.article.application.ArticleService; import myblog.blog.comment.dto.CommentDto; import myblog.blog.comment.dto.CommentForm; import myblog.blog.comment.service.CommentService; @@ -22,7 +23,6 @@ import java.util.Objects; public class CommentController { private final CommentService commentService; - private final ArticleService articleService; /* - 아티클 조회시 아티클에 달린 댓글들 전체 조회 @@ -45,14 +45,12 @@ public class CommentController { } Member member = principal.getMember(); - Article article = articleService.readArticle(articleId); - // 부모 댓글인지 자식댓글인지 분기로 저장 if(parentId != null){ - commentService.saveCComment(commentForm, member, article, parentId); + commentService.saveCComment(commentForm, member, articleId, parentId); } else { - commentService.savePComment(commentForm, member, article); + commentService.savePComment(commentForm, member, articleId); } return CommentDto.listCreateFrom(commentService.getCommentList(articleId),0); diff --git a/src/main/java/myblog/blog/comment/service/CommentService.java b/src/main/java/myblog/blog/comment/service/CommentService.java index 9ab388c..be405f1 100644 --- a/src/main/java/myblog/blog/comment/service/CommentService.java +++ b/src/main/java/myblog/blog/comment/service/CommentService.java @@ -1,6 +1,7 @@ package myblog.blog.comment.service; import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.incomming.ArticleUseCase; import myblog.blog.article.domain.Article; import myblog.blog.comment.domain.Comment; import myblog.blog.comment.dto.CommentDtoForLayout; @@ -21,6 +22,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class CommentService { + private final ArticleUseCase articleUseCase; + private final CommentRepository commentRepository; private final NaCommentRepository naCommentRepository; @@ -35,7 +38,9 @@ public class CommentService { - 부모 댓글 저장 */ @CacheEvict(value = "layoutRecentCommentCaching", allEntries = true) - public void savePComment(CommentForm commentForm, Member member, Article article){ + public void savePComment(CommentForm commentForm, Member member, Long articleId){ + + Article article = articleUseCase.getArticle(articleId); Comment comment = Comment.builder() .article(article) @@ -54,8 +59,9 @@ public class CommentService { - 자식 댓글 저장 */ @CacheEvict(value = "layoutRecentCommentCaching", allEntries = true) - public void saveCComment(CommentForm commentForm, Member member, Article article, Long parentId) { + public void saveCComment(CommentForm commentForm, Member member, Long articleId, Long parentId) { + Article article = articleUseCase.getArticle(articleId); Comment pComment = commentRepository.findById(parentId).get(); Comment comment = Comment.builder() diff --git a/src/main/java/myblog/blog/member/dto/MemberDto.java b/src/main/java/myblog/blog/member/dto/MemberDto.java deleted file mode 100644 index 73ea6c8..0000000 --- a/src/main/java/myblog/blog/member/dto/MemberDto.java +++ /dev/null @@ -1,24 +0,0 @@ -package myblog.blog.member.dto; - -import lombok.Getter; -import lombok.Setter; - -import javax.persistence.Column; - -/* - - 뷰단에 사용할 멈버 DTO -*/ -@Getter @Setter -public class MemberDto { - - private Long id; - - private String username; - - private String userId; - - private String email; - - private String picUrl; - -} diff --git a/src/main/java/myblog/blog/member/dto/MemberVo.java b/src/main/java/myblog/blog/member/dto/MemberVo.java new file mode 100644 index 0000000..2255826 --- /dev/null +++ b/src/main/java/myblog/blog/member/dto/MemberVo.java @@ -0,0 +1,32 @@ +package myblog.blog.member.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import myblog.blog.member.doamin.Member; + +/* + - 뷰단에 사용할 멈버 DTO +*/ +@Getter +@AllArgsConstructor +public class MemberVo { + + private Long id; + + private String username; + + private String userId; + + private String email; + + private String picUrl; + + static public MemberVo from(Member member){ + return new MemberVo(member.getId(), + member.getUsername(), + member.getUserId(), + member.getEmail(), + member.getPicUrl()); + } +} diff --git a/src/main/java/myblog/blog/member/service/Oauth2MemberService.java b/src/main/java/myblog/blog/member/service/Oauth2MemberService.java index 51c42c5..3596506 100644 --- a/src/main/java/myblog/blog/member/service/Oauth2MemberService.java +++ b/src/main/java/myblog/blog/member/service/Oauth2MemberService.java @@ -112,4 +112,8 @@ public class Oauth2MemberService extends DefaultOAuth2UserService { } + public Member findById(Long memberId) { + return memberRepository.findById(memberId) + .orElseThrow(() -> new IllegalArgumentException("NotFoundMemberException")); + } } diff --git a/src/main/java/myblog/blog/rss/RssController.java b/src/main/java/myblog/blog/seo/adapter/incomming/RssController.java similarity index 73% rename from src/main/java/myblog/blog/rss/RssController.java rename to src/main/java/myblog/blog/seo/adapter/incomming/RssController.java index 28c94ae..144fea1 100644 --- a/src/main/java/myblog/blog/rss/RssController.java +++ b/src/main/java/myblog/blog/seo/adapter/incomming/RssController.java @@ -1,8 +1,9 @@ -package myblog.blog.rss; +package myblog.blog.seo.adapter.incomming; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import myblog.blog.article.application.port.incomming.RssUseCase; /* - rss 피드 발행 요청 @@ -12,10 +13,10 @@ import org.springframework.web.bind.annotation.*; @Controller @RequiredArgsConstructor public class RssController { - private final RssService rssService; + private final RssUseCase rssUseCase; @GetMapping(value = "/rss",produces = "application/xml;charset=utf-8") public @ResponseBody String rssFeed() { - return rssService.getRssFeed(); + return rssUseCase.getRssFeed(); } } diff --git a/src/main/java/myblog/blog/sitemap/SiteMapController.java b/src/main/java/myblog/blog/seo/adapter/incomming/SiteMapController.java similarity index 71% rename from src/main/java/myblog/blog/sitemap/SiteMapController.java rename to src/main/java/myblog/blog/seo/adapter/incomming/SiteMapController.java index f10b424..22bc8fd 100644 --- a/src/main/java/myblog/blog/sitemap/SiteMapController.java +++ b/src/main/java/myblog/blog/seo/adapter/incomming/SiteMapController.java @@ -1,8 +1,9 @@ -package myblog.blog.sitemap; +package myblog.blog.seo.adapter.incomming; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import myblog.blog.article.application.port.incomming.SiteMapUseCase; /* - siteMap.xml 요청 @@ -12,10 +13,10 @@ import org.springframework.web.bind.annotation.*; @Controller @RequiredArgsConstructor public class SiteMapController { - private final SiteMapService siteMapService; + private final SiteMapUseCase siteMapUseCase; @GetMapping(value = "/sitemap",produces = "application/xml;charset=utf-8") public @ResponseBody String getSiteMap() { - return siteMapService.getSiteMap(); + return siteMapUseCase.getSiteMap(); } } diff --git a/src/main/java/myblog/blog/rss/RssService.java b/src/main/java/myblog/blog/seo/application/RssService.java similarity index 90% rename from src/main/java/myblog/blog/rss/RssService.java rename to src/main/java/myblog/blog/seo/application/RssService.java index 5d2e8d3..68f23b6 100644 --- a/src/main/java/myblog/blog/rss/RssService.java +++ b/src/main/java/myblog/blog/seo/application/RssService.java @@ -1,12 +1,13 @@ -package myblog.blog.rss; +package myblog.blog.seo.application; import lombok.RequiredArgsConstructor; +import myblog.blog.article.application.port.incomming.ArticleUseCase; +import myblog.blog.article.application.port.incomming.RssUseCase; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import myblog.blog.article.domain.Article; -import myblog.blog.article.service.ArticleService; import org.jdom2.*; import org.jdom2.output.*; import java.sql.Timestamp; @@ -24,15 +25,16 @@ import static myblog.blog.shared.utils.MarkdownUtils.*; @Service @Transactional @RequiredArgsConstructor -public class RssService { +public class RssService implements RssUseCase { static final String ITEM_ROOT = "https://www.jiniaslog.co.kr/article/view?articleId="; - private final ArticleService articleService; + private final ArticleUseCase articleUseCase; + @Override @Cacheable(value = "seoCaching", key = "0") public String getRssFeed() { - List
articles = articleService.getTotalArticle(); + List
articles = articleUseCase.getTotalArticle(); Document doc = makeRssFeedDocumentFrom(articles); XMLOutputter xmlOutputter = getXmlOutputter(); return xmlOutputter.outputString(doc); diff --git a/src/main/java/myblog/blog/sitemap/SiteMapService.java b/src/main/java/myblog/blog/seo/application/SiteMapService.java similarity index 87% rename from src/main/java/myblog/blog/sitemap/SiteMapService.java rename to src/main/java/myblog/blog/seo/application/SiteMapService.java index 8a0f9b8..013859c 100644 --- a/src/main/java/myblog/blog/sitemap/SiteMapService.java +++ b/src/main/java/myblog/blog/seo/application/SiteMapService.java @@ -1,12 +1,14 @@ -package myblog.blog.sitemap; +package myblog.blog.seo.application; +import myblog.blog.article.application.port.incomming.ArticleUseCase; +import myblog.blog.article.application.port.incomming.SiteMapUseCase; +import org.springframework.cache.annotation.Cacheable; import org.springframework.transaction.annotation.Transactional; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import myblog.blog.article.domain.Article; import myblog.blog.category.domain.Category; -import myblog.blog.article.service.ArticleService; import myblog.blog.category.service.CategoryService; import org.jdom2.*; import org.jdom2.output.*; @@ -18,7 +20,7 @@ import java.util.*; @Service @Transactional @RequiredArgsConstructor -public class SiteMapService { +public class SiteMapService implements SiteMapUseCase { static final String NAMESPACE = "http://www.sitemaps.org/schemas/sitemap/0.9"; static final String ROOT = "https://www.jiniaslog.co.kr"; @@ -26,11 +28,13 @@ public class SiteMapService { static final String CATEGORYPRO = "&page=1"; static final String ARTICLEPREV = "/article/view?articleId="; - private final ArticleService articleService; + private final ArticleUseCase articleUseCase; private final CategoryService categoryService; + @Override + @Cacheable(value = "seoCaching", key = "1") public String getSiteMap(){ - List
articles = articleService.getTotalArticle(); + List
articles = articleUseCase.getTotalArticle(); List allCategories = categoryService.getAllCategories(); Document doc = makeSiteMapDocument(articles, allCategories); XMLOutputter xmlOutputter = getXmlOutputter(); diff --git a/src/main/java/myblog/blog/tags/dto/TagsDto.java b/src/main/java/myblog/blog/tags/dto/TagsDto.java deleted file mode 100644 index 9b4c894..0000000 --- a/src/main/java/myblog/blog/tags/dto/TagsDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package myblog.blog.tags.dto; - -import lombok.Data; - - /* - - 뷰단 사용을 위한 DTO - */ -@Data -public class TagsDto { - private String name; - public TagsDto(){} - public TagsDto(String name) { - this.name = name; - } -} diff --git a/src/main/java/myblog/blog/tags/queries/TagsQueries.java b/src/main/java/myblog/blog/tags/queries/TagsQueries.java deleted file mode 100644 index e1aab4d..0000000 --- a/src/main/java/myblog/blog/tags/queries/TagsQueries.java +++ /dev/null @@ -1,28 +0,0 @@ -package myblog.blog.tags.queries; - -import lombok.RequiredArgsConstructor; -import myblog.blog.shared.utils.MapperUtils; -import myblog.blog.tags.domain.Tags; -import myblog.blog.tags.dto.TagsDto; -import myblog.blog.tags.repository.ArticleTagListsRepository; -import myblog.blog.tags.repository.TagsRepository; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -@Component -@Transactional -@RequiredArgsConstructor -public class TagsQueries { - private final TagsRepository tagsRepository; - private final ArticleTagListsRepository articleTagListsRepository; - - public List findAllTagDtos(){ - List tags = tagsRepository.findAll(); - return tags.stream() - .map(tag -> MapperUtils.getModelMapper().map(tag, TagsDto.class)) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/myblog/blog/tags/repository/TagsRepository.java b/src/main/java/myblog/blog/tags/repository/TagsRepository.java deleted file mode 100644 index 5d7caa5..0000000 --- a/src/main/java/myblog/blog/tags/repository/TagsRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package myblog.blog.tags.repository; - -import myblog.blog.tags.domain.Tags; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface TagsRepository extends JpaRepository { - Optional findByName(String name); -} diff --git a/src/test/kotlin/myblog/blog/rss/RssServiceTests.kt b/src/test/kotlin/myblog/blog/rss/RssServiceTests.kt index b01de79..48cda0c 100644 --- a/src/test/kotlin/myblog/blog/rss/RssServiceTests.kt +++ b/src/test/kotlin/myblog/blog/rss/RssServiceTests.kt @@ -1,7 +1,8 @@ package myblog.blog.rss import myblog.blog.article.domain.Article -import myblog.blog.article.service.ArticleService +import myblog.blog.article.application.ArticleService +import myblog.blog.seo.application.RssService import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith diff --git a/src/test/kotlin/myblog/blog/sitemap/SiteMapServiceTests.kt b/src/test/kotlin/myblog/blog/sitemap/SiteMapServiceTests.kt index fd4e210..452dc3c 100644 --- a/src/test/kotlin/myblog/blog/sitemap/SiteMapServiceTests.kt +++ b/src/test/kotlin/myblog/blog/sitemap/SiteMapServiceTests.kt @@ -1,7 +1,8 @@ package myblog.blog.sitemap import myblog.blog.article.domain.Article -import myblog.blog.article.service.ArticleService +import myblog.blog.article.application.ArticleService +import myblog.blog.seo.application.SiteMapService import myblog.blog.category.domain.Category import myblog.blog.category.service.CategoryService import org.assertj.core.api.Assertions.assertThat