- 最近查看spring-data-jpa官方文档,发现pageable分页对象可以直接作为controller方法的参数。测试后发现在springfox swagger上展示太好,暴露接口的所有get方法作为了参数。
- 尝试通过springfox swagger的扩展进行定制化,搜索后在stackoverflow发现一篇帖子有解决这个问题。最终修改后满足自己的需求。代码如下:
@Configuration
@SuppressWarnings("SpringJavaAutowiringInspection")
public class SpringDataPageConfiguration {
@Bean
public AlternateTypeRuleConvention pageableConvention(final SpringDataWebProperties webProperties) {
return new AlternateTypeRuleConvention() {
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override
public List<AlternateTypeRule> rules() {
return singletonList(
newRule(Pageable.class, pageableDocumentedType(webProperties.getPageable(), webProperties.getSort()))
);
}
};
}
private Type pageableDocumentedType(SpringDataWebProperties.Pageable pageable, SpringDataWebProperties.Sort sort) {
final String firstPage = pageable.isOneIndexedParameters() ? "1" : "0";
return new AlternateTypeBuilder()
.fullyQualifiedClassName(fullyQualifiedName(Pageable.class))
.property(property(pageable.getPageParameter(), Integer.class, ImmutableMap.of(
"value", "页码," + String.format("允许范围[%s, %s]", firstPage, Integer.MAX_VALUE),
"defaultValue", firstPage,
"allowableValues", String.format("range[%s, %s]", firstPage, Integer.MAX_VALUE),
"example", firstPage,
"required", true
)))
.property(property(pageable.getSizeParameter(), Integer.class, ImmutableMap.of(
"value", "每页大小," + String.format("允许范围[1, %s]", pageable.getMaxPageSize()),
"defaultValue", String.valueOf(pageable.getDefaultPageSize()),
"allowableValues", String.format("range[1, %s]", pageable.getMaxPageSize()),
"example", "10",
"required", true
)))
.property(property(sort.getSortParameter(), String[].class, ImmutableMap.of(
"value", "页面排序,格式为: 字段名,(asc|desc),asc表升序,desc表降序"
)))
.build();
}
private String fullyQualifiedName(Class<?> convertedClass) {
return String.format("%s.generated.%s", convertedClass.getPackage().getName(), convertedClass.getSimpleName());
}
private AlternateTypePropertyBuilder property(String name, Class<?> type, Map<String, Object> parameters) {
return new AlternateTypePropertyBuilder()
.withName(name)
.withType(type)
.withCanRead(true)
.withCanWrite(true)
.withAnnotations(singletonList(AnnotationProxy.of(ApiParam.class, parameters)));
}
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Accessors(fluent = true)
public class AnnotationProxy implements Annotation, InvocationHandler {
@Getter
private final Class<? extends Annotation> annotationType;
private final Map<String, Object> values;
public static <A extends Annotation> A of(Class<A> annotation, Map<String, Object> values) {
return (A) Proxy.newProxyInstance(annotation.getClassLoader(),
new Class[]{annotation},
new AnnotationProxy(annotation, new HashMap<>(values) {{
put("annotationType", annotation); // Required because getDefaultValue() returns null for this call
}}));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
return values.getOrDefault(method.getName(), method.getDefaultValue());
}
}
- 页面展示效果如下: