Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@
import com.example.solidconnection.admin.service.AdminGpaScoreService;
import com.example.solidconnection.admin.service.AdminLanguageTestScoreService;
import com.example.solidconnection.custom.response.PageResponse;
import com.example.solidconnection.util.PagingUtils;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -35,15 +31,15 @@ public class AdminScoreController {
private final AdminGpaScoreService adminGpaScoreService;
private final AdminLanguageTestScoreService adminLanguageTestScoreService;

// todo: 추후 커스텀 페이지 객체 & argumentResolver를 적용 필요
@GetMapping("/gpas")
public ResponseEntity<PageResponse<GpaScoreSearchResponse>> searchGpaScores(
@Valid @ModelAttribute ScoreSearchCondition scoreSearchCondition,
@PageableDefault(page = 1) Pageable pageable
Pageable pageable
) {
PagingUtils.validatePage(pageable.getPageNumber(), pageable.getPageSize());
Pageable internalPageable = PageRequest.of(pageable.getPageNumber() - 1, pageable.getPageSize());
Page<GpaScoreSearchResponse> page = adminGpaScoreService.searchGpaScores(scoreSearchCondition, internalPageable);
Page<GpaScoreSearchResponse> page = adminGpaScoreService.searchGpaScores(
scoreSearchCondition,
pageable
);
return ResponseEntity.ok(PageResponse.of(page));
}

Expand All @@ -56,15 +52,15 @@ public ResponseEntity<GpaScoreResponse> updateGpaScore(
return ResponseEntity.ok(response);
}

// todo: 추후 커스텀 페이지 객체 & argumentResolver를 적용 필요
@GetMapping("/language-tests")
public ResponseEntity<PageResponse<LanguageTestScoreSearchResponse>> searchLanguageTestScores(
@Valid @ModelAttribute ScoreSearchCondition scoreSearchCondition,
@PageableDefault(page = 1) Pageable pageable
Pageable pageable
) {
PagingUtils.validatePage(pageable.getPageNumber(), pageable.getPageSize());
Pageable internalPageable = PageRequest.of(pageable.getPageNumber() - 1, pageable.getPageSize());
Page<LanguageTestScoreSearchResponse> page = adminLanguageTestScoreService.searchLanguageTestScores(scoreSearchCondition, internalPageable);
Page<LanguageTestScoreSearchResponse> page = adminLanguageTestScoreService.searchLanguageTestScores(
scoreSearchCondition,
pageable
);
return ResponseEntity.ok(PageResponse.of(page));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.example.solidconnection.config.web;


import com.example.solidconnection.custom.resolver.AuthorizedUserResolver;
import com.example.solidconnection.custom.resolver.CustomPageableHandlerMethodArgumentResolver;
import com.example.solidconnection.custom.resolver.ExpiredTokenResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
Expand All @@ -16,12 +16,14 @@ public class WebMvcConfig implements WebMvcConfigurer {

private final AuthorizedUserResolver authorizedUserResolver;
private final ExpiredTokenResolver expiredTokenResolver;
private final CustomPageableHandlerMethodArgumentResolver customPageableHandlerMethodArgumentResolver;

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.addAll(List.of(
authorizedUserResolver,
expiredTokenResolver
expiredTokenResolver,
customPageableHandlerMethodArgumentResolver
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,6 @@ public enum ErrorCode {
USER_DO_NOT_HAVE_GPA(HttpStatus.BAD_REQUEST.value(), "해당 유저의 학점을 찾을 수 없음"),
REJECTED_REASON_REQUIRED(HttpStatus.BAD_REQUEST.value(), "거절 사유가 필요합니다."),

// page
INVALID_PAGE(HttpStatus.BAD_REQUEST.value(), "페이지 번호는 1 이상 50 이하만 가능합니다."),
INVALID_SIZE(HttpStatus.BAD_REQUEST.value(), "페이지 크기는 1 이상 50 이하만 가능합니다."),

// general
JSON_PARSING_FAILED(HttpStatus.BAD_REQUEST.value(), "JSON 파싱을 할 수 없습니다."),
JWT_EXCEPTION(HttpStatus.BAD_REQUEST.value(), "JWT 토큰을 처리할 수 없습니다."),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.solidconnection.custom.resolver;

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;

@Component
public class CustomPageableHandlerMethodArgumentResolver extends PageableHandlerMethodArgumentResolver {

public static final int MAX_SIZE = 50;
private static final int DEFAULT_SIZE = 10;

public CustomPageableHandlerMethodArgumentResolver() {
setOneIndexedParameters(true);
setFallbackPageable(PageRequest.of(0, 10));
}

@Override
public Pageable resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
Pageable pageable = super.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);
if (pageable.getPageSize() > MAX_SIZE) {
return PageRequest.of(pageable.getPageNumber(), DEFAULT_SIZE, pageable.getSort());
}
return pageable;
}
}
26 changes: 0 additions & 26 deletions src/main/java/com/example/solidconnection/util/PagingUtils.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package com.example.solidconnection.custom.resolver;

import com.example.solidconnection.support.TestContainerSpringBootTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.Pageable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;

import java.lang.reflect.Method;

import static com.example.solidconnection.custom.resolver.CustomPageableHandlerMethodArgumentResolver.MAX_SIZE;
import static org.assertj.core.api.Assertions.assertThat;

@TestContainerSpringBootTest
@DisplayName("커스텀 페이지 요청 argument resolver 테스트")
class CustomPageableHandlerMethodArgumentResolverTest {

private static final String PAGE_PARAMETER = "page";
private static final String SIZE_PARAMETER = "size";
private static final int DEFAULT_PAGE = 1;
private static final int DEFAULT_SIZE = 10;

@Autowired
private CustomPageableHandlerMethodArgumentResolver customPageableHandlerMethodArgumentResolver;

private MockHttpServletRequest request;
private NativeWebRequest webRequest;
private MethodParameter parameter;

@BeforeEach
void setUp() throws NoSuchMethodException {
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request);
Method method = TestController.class.getMethod("pageableMethod", Pageable.class);
parameter = new MethodParameter(method, 0);
}

@Test
void 파라미터가_없으면_기본값을_사용한다() {
// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

@Test
void 유효한_파라미터가_있으면_해당_값을_사용한다() {
// given
int expectedPage = 2;
int expectedSize = 20;
request.setParameter(PAGE_PARAMETER, String.valueOf(expectedPage));
request.setParameter(SIZE_PARAMETER, String.valueOf(expectedSize));

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(expectedPage - 1);
assertThat(pageable.getPageSize()).isEqualTo(expectedSize);
}

@Test
void 파라미터가_숫자가_아니면_기본값을_사용한다() {
// given
request.setParameter(PAGE_PARAMETER, "invalid");
request.setParameter(SIZE_PARAMETER, "invalid");

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

@Test
void 페이지_파라미터가_최소값보다_작으면_기본값을_사용한다() {
// given
request.setParameter(PAGE_PARAMETER, "0");

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

@Test
void 페이지_파라미터가_음수이면_기본값을_사용한다() {
// given
request.setParameter(PAGE_PARAMETER, "-1");

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

@Test
void 사이즈_파라미터가_최소값보다_작으면_기본값을_사용한다() {
// given
request.setParameter(SIZE_PARAMETER, "0");

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

@Test
void 사이즈_파라미터가_최대값보다_크면_기본값을_사용한다() {
// given
request.setParameter(SIZE_PARAMETER, String.valueOf(MAX_SIZE + 1));

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

@Test
void 사이즈_파라미터가_음수이면_기본값을_사용한다() {
// given
request.setParameter(SIZE_PARAMETER, "-1");

// when
Pageable pageable = customPageableHandlerMethodArgumentResolver
.resolveArgument(parameter, null, webRequest, null);

// then
assertThat(pageable.getPageNumber()).isEqualTo(DEFAULT_PAGE - 1);
assertThat(pageable.getPageSize()).isEqualTo(DEFAULT_SIZE);
}

private static class TestController {

public void pageableMethod(Pageable pageable) {
}
}
}

This file was deleted.