본문 바로가기

Spring/기타

springboot custom Pageable default annotation

반응형

springboot controller parameter로 아래 샘플 코드와 같이 Pageable parameter를 받을수 있는데, 

이때 Pageable 값이 안넘어 올때 기본값을 설정 할 수 있는 @PageableDefault 라는 annotation이 있다.

 

간단하게 해당 annotation에서 설정가능한게 무었인지 확인해 보았다.

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

   /**
    * Alias for {@link #size()}. Prefer to use the {@link #size()} method as it makes the annotation declaration more
    * expressive and you'll probably want to configure the {@link #page()} anyway.
    *
    * @return
    */
   int value() default 10;

   /**
    * The default-size the injected {@link org.springframework.data.domain.Pageable} should get if no corresponding
    * parameter defined in request (default is 10).
    */
   int size() default 10;

   /**
    * The default-pagenumber the injected {@link org.springframework.data.domain.Pageable} should get if no corresponding
    * parameter defined in request (default is 0).
    */
   int page() default 0;

   /**
    * The properties to sort by by default. If unset, no sorting will be applied at all.
    *
    * @return
    */
   String[] sort() default {};

   /**
    * The direction to sort by. Defaults to {@link Direction#ASC}.
    *
    * @return
    */
   Direction direction() default Direction.ASC;
}

위와 같이 size , page , sort 필드명 , 정렬 방법을 설정할수 있다. 

그런데 좀 이상한 부분은 필드명은 배열로 여러개 받을수 있는데  정렬 순서는 하나만 설정할수 있게 되어 있다.

 

확인해 본결과 @PageableDefault는 하나의 정렬 방법만 설정할수 있게 된다고 한다. 결국 우리가 원하는 

&sort=feildA,asc&sort=feildB,desc 라는 두개필드의 다른 정렬 방식을 적용이 할 수 없는 반쪽 짜리 설정이였다.

 

그래서 custom @PageableDefault annotation을 만들어서 적용해 보았다. 

아래와 같이 custom annotation을 만든다.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CustomPageableDefault {
    int fixPageSize() default 0;

    int page() default 0;

    /**
     * sort = {"startDisplayTime,desc","seq,asc"} 의 형태로 입력
     * @return
     */
    String[] sort() default {};
}
@Configuration
public class PageableConfiguration extends SpringDataWebConfiguration {

    public PageableConfiguration(ApplicationContext context, ObjectFactory<ConversionService> conversionService) {
        super(context, conversionService);
    }

    @Bean
    @Override
    public PageableHandlerMethodArgumentResolver pageableResolver() {
        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver() {
            @Override
            public Pageable resolveArgument(MethodParameter methodParameter, @Nullable ModelAndViewContainer mavContainer,
                                            NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) {
                Pageable p = super.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);
                return getLimitsFromAnnotation(p, methodParameter);
            }

            private Pageable getLimitsFromAnnotation(Pageable p, MethodParameter methodParameter) {
                CustomPageableDefault customPageable = methodParameter.getParameterAnnotation(CustomPageableDefault.class);
                if (customPageable == null) return p;

                int pageSize = p.getPageSize();
                if (customPageable.fixPageSize() > 0) {
                    pageSize = customPageable.fixPageSize();
                }
                Sort sort = p.getSort();
                if (sort == null || sort.isUnsorted()) {
                    String[] sorts = customPageable.sort();
                    if (sorts != null) {
                        List<Sort.Order> orders = new ArrayList<>();
                        for (String sortStr : sorts) {
                            String[] st = sortStr.split(",");
                            if (st.length < 2) {
                                throw new RuntimeException(String.format("정렬 설정이 잘못 되었습니다. (%s) ", sortStr));
                            } else {
                                orders.add(new Sort.Order(Sort.Direction.fromString(st[1]), st[0]));
                            }
                        }
                        sort = Sort.by(orders);
                    }
                }
                return PageRequest.of(p.getPageNumber(), pageSize, sort);
            }
        };
        resolver.setOneIndexedParameters(false);
        //pagebale max 조회 건수 조정 - default : 2,000 -> 5,000
        resolver.setMaxPageSize(5000);
        return resolver;
    }

}

위와 같이 설정하게 되면 정렬 값을 우리가 원하는데로 2개이상 설정이 가능하고 , pageable parameter에 여러가지를 

원하는데로 설정이 가능하게 된다. 

 

아래는 springboot data의 page 관련 기본 설정 옵션값이다. 

# DATA WEB (SpringDataWebProperties)
spring.data.web.pageable.default-page-size=20         # Default page size.
spring.data.web.pageable.max-page-size=2000           # Maximum page size to be accepted.
spring.data.web.pageable.one-indexed-parameters=false # Whether to expose and assume 1-based page number indexes.
spring.data.web.pageable.page-parameter=page          # Page index parameter name.
spring.data.web.pageable.prefix=                      # General prefix to be prepended to the page number and page size parameters.
spring.data.web.pageable.qualifier-delimiter=_        # Delimiter to be used between the qualifier and the actual page number and size properties.
spring.data.web.pageable.size-parameter=size          # Page size parameter name.
spring.data.web.sort.sort-parameter=sort              # Sort parameter name.

위와 같은 기본옵션이 설정 되어 있다. (참고)

'Spring > 기타' 카테고리의 다른 글

undertow upload max-file-size exception handler  (0) 2022.12.05