一、背景
- 接口定义:
@ApiOperation(value = "分页查询会话")
@PostMapping(Routes.SESSIONS_QUERY)
JsonResult<Pagination<SessionInfo>> querySessions(@RequestBody @Valid SessionsQo qo,
@PageableDefault(size = 20, sort = "id", direction = Sort.Direction.DESC) Pageable pageable);
- 服务消费方调用报错:
Method has too many Body parameters: public abstract com.xingren.common.data.JsonResult com.xingren.xxx.yyy.contract.api.controller.ISessionController.querySessions(com.xingren.xxx.yyy.contract.qo.SessionsQo,org.springframework.data.domain.Pageable)
二、解决
通过搜索、调研,目前有三种解决方法:
1、将分页属性直接通过入参传递,接口定义如下:言七墨
@ApiOperation(value = "分页查询会话")
@PostMapping(Routes.SESSIONS_QUERY)
JsonResult<Pagination<SessionInfo>> querySessions(@RequestBody @Valid SessionsQo qo,
@RequestParam("page") Integer page, @RequestParam("size") Integer size, @RequestParam("sort") Sort sort);
2、将分页对象冗余在Qo
中(通过继承
实现):
@Data
@NoArgsConstructor
@ApiModel(value = "查询会话")
public class SessionsQo extends PageableParam {
@ApiParam(value = "会话id列表")
private List<Long> sessionIdIn = Lists.newArrayList();
...
}
3、通过注解传递(参考:Issue):
- 服务提供方定义注解
言七墨 :
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface PageableParam {
}
- 服务提供方定义接口:
@ApiOperation(value = "分页查询会话")
@PostMapping(Routes.SESSIONS_QUERY)
JsonResult<Pagination<SessionInfo>> querySessions(@RequestBody @Valid SessionsQo qo,
@PageableParam @SpringQueryMap Pageable pageable);
- 服务消费方定义
processor
:
@Bean
public PageableParamProcessor pageableParamProcessor() {
return new PageableParamProcessor();
}
public static class PageableParamProcessor implements AnnotatedParameterProcessor {
private static final Class<PageableParam> ANNOTATION = PageableParam.class;
@Override
public Class<? extends Annotation> getAnnotationType() {
return ANNOTATION;
}
@Override
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
int parameterIndex = context.getParameterIndex();
MethodMetadata data = context.getMethodMetadata();
data.queryMapIndex(parameterIndex);
return true;
}
}
- 服务消费方自定义
PageableUtil
:
public class PageableUtil extends PageRequest implements Map<String, Object> {
public static final String PAGE = "page";
public static final String SIZE = "size";
public static final String SORT = "sort";
@Delegate
protected Map<String, Object> delegate = Maps.newHashMap();
public PageableUtil(int page, int size, Sort sort) {
super(page, size, sort);
delegate.put(PAGE, page);
delegate.put(SIZE, size);
if (Objects.nonNull(sort)) {
delegate.put(SORT, sort.toString().replace(": ", ","));
}
}
public PageableUtil(int page, int size) {
super(page, size);
delegate.put(PAGE, page);
delegate.put(SIZE, size);
}
}
- 定义
PageableUtil
原因:主要是因为Feign
对QueryMap
类型参数的序列化和反序列化的方式与Sort.Order
的不兼容,导致排序失效。
- 服务消费方调用方式:
SessionsQo qo = SessionsQo.builder().sessionIdIn(Collections.singletonList(20L)).build();
JsonResult<Pagination<SessionInfo>> pageInfo = sessionContract.querySessions(qo, new PageableUtil(0, 5, new Sort(Sort.Direction.DESC, "session_id")));
可以仿你的模板吗
bx