Skip to content

Commit

Permalink
MATE-112 : [FEAT] Pageable 객체 유효성 검증 커스텀 어노테이션 구현 (#102)
Browse files Browse the repository at this point in the history
* MATE-112 : [CHORE] 패키지 구조 수정

- utils 패키지 삭제, validator 패키지 위치 변경
- test 패키지 FileValidatorTest 클래스 위치 변경

* MATE-112 : [FEAT] Pageable 객체 유효성 검증 커스텀 어노테이션 구현

* MATE-112 : [REFACTOR] @PageableDefault 어노테이션을 @ValidPageable 어노테이션으로 변경

* MATE-112 : [REFACTOR] 기존 Pageable 유효성 검증 로직 삭제

* MATE-112 : [FEAT] PageResponse 생성 메서드 구현

* MATE-112 : [REFACTOR] 중복 코드 제거
  • Loading branch information
hongjeZZ authored Dec 7, 2024
1 parent 5fc3e2d commit bdd7529
Show file tree
Hide file tree
Showing 23 changed files with 176 additions and 163 deletions.
23 changes: 23 additions & 0 deletions src/main/java/com/example/mate/common/config/WebMvcConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.example.mate.common.config;

import com.example.mate.common.validator.ValidPageableArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

private final ValidPageableArgumentResolver validPageableArgumentResolver;

public WebMvcConfig(ValidPageableArgumentResolver validPageableArgumentResolver) {
this.validPageableArgumentResolver = validPageableArgumentResolver;
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(validPageableArgumentResolver);
}
}
26 changes: 16 additions & 10 deletions src/main/java/com/example/mate/common/response/PageResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

@Getter
@Builder
Expand Down Expand Up @@ -41,13 +39,21 @@ public static <R, T> PageResponse<T> from(Page<R> page, List<T> content) {
.build();
}

// Pageable 검증 메서드
public static Pageable validatePageable(Pageable pageable) {
// pageNumber 검증: 0보다 작은 값은 0으로 처리
int pageNumber = Math.max(pageable.getPageNumber(), 0);

// pageSize 검증: 0 이하이면 기본값 10으로 설정
int pageSize = pageable.getPageSize() <= 0 ? 10 : pageable.getPageSize();
return PageRequest.of(pageNumber, pageSize, pageable.getSort());
/**
* Page 객체를 기반으로 PageResponse 를 생성하는 팩토리 메서드
*
* @param page Spring Data JPA 의 Page 객체
* @param <T> 변환된 데이터 타입
* @return PageResponse
*/
public static <T> PageResponse<T> from(Page<T> page) {
return PageResponse.<T>builder()
.content(page.getContent())
.totalPages(page.getTotalPages())
.totalElements(page.getTotalElements())
.hasNext(page.hasNext())
.pageNumber(page.getNumber())
.pageSize(page.getSize())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.mate.common.utils.validator;
package com.example.mate.common.validator;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.mate.common.utils.validator;
package com.example.mate.common.validator;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/example/mate/common/validator/ValidPageable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.example.mate.common.validator;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.domain.Sort.Direction;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface ValidPageable {

@AliasFor("size")
int value() default 10;

@AliasFor("value")
int size() default 10;

int page() default 0;

String[] sort() default {};

Direction direction() default Direction.ASC;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.example.mate.common.validator;

import org.springframework.core.MethodParameter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
* 커스텀 Pageable 리졸버로, {@code @ValidPageable} 어노테이션이 붙은 Pageable 매개변수의 유효성 검사를 수행합니다.
*/
@Component
public class ValidPageableArgumentResolver extends PageableHandlerMethodArgumentResolver {

@Override
public Pageable resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {

// 기본 Pageable 생성
Pageable pageable = super.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);

// @ValidPageable 어노테이션 확인
ValidPageable validPageable = methodParameter.getParameterAnnotation(ValidPageable.class);

int pageNumber = Math.max(pageable.getPageNumber(), validPageable != null ? validPageable.page() : 0);
int pageSize = pageable.getPageSize() > 0
? pageable.getPageSize()
: validPageable != null ? validPageable.size() : 10;

return PageRequest.of(pageNumber, pageSize, pageable.getSort());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.mate.common.response.ApiResponse;
import com.example.mate.common.response.PageResponse;
import com.example.mate.common.security.auth.AuthMember;
import com.example.mate.common.validator.ValidPageable;
import com.example.mate.domain.goods.dto.request.GoodsPostRequest;
import com.example.mate.domain.goods.dto.request.GoodsReviewRequest;
import com.example.mate.domain.goods.dto.response.GoodsPostResponse;
Expand All @@ -14,7 +15,6 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
Expand Down Expand Up @@ -84,7 +84,7 @@ public ResponseEntity<ApiResponse<List<GoodsPostSummaryResponse>>> getGoodsPosts
public ResponseEntity<ApiResponse<PageResponse<GoodsPostSummaryResponse>>> getGoodsPosts(
@Parameter(description = "팀 ID") @RequestParam(required = false) Long teamId,
@Parameter(description = "카테고리") @RequestParam(required = false) String category,
@Parameter(description = "페이징 정보", required = true) @PageableDefault Pageable pageable
@Parameter(description = "페이징 정보", required = true) @ValidPageable Pageable pageable
) {
PageResponse<GoodsPostSummaryResponse> pageGoodsPosts = goodsService.getPageGoodsPosts(teamId, category, pageable);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.example.mate.domain.goods.dto.request;

import com.example.mate.common.utils.validator.ValidEnum;
import com.example.mate.common.validator.ValidEnum;
import com.example.mate.domain.goods.dto.LocationInfo;
import com.example.mate.domain.goods.entity.Category;
import com.example.mate.domain.goods.entity.GoodsPost;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.example.mate.domain.goods.dto.request;

import com.example.mate.common.utils.validator.ValidEnum;
import com.example.mate.common.validator.ValidEnum;
import com.example.mate.domain.constant.Rating;
import com.example.mate.domain.goods.entity.GoodsPost;
import com.example.mate.domain.goods.entity.GoodsReview;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.mate.common.response.ApiResponse;
import com.example.mate.common.response.PageResponse;
import com.example.mate.common.security.auth.AuthMember;
import com.example.mate.common.validator.ValidPageable;
import com.example.mate.domain.goodsChat.dto.response.GoodsChatMessageResponse;
import com.example.mate.domain.goodsChat.dto.response.GoodsChatRoomResponse;
import com.example.mate.domain.goodsChat.dto.response.GoodsChatRoomSummaryResponse;
Expand All @@ -11,7 +12,6 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand Down Expand Up @@ -40,15 +40,15 @@ public ResponseEntity<ApiResponse<GoodsChatRoomResponse>> createGoodsChatRoom(@A
public ResponseEntity<ApiResponse<PageResponse<GoodsChatMessageResponse>>> getGoodsChatRoomMessages(
@AuthenticationPrincipal AuthMember member,
@PathVariable Long chatRoomId,
@PageableDefault(page = 1, size = 20) Pageable pageable
@ValidPageable Pageable pageable
) {
PageResponse<GoodsChatMessageResponse> response = goodsChatService.getMessagesForChatRoom(chatRoomId, member.getMemberId(), pageable);
return ResponseEntity.ok(ApiResponse.success(response));
}

@GetMapping
public ResponseEntity<ApiResponse<PageResponse<GoodsChatRoomSummaryResponse>>> getGoodsChatRooms(@AuthenticationPrincipal AuthMember member,
@PageableDefault Pageable pageable) {
@ValidPageable Pageable pageable) {
PageResponse<GoodsChatRoomSummaryResponse> response = goodsChatService.getGoodsChatRooms(member.getMemberId(), pageable);
return ResponseEntity.ok(ApiResponse.success(response));
}
Expand Down
Loading

0 comments on commit bdd7529

Please sign in to comment.