리아키텍쳐링중
This commit is contained in:
@@ -2,11 +2,14 @@ package myblog.blog.article.adapter.incomming.web;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import myblog.blog.article.application.TagsQueries;
|
||||
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.TempArticleUseCase;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.article.dto.*;
|
||||
import myblog.blog.article.application.port.response.ArticleResponseForCardBox;
|
||||
import myblog.blog.article.model.*;
|
||||
import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase;
|
||||
import myblog.blog.article.application.port.incomming.TagsQueriesUseCase;
|
||||
import myblog.blog.category.service.CategoryService;
|
||||
import myblog.blog.category.dto.*;
|
||||
import myblog.blog.member.auth.PrincipalDetails;
|
||||
@@ -39,9 +42,10 @@ import static myblog.blog.shared.utils.MarkdownUtils.*;
|
||||
public class ArticleController {
|
||||
|
||||
private final ArticleUseCase articleUseCase;
|
||||
private final ArticleQueriesUseCase articleQueriesUseCase;
|
||||
private final TempArticleUseCase tempArticleUseCase;
|
||||
private final CategoryService categoryService;
|
||||
private final TagsQueries tagsQueries;
|
||||
private final TagsQueriesUseCase tagsQueriesUseCase;
|
||||
private final LayoutRenderingQueries layoutRenderingQueries;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
@@ -49,7 +53,7 @@ public class ArticleController {
|
||||
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,7 +68,7 @@ public class ArticleController {
|
||||
if (errors.hasErrors()) {
|
||||
getArticleWriteForm(model);
|
||||
}
|
||||
Long articleId = articleUseCase.writeArticle(articleForm, principal.getMember());
|
||||
Long articleId = articleUseCase.writeArticle(ArticleCreateRequest.from(articleForm,principal.getMemberId()));
|
||||
articleUseCase.backupArticle(articleId);
|
||||
tempArticleUseCase.deleteTemp();
|
||||
return "redirect:/article/view?articleId=" + articleId;
|
||||
@@ -74,18 +78,10 @@ public class ArticleController {
|
||||
*/
|
||||
@GetMapping("/article/edit")
|
||||
String updateArticle(@RequestParam Long articleId, Model model) {
|
||||
// 기존 아티클 DTO 전처리
|
||||
Article article = articleUseCase.readArticle(articleId);
|
||||
ArticleDtoForEdit articleDto = modelMapper.map(article, ArticleDtoForEdit.class);
|
||||
List<String> articleTagStrings = article.getArticleTagLists()
|
||||
.stream()
|
||||
.map(articleTag -> articleTag.getTags().getName())
|
||||
.collect(Collectors.toList());
|
||||
articleDto.setArticleTagList(articleTagStrings);
|
||||
//
|
||||
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";
|
||||
}
|
||||
@@ -97,7 +93,7 @@ public class ArticleController {
|
||||
@Transactional
|
||||
String editArticle(@RequestParam Long articleId,
|
||||
@ModelAttribute ArticleForm articleForm) {
|
||||
articleUseCase.editArticle(articleId, articleForm);
|
||||
articleUseCase.editArticle(ArticleEditRequest.from(articleId, articleForm));
|
||||
return "redirect:/article/view?articleId=" + articleId;
|
||||
}
|
||||
|
||||
@@ -120,16 +116,13 @@ public class ArticleController {
|
||||
@RequestParam Integer tier,
|
||||
@RequestParam Integer page,
|
||||
Model model) {
|
||||
// DTO 매핑 전처리
|
||||
PagingBoxDto pagingBoxDto =
|
||||
PagingBoxDto.createOf(page, getTotalArticleCntByCategory(category, categoryService.getCategoryForView()));
|
||||
|
||||
Slice<ArticleDtoForCardBox> articleDtoList =
|
||||
articleUseCase.getArticlesByCategory(category, tier, pagingBoxDto.getCurPageNum())
|
||||
.map(article -> modelMapper.map(article, ArticleDtoForCardBox.class));
|
||||
//
|
||||
Slice<ArticleResponseForCardBox> articleDtoList =
|
||||
articleQueriesUseCase.getArticlesByCategory(category, tier, pagingBoxDto.getCurPageNum());
|
||||
|
||||
for(ArticleDtoForCardBox articleDto : articleDtoList){
|
||||
for(ArticleResponseForCardBox articleDto : articleDtoList){
|
||||
articleDto.setContent(Jsoup.parse(getHtmlRenderer().render(getParser().parse(articleDto.getContent()))).text());
|
||||
}
|
||||
|
||||
@@ -148,13 +141,10 @@ public class ArticleController {
|
||||
String getArticlesListByTag(@RequestParam Integer page,
|
||||
@RequestParam String tagName,
|
||||
Model model) {
|
||||
// DTO 매핑 전처리
|
||||
Page<ArticleDtoForCardBox> articleList =
|
||||
articleUseCase.getArticlesByTag(tagName, page)
|
||||
.map(article ->
|
||||
modelMapper.map(article, ArticleDtoForCardBox.class));
|
||||
Page<ArticleResponseForCardBox> articleList =
|
||||
articleQueriesUseCase.getArticlesByTag(tagName, page);
|
||||
|
||||
for(ArticleDtoForCardBox article : articleList){
|
||||
for(ArticleResponseForCardBox article : articleList){
|
||||
article.setContent(Jsoup.parse(getHtmlRenderer().render(getParser().parse(article.getContent()))).text());
|
||||
}
|
||||
|
||||
@@ -176,13 +166,10 @@ public class ArticleController {
|
||||
String getArticlesListByKeyword(@RequestParam Integer page,
|
||||
@RequestParam String keyword,
|
||||
Model model) {
|
||||
// DTO 매핑 전처리
|
||||
Page<ArticleDtoForCardBox> articleList =
|
||||
articleUseCase.getArticlesByKeyword(keyword, page)
|
||||
.map(article ->
|
||||
modelMapper.map(article, ArticleDtoForCardBox.class));
|
||||
Page<ArticleResponseForCardBox> articleList =
|
||||
articleQueriesUseCase.getArticlesByKeyword(keyword, page);
|
||||
|
||||
for(ArticleDtoForCardBox article : articleList){
|
||||
for(ArticleResponseForCardBox article : articleList){
|
||||
article.setContent(Jsoup.parse(getHtmlRenderer().render(getParser().parse(article.getContent()))).text());
|
||||
}
|
||||
|
||||
@@ -220,33 +207,18 @@ public class ArticleController {
|
||||
}
|
||||
|
||||
/*
|
||||
DTO 매핑 전처리
|
||||
2. 게시물 상세조회용
|
||||
2.화면단을 위한 처리
|
||||
*/
|
||||
Article article = articleUseCase.readArticle(articleId);
|
||||
ArticleDtoForDetail articleDtoForDetail = articleQueriesUseCase.getArticleForDetail(articleId);
|
||||
articleDtoForDetail.setContent(getHtmlRenderer().render(getParser().parse(articleDtoForDetail.getContent())));
|
||||
|
||||
ArticleDtoForDetail articleDtoForDetail =
|
||||
modelMapper.map(article, ArticleDtoForDetail.class);
|
||||
|
||||
List<String> tags =
|
||||
article.getArticleTagLists()
|
||||
.stream()
|
||||
.map(tag -> tag.getTags().getName())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
articleDtoForDetail.setTags(tags);
|
||||
articleDtoForDetail.setContent(getHtmlRenderer().render(getParser().parse(article.getContent())));
|
||||
|
||||
List<ArticleDtoByCategory> articleTitlesSortByCategory =
|
||||
articleUseCase
|
||||
.getArticlesByCategoryForDetailView(article.getCategory())
|
||||
.stream()
|
||||
.map(article1 -> modelMapper.map(article1, ArticleDtoByCategory.class))
|
||||
.collect(Collectors.toList());
|
||||
List<ArticleResponseByCategory> articleTitlesSortByCategory =
|
||||
articleQueriesUseCase
|
||||
.getArticlesByCategoryForDetailView(articleDtoForDetail.getCategory());
|
||||
|
||||
// 3. 메타 태그용 Dto 전처리
|
||||
StringBuilder metaTags = new StringBuilder();
|
||||
for (String tag : tags) {
|
||||
for (String tag : articleDtoForDetail.getTags()) {
|
||||
metaTags.append(tag).append(", ");
|
||||
}
|
||||
|
||||
@@ -263,25 +235,24 @@ public class ArticleController {
|
||||
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);
|
||||
articleUseCase.addHit(article);
|
||||
response.addCookie(viewCookie);
|
||||
return true;
|
||||
} else {
|
||||
boolean addHitAvailable = false;
|
||||
boolean isRead = false;
|
||||
String[] viewCookieList = cookie.split("/");
|
||||
for (String alreadyRead : viewCookieList) {
|
||||
@@ -292,9 +263,10 @@ public class ArticleController {
|
||||
}
|
||||
if (!isRead) {
|
||||
cookie += articleId + "/";
|
||||
article.addHit();
|
||||
addHitAvailable = true;
|
||||
}
|
||||
response.addCookie(new Cookie("view", cookie));
|
||||
return addHitAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
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.application.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 +25,7 @@ public class MainController {
|
||||
@GetMapping("/")
|
||||
public String main(Model model) {
|
||||
// Dto 전처리
|
||||
List<ArticleDtoForCardBox> popularArticles = articleService.getPopularArticles()
|
||||
.stream()
|
||||
.map(article -> modelMapper.map(article, ArticleDtoForCardBox.class))
|
||||
.collect(Collectors.toList());
|
||||
List<ArticleResponseForCardBox> popularArticles = articleQueriesUseCase.getPopularArticles();
|
||||
//
|
||||
layoutRenderingQueries.AddLayoutTo(model);
|
||||
model.addAttribute("popularArticles", popularArticles);
|
||||
@@ -45,17 +37,14 @@ public class MainController {
|
||||
*/
|
||||
@GetMapping("/main/article/{lastArticleId}")
|
||||
public @ResponseBody
|
||||
List<ArticleDtoForCardBox> mainNextPage(@PathVariable(required = false) Long lastArticleId) {
|
||||
List<ArticleResponseForCardBox> mainNextPage(@PathVariable(required = false) Long lastArticleId) {
|
||||
|
||||
// Entity to Dto
|
||||
List<ArticleDtoForCardBox> articles = articleService.getRecentArticles(lastArticleId)
|
||||
.stream()
|
||||
.map(article -> modelMapper.map(article, ArticleDtoForCardBox.class))
|
||||
.collect(Collectors.toList());
|
||||
List<ArticleResponseForCardBox> 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);
|
||||
@@ -3,7 +3,7 @@ package myblog.blog.article.adapter.incomming.web;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.article.domain.TempArticle;
|
||||
import myblog.blog.article.application.TempArticleService;
|
||||
import myblog.blog.article.dto.TempArticleDto;
|
||||
import myblog.blog.article.model.TempArticleDto;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -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.article.model.ArticleResponseByCategory;
|
||||
import myblog.blog.article.model.ArticleDtoForDetail;
|
||||
import myblog.blog.article.model.ArticleResponseForEdit;
|
||||
import myblog.blog.category.domain.Category;
|
||||
|
||||
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<ArticleResponseForCardBox> getPopularArticles() {
|
||||
return articleRepositoryPort.findTop6ByOrderByHitDesc()
|
||||
.stream()
|
||||
.map(article -> modelMapper.map(article, ArticleResponseForCardBox.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
/*
|
||||
- 메인화면 위한 최신 아티클 커서 페이징해서 가져오기
|
||||
- 레이아웃 렌더링 성능 향상을 위해 캐싱작업
|
||||
카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화
|
||||
*/
|
||||
@Override
|
||||
@Cacheable(value = "layoutRecentArticleCaching", key = "#lastArticleId")
|
||||
public List<ArticleResponseForCardBox> getRecentArticles(Long lastArticleId) {
|
||||
List<Article> 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<ArticleResponseForCardBox> getArticlesByCategory(String category, Integer tier, Integer page) {
|
||||
Slice<Article> 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<String> articleTagStrings = article.getArticleTagLists()
|
||||
.stream()
|
||||
.map(articleTag -> articleTag.getTags().getName())
|
||||
.collect(Collectors.toList());
|
||||
articleDto.setArticleTagList(articleTagStrings);
|
||||
return articleDto;
|
||||
}
|
||||
/*
|
||||
* - 아티클 상세 조회를 위한 쿼리
|
||||
* */
|
||||
@Override
|
||||
public ArticleDtoForDetail getArticleForDetail(Long id){
|
||||
Article article = articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id);
|
||||
ArticleDtoForDetail articleDtoForDetail =
|
||||
modelMapper.map(article, ArticleDtoForDetail.class);
|
||||
|
||||
List<String> tags =
|
||||
article.getArticleTagLists()
|
||||
.stream()
|
||||
.map(tag -> tag.getTags().getName())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
articleDtoForDetail.setTags(tags);
|
||||
return articleDtoForDetail;
|
||||
}
|
||||
|
||||
/*
|
||||
- 카테고리별 최신게시물 6개만 아티클 상세뷰 위해 가져오는로직
|
||||
*/
|
||||
@Override
|
||||
public List<ArticleResponseByCategory> 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<ArticleResponseForCardBox> getArticlesByTag(String tag, Integer page) {
|
||||
return articleRepositoryPort
|
||||
.findAllByArticleTagsOrderById(PageRequest.of(pageResolve(page), 5), tag)
|
||||
.map(article ->
|
||||
modelMapper.map(article, ArticleResponseForCardBox.class));
|
||||
}
|
||||
/*
|
||||
- 검색어별 게시물 페이징 처리해서 가져오기
|
||||
*/
|
||||
@Override
|
||||
public Page<ArticleResponseForCardBox> 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;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,25 @@
|
||||
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.adapter.incomming.web.ArticleForm;
|
||||
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 org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import myblog.blog.member.service.Oauth2MemberService;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@@ -23,157 +27,48 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class ArticleService implements ArticleUseCase {
|
||||
|
||||
|
||||
private final TagsService tagsService;
|
||||
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(ArticleForm articleDto, Member writer) {
|
||||
Article newArticle = articleFrom(articleDto, writer);
|
||||
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);
|
||||
tagsService.createNewTagsAndArticleTagList(articleDto.getTags(), newArticle);
|
||||
tagUseCase.createNewTagsAndArticleTagList(articleCreateRequest.getTags(), newArticle);
|
||||
return newArticle.getId();
|
||||
}
|
||||
|
||||
/*
|
||||
- 아티클 수정 로직
|
||||
- 글 수정시 아티클 캐싱 초기화
|
||||
*/
|
||||
@Override
|
||||
@CacheEvict(value = {"layoutCaching", "layoutRecentArticleCaching","seoCaching"}, allEntries = true)
|
||||
public void editArticle(Long articleId, ArticleForm articleForm) {
|
||||
Article article = articleRepositoryPort.findById(articleId).get();
|
||||
Category category = categoryService.findCategory(articleForm.getCategory());
|
||||
tagsService.deleteAllTagsWith(article);
|
||||
tagsService.createNewTagsAndArticleTagList(articleForm.getTags(), article);
|
||||
article.isEditedFrom(articleForm,category);
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
- 메인화면 위한 인기 아티클 6개 목록 가져오기
|
||||
- 레이아웃 렌더링 성능 향상을 위해 캐싱작업
|
||||
카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화
|
||||
DTO 매핑 로직 서비스단에서 처리
|
||||
*/
|
||||
@Override
|
||||
@Cacheable(value = "layoutCaching", key = "1")
|
||||
public List<Article> getPopularArticles() {
|
||||
return articleRepositoryPort.findTop6ByOrderByHitDesc();
|
||||
}
|
||||
|
||||
/*
|
||||
- 메인화면 위한 최신 아티클 커서 페이징해서 가져오기
|
||||
- 레이아웃 렌더링 성능 향상을 위해 캐싱작업
|
||||
카테고리 변경 / 아티클 변경이 존재할경우 레이아웃 캐시 초기화
|
||||
*/
|
||||
@Override
|
||||
@Cacheable(value = "layoutRecentArticleCaching", key = "#lastArticleId")
|
||||
public List<Article> getRecentArticles(Long lastArticleId) {
|
||||
return lastArticleId.equals(0L)?
|
||||
articleRepositoryPort
|
||||
.findByOrderByIdDescWithList(PageRequest.of(0, 5))
|
||||
:
|
||||
articleRepositoryPort
|
||||
.findByOrderByIdDesc(lastArticleId, PageRequest.of(0, 5));
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
- 카테고리별 게시물 페이징 처리해서 가져오기
|
||||
*/
|
||||
@Override
|
||||
public Slice<Article> getArticlesByCategory(String category, Integer tier, Integer page) {
|
||||
Slice<Article> articles = null;
|
||||
|
||||
if (tier.equals(0)) {
|
||||
articles = articleRepositoryPort
|
||||
.findByOrderByIdDesc(
|
||||
PageRequest.of(pageResolve(page), 5));
|
||||
}
|
||||
|
||||
if (tier.equals(1)) {
|
||||
articles = articleRepositoryPort
|
||||
.findBySupCategoryOrderByIdDesc(
|
||||
PageRequest.of(pageResolve(page), 5), category);
|
||||
|
||||
}
|
||||
|
||||
if (tier.equals(2)) {
|
||||
articles = articleRepositoryPort
|
||||
.findBySubCategoryOrderByIdDesc(
|
||||
PageRequest.of(pageResolve(page), 5), category);
|
||||
}
|
||||
|
||||
return articles;
|
||||
}
|
||||
|
||||
/*
|
||||
- 아티클 읽기 위한 페치로 전체 가져오기
|
||||
*/
|
||||
@Override
|
||||
public Article readArticle(Long id){
|
||||
return articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id);
|
||||
}
|
||||
|
||||
/*
|
||||
- 모든 게시물 조회
|
||||
*/
|
||||
@Override
|
||||
public List<Article> getTotalArticle(){
|
||||
return articleRepositoryPort.findAllByOrderByIdDesc();
|
||||
}
|
||||
|
||||
/*
|
||||
- 카테고리별 최신게시물 6개만 아티클 상세뷰 위해 가져오는로직
|
||||
*/
|
||||
@Override
|
||||
public List<Article> getArticlesByCategoryForDetailView(Category category){
|
||||
return articleRepositoryPort.findTop6ByCategoryOrderByIdDesc(category);
|
||||
}
|
||||
|
||||
/*
|
||||
- 태그별 게시물 페이징 처리해서 가져오기
|
||||
*/
|
||||
@Override
|
||||
public Page<Article> getArticlesByTag(String tag, Integer page) {
|
||||
return articleRepositoryPort
|
||||
.findAllByArticleTagsOrderById(PageRequest.of(pageResolve(page), 5), tag);
|
||||
}
|
||||
|
||||
/*
|
||||
- 검색어별 게시물 페이징 처리해서 가져오기
|
||||
*/
|
||||
@Override
|
||||
public Page<Article> getArticlesByKeyword(String keyword, Integer page) {
|
||||
return articleRepositoryPort
|
||||
.findAllByKeywordOrderById(PageRequest.of(pageResolve(page),5), keyword);
|
||||
}
|
||||
|
||||
/*
|
||||
- 아티클 조회수 추가
|
||||
*/
|
||||
@Override
|
||||
public void addHit(Article article) {
|
||||
article.addHit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void backupArticle(Long articleId) {
|
||||
Article article = articleRepositoryPort.findById(articleId)
|
||||
@@ -181,27 +76,25 @@ public class ArticleService implements ArticleUseCase {
|
||||
articleBackupRepositoryPort.backup(article);
|
||||
}
|
||||
|
||||
/*
|
||||
- 페이지 시작점 0~1변경 메서드
|
||||
*/
|
||||
private int pageResolve(Integer rawPage) {
|
||||
if (rawPage == null || rawPage == 1) {
|
||||
return 0;
|
||||
} else return rawPage - 1;
|
||||
@Override
|
||||
public void addHit(Long articleId) {
|
||||
Article article = articleRepositoryPort.findById(articleId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("NotFoundArticleException"));
|
||||
article.addHit();
|
||||
}
|
||||
|
||||
/*
|
||||
- 새로운 아티클 도메인 생성 메서드
|
||||
- 아티클 도메인으로 반환
|
||||
*/
|
||||
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();
|
||||
@Override
|
||||
public Article getArticle(Long id){
|
||||
return articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id);
|
||||
}
|
||||
/*
|
||||
- 모든 아티클 도메인으로 반환
|
||||
*/
|
||||
@Override
|
||||
public List<Article> getTotalArticle(){
|
||||
return articleRepositoryPort.findAllByOrderByIdDesc();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package myblog.blog.article.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.application.ArticleService;
|
||||
import org.jdom2.*;
|
||||
import org.jdom2.output.*;
|
||||
import java.sql.Timestamp;
|
||||
@@ -29,12 +29,12 @@ 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<Article> articles = articleService.getTotalArticle();
|
||||
List<Article> articles = articleUseCase.getTotalArticle();
|
||||
Document doc = makeRssFeedDocumentFrom(articles);
|
||||
XMLOutputter xmlOutputter = getXmlOutputter();
|
||||
return xmlOutputter.outputString(doc);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package myblog.blog.article.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;
|
||||
@@ -8,7 +9,6 @@ import lombok.RequiredArgsConstructor;
|
||||
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.category.domain.Category;
|
||||
import myblog.blog.article.application.ArticleService;
|
||||
import myblog.blog.category.service.CategoryService;
|
||||
import org.jdom2.*;
|
||||
import org.jdom2.output.*;
|
||||
@@ -28,13 +28,13 @@ public class SiteMapService implements SiteMapUseCase {
|
||||
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<Article> articles = articleService.getTotalArticle();
|
||||
List<Article> articles = articleUseCase.getTotalArticle();
|
||||
List<Category> allCategories = categoryService.getAllCategories();
|
||||
Document doc = makeSiteMapDocument(articles, allCategories);
|
||||
XMLOutputter xmlOutputter = getXmlOutputter();
|
||||
|
||||
@@ -3,9 +3,9 @@ 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.dto.TagsDto;
|
||||
import myblog.blog.article.adapter.outgoing.persistence.JpaTagsRepository;
|
||||
import myblog.blog.article.model.TagsDto;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.stream.Collectors;
|
||||
@Component
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class TagsQueries {
|
||||
public class TagsQueries implements TagsQueriesUseCase {
|
||||
private final TagRepositoryPort tagRepositoryPort;
|
||||
|
||||
public List<TagsDto> findAllTagDtos(){
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package myblog.blog.article.application.port.incomming;
|
||||
|
||||
import myblog.blog.article.application.port.response.ArticleResponseForCardBox;
|
||||
import myblog.blog.article.model.ArticleResponseByCategory;
|
||||
import myblog.blog.article.model.ArticleDtoForDetail;
|
||||
import myblog.blog.article.model.ArticleResponseForEdit;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Slice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ArticleQueriesUseCase {
|
||||
List<ArticleResponseForCardBox> getPopularArticles();
|
||||
List<ArticleResponseForCardBox> getRecentArticles(Long lastArticleId);
|
||||
Slice<ArticleResponseForCardBox> getArticlesByCategory(String category, Integer tier, Integer page);
|
||||
ArticleResponseForEdit getArticleForEdit(Long id);
|
||||
ArticleDtoForDetail getArticleForDetail(Long id);
|
||||
List<ArticleResponseByCategory> getArticlesByCategoryForDetailView(String category);
|
||||
Page<ArticleResponseForCardBox> getArticlesByTag(String tag, Integer page);
|
||||
Page<ArticleResponseForCardBox> getArticlesByKeyword(String keyword, Integer page);
|
||||
}
|
||||
@@ -1,27 +1,17 @@
|
||||
package myblog.blog.article.application.port.incomming;
|
||||
|
||||
import myblog.blog.article.adapter.incomming.web.ArticleForm;
|
||||
import myblog.blog.article.application.port.request.ArticleCreateRequest;
|
||||
import myblog.blog.article.application.port.request.ArticleEditRequest;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.category.domain.Category;
|
||||
import myblog.blog.member.doamin.Member;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Slice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ArticleUseCase {
|
||||
Long writeArticle(ArticleForm articleForm, Member member);
|
||||
void editArticle(Long articleId, ArticleForm articleForm);
|
||||
Long writeArticle(ArticleCreateRequest articleCreateRequest);
|
||||
void editArticle(ArticleEditRequest articleEditRequest);
|
||||
void deleteArticle(Long articleId);
|
||||
List<Article> getPopularArticles();
|
||||
List<Article> getRecentArticles(Long lastArticleId);
|
||||
Slice<Article> getArticlesByCategory(String category, Integer tier, Integer page);
|
||||
Article readArticle(Long id);
|
||||
List<Article> getTotalArticle();
|
||||
List<Article> getArticlesByCategoryForDetailView(Category category);
|
||||
Page<Article> getArticlesByTag(String tag, Integer page);
|
||||
Page<Article> getArticlesByKeyword(String keyword, Integer page);
|
||||
void addHit(Article article);
|
||||
void addHit(Long articleId);
|
||||
void backupArticle(Long articleId);
|
||||
|
||||
Article getArticle(Long id);
|
||||
List<Article> getTotalArticle();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package myblog.blog.article.application.port.incomming;
|
||||
|
||||
import myblog.blog.article.model.TagsDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TagsQueriesUseCase {
|
||||
List<TagsDto> findAllTagDtos();
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -1,19 +1,20 @@
|
||||
package myblog.blog.article.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import myblog.blog.article.adapter.incomming.web.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 lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/*
|
||||
- 아티클 Entity
|
||||
- toc 추후 개발 예정
|
||||
@@ -88,14 +89,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();
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package myblog.blog.article.dto;
|
||||
package myblog.blog.article.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package myblog.blog.article.dto;
|
||||
package myblog.blog.article.model;
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package myblog.blog.article.dto;
|
||||
package myblog.blog.article.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
- 아티클 수정 폼을 위한 DTO
|
||||
*/
|
||||
@Getter @Setter
|
||||
public class ArticleDtoForEdit {
|
||||
public class ArticleResponseForEdit {
|
||||
|
||||
private Long id;
|
||||
private String title;
|
||||
@@ -1,8 +1,7 @@
|
||||
package myblog.blog.article.dto;
|
||||
package myblog.blog.article.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
/*
|
||||
- 뷰단 페이징 박스 처리를 위한 핸들러
|
||||
@@ -1,4 +1,4 @@
|
||||
package myblog.blog.article.dto;
|
||||
package myblog.blog.article.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package myblog.blog.article.dto;
|
||||
package myblog.blog.article.model;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -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, Long> {
|
||||
|
||||
/*
|
||||
- 카테고리 이름으로 카테고리 찾기
|
||||
*/
|
||||
Category findByTitle(String title);
|
||||
Optional<Category> findByTitle(String title);
|
||||
|
||||
/*
|
||||
- 티어별 카테고리들 가져오기
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@@ -25,7 +26,8 @@ public class CategoryService {
|
||||
- 카테고리 이름으로 카테고리 찾기
|
||||
*/
|
||||
public Category findCategory(String title) {
|
||||
return categoryRepository.findByTitle(title);
|
||||
return categoryRepository.findByTitle(title)
|
||||
.orElseThrow(() -> new IllegalArgumentException("NotFoundCategoryException"));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -152,7 +154,8 @@ public class CategoryService {
|
||||
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()
|
||||
@@ -190,7 +193,7 @@ public class CategoryService {
|
||||
/*
|
||||
- 최초 필수 더미 카테고리 추가 코드
|
||||
*/
|
||||
@PostConstruct
|
||||
// @PostConstruct
|
||||
private void insertDummyCategory() {
|
||||
if(categoryRepository.findByTitle("total")==null) {
|
||||
Category category0 = Category.builder()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
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.application.ArticleService;
|
||||
import myblog.blog.comment.dto.CommentDto;
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -112,4 +112,8 @@ public class Oauth2MemberService extends DefaultOAuth2UserService {
|
||||
|
||||
}
|
||||
|
||||
public Member findById(Long memberId) {
|
||||
return memberRepository.findById(memberId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("NotFoundMemberException"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user