Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'

//s3
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

//test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.gaplog.server.domain.comment.dto.response.CommentLikeUpdateResponse;
import com.gaplog.server.domain.comment.dto.response.CommentResponse;
import com.gaplog.server.domain.comment.dto.response.CommentUpdateResponse;
import com.gaplog.server.domain.post.application.PostService;
import com.gaplog.server.domain.post.dao.PostRepository;
import com.gaplog.server.domain.post.domain.Post;
import com.gaplog.server.domain.user.dao.UserRepository;
Expand All @@ -28,6 +29,7 @@ public class CommentService {
private final PostRepository postRepository;
private final UserRepository userRepository;
private final CommentLikeRepository commentLikeRepository;
private final PostService postService;

@Transactional
public CommentResponse createComment(Long postId, Long userId, String text, Long parentId) {
Expand All @@ -40,6 +42,8 @@ public CommentResponse createComment(Long postId, Long userId, String text, Long

Comment newComment = Comment.of(post, user, text, parentId);

postService.PostCommentCountUpdate(postId, true);

commentRepository.save(newComment);
return CommentResponse.of(newComment);
}
Expand Down Expand Up @@ -99,6 +103,7 @@ public void deleteComment(Long commentId) {
//case 2 & case 3의 자식 댓글 setDeleted
comment.setDeleted(true);
commentRepository.save(comment);
postService.PostCommentCountUpdate(comment.getPost().getId(),false);
}
}

Expand Down

This file was deleted.

48 changes: 43 additions & 5 deletions src/main/java/com/gaplog/server/domain/post/api/PostApi.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
package com.gaplog.server.domain.post.api;


import com.gaplog.server.domain.post.application.PostImageService;
import com.gaplog.server.domain.post.application.PostService;
import com.gaplog.server.domain.post.domain.Post;
import com.gaplog.server.domain.post.dto.request.*;
import com.gaplog.server.domain.post.dto.response.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping("/api/posts")
@RequiredArgsConstructor
@Tag(name = "post API", description = "post API")
public class PostApi {
private final PostService postService;
private final PostImageService postImageService;

@Autowired
public PostApi(PostService postService, PostImageService postImageService) {
this.postService = postService;
this.postImageService = postImageService;
}

@PostMapping("/upload")
public String upload(MultipartFile image) throws IOException {
String imageUrl = postImageService.upload(image);
//return "<img th:src=\"${"+imageUrl+"}\" alt=\"이미지\"/>";
return imageUrl;
}

@PutMapping("/")
@Operation(summary = "게시글 작성", description = "게시글을 작성합니다.")
Expand Down Expand Up @@ -76,11 +92,33 @@ public ResponseEntity<SelectedPostResponse> getSelectedPost(@PathVariable ("post
return ResponseEntity.ok(response);
}

@GetMapping("/")
@Operation(summary = "메인 페이지 게시글 조회", description = "메인 페이지에 뜨는 게시글의 정보를 얻습니다.")
public ResponseEntity<List<MainPostResponse>> getMainPost() {
@GetMapping("/recent")
@Operation(summary = "메인 페이지 최근 게시글 조회", description = "메인 페이지에 뜨는 최근 게시글의 정보를 얻습니다.")
public ResponseEntity<List<MainPostResponse>> getMainRecentPost() {
try {
List<MainPostResponse> posts = postService.getMainRecentPostInfo();
return new ResponseEntity<>(posts, HttpStatus.OK);
} catch (RuntimeException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

@GetMapping("/hot")
@Operation(summary = "메인 페이지 인기 게시글 조회", description = "메인 페이지에 뜨는 인기 게시글의 정보를 얻습니다.")
public ResponseEntity<List<MainPostResponse>> getMainHotPost() {
try {
List<MainPostResponse> posts = postService.getMainHotPostInfo();
return new ResponseEntity<>(posts, HttpStatus.OK);
} catch (RuntimeException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

@GetMapping("/follow/{user_id}")
@Operation(summary = "메인 페이지 팔로우하는 유저 게시글 조회", description = "메인 페이지에 뜨는 팔로우하는 유저 게시글의 정보를 얻습니다.")
public ResponseEntity<List<MainPostResponse>> getMainFollowPost(@PathVariable("user_id") Long userId) {
try {
List<MainPostResponse> posts = postService.getMainPostInfo();
List<MainPostResponse> posts = postService.getMainFollowPostInfo(userId);
return new ResponseEntity<>(posts, HttpStatus.OK);
} catch (RuntimeException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.gaplog.server.domain.post.application;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.ObjectMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Service
public class PostImageService {
private final AmazonS3Client s3Client;

@Autowired
public PostImageService(AmazonS3Client s3Client) {
this.s3Client = s3Client;
}

@Value("${s3.bucket}")
private String bucket;

public String upload(MultipartFile image) throws IOException {
String originalFileName = image.getOriginalFilename();
String fileName = changeFileName(originalFileName);

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(image.getContentType());
metadata.setContentLength(image.getSize());

s3Client.putObject(bucket, fileName, image.getInputStream(), metadata);

return s3Client.getUrl(bucket, fileName).toString();
}

private String changeFileName(String originalFileName) {
/* 업로드할 파일의 이름을 변경하는 로직 */
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
return originalFileName + "_" + LocalDateTime.now().format(formatter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -108,7 +109,7 @@ public void deletePost(Long postId) {
//조회 기능
//메인화면 게시글 조회
@Transactional
public List<MainPostResponse> getMainPostInfo() {
public List<MainPostResponse> getMainRecentPostInfo() {
List<Post> posts = postRepository.findTop20ByOrderByCreatedAtDesc(PageRequest.of(0, 20));

// Post 엔티티를 PostResponse DTO로 변환
Expand All @@ -117,6 +118,29 @@ public List<MainPostResponse> getMainPostInfo() {
.collect(Collectors.toList());
}

@Transactional
public List<MainPostResponse> getMainHotPostInfo() {
List<Post> posts = postRepository.findAllByOrderByLikeCountDesc(PageRequest.of(0, 20));

// Post 엔티티를 PostResponse DTO로 변환
return posts.stream()
.map(MainPostResponse::of)
.collect(Collectors.toList());
}

@Transactional
public List<MainPostResponse> getMainFollowPostInfo(Long userId) {
List<Post> posts = postRepository.findLatestPostsByFollowedUsers(userId);

// 게시물들을 최신순으로 정렬하고 상위 20개만 반환
return posts.stream()
.sorted(Comparator.comparing(Post::getCreatedAt).reversed())
.limit(20)
.map(MainPostResponse::of)
.collect(Collectors.toList());

}

//특정 게시물(선택된 게시물) 조회
@Transactional
public SelectedPostResponse getSelectedPostInfo(Long postId) {
Expand Down Expand Up @@ -227,4 +251,20 @@ public PostScrapUpdateResponse PostScrapUpdate(Long postId, PostScrapUpdateReque
return PostScrapUpdateResponse.of(updatedPost);
}

@Transactional
public void PostCommentCountUpdate(Long postId, Boolean bool) {
Post post = postRepository.findById(postId).orElseThrow(()
->new IllegalArgumentException("Post not found: " + postId));
if(bool){
post.increaseCommentCount();
}
else{
post.decreaseCommentCount();
}

postRepository.save(post);

return;
}

}
32 changes: 32 additions & 0 deletions src/main/java/com/gaplog/server/domain/post/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.gaplog.server.domain.post.config;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {

@Value("${s3.credentials.access-key}")
private String accessKey;

@Value("${s3.credentials.secret-key}")
private String secretKey;

@Value("${s3.credentials.region}")
private String region;

@Bean
public AmazonS3Client s3Client(){
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);

return (AmazonS3Client) AmazonS3Client.builder()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;


import java.util.List;
Expand All @@ -16,6 +17,11 @@ public interface PostRepository extends JpaRepository<Post, Long> {
@Query("SELECT p FROM Post p ORDER BY p.createdAt DESC")
List<Post> findTop20ByOrderByCreatedAtDesc(Pageable pageable);
List<Post> findByTitleContainingOrContentContaining(String titleKeyword, String contentKeyword);
List<Post> findAllByOrderByLikeCountDesc(Pageable pageable);
@Query("SELECT p FROM Post p WHERE p.user IN " +
"(SELECT ur.followee FROM UserRelationships ur WHERE ur.follower.id = :userId) " +
"AND p.createdAt = (SELECT MAX(p2.createdAt) FROM Post p2 WHERE p2.user = p.user)")
List<Post> findLatestPostsByFollowedUsers(@Param("userId") Long userId);
// 특정 유저가 작성한 게시물 조회
List<Post> findByUserId(Long userId);
}

This file was deleted.

Loading