1. @ApiParam
的hidden屬性不生效
項(xiàng)目采用Swagger生成在線文檔,由于SpringMVC有一些內(nèi)置對(duì)象可以直接注入到處理器方法參數(shù)上袁铐,所以為了方便,在處理器方法上注入了Principal參數(shù)伺帘,獲取當(dāng)前登錄對(duì)象昭躺,相關(guān)的代碼如下。
@PostMapping("/setProjectManager")
@ApiOperation(value = "設(shè)置項(xiàng)目經(jīng)理", notes = "設(shè)置項(xiàng)目經(jīng)理 0-否 1-是")
public ControllerResult<String> setProjectManager(@Valid @RequestBody SetProjectManagerReq req, BindingResult bindingResult,
@ApiParam(name = "principal",value = "登錄用戶",hidden = true) Principal principal) {
// 省略...
}
由于Principal是SpringMVC自動(dòng)注入的參數(shù)伪嫁,不需要前端傳遞领炫,但實(shí)際上打開該接口的在線文檔,發(fā)現(xiàn)Principal參數(shù)雖然通過@ApiParam
的hidden屬性张咳,設(shè)置了隱藏帝洪,仍然體現(xiàn)在接口參數(shù)中。
為了不誤導(dǎo)前端傳參脚猾,想要將多出來的參數(shù)name隱藏起來葱峡,通過追蹤Swagger源碼,在OperationParameterReader
類中發(fā)現(xiàn)如下邏輯龙助。
private List<Compatibility<springfox.documentation.service.Parameter, RequestParameter>> readParameters(OperationContext context) {
// 解析處理器上的所有參數(shù)
List<ResolvedMethodParameter> methodParameters = context.getParameters();
List<Compatibility<springfox.documentation.service.Parameter, RequestParameter>> parameters = new ArrayList<>();
LOGGER.debug("Reading parameters for method {} at path {}", context.getName(), context.requestMappingPattern());
int index = 0;
for (ResolvedMethodParameter methodParameter : methodParameters) {
LOGGER.debug("Processing parameter {}", methodParameter.defaultName().orElse("<unknown>"));
ResolvedType alternate = context.alternateFor(methodParameter.getParameterType());
// 是否跳過當(dāng)前參數(shù)的顯示
if (!shouldIgnore(methodParameter, alternate, context.getIgnorableParameterTypes())) {
ParameterContext parameterContext = new ParameterContext(methodParameter,
context.getDocumentationContext(),
context.getGenericsNamingStrategy(),
context,
index++);
// 是否應(yīng)該將該參數(shù)展開展示
if (shouldExpand(methodParameter, alternate)) {
parameters.addAll(
expander.expand(
new ExpansionContext("", alternate, context)));
} else {
parameters.add(pluginsManager.parameter(parameterContext));
}
}
}
return parameters.stream()
.filter(hiddenParameter().negate()) // 根據(jù)注解的hidden屬性過濾改參數(shù)是否顯示
.collect(toList());
}
在上述源碼中砰奕,可以看到關(guān)鍵的兩個(gè)方法shouldIgnore
,shouldExpand
,這兩個(gè)方法源碼如下。
private boolean shouldIgnore(final ResolvedMethodParameter parameter, ResolvedType resolvedParameterType, final Set<Class> ignorableParamTypes) {
if (ignorableParamTypes.contains(resolvedParameterType.getErasedType())) {
return true;
}
return ignorableParamTypes.stream()
.filter(Annotation.class::isAssignableFrom)
.anyMatch(parameter::hasParameterAnnotation);
}
private boolean shouldExpand(final ResolvedMethodParameter parameter, ResolvedType resolvedParamType) {
return !parameter.hasParameterAnnotation(RequestBody.class)
&& !parameter.hasParameterAnnotation(RequestPart.class)
&& !parameter.hasParameterAnnotation(RequestParam.class)
&& !parameter.hasParameterAnnotation(PathVariable.class)
&& !builtInScalarType(resolvedParamType.getErasedType()).isPresent()
&& !enumTypeDeterminer.isEnum(resolvedParamType.getErasedType())
&& !isContainerType(resolvedParamType)
&& !isMapType(resolvedParamType);
}
通過上述源碼军援,可以了解到Swagger在解析方法參數(shù)時(shí)仅淑,會(huì)在shouldIgnore
根據(jù)一定規(guī)則過濾參數(shù),通過過濾之后的參數(shù)胸哥,Swagger又會(huì)通過shouldExpand
判斷當(dāng)前參數(shù)是否需要展開涯竟,再進(jìn)一步追溯Swagger對(duì)參數(shù)的過濾條件,可以在Defaults
類中看到注冊的過濾條件空厌。
private void initIgnorableTypes() {
ignored = new HashSet<>();
ignored.add(Class.class);
ignored.add(Void.class);
ignored.add(Void.TYPE);
ignored.add(HttpHeaders.class);
ignored.add(BindingResult.class);
ignored.add(UriComponentsBuilder.class);
ignored.add(ApiIgnore.class); //用于忽略參數(shù)
classFor("javax.servlet.ServletRequest").ifPresent(it -> ignored.add(it));
classFor("javax.servlet.ServletResponse").ifPresent(it -> ignored.add(it));
classFor("javax.servlet.http.HttpServletRequest").ifPresent(it -> ignored.add(it));
classFor("javax.servlet.http.HttpServletResponse").ifPresent(it -> ignored.add(it));
classFor("javax.servlet.ServletContext").ifPresent(it -> ignored.add(it));
}
綜合上述源碼邏輯,由于Principal
參數(shù)不符合過濾條件筐钟,同時(shí)滿足展開條件哮内,那么Swagger就會(huì)解析接口中的getXXX函數(shù),從而作為方法的參數(shù)進(jìn)行展示纹因,而被展開的類屬性考慮應(yīng)該是使用@ApiModelProperty
注解的hidden屬性隱藏(未驗(yàn)證)琳拨。
因此回到本坑最初的問題,@ApiParam
注解的hidden屬性并非沒有用狱庇,而是他只能作用于非復(fù)合類的處理器參數(shù)上,如果要讓一個(gè)處理器的復(fù)合參數(shù)不顯示颜启,應(yīng)該為其添加@ApiIgnore
注解缰盏。