背景
我们有一个接口要支持后端排序,所以需要在请求对象里面增加两个参数:排序字段名、排序方式(asc、desc)。
正好基础jar包中有一个类可以直接拿来用。
@Data
public class OrderByItem {private String column;private String direction;
}
但是考虑到前端使用的是element框架,默认使用prop
来定义排序字段,使用order
来定义排序方式。
因此,考虑使用这两个属性来接受排序字段。但是仍然用OrderByItem
这个类来接收参数。
为啥不重新定义一个类呢?
因为OrderByItem
这个类还有配套的工具类,用来进行相关的转换。所以为了复用这个工具类,就有了这个奇葩需求——我要用OrderByItem
这个类型来接受参数,但是这两个参数在Swagger中要展示成另外的名字,前端也需要用另外的名字来传参。
老实说,直接用column
和direction
没啥大问题。因此我们不去讨论这样做是否合理,姑且看如果我想实现类似的效果应该怎么处理。
JSON格式
如果OrderByItem
作为JSON格式使用,那么就很简单了:
@Data
public class OrderByItem {@JsonProperty("prop")private String column;@JsonProperty("order")private String direction;
}
这里直接使用JsonProperty
注解即可。
非JSON格式
如果不是JSON格式,事情会变得麻烦一点。
首先是要解决参数接收的问题,这里可以定义一个HandlerMethodArgumentResolver
。
public static class OrderItemHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {private static final String ORDER = "order";private static final String ORDER_DESC = "descending";private static final String ORDER_ASC = "ascending";private static final String PROP = "prop";@Overridepublic boolean supportsParameter(MethodParameter parameter) {return OrderByItem.class.isAssignableFrom(parameter.getParameterType());}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {String prop = webRequest.getParameter(PROP);if (StringUtils.isBlank(prop)) {return null;}String order = webRequest.getParameter(ORDER);// validate orderOrderByItem orderByItem = new OrderByItem();orderByItem.setColumn(prop);orderByItem.setDirection(order);return orderByItem;}}
注册OrderItemHandlerMethodArgumentResolver:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(new OrderItemHandlerMethodArgumentResolver());}
}
这里虽然解决了参数接收的问题,但是Swagger生成的文档参数名还是column
和direction
。我们需要改成prop
和order
。
由于OrderByItem
是jar包中的类,无法修改源码,所以不能直接使用ApiModelProperty
这个注解。
好在Swagger提供了一个“替身”功能,我们需要先定义一个替身类:
@Data
@ApiModel("排序")
public static class OrderRequest {@ApiModelProperty("字段名称")private String prop;@ApiModelProperty("排序方式:descending倒序,ascending:正序")private String order;
}
然后使用替身:
@Configuration
public class SwaggerConfig {private ApiInfo apiInfo() {return new ApiInfoBuilder().title("test").description("test").version("1.0").build();}@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build().directModelSubstitute(OrderByItem.class, OrderRequest.class);}
}
这样做,当Swagger显示OrderByItem
类时,就会用OrderByItem
代替。