728x90
320x100
✅ 필요한 것
- 게시글을 올린 user 정보 (이름, 프로필사진)
- 사진에 대한 정보
- 캡션에 대한 정보
- 좋아요, 댓글에 대한 정보 (좀 뒤에 구현 예정)
📌 ImageDto
package yerong.InstagramCloneCoding.web.dto.image;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;
import yerong.InstagramCloneCoding.domain.user.User;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class ImageDto {
private Long id;
private String caption;
private String postImageUrl;
private Long userId;
private String username;
private String profileImageUrl;
}
- 필요한 정보들을 담을 dto 생성
📌 Image 엔티티
package yerong.InstagramCloneCoding.domain.image;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import lombok.*;
import yerong.InstagramCloneCoding.domain.user.User;
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Builder
@Entity
public class Image {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "image_id")
private Long id;
private String caption;
private String postImageUrl;
@JsonIgnoreProperties({"images"}) //user에 있는 images는 무시
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
//좋아요
//댓글
}
- user에 @JsonIgnoreProperties를 걸어줘서 무한로딩을 방지
📌 Image Repository
package yerong.InstagramCloneCoding.repository.image;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import yerong.InstagramCloneCoding.domain.image.Image;
import java.util.List;
@Repository
public interface ImageRepository extends JpaRepository<Image, Long> {
@Query(value = "SELECT * from image where user_id = :principalId OR user_id In (SELECT to_user_id FROM subscribe WHERE from_user_id = :principalId) ", nativeQuery = true)
List<Image> mStory(Long principalId);
}
- 자신이 구독한 사람들의 이미지들과 나의 이미지를 가져오는 코드 구현
📌 ImageApiController
package yerong.InstagramCloneCoding.web.api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import yerong.InstagramCloneCoding.config.auth.PrincipalDetails;
import yerong.InstagramCloneCoding.service.ImageService;
import yerong.InstagramCloneCoding.web.dto.CMRespDto;
import yerong.InstagramCloneCoding.web.dto.image.ImageDto;
import java.util.List;
@RequiredArgsConstructor
@RestController
@Slf4j
public class ImageApiController {
private final ImageService imageService;
@GetMapping("/api/image")
public ResponseEntity<CMRespDto<?>> imageStory(@AuthenticationPrincipal PrincipalDetails principalDetails){
List<ImageDto> imageDtos = imageService.imageStory(principalDetails.getUser().getId());
return new ResponseEntity<CMRespDto<?>>(new CMRespDto<>(1, "이미지 정보 가져오기 성공", imageDtos), HttpStatus.OK);
}
}
- 이미지 정보를 들고오는 controller
✔️ 페이징하기
📌 ImageApiController
package yerong.InstagramCloneCoding.web.api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import yerong.InstagramCloneCoding.config.auth.PrincipalDetails;
import yerong.InstagramCloneCoding.service.ImageService;
import yerong.InstagramCloneCoding.web.dto.CMRespDto;
import yerong.InstagramCloneCoding.web.dto.image.ImageDto;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class ImageApiController {
private final ImageService imageService;
@GetMapping("/api/image")
public ResponseEntity<CMRespDto<?>> imageStory(
@AuthenticationPrincipal PrincipalDetails principalDetails,
@PageableDefault(size = 3)Pageable pageable
){
Page<ImageDto> imageDtos = imageService.imageStory(principalDetails.getUser().getId(), pageable);
return new ResponseEntity<CMRespDto<?>>(new CMRespDto<>(1, "이미지 정보 가져오기 성공", imageDtos), HttpStatus.OK);
}
}
- @PageableDefault 추가
- size = 3 : 3개씩 뽑아옴
📌 ImageServiceImpl
package yerong.InstagramCloneCoding.service.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yerong.InstagramCloneCoding.domain.image.Image;
import yerong.InstagramCloneCoding.domain.user.User;
import yerong.InstagramCloneCoding.handler.exception.CustomValidationApiException;
import yerong.InstagramCloneCoding.repository.image.ImageRepository;
import yerong.InstagramCloneCoding.repository.user.UserRepository;
import yerong.InstagramCloneCoding.service.ImageService;
import yerong.InstagramCloneCoding.web.dto.image.ImageDto;
import yerong.InstagramCloneCoding.web.dto.image.ImageUploadDto;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Service
@RequiredArgsConstructor
public class ImageServiceImpl implements ImageService {
private final ImageRepository imageRepository;
private final UserRepository userRepository;
@Transactional(readOnly = true)
@Override
public Page<ImageDto> imageStory(Long principalId, Pageable pageable){
Page<Image> images = imageRepository.mStory(principalId, pageable);
return images.map(image -> ImageDto.builder()
.id(image.getId())
.caption(image.getCaption())
.postImageUrl(image.getPostImageUrl())
.userId(image.getUser().getId())
.username(image.getUser().getUsername())
.profileImageUrl(image.getUser().getProfileImageUrl())
.build());
}
@Value("${file.path}")
private String uploadFolder;
@Override
@Transactional
public void imageUpload(Long userId, ImageUploadDto imageUploadDto){
UUID uuid = UUID.randomUUID();
String imageFileName = uuid + "_" + imageUploadDto.getFile().getOriginalFilename();
Path imageFilePath = Paths.get(uploadFolder+imageFileName);
try{
Files.write(imageFilePath, imageUploadDto.getFile().getBytes());
}
catch (Exception e){
e.printStackTrace();
}
User user = userRepository.findById(userId).orElseThrow(() -> new CustomValidationApiException("찾을 수 없는 Id 입니다."));
Image image = imageUploadDto.toEntity(imageFileName, user);
Image savedImage = imageRepository.save(image);
user.addImage(savedImage);
}
}
- List를 Page로 바꾸고 pageable을 받아옴
📌 ImageRepository
package yerong.InstagramCloneCoding.repository.image;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import yerong.InstagramCloneCoding.domain.image.Image;
import java.util.List;
@Repository
public interface ImageRepository extends JpaRepository<Image, Long> {
@Query(value = "SELECT * from image where user_id = :principalId OR user_id In (SELECT to_user_id FROM subscribe WHERE from_user_id = :principalId) ORDER BY image_id DESC ", nativeQuery = true)
Page<Image> mStory(Long principalId, Pageable pageable);
}
- 페이징 코드 추가
PREV
NEXT
728x90
반응형
'프로젝트 > 인스타그램 클론 코딩' 카테고리의 다른 글
[인스타그램 클론 코딩][Spring boot] 11. 댓글 구현 (0) | 2024.03.01 |
---|---|
[인스타그램 클론 코딩][Spring boot] 10. 좋아요 및 인기 페이지 구현 (0) | 2024.02.23 |
[인스타그램 클론 코딩][Spring boot] 8. 구독 정보 뷰 렌더링 (0) | 2024.02.21 |
[인스타그램 클론 코딩][Spring boot] 7. 프로필 페이지 (2) | 2024.02.20 |
[인스타그램 클론 코딩][Spring boot] 6. 구독하기 (0) | 2024.02.19 |