1차 리아키텍쳐링, article 모듈

This commit is contained in:
jinia91
2022-03-24 00:04:19 +09:00
parent 561df13bca
commit 463d4e5bad
23 changed files with 116 additions and 111 deletions

View File

@@ -2,22 +2,23 @@ package myblog.blog.article.adapter.incomming.web;
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.TempArticleUseCase;
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.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.member.dto.MemberVo;
import myblog.blog.shared.queries.LayoutRenderingQueries;
import org.jsoup.Jsoup;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.*;
@@ -44,8 +45,8 @@ public class ArticleController {
private final ArticleUseCase articleUseCase;
private final ArticleQueriesUseCase articleQueriesUseCase;
private final TempArticleUseCase tempArticleUseCase;
private final CategoryService categoryService;
private final TagsQueriesUseCase tagsQueriesUseCase;
private final CategoryService categoryService;
private final LayoutRenderingQueries layoutRenderingQueries;
private final ModelMapper modelMapper;
@@ -116,18 +117,18 @@ public class ArticleController {
@RequestParam Integer tier,
@RequestParam Integer page,
Model model) {
PagingBoxDto pagingBoxDto =
PagingBoxDto.createOf(page, getTotalArticleCntByCategory(category, categoryService.getCategoryForView()));
PagingBoxHandler pagingBoxHandler =
PagingBoxHandler.createOf(page, getTotalArticleCntByCategory(category, categoryService.getCategoryForView()));
Slice<ArticleResponseForCardBox> articleDtoList =
articleQueriesUseCase.getArticlesByCategory(category, tier, pagingBoxDto.getCurPageNum());
articleQueriesUseCase.getArticlesByCategory(category, tier, pagingBoxHandler.getCurPageNum());
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";
@@ -148,12 +149,12 @@ public class ArticleController {
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";
}
@@ -173,12 +174,12 @@ public class ArticleController {
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";
@@ -201,7 +202,7 @@ public class ArticleController {
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);
}
@@ -209,28 +210,28 @@ public class ArticleController {
/*
2.화면단을 위한 처리
*/
ArticleDtoForDetail articleDtoForDetail = articleQueriesUseCase.getArticleForDetail(articleId);
articleDtoForDetail.setContent(getHtmlRenderer().render(getParser().parse(articleDtoForDetail.getContent())));
ArticleResponseForDetail articleResponseForDetail = articleQueriesUseCase.getArticleForDetail(articleId);
articleResponseForDetail.setContent(getHtmlRenderer().render(getParser().parse(articleResponseForDetail.getContent())));
List<ArticleResponseByCategory> articleTitlesSortByCategory =
articleQueriesUseCase
.getArticlesByCategoryForDetailView(articleDtoForDetail.getCategory());
.getArticlesByCategoryForDetailView(articleResponseForDetail.getCategory());
// 3. 메타 태그용 Dto 전처리
StringBuilder metaTags = new StringBuilder();
for (String tag : articleDtoForDetail.getTags()) {
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);

View File

@@ -1,6 +1,7 @@
package myblog.blog.article.adapter.incomming.web;
import lombok.RequiredArgsConstructor;
import myblog.blog.article.application.port.response.ArticleResponseForCardBox;
import myblog.blog.article.application.port.incomming.ArticleQueriesUseCase;
import myblog.blog.shared.queries.LayoutRenderingQueries;

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.model;
package myblog.blog.article.adapter.incomming.web;
import lombok.Getter;
import lombok.Setter;
@@ -7,7 +7,7 @@ import lombok.Setter;
- 뷰단 페이징 박스 처리를 위한 핸들러
*/
@Getter @Setter
public class PagingBoxDto {
public class PagingBoxHandler {
private int curPageNum;
private int lastPageNum;
@@ -19,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));

View File

@@ -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.model.TempArticleDto;
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> 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;
}
}

View File

@@ -7,10 +7,10 @@ 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.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;
@@ -105,10 +105,10 @@ public class ArticleQueries implements ArticleQueriesUseCase {
* - 아티클 상세 조회를 위한 쿼리
* */
@Override
public ArticleDtoForDetail getArticleForDetail(Long id){
public ArticleResponseForDetail getArticleForDetail(Long id){
Article article = articleRepositoryPort.findArticleByIdFetchCategoryAndTags(id);
ArticleDtoForDetail articleDtoForDetail =
modelMapper.map(article, ArticleDtoForDetail.class);
ArticleResponseForDetail articleResponseForDetail =
modelMapper.map(article, ArticleResponseForDetail.class);
List<String> tags =
article.getArticleTagLists()
@@ -116,8 +116,8 @@ public class ArticleQueries implements ArticleQueriesUseCase {
.map(tag -> tag.getTags().getName())
.collect(Collectors.toList());
articleDtoForDetail.setTags(tags);
return articleDtoForDetail;
articleResponseForDetail.setTags(tags);
return articleResponseForDetail;
}
/*

View File

@@ -5,7 +5,7 @@ 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.model.TagsDto;
import myblog.blog.article.application.port.response.TagsResponse;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -18,10 +18,10 @@ import java.util.stream.Collectors;
public class TagsQueries implements TagsQueriesUseCase {
private final TagRepositoryPort tagRepositoryPort;
public List<TagsDto> findAllTagDtos(){
public List<TagsResponse> findAllTagDtos(){
List<Tags> tags = tagRepositoryPort.findAll();
return tags.stream()
.map(tag -> MapperUtils.getModelMapper().map(tag, TagsDto.class))
.map(tag -> MapperUtils.getModelMapper().map(tag, TagsResponse.class))
.collect(Collectors.toList());
}
}

View File

@@ -1,9 +1,9 @@
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 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;
@@ -14,7 +14,7 @@ public interface ArticleQueriesUseCase {
List<ArticleResponseForCardBox> getRecentArticles(Long lastArticleId);
Slice<ArticleResponseForCardBox> getArticlesByCategory(String category, Integer tier, Integer page);
ArticleResponseForEdit getArticleForEdit(Long id);
ArticleDtoForDetail getArticleForDetail(Long id);
ArticleResponseForDetail getArticleForDetail(Long id);
List<ArticleResponseByCategory> getArticlesByCategoryForDetailView(String category);
Page<ArticleResponseForCardBox> getArticlesByTag(String tag, Integer page);
Page<ArticleResponseForCardBox> getArticlesByKeyword(String keyword, Integer page);

View File

@@ -1,9 +1,9 @@
package myblog.blog.article.application.port.incomming;
import myblog.blog.article.model.TagsDto;
import myblog.blog.article.application.port.response.TagsResponse;
import java.util.List;
public interface TagsQueriesUseCase {
List<TagsDto> findAllTagDtos();
List<TagsResponse> findAllTagDtos();
}

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.model;
package myblog.blog.article.application.port.response;
import lombok.Getter;
import lombok.Setter;

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.model;
package myblog.blog.article.application.port.response;
import lombok.Getter;
import lombok.Setter;
@@ -10,7 +10,7 @@ import java.util.List;
- 아티클 상세조회용 DTO
*/
@Getter @Setter
public class ArticleDtoForDetail {
public class ArticleResponseForDetail {
private Long id;
private String title;

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.model;
package myblog.blog.article.application.port.response;
import lombok.Getter;
import lombok.Setter;

View File

@@ -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;
}
}

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.model;
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;
}

View File

@@ -1,7 +1,5 @@
package myblog.blog.article.domain;
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;
@@ -11,7 +9,6 @@ import lombok.Builder;
import lombok.Getter;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
import javax.persistence.*;
import java.util.*;

View File

@@ -1,15 +0,0 @@
package myblog.blog.article.model;
import lombok.Data;
/*
- 뷰단 사용을 위한 DTO
*/
@Data
public class TagsDto {
private String name;
public TagsDto(){}
public TagsDto(String name) {
this.name = name;
}
}

View File

@@ -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;
}

View File

@@ -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());
}
}

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.adapter.incomming.web;
package myblog.blog.seo.adapter.incomming;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.adapter.incomming.web;
package myblog.blog.seo.adapter.incomming;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.application;
package myblog.blog.seo.application;
import lombok.RequiredArgsConstructor;
import myblog.blog.article.application.port.incomming.ArticleUseCase;

View File

@@ -1,4 +1,4 @@
package myblog.blog.article.application;
package myblog.blog.seo.application;
import myblog.blog.article.application.port.incomming.ArticleUseCase;
import myblog.blog.article.application.port.incomming.SiteMapUseCase;

View File

@@ -2,7 +2,7 @@ package myblog.blog.rss
import myblog.blog.article.domain.Article
import myblog.blog.article.application.ArticleService
import myblog.blog.article.application.RssService
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

View File

@@ -2,18 +2,15 @@ package myblog.blog.sitemap
import myblog.blog.article.domain.Article
import myblog.blog.article.application.ArticleService
import myblog.blog.article.application.SiteMapService
import myblog.blog.seo.application.SiteMapService
import myblog.blog.category.domain.Category
import myblog.blog.category.service.CategoryService
import myblog.blog.rss.RssService
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
//import org.junit.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.whenever
import java.lang.reflect.Field