From ca4678a35d335c623d587d04bd9aeb739051e48c Mon Sep 17 00:00:00 2001 From: jinia91 Date: Sat, 11 Dec 2021 19:38:08 +0900 Subject: [PATCH] =?UTF-8?q?21.12.11=20fts=20=EC=BF=BC=EB=A6=AC=20=ED=8A=9C?= =?UTF-8?q?=EB=8B=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../article/controller/ArticleController.java | 17 +- .../myblog/blog/article/domain/Article.java | 16 +- .../article/repository/ArticleRepository.java | 10 +- .../repository/NaArticleRepository.java | 1 + .../blog/article/service/ArticleService.java | 2 +- .../myblog/blog/base/MysqlDialectCustom.java | 21 +++ .../myblog/blog/category/domain/Category.java | 2 +- .../category/service/CategoryService.java | 80 ++------- .../java/myblog/blog/main/MainController.java | 23 ++- .../myblog/blog/member/doamin/Member.java | 4 +- .../member/service/Oauth2MemberService.java | 1 - .../java/myblog/blog/tags/domain/Tags.java | 2 +- src/main/resources/application.yml | 4 +- src/main/resources/static/css/articleView.css | 16 +- src/main/resources/static/css/mainCss.css | 13 ++ .../resources/static/js/infinityScroll.js | 1 + .../templates/article/articleList.html | 1 + .../article/articleListByKeyword.html | 17 +- .../templates/article/articleListByTag.html | 1 + .../templates/article/articleView.html | 14 +- src/main/resources/templates/index.html | 1 + .../resources/templates/layout/layout.html | 4 +- .../resources/templates/layout/sideBar.html | 18 +- .../repository/ArticleRepositoryTest.java | 157 +++++++++++++++++- 24 files changed, 310 insertions(+), 116 deletions(-) create mode 100644 src/main/java/myblog/blog/base/MysqlDialectCustom.java diff --git a/src/main/java/myblog/blog/article/controller/ArticleController.java b/src/main/java/myblog/blog/article/controller/ArticleController.java index 7d9d3fd..2714c3d 100644 --- a/src/main/java/myblog/blog/article/controller/ArticleController.java +++ b/src/main/java/myblog/blog/article/controller/ArticleController.java @@ -153,6 +153,11 @@ public class ArticleController { Slice articleList = articleService.getArticlesByCategory(category, tier, pagingBoxDto.getCurPageNum()) .map(article -> modelMapper.map(article, ArticleDtoForMain.class)); + + for(ArticleDtoForMain article : articleList){ + article.setContent(Jsoup.parse(htmlRenderer.render(parser.parse(article.getContent()))).text()); + } + // model.addAttribute("pagingBox", pagingBoxDto); @@ -179,6 +184,11 @@ public class ArticleController { PagingBoxDto pagingBoxDto = PagingBoxDto.createOf(page, (int)articleList.getTotalElements()); modelsForLayout(model); + + for(ArticleDtoForMain article : articleList){ + article.setContent(Jsoup.parse(htmlRenderer.render(parser.parse(article.getContent()))).text()); + } + // model.addAttribute("articleList", articleList); @@ -205,6 +215,11 @@ public class ArticleController { PagingBoxDto pagingBoxDto = PagingBoxDto.createOf(page, (int)articleList.getTotalElements()); modelsForLayout(model); + + for(ArticleDtoForMain article : articleList){ + article.setContent(Jsoup.parse(htmlRenderer.render(parser.parse(article.getContent()))).text()); + } + // model.addAttribute("articleList", articleList); @@ -255,7 +270,7 @@ public class ArticleController { List articleTitlesSortByCategory = articleService - .getArticlesByCategoryForDetailView(article.getCategory()) + .getArticlesByCategoryForDetailView(article.getCategory(), article) .stream() .map(article1 -> modelMapper.map(article1, ArticleDtoByCategory.class)) .collect(Collectors.toList()); diff --git a/src/main/java/myblog/blog/article/domain/Article.java b/src/main/java/myblog/blog/article/domain/Article.java index 0b10803..319c89a 100644 --- a/src/main/java/myblog/blog/article/domain/Article.java +++ b/src/main/java/myblog/blog/article/domain/Article.java @@ -19,13 +19,23 @@ import java.util.List; /* - 아티클 Entity - toc 추후 개발 예정 + - 채번을 배치로 하게 하여 성능향상을 시켰고 + 네트워크를 두번타는 identity 대신 table 방식으로 구현된 시퀸스 방식을 채택하여 배치 인서트의 확장성을 열어둠 */ @Entity -@Getter @SequenceGenerator( name = "ARTICLE_SEQ_GENERATOR", sequenceName = "ARTICLE_SEQ", initialValue = 1, allocationSize = 50) +/* + - fts 구현을 위한 인덱스 설정 + - +*/ +@Table(indexes = { + @Index(name="i_article_title", columnList = "title"), + @Index(name = "i_article_content", columnList = "content") +}) +@Getter public class Article extends BasicEntity { @Id @@ -33,10 +43,10 @@ public class Article extends BasicEntity { @Column(name = "article_id") private Long id; - @Column(nullable = false) + @Column(nullable = false, length = 50) private String title; - @Column(nullable = false, columnDefinition = "TEXT") + @Column(nullable = false, length = 10000) private String content; @Column(columnDefinition = "bigint default 0",nullable = false) diff --git a/src/main/java/myblog/blog/article/repository/ArticleRepository.java b/src/main/java/myblog/blog/article/repository/ArticleRepository.java index d837cdb..c37a0b1 100644 --- a/src/main/java/myblog/blog/article/repository/ArticleRepository.java +++ b/src/main/java/myblog/blog/article/repository/ArticleRepository.java @@ -19,7 +19,7 @@ public interface ArticleRepository extends JpaRepository { List
findTop6ByOrderByHitDesc(); /* - - 카테고리별 최대 6개 최신 게시물순으로 가져오기 페이징처리 x + - 카테고리별 최신 게시물 6개 가져오기 */ List
findTop6ByCategoryOrderByIdDesc(Category category); @@ -41,6 +41,7 @@ public interface ArticleRepository extends JpaRepository { /* - 카테고리별(상위 카테고리) 페이징 처리해서 최신게시물순으로 Slice 가져오기 + - 토탈카운트 쿼리 x */ @Query("select a " + "from Article a " + @@ -70,19 +71,24 @@ public interface ArticleRepository extends JpaRepository { "from Article a " + "join a.articleTagLists at " + "join at.tags t " + - "where t.name in :tag " + + "where t.name =:tag " + "order by a.id desc ") Page
findAllByArticleTagsOrderById(Pageable pageable, @Param("tag") String tag); /* - 키워드별 아티클 페이징 처리해서 조회 - 토탈 카운트 쿼리 o + - 배포시 fts로 개선해보자 */ @Query("select a " + "from Article a " + "where a.title like %:keyword% " + "or a.content like %:keyword% " + "order by a.id desc ") +// @Query(value = "select * " + +// "from article " + +// "where match(content, :keyword) " + +// "order by article_id desc",nativeQuery = true) Page
findAllByKeywordOrderById(Pageable pageable, @Param("keyword") String keyword); /* diff --git a/src/main/java/myblog/blog/article/repository/NaArticleRepository.java b/src/main/java/myblog/blog/article/repository/NaArticleRepository.java index 9b2dca1..15ae74a 100644 --- a/src/main/java/myblog/blog/article/repository/NaArticleRepository.java +++ b/src/main/java/myblog/blog/article/repository/NaArticleRepository.java @@ -12,4 +12,5 @@ public interface NaArticleRepository { @Delete("delete from article " + "where article_id = #{articleId} ") void deleteArticle(Long articleId); + } diff --git a/src/main/java/myblog/blog/article/service/ArticleService.java b/src/main/java/myblog/blog/article/service/ArticleService.java index 8e7e318..5fe73ed 100644 --- a/src/main/java/myblog/blog/article/service/ArticleService.java +++ b/src/main/java/myblog/blog/article/service/ArticleService.java @@ -151,7 +151,7 @@ public class ArticleService { /* - 카테고리별 최신게시물 6개만 아티클 상세뷰 위해 가져오는로직 */ - public List
getArticlesByCategoryForDetailView(Category category){ + public List
getArticlesByCategoryForDetailView(Category category, Article article){ return articleRepository.findTop6ByCategoryOrderByIdDesc(category); diff --git a/src/main/java/myblog/blog/base/MysqlDialectCustom.java b/src/main/java/myblog/blog/base/MysqlDialectCustom.java new file mode 100644 index 0000000..b6cc855 --- /dev/null +++ b/src/main/java/myblog/blog/base/MysqlDialectCustom.java @@ -0,0 +1,21 @@ +package myblog.blog.base; + +import org.hibernate.dialect.MySQL57Dialect; +import org.hibernate.dialect.MySQL8Dialect; +import org.hibernate.dialect.function.SQLFunctionTemplate; +import org.hibernate.type.StandardBasicTypes; + + +/* + - FTS 지원을 위해 JPA에 SQL에 MYSQL 문법 추가 등록 +*/ +public class MysqlDialectCustom extends MySQL8Dialect { + + public MysqlDialectCustom(){ + super(); + + registerFunction( + "match", new SQLFunctionTemplate(StandardBasicTypes.DOUBLE, "match(?1) against (?2 in boolean mode)" + )); + } +} diff --git a/src/main/java/myblog/blog/category/domain/Category.java b/src/main/java/myblog/blog/category/domain/Category.java index 7b0ffad..fb432b1 100644 --- a/src/main/java/myblog/blog/category/domain/Category.java +++ b/src/main/java/myblog/blog/category/domain/Category.java @@ -26,7 +26,7 @@ public class Category extends BasicEntity { @Column(name = "category_id") private Long id; - @Column(nullable = false, unique = true) + @Column(nullable = false, unique = true, length = 20) private String title; @OneToMany(mappedBy = "category") diff --git a/src/main/java/myblog/blog/category/service/CategoryService.java b/src/main/java/myblog/blog/category/service/CategoryService.java index c809a78..18f9849 100644 --- a/src/main/java/myblog/blog/category/service/CategoryService.java +++ b/src/main/java/myblog/blog/category/service/CategoryService.java @@ -65,7 +65,7 @@ public class CategoryService { /* - 카테고리와 카테고리별 아티클 수 찾기 */ - public List getCategorytCountList(){ + public List getCategorytCountList() { return naCategoryRepository.getCategoryCount(); } @@ -97,7 +97,7 @@ public class CategoryService { 3-3 DB에만 존재하는 카테고리는 삭제처리 */ @Transactional - @CacheEvict(value = {"layoutCaching","seoCaching"}, allEntries = true) + @CacheEvict(value = {"layoutCaching", "seoCaching"}, allEntries = true) public void changeCategory(List categoryList) { // 1.카테고리 리스트 순서 작성 @@ -204,73 +204,19 @@ public class CategoryService { } /* - - 최초 더미 카테고리 추가 코드 + - 최초 필수 더미 카테고리 추가 코드 */ -// @PostConstruct - public void insertCategory() { - - Category category0 = Category.builder() - .tier(0) - .title("total") - .pSortNum(0) - .cSortNum(0) - .build(); + @PostConstruct + public void insertDummyCategory() { + if(categoryRepository.findByTitle("total")==null) { + Category category0 = Category.builder() + .tier(0) + .title("total") + .pSortNum(0) + .cSortNum(0) + .build(); categoryRepository.save(category0); - - Category category1 = Category.builder() - .tier(1) - .title("카테고리 부모") - .pSortNum(1) - .cSortNum(0) - .build(); - categoryRepository.save(category1); - Category category2 = Category.builder() - .tier(2) - .title("카테고리 자식") - .pSortNum(1) - .cSortNum(1) - .parents(category1) - .build(); - categoryRepository.save(category2); - Category category3 = Category.builder() - .tier(1) - .title("카테고리 부모2") - .pSortNum(2) - .cSortNum(0) - .build(); - categoryRepository.save(category3); - Category category4 = Category.builder() - .tier(1) - .title("카테고리 부모3") - .pSortNum(3) - .cSortNum(0) - .build(); - categoryRepository.save(category4); - Category category5 = Category.builder() - .tier(2) - .title("카테고리 자식2") - .pSortNum(2) - .cSortNum(1) - .parents(category3) - .build(); - categoryRepository.save(category5); - Category category6 = Category.builder() - .tier(2) - .title("카테고리 자식3") - .pSortNum(2) - .cSortNum(2) - .parents(category3) - .build(); - categoryRepository.save(category6); - Category category7 = Category.builder() - .tier(2) - .title("카테고리 자식4") - .pSortNum(3) - .cSortNum(1) - .parents(category4) - .build(); - categoryRepository.save(category7); - + } } } diff --git a/src/main/java/myblog/blog/main/MainController.java b/src/main/java/myblog/blog/main/MainController.java index 50930ae..b153cac 100644 --- a/src/main/java/myblog/blog/main/MainController.java +++ b/src/main/java/myblog/blog/main/MainController.java @@ -8,6 +8,9 @@ import myblog.blog.category.dto.CategoryForView; import myblog.blog.category.service.CategoryService; import myblog.blog.comment.dto.CommentDtoForLayout; import myblog.blog.comment.service.CommentService; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; +import org.jsoup.Jsoup; import org.modelmapper.ModelMapper; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Controller; @@ -27,6 +30,8 @@ public class MainController { private final ArticleService articleService; private final CategoryService categoryService; private final CommentService commentService; + private final HtmlRenderer htmlRenderer; + private final Parser parser; /* - 메인 화면 제어용 컨트롤러 @@ -41,6 +46,11 @@ public class MainController { List popularArticles = articleService.getPopularArticles(); Slice recentArticles = articleService.getRecentArticles(0); + + for(ArticleDtoForMain article : recentArticles){ + article.setContent(Jsoup.parse(htmlRenderer.render(parser.parse(article.getContent()))).text()); + } + // model.addAttribute("category",categoryForView); @@ -58,7 +68,18 @@ public class MainController { public @ResponseBody List mainNextPage(@PathVariable int pageNum) { - return articleService.getRecentArticles(pageNum).getContent(); + + List articles = articleService.getRecentArticles(pageNum).getContent(); + + for(ArticleDtoForMain article : articles){ + String content = Jsoup.parse(htmlRenderer.render(parser.parse(article.getContent()))).text(); + if(content.length()>300) { + content = content.substring(0, 300); + } + article.setContent(content); + } + + return articles; } } diff --git a/src/main/java/myblog/blog/member/doamin/Member.java b/src/main/java/myblog/blog/member/doamin/Member.java index 6cf1331..3eb8161 100644 --- a/src/main/java/myblog/blog/member/doamin/Member.java +++ b/src/main/java/myblog/blog/member/doamin/Member.java @@ -27,13 +27,13 @@ public class Member extends BasicEntity { @Column(name = "member_id") private Long id; - @Column(nullable = false) + @Column(nullable = false, length = 50) private String username; @Column(nullable = false) private String userId; - @Column(nullable = false, unique = true) + @Column(nullable = false, unique = true, length = 50) private String email; private String picUrl; diff --git a/src/main/java/myblog/blog/member/service/Oauth2MemberService.java b/src/main/java/myblog/blog/member/service/Oauth2MemberService.java index e07e61f..f147b74 100644 --- a/src/main/java/myblog/blog/member/service/Oauth2MemberService.java +++ b/src/main/java/myblog/blog/member/service/Oauth2MemberService.java @@ -95,7 +95,6 @@ public class Oauth2MemberService extends DefaultOAuth2UserService { public void insertAdmin(){ Member admin = memberRepository.findByEmail(adminEmail); - if(admin == null){ admin = Member.builder() .username(adminUsername+"#"+adminProviderId.substring(0,5)) diff --git a/src/main/java/myblog/blog/tags/domain/Tags.java b/src/main/java/myblog/blog/tags/domain/Tags.java index 189dd72..064d621 100644 --- a/src/main/java/myblog/blog/tags/domain/Tags.java +++ b/src/main/java/myblog/blog/tags/domain/Tags.java @@ -20,7 +20,7 @@ public class Tags extends BasicEntity { @Column(name = "tags_id") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TAGS_SEQ_GENERATOR") private Long id; - @Column(unique = true, nullable = false) + @Column(unique = true, nullable = false, length = 20) private String name; @OneToMany(mappedBy = "tags") private List articleTagLists = new ArrayList<>(); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e8f4602..dac532a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -19,9 +19,9 @@ server: properties: hibernate: # show_sql: true - format_sql: true + format_sql: jdbc: - batch_size: 100 + batch_size: git: diff --git a/src/main/resources/static/css/articleView.css b/src/main/resources/static/css/articleView.css index 1dc0dc2..81d8ccf 100644 --- a/src/main/resources/static/css/articleView.css +++ b/src/main/resources/static/css/articleView.css @@ -695,7 +695,7 @@ ul.toolList li { border-bottom: 1px solid #dbdbdb; } -ul.toolList li:before { +ul.toolList .otherArticle:before { content: "\f550"; font-family: FontAwesome; -webkit-font-smoothing: antialiased; @@ -705,6 +705,17 @@ ul.toolList li:before { margin-right: 3px; } +ul.toolList .curArticle:before { + content: "\f518"; + font-family: FontAwesome; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + display: inline-block; + vertical-align: middle; + margin-right: 3px; +} + + .badge:before { content: "\f02c"; font-family: FontAwesome; @@ -810,4 +821,5 @@ ul.toolList li:before { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; -} \ No newline at end of file +} + diff --git a/src/main/resources/static/css/mainCss.css b/src/main/resources/static/css/mainCss.css index 982402f..d5334e3 100644 --- a/src/main/resources/static/css/mainCss.css +++ b/src/main/resources/static/css/mainCss.css @@ -118,6 +118,15 @@ body::-webkit-scrollbar-track { .navbar { opacity: 0.98; + height: 50px; +} + +.nav-brand{ + position: absolute; + left: 50%; + margin-left: -50px; + font-size: 20px; + } .navbar-toggler { @@ -437,3 +446,7 @@ body::-webkit-scrollbar-track { .categoryBox .fw-bold{ color: #1f70de !important; } + +.fa-bars{ + font-size: 20px; +} diff --git a/src/main/resources/static/js/infinityScroll.js b/src/main/resources/static/js/infinityScroll.js index 6bbbb6b..f5cf54a 100644 --- a/src/main/resources/static/js/infinityScroll.js +++ b/src/main/resources/static/js/infinityScroll.js @@ -57,6 +57,7 @@ function makeNextPage() {

${listElement.title}

+

${listElement.content}

${date}

diff --git a/src/main/resources/templates/article/articleList.html b/src/main/resources/templates/article/articleList.html index f6daba9..396fad1 100644 --- a/src/main/resources/templates/article/articleList.html +++ b/src/main/resources/templates/article/articleList.html @@ -63,6 +63,7 @@

글 제목

+

diff --git a/src/main/resources/templates/article/articleListByKeyword.html b/src/main/resources/templates/article/articleListByKeyword.html index 67223f6..6e87ca7 100644 --- a/src/main/resources/templates/article/articleListByKeyword.html +++ b/src/main/resources/templates/article/articleListByKeyword.html @@ -51,7 +51,7 @@

-

+


@@ -63,6 +63,7 @@

글 제목

+

@@ -72,8 +73,6 @@

- -
@@ -85,7 +84,7 @@

글 제목

+

diff --git a/src/main/resources/templates/layout/layout.html b/src/main/resources/templates/layout/layout.html index 4b2dd60..5b3a87e 100644 --- a/src/main/resources/templates/layout/layout.html +++ b/src/main/resources/templates/layout/layout.html @@ -15,8 +15,8 @@ aria-controls="offcanvasMenu"> -