211110 메인화면 개발중
1. 메인화면에 필요한 게시물 리스트 조회 로직과 화면 렌더링 구현 2. 조회수순으로 메인화면 노출과 최신 업로드 순 게시물 노출 로직 구분 3. 무한스크롤 구현 4. 스크롤 화살표 구현 5. 계층형 카테고리 개발과 화면 렌더링 완료 - 롤업함수와 백트래킹으로 구현
This commit is contained in:
@@ -1,40 +1,62 @@
|
||||
package myblog.blog.article.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.article.dto.ArticleForMainView;
|
||||
import myblog.blog.article.dto.NewArticleDto;
|
||||
import myblog.blog.article.service.ArticleService;
|
||||
import myblog.blog.category.dto.CategoryForMainView;
|
||||
import myblog.blog.category.service.CategoryService;
|
||||
import myblog.blog.member.auth.PrincipalDetails;
|
||||
import myblog.blog.tags.service.TagsService;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class ArticleController {
|
||||
|
||||
private final ArticleService articleService;
|
||||
private final TagsService tagsService;
|
||||
private final CategoryService categoryService;
|
||||
|
||||
@GetMapping("article/write")
|
||||
public String writeArticleForm(NewArticleDto newArticleDto, Model model){
|
||||
|
||||
|
||||
CategoryForMainView categoryForView = categoryService.getCategoryForView();
|
||||
|
||||
model.addAttribute("category",categoryForView);
|
||||
model.addAttribute(newArticleDto);
|
||||
|
||||
return "articleWriteForm";
|
||||
return "article/articleWriteForm";
|
||||
}
|
||||
|
||||
@PostMapping("article/write")
|
||||
@Transactional
|
||||
public String WriteArticle(@ModelAttribute NewArticleDto newArticleDto, Authentication authentication){
|
||||
|
||||
|
||||
PrincipalDetails principal = (PrincipalDetails) authentication.getPrincipal();
|
||||
newArticleDto.setMemberId(principal.getMemberId());
|
||||
|
||||
Long articleId = articleService.writeArticle(newArticleDto);
|
||||
articleService.writeArticle(newArticleDto);
|
||||
|
||||
return "redirect:/";
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/main/article/{pageNum}")
|
||||
public @ResponseBody
|
||||
List<ArticleForMainView> nextPage(@PathVariable int pageNum){
|
||||
|
||||
return articleService.getRecentArticles(pageNum).getContent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,13 @@ package myblog.blog.article.domain;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import myblog.blog.base.domain.BasicEntity;
|
||||
import myblog.blog.category.domain.Category;
|
||||
import myblog.blog.member.doamin.Member;
|
||||
import myblog.blog.tags.domain.ArticleTagList;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@@ -27,20 +31,31 @@ public class Article extends BasicEntity {
|
||||
@Column(columnDefinition = "bigint default 0",nullable = false)
|
||||
private Long hit;
|
||||
private String toc;
|
||||
|
||||
private String thumbnailUrl;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "member_id")
|
||||
private Member member;
|
||||
private String thumbnailUrl;
|
||||
|
||||
@OneToMany(mappedBy = "article")
|
||||
private List<ArticleTagList> articleTagLists = new ArrayList<>();
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "category_id")
|
||||
private Category category;
|
||||
|
||||
protected Article() {
|
||||
}
|
||||
|
||||
@Builder
|
||||
public Article(String title, String content, String toc, Member member) {
|
||||
public Article(String title, String content, String toc, Member member, String thumbnailUrl, Category category) {
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
this.toc = toc;
|
||||
this.member = member;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.hit = 0L;
|
||||
this.category = category;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package myblog.blog.article.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ArticleForMainView {
|
||||
|
||||
private Long id;
|
||||
private String title;
|
||||
private String content;
|
||||
private String thumbnailUrl;
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
}
|
||||
@@ -1,9 +1,16 @@
|
||||
package myblog.blog.article.dto;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import myblog.blog.tags.domain.Tags;
|
||||
import myblog.blog.tags.dto.TagsDto;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
@@ -19,5 +26,8 @@ public class NewArticleDto {
|
||||
|
||||
private String thumbnailUrl;
|
||||
|
||||
private String category;
|
||||
private String tags;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package myblog.blog.article.repository;
|
||||
|
||||
import myblog.blog.article.domain.Article;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
public interface ArticlePagingRepository extends Repository<Article,Long> {
|
||||
|
||||
Slice<Article> findBy(Pageable pageable);
|
||||
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
package myblog.blog.article.repository;
|
||||
|
||||
import myblog.blog.article.domain.Article;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public interface ArticleRepository extends JpaRepository<Article, Long> {
|
||||
|
||||
List<Article> findTop6ByOrderByHitDesc();
|
||||
|
||||
Slice<Article> findByOrderByCreatedDateDesc(Pageable pageable);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,27 +2,70 @@ package myblog.blog.article.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.article.dto.ArticleForMainView;
|
||||
import myblog.blog.article.dto.NewArticleDto;
|
||||
import myblog.blog.article.repository.ArticleRepository;
|
||||
import myblog.blog.category.service.CategoryService;
|
||||
import myblog.blog.member.doamin.Member;
|
||||
import myblog.blog.member.repository.MemberRepository;
|
||||
import myblog.blog.member.service.Oauth2MemberService;
|
||||
import myblog.blog.tags.service.TagsService;
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class ArticleService {
|
||||
|
||||
private final ArticleRepository articleRepository;
|
||||
private final ArticleRepository
|
||||
articleRepository;
|
||||
private final MemberRepository memberRepository;
|
||||
private final TagsService tagsService;
|
||||
private final CategoryService categoryService;
|
||||
private final Oauth2MemberService memberService;
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public Long writeArticle(NewArticleDto articleDto) {
|
||||
|
||||
Article newArticle = createNewArticleFrom(articleDto);
|
||||
|
||||
articleRepository.save(newArticle);
|
||||
tagsService.createNewTagsAndArticleTagList(articleDto.getTags(), newArticle);
|
||||
|
||||
return newArticle.getId();
|
||||
|
||||
}
|
||||
|
||||
public List<ArticleForMainView> getPopularArticles() {
|
||||
List<Article> top6ByOrderByHitDesc = articleRepository.findTop6ByOrderByHitDesc();
|
||||
|
||||
List<ArticleForMainView> articles = new ArrayList<>();
|
||||
|
||||
for (Article article : top6ByOrderByHitDesc) {
|
||||
articles.add(modelMapper.map(article, ArticleForMainView.class));
|
||||
}
|
||||
|
||||
|
||||
return articles;
|
||||
|
||||
}
|
||||
|
||||
public Slice<ArticleForMainView> getRecentArticles(int page) {
|
||||
|
||||
return articleRepository.findByOrderByCreatedDateDesc(PageRequest.of(page, 5))
|
||||
.map(article -> modelMapper.map(article, ArticleForMainView.class));
|
||||
|
||||
}
|
||||
|
||||
private Article createNewArticleFrom(NewArticleDto articleDto) {
|
||||
Member member =
|
||||
memberRepository.findById(articleDto.getMemberId()).orElseThrow(() -> {
|
||||
@@ -33,7 +76,13 @@ public class ArticleService {
|
||||
.title(articleDto.getTitle())
|
||||
.content(articleDto.getContent())
|
||||
.toc(articleDto.getToc())
|
||||
.thumbnailUrl(articleDto.getThumbnailUrl())
|
||||
.category(categoryService.findCategory(articleDto.getCategory()))
|
||||
.member(member)
|
||||
.build();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
13
src/main/java/myblog/blog/base/config/AppConfig.java
Normal file
13
src/main/java/myblog/blog/base/config/AppConfig.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package myblog.blog.base.config;
|
||||
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public ModelMapper modelMapper(){ return new ModelMapper();}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@@ -43,6 +44,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.logoutSuccessUrl("/")
|
||||
.deleteCookies("JSESSIONID","remember-me")
|
||||
|
||||
.and().csrf()
|
||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||
|
||||
|
||||
.and()
|
||||
.oauth2Login()
|
||||
@@ -51,6 +55,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.userInfoEndpoint()
|
||||
.userService(oauth2MemberService)
|
||||
|
||||
|
||||
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
51
src/main/java/myblog/blog/category/domain/Category.java
Normal file
51
src/main/java/myblog/blog/category/domain/Category.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package myblog.blog.category.domain;
|
||||
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.base.domain.BasicEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@SequenceGenerator(
|
||||
name = "CATEGORY_SEQ_GENERATOR",
|
||||
sequenceName = "CATEGORY_SEQ",
|
||||
initialValue = 1, allocationSize = 50)
|
||||
public class Category extends BasicEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CATEGORY_SEQ_GENERATOR")
|
||||
@Column(name = "category_id")
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
@OneToMany(mappedBy = "category")
|
||||
private List<Article> articles = new ArrayList<>();
|
||||
|
||||
@Column(nullable = false)
|
||||
private int tier;
|
||||
|
||||
// 셀프조인
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "parents_id")
|
||||
private Category parents;
|
||||
|
||||
@OneToMany(mappedBy = "parents")
|
||||
private List<Category> child = new ArrayList<>();
|
||||
|
||||
@Builder
|
||||
public Category(String title, Category parents, int tier) {
|
||||
this.title = title;
|
||||
this.parents = parents;
|
||||
this.tier = tier;
|
||||
}
|
||||
|
||||
protected Category() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package myblog.blog.category.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class CategoryCountForRepository {
|
||||
|
||||
private String title;
|
||||
private int tier;
|
||||
private int count;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package myblog.blog.category.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class CategoryForMainView {
|
||||
|
||||
private int count;
|
||||
private String title;
|
||||
private List<CategoryForMainView> categoryTCountList = new ArrayList<>();
|
||||
|
||||
|
||||
public static CategoryForMainView createCategory(List<CategoryCountForRepository> crList) {
|
||||
|
||||
Collections.reverse(crList);
|
||||
return recursBuilding(0, crList);
|
||||
|
||||
}
|
||||
|
||||
private static CategoryForMainView recursBuilding(int d, List<CategoryCountForRepository> crList) {
|
||||
|
||||
CategoryForMainView categoryForMainView = new CategoryForMainView();
|
||||
|
||||
while (!crList.isEmpty()) {
|
||||
CategoryCountForRepository cSource = crList.get(0);
|
||||
|
||||
if (cSource.getTier() == d) {
|
||||
if(categoryForMainView.getTitle() != null
|
||||
&& categoryForMainView.getTitle() != cSource.getTitle()){
|
||||
return categoryForMainView;
|
||||
}
|
||||
categoryForMainView.setTitle(cSource.getTitle());
|
||||
categoryForMainView.setCount(cSource.getCount());
|
||||
crList.remove(0);
|
||||
} else if (cSource.getTier() > d) {
|
||||
CategoryForMainView sub = recursBuilding(d + 1, crList);
|
||||
categoryForMainView.getCategoryTCountList().add(sub);
|
||||
} else {
|
||||
return categoryForMainView;
|
||||
}
|
||||
|
||||
}
|
||||
return categoryForMainView;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package myblog.blog.category.repository;
|
||||
|
||||
import myblog.blog.category.domain.Category;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CategoryRepository extends JpaRepository<Category, Long> {
|
||||
|
||||
Category findByTitle(String title);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package myblog.blog.category.repository;
|
||||
|
||||
import myblog.blog.category.dto.CategoryCountForRepository;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface NaCategoryRepository {
|
||||
|
||||
@Select("select ifnull(f.title,'total') as title,ifnull(tier,0) as tier, count\n" +
|
||||
"from \n" +
|
||||
"(select ifnull(child,parent) as title, count\n" +
|
||||
"from\n" +
|
||||
"(select c.title 'parent', b.title as 'child' , count(*) as 'count'\n" +
|
||||
"from article a\n" +
|
||||
"join category b on (a.category_id = b.category_id)\n" +
|
||||
"left join category c on (b.parents_id = c.category_id)\n" +
|
||||
"group by parent, child with rollup) d\n" +
|
||||
") e\n" +
|
||||
"left join category f on (e.title = f.title)")
|
||||
List<CategoryCountForRepository> getCategoryCount();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package myblog.blog.category.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.category.domain.Category;
|
||||
import myblog.blog.category.dto.CategoryCountForRepository;
|
||||
import myblog.blog.category.dto.CategoryForMainView;
|
||||
import myblog.blog.category.repository.CategoryRepository;
|
||||
import myblog.blog.category.repository.NaCategoryRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CategoryService {
|
||||
|
||||
private final CategoryRepository categoryRepository;
|
||||
private final NaCategoryRepository naCategoryRepository;
|
||||
|
||||
public Long createNewCategory(String title, String parent) {
|
||||
|
||||
Category parentCategory = null;
|
||||
if (parent != null) {
|
||||
parentCategory = categoryRepository.findByTitle(parent);
|
||||
}
|
||||
|
||||
Category category = Category.builder()
|
||||
.title(title)
|
||||
.parents(parentCategory)
|
||||
.build();
|
||||
|
||||
return category.getId();
|
||||
}
|
||||
|
||||
public Category findCategory(String title){
|
||||
return categoryRepository.findByTitle(title);
|
||||
}
|
||||
|
||||
public CategoryForMainView getCategoryForView(){
|
||||
|
||||
List<CategoryCountForRepository> categoryCount = naCategoryRepository.getCategoryCount();
|
||||
|
||||
return CategoryForMainView.createCategory(categoryCount);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package myblog.blog.img.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.img.domain.UploadedImg;
|
||||
import myblog.blog.img.dto.UploadImgDto;
|
||||
import myblog.blog.img.service.UploadImgService;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class UploadImgController {
|
||||
|
||||
private final UploadImgService uploadImgService;
|
||||
|
||||
@PostMapping("/article/uploadImg")
|
||||
public @ResponseBody
|
||||
String imgUpload(@ModelAttribute UploadImgDto uploadImgDto) throws IOException {
|
||||
|
||||
return uploadImgService.storeImg(uploadImgDto.getImg());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UploadedImg {
|
||||
|
||||
private String uploadFileName;
|
||||
|
||||
13
src/main/java/myblog/blog/img/dto/UploadImgDto.java
Normal file
13
src/main/java/myblog/blog/img/dto/UploadImgDto.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package myblog.blog.img.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UploadImgDto {
|
||||
|
||||
private MultipartFile img;
|
||||
|
||||
}
|
||||
@@ -15,19 +15,18 @@ import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ImgService {
|
||||
public class UploadImgService {
|
||||
|
||||
@Value("${git.gitToken}")
|
||||
private String gitToken;
|
||||
@Value("${git.imgRepo}")
|
||||
|
||||
@Value("${git.imgRepo}")
|
||||
private String gitRepo;
|
||||
|
||||
@Value("${git.imgUrl}")
|
||||
private String imgUrl;
|
||||
|
||||
private final ModelMapper modelMapper;
|
||||
|
||||
public UploadedImg storeImg(MultipartFile multipartFile) throws IOException {
|
||||
public String storeImg(MultipartFile multipartFile) throws IOException {
|
||||
if (multipartFile.isEmpty()) {
|
||||
throw new IllegalArgumentException("이미지가 존재하지 않습니다.");
|
||||
}
|
||||
@@ -41,7 +40,9 @@ public class ImgService {
|
||||
repository.createContent().path("img/"+storeFileName)
|
||||
.content(multipartFile.getBytes()).message("test").branch("main").commit();
|
||||
|
||||
return new UploadedImg(originalFilename, storeFileName, imgUrl +storeFileName+"?raw=true");
|
||||
UploadedImg uploadedImg = new UploadedImg(originalFilename, storeFileName, imgUrl + storeFileName + "?raw=true");
|
||||
|
||||
return uploadedImg.getUploadUrl();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,41 @@
|
||||
package myblog.blog.main;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.article.dto.ArticleForMainView;
|
||||
import myblog.blog.article.service.ArticleService;
|
||||
import myblog.blog.category.dto.CategoryForMainView;
|
||||
import myblog.blog.category.service.CategoryService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class MainController {
|
||||
|
||||
private final ArticleService articleService;
|
||||
private final CategoryService categoryService;
|
||||
|
||||
@GetMapping("/")
|
||||
public String main() {
|
||||
public String main(Model model) {
|
||||
|
||||
List<ArticleForMainView> popularArticles = articleService.getPopularArticles();
|
||||
Slice<ArticleForMainView> recentArticles = articleService.getRecentArticles(0);
|
||||
CategoryForMainView categoryForView = categoryService.getCategoryForView();
|
||||
|
||||
model.addAttribute("category",categoryForView);
|
||||
model.addAttribute("popularArticles", popularArticles);
|
||||
model.addAttribute("recentArticles",recentArticles);
|
||||
|
||||
return "main";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
package myblog.blog.member.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.category.dto.CategoryForMainView;
|
||||
import myblog.blog.category.service.CategoryService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class MemberController {
|
||||
|
||||
private final CategoryService categoryService;
|
||||
|
||||
@GetMapping("/login")
|
||||
public String loginFrom(@RequestParam(value = "error",required = false) String error, Model model){
|
||||
|
||||
@@ -15,6 +21,11 @@ public class MemberController {
|
||||
model.addAttribute("errMsg","이미 가입된 이메일입니다.");
|
||||
}
|
||||
|
||||
CategoryForMainView categoryForView = categoryService.getCategoryForView();
|
||||
|
||||
model.addAttribute("category",categoryForView);
|
||||
|
||||
|
||||
return "login";
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import myblog.blog.member.doamin.Member;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface MemberRepository extends JpaRepository<Member, Long> {
|
||||
|
||||
Member findByUserId(String userId);
|
||||
|
||||
@@ -77,7 +77,6 @@ public class Oauth2MemberService extends DefaultOAuth2UserService {
|
||||
return member;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void insertAdmin(){
|
||||
|
||||
Member admin = memberRepository.findByEmail(adminEmail);
|
||||
|
||||
37
src/main/java/myblog/blog/tags/domain/ArticleTagList.java
Normal file
37
src/main/java/myblog/blog/tags/domain/ArticleTagList.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package myblog.blog.tags.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.base.domain.BasicEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@SequenceGenerator(
|
||||
name = "ARTICLE_TAG_LIST_SEQ_GENERATOR",
|
||||
sequenceName = "ARTICLE_TAG_LIST_SEQ",
|
||||
initialValue = 1, allocationSize = 50)
|
||||
public class ArticleTagList extends BasicEntity {
|
||||
@Id
|
||||
@Column(name = "article_tag_list_id")
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ARTICLE_TAG_LIST_SEQ_GENERATOR")
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "article_id")
|
||||
private Article article;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "tags_id")
|
||||
private Tags tags;
|
||||
|
||||
@Builder
|
||||
public ArticleTagList(Article article, Tags tags) {
|
||||
this.article = article;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
protected ArticleTagList() {
|
||||
|
||||
}
|
||||
}
|
||||
36
src/main/java/myblog/blog/tags/domain/Tags.java
Normal file
36
src/main/java/myblog/blog/tags/domain/Tags.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package myblog.blog.tags.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import myblog.blog.base.domain.BasicEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@SequenceGenerator(
|
||||
name = "TAGS_SEQ_GENERATOR",
|
||||
sequenceName = "TAGS_SEQ",
|
||||
initialValue = 1, allocationSize = 50)
|
||||
@Getter
|
||||
public class Tags extends BasicEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = "tags_id")
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TAGS_SEQ_GENERATOR")
|
||||
private Long id;
|
||||
@Column(unique = true, nullable = false)
|
||||
private String name;
|
||||
@OneToMany(mappedBy = "tags")
|
||||
private List<ArticleTagList> articleTagLists = new ArrayList<>();
|
||||
|
||||
@Builder
|
||||
public Tags(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected Tags() {
|
||||
|
||||
}
|
||||
}
|
||||
14
src/main/java/myblog/blog/tags/dto/TagsDto.java
Normal file
14
src/main/java/myblog/blog/tags/dto/TagsDto.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package myblog.blog.tags.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TagsDto {
|
||||
|
||||
private String value;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ value : " + value + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package myblog.blog.tags.repository;
|
||||
|
||||
import myblog.blog.tags.domain.ArticleTagList;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface ArticleTagListsRepository extends JpaRepository<ArticleTagList, Long> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package myblog.blog.tags.repository;
|
||||
|
||||
import myblog.blog.tags.domain.Tags;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface TagsRepository extends JpaRepository<Tags, Long> {
|
||||
|
||||
Tags findByName(String name);
|
||||
|
||||
}
|
||||
49
src/main/java/myblog/blog/tags/service/TagsService.java
Normal file
49
src/main/java/myblog/blog/tags/service/TagsService.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package myblog.blog.tags.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import myblog.blog.article.domain.Article;
|
||||
import myblog.blog.article.repository.ArticleRepository;
|
||||
import myblog.blog.tags.domain.ArticleTagList;
|
||||
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.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class TagsService {
|
||||
|
||||
private final TagsRepository tagsRepository;
|
||||
private final ArticleTagListsRepository articleTagListsRepository;
|
||||
|
||||
public void createNewTagsAndArticleTagList(String names, Article article) {
|
||||
|
||||
Gson gson = new Gson();
|
||||
ArrayList<Map> tagsDtoArrayList = gson.fromJson(names, ArrayList.class);
|
||||
|
||||
for (Map tags : tagsDtoArrayList) {
|
||||
|
||||
Tags tag = tagsRepository.findByName(tags.get("value").toString());
|
||||
if (tag == null) {
|
||||
tag = tagsRepository.save(Tags.builder().name(tags.get("value").toString()).build());
|
||||
|
||||
}
|
||||
articleTagListsRepository.save(ArticleTagList.builder()
|
||||
.article(article)
|
||||
.tags(tag)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user