728x90
반응형
이번에는 백엔드 상품 등록 및 변경 기능을 구현해보겠습니다.
먼저 상품 엔티티를 등록합니다.
import javax.persistence.*
@Entity
@Table(name = "products")
data class Product(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
val name: String,
val description: String,
val price: Float,
val imageUrl: String? = null
)
리파지토리 구현
import com.hsproject.envmarket.products.Product
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface ProductRepository: JpaRepository<Product, Long> {
fun findByName(name: String): List<Product>
}
서비스 구현
import com.hsproject.envmarket.products.Product
import com.hsproject.envmarket.repository.ProductRepository
import org.springframework.stereotype.Service
import javax.persistence.EntityNotFoundException
@Service
class ProductService(private val productRepository: ProductRepository) {
fun getAllProducts(): List<Product> = productRepository.findAll()
fun getProductById(productId: Long): Product =
productRepository.findById(productId).orElseThrow { EntityNotFoundException("Product not found") }
fun getProductByName(productName: String): List<Product> {
val products = productRepository.findByName(productName)
// if (products.isNotEmpty()) {
// return products
// } else {
// throw EntityNotFoundException("Product not found")
// }
return products
}
fun insertProduct(product: Product): Product {
if (product.id == null || !productRepository.existsById(product.id)) {
return productRepository.save(product)
}
throw Exception("Product already exist")
}
fun updateProduct(product: Product): Product {
if (product.id == null || !productRepository.existsById(product.id)) {
throw EntityNotFoundException("Product not found")
}
return productRepository.save(product)
}
}
컨트롤러 구현
import com.hsproject.envmarket.products.Product
import com.hsproject.envmarket.service.ProductService
import com.hsproject.envmarket.service.StorageService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
@RestController
@RequestMapping("/products")
@CrossOrigin("*")
class ProductController(private val productService: ProductService, private val storageService: StorageService) {
//상품 전체 조회
@GetMapping
fun getAllProducts(): ResponseEntity<List<Product>> {
val products = productService.getAllProducts()
return ResponseEntity.ok(products)
}
// 상품 하나 조회
@GetMapping("/{productId}")
fun getProductById(@PathVariable productId: Long): ResponseEntity<Product> {
val product = productService.getProductById(productId)
return ResponseEntity.ok(product)
}
// 상품 이름으로 검색
@GetMapping("/search")
fun getProductByName(@RequestParam searchName: String): ResponseEntity<List<Product>> {
val searchProduct = productService.getProductByName(searchName)
return if (searchProduct.isNotEmpty()) {
ResponseEntity.ok(searchProduct)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(emptyList())
}
}
//상품 등록
@PostMapping("/enroll")
fun productEnroll(
@RequestParam("file") file: MultipartFile,
@RequestParam("name") name: String,
@RequestParam("description") description: String,
@RequestParam("price") price: Float
): ResponseEntity<Product> {
val imageUrl = storageService.storeFile(file)
val product = Product(name = name, description = description, price = price, imageUrl = imageUrl)
val savedProduct = productService.insertProduct(product)
return ResponseEntity.ok(savedProduct)
}
//상품 이미지 업데이트
@PostMapping("/{productId}/image")
fun uploadImage(
@PathVariable productId: Long,
@RequestParam("file") file: MultipartFile
): ResponseEntity<Product> {
val product = productService.getProductById(productId)
val imageUrl = storageService.storeFile(file)
val updatedProduct = product.copy(imageUrl = imageUrl)
productService.updateProduct(updatedProduct)
return ResponseEntity.ok(updatedProduct)
}
}
스토리지 서비스 구현
import com.hsproject.envmarket.config.StorageProperties
import lombok.extern.slf4j.Slf4j
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import org.springframework.util.StringUtils
import org.springframework.web.multipart.MultipartFile
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
@Slf4j
@Service
class StorageService(private val storageProperties: StorageProperties) {
val logger: Logger = LoggerFactory.getLogger(StorageService::class.java)
private val uploadDir: Path = Paths.get(storageProperties.uploadDir)
init {
Files.createDirectories(uploadDir)
}
fun storeFile(file: MultipartFile): String {
try {
logger.info("경로 {}" , uploadDir)
val filename = StringUtils.cleanPath(file.originalFilename!!)
logger.info("파일 이름: {}", filename)
val targetLocation = uploadDir.resolve(filename)
logger.info("타겟 위치: {}", targetLocation)
Files.createDirectories(uploadDir)
Files.copy(file.inputStream, targetLocation, StandardCopyOption.REPLACE_EXISTING)
logger.info("파일 저장 성공")
val fileUrl = "/img/$filename"
logger.info("저장된 파일 URL: {}", fileUrl)
return fileUrl
} catch (e: Exception) {
logger.error("파일 저장 실패", e)
throw e
}
}
}
이미지 파일을 저장할때 스토리지에 저장하고 불러올때는 DB의 url을 저장하여 불러내는 방식입니다.
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration
@Configuration
@ConfigurationProperties(prefix = "storage")
data class StorageProperties(
var uploadDir: String = ""
)
이렇게 경로를 설정해줍니다. 해당경로는 application.yml에 프론트 UPLOAD PATH로 설정하여
지정해주면 해당 폴더에서 URL로 찾을 수 있습니다.
자 다음에는 프론트에서 상품등록을 구현해보겠습니다.
728x90
반응형
'포트폴리오' 카테고리의 다른 글
React와 TensorFlow.js로 당뇨병 예측 웹앱 만들기: 머신러닝 기반 프로젝트 튜토리얼 (0) | 2023.08.09 |
---|---|
포트폴리오 리뷰: AI 갤러리 프로젝트 - Node.js, MongoDB, EJS 템플릿 엔진을 활용한 웹 개발 (0) | 2023.07.20 |
친환경 쇼핑몰 프로젝트 구축하기: 리액트와 리코일을 이용한 로그인 및 회원가입 페이지 구현 - 전역 상태 관리와 라우팅 적용 (3) (0) | 2023.06.26 |
친환경 쇼핑몰 프로젝트 구축하기: 스프링 부트와 JWT를 활용한 회원가입 및 로그인 기능 구현 - 보안 설정 및 인증 과정 개요 (2) (0) | 2023.06.26 |
친환경 쇼핑몰 프로젝트 구축하기: 1인 개발자의 웹사이트 제작 및 기술 스택 소개 (1) (0) | 2023.06.26 |
댓글