diff --git a/src/main/java/com/example/fiurinee/domain/dictionary/controller/DictionaryController.java b/src/main/java/com/example/fiurinee/domain/dictionary/controller/DictionaryController.java new file mode 100644 index 0000000..9161906 --- /dev/null +++ b/src/main/java/com/example/fiurinee/domain/dictionary/controller/DictionaryController.java @@ -0,0 +1,37 @@ +package com.example.fiurinee.domain.dictionary.controller; + +import com.example.fiurinee.domain.dictionary.controller.api.DictionaryApi; +import com.example.fiurinee.domain.dictionary.dto.DictionaryResponseDTO; +import com.example.fiurinee.domain.dictionary.service.DictionaryService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +public class DictionaryController implements DictionaryApi { + private final DictionaryService dictionaryService; + + @Override + public ResponseEntity> getAllFlowers(int page) { + int size = 30; // 한 페이지에 보여줄 꽃의 개수 + List flowers = dictionaryService.getAllFlowers(page, size); + return ResponseEntity.ok(flowers); + } + + @Override + public ResponseEntity> searchFlowers(String name) { + List flowers = dictionaryService.searchFlowersByName(name); + return ResponseEntity.ok(flowers); + } + + @Override + public ResponseEntity getTotalPages(int size) { + int totalPages = dictionaryService.getTotalPages(size); + return ResponseEntity.ok(totalPages); + } + +} + diff --git a/src/main/java/com/example/fiurinee/domain/dictionary/controller/api/DictionaryApi.java b/src/main/java/com/example/fiurinee/domain/dictionary/controller/api/DictionaryApi.java new file mode 100644 index 0000000..2006747 --- /dev/null +++ b/src/main/java/com/example/fiurinee/domain/dictionary/controller/api/DictionaryApi.java @@ -0,0 +1,48 @@ +package com.example.fiurinee.domain.dictionary.controller.api; + +import com.example.fiurinee.domain.dictionary.dto.DictionaryResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@Tag(name = "Dictionary", description = "사전 관련 API") +@RequestMapping("/dictionary") +public interface DictionaryApi { + @Operation( + summary = "모든 꽃 조회", + description = "페이지 단위로 모든 꽃을 조회합니다.", + security = @SecurityRequirement(name = "bearerAuth") + ) + @ApiResponse(responseCode = "200", description = "꽃 조회 성공") + @ApiResponse(responseCode = "401", description = "인증 실패") + @GetMapping + ResponseEntity> getAllFlowers(@RequestParam int page); + + @Operation( + summary = "꽃 이름으로 검색", + description = "이름에 특정 단어가 포함된 꽃을 검색합니다.", + security = @SecurityRequirement(name = "bearerAuth") + ) + @ApiResponse(responseCode = "200", description = "꽃 검색 성공") + @ApiResponse(responseCode = "401", description = "인증 실패") + @GetMapping("/search") + ResponseEntity> searchFlowers(@RequestParam String name); + + @Operation( + summary = "총 페이지 수 조회", + description = "전체 꽃 목록의 총 페이지 수를 조회합니다.", + security = @SecurityRequirement(name = "bearerAuth") + ) + @ApiResponse(responseCode = "200", description = "총 페이지 수 조회 성공") + @ApiResponse(responseCode = "401", description = "인증 실패") + @GetMapping("/total-pages") + ResponseEntity getTotalPages(@RequestParam int size); +} + diff --git a/src/main/java/com/example/fiurinee/domain/dictionary/dto/DictionaryResponseDTO.java b/src/main/java/com/example/fiurinee/domain/dictionary/dto/DictionaryResponseDTO.java new file mode 100644 index 0000000..1bad4a0 --- /dev/null +++ b/src/main/java/com/example/fiurinee/domain/dictionary/dto/DictionaryResponseDTO.java @@ -0,0 +1,25 @@ +package com.example.fiurinee.domain.dictionary.dto; + +import com.example.fiurinee.domain.flower.entity.Flower; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class DictionaryResponseDTO { + private String flower; + private String period; + private String flowerLanguage; + private String explain; + private String image; + + public static DictionaryResponseDTO of(Flower flower) { + return DictionaryResponseDTO.builder() + .flower(flower.getName()) + .period(String.format("%02d", flower.getPeriod() / 100)) + .flowerLanguage(flower.getFlowerLanguage()) + .explain(flower.getExplain()) + .image(flower.getImage().toString()) + .build(); + } +} diff --git a/src/main/java/com/example/fiurinee/domain/dictionary/service/DictionaryService.java b/src/main/java/com/example/fiurinee/domain/dictionary/service/DictionaryService.java new file mode 100644 index 0000000..9559984 --- /dev/null +++ b/src/main/java/com/example/fiurinee/domain/dictionary/service/DictionaryService.java @@ -0,0 +1,39 @@ +package com.example.fiurinee.domain.dictionary.service; + + +import com.example.fiurinee.domain.dictionary.dto.DictionaryResponseDTO; +import com.example.fiurinee.domain.flower.entity.Flower; +import com.example.fiurinee.domain.flower.repository.FlowerRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class DictionaryService { + private final FlowerRepository flowerRepository; + + public List getAllFlowers(int page, int size) { + PageRequest pageRequest = PageRequest.of(page - 1, size); + List flowers = flowerRepository.findDistinctAll(pageRequest); + return flowers.stream() + .map(DictionaryResponseDTO::of) + .collect(Collectors.toList()); + } + + public List searchFlowersByName(String name) { + List flowers = flowerRepository.findDistinctByNameContaining(name); + return flowers.stream() + .map(DictionaryResponseDTO::of) + .collect(Collectors.toList()); + } + + public int getTotalPages(int size) { + long count = flowerRepository.countDistinctFlowers(); + return (int) Math.ceil((double) count / size); + } +} diff --git a/src/main/java/com/example/fiurinee/domain/flower/repository/FlowerRepository.java b/src/main/java/com/example/fiurinee/domain/flower/repository/FlowerRepository.java index ecca8e9..6173c34 100644 --- a/src/main/java/com/example/fiurinee/domain/flower/repository/FlowerRepository.java +++ b/src/main/java/com/example/fiurinee/domain/flower/repository/FlowerRepository.java @@ -1,6 +1,8 @@ package com.example.fiurinee.domain.flower.repository; import com.example.fiurinee.domain.flower.entity.Flower; +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.data.repository.query.Param; @@ -18,4 +20,13 @@ public interface FlowerRepository extends JpaRepository { List findByNameAndFlowerLanguage(String name,String flowerLanguage); List findByName(String name); + + @Query(value = "SELECT DISTINCT ON (f.name) f.* FROM flower f WHERE f.name LIKE %:name%", nativeQuery = true) + List findDistinctByNameContaining(@Param("name") String name); + + @Query(value = "SELECT DISTINCT ON (f.name) f.* FROM flower f", nativeQuery = true) + List findDistinctAll(Pageable pageable); + + @Query(value = "SELECT COUNT(DISTINCT f.name) FROM flower f", nativeQuery = true) + long countDistinctFlowers(); } diff --git a/src/main/java/com/example/fiurinee/global/security/config/SecurityConfig.java b/src/main/java/com/example/fiurinee/global/security/config/SecurityConfig.java index bf08140..4be896b 100644 --- a/src/main/java/com/example/fiurinee/global/security/config/SecurityConfig.java +++ b/src/main/java/com/example/fiurinee/global/security/config/SecurityConfig.java @@ -79,7 +79,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers("/oauth2/login", "/login/oauth2/code/**", "/oauth2/authorization/**","/login/oauth2/code/google","/member/*/refresh","/model/test", "/swagger-ui/index.html", "/swagger-ui/**", "/v3/api-docs/**","/swagger-resources/**", "/v3/api-docs").permitAll() //비회원 전용 api - .requestMatchers("/main/today","/main/season","/model/ment","/model/*/non").permitAll() + .requestMatchers("/main/today","/main/season","/model/ment","/model/*/non", "/dictionary/**", "dictionary/search/**", "/dictionary", "/dictionary/search", "/dictionary/total-pages", "/dictionary/total-pages/**").permitAll() //sms api .requestMatchers("/sms/prove/*","/sms/send").permitAll() //ALB diff --git a/src/main/java/com/example/fiurinee/global/security/filter/JwtVerifyFilter.java b/src/main/java/com/example/fiurinee/global/security/filter/JwtVerifyFilter.java index 383ac20..7d07c71 100644 --- a/src/main/java/com/example/fiurinee/global/security/filter/JwtVerifyFilter.java +++ b/src/main/java/com/example/fiurinee/global/security/filter/JwtVerifyFilter.java @@ -29,7 +29,7 @@ public class JwtVerifyFilter extends OncePerRequestFilter { //Swagger "/swagger-ui/index.html", "/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**", "/v3/api-docs", //비회원 전용 api - "/main/today","/main/season","/model/ment","/model/*/non", + "/main/today","/main/season","/model/ment","/model/*/non", "/dictionary/**", "dictionary/search/**", "/dictionary", "/dictionary/search", "/dictionary/total-pages", "/dictionary/total-pages/**", //sms api "/sms/prove/*","/sms/send", //ALB