描述
目前使用Swagger2形成接口文檔時,當系統設計的接口返回的類型不是實體對象時,Swagger2無法在接口文檔頁面中顯示返回結果字段說明,比如返回json、map等可以存儲key-val形式的類型;均無法在接口文檔頁面上顯示返回的字段備註說明,所以怎麼才能像實體對象一樣顯示正常的model字段說明是我們這次需要解決的問題;
- 首先告訴Swagger2該接口需要返回的字段具體有哪些
定義兩個註解,方便來定義返回json或者map的固定參數;如
/**
* @ClassName: ApiReturnJson
* @Description: 返回對象的定義 (描述這個類的作用)
* @author willem
* @date 2020年3月5日 15:25:01
*/
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiReturnJson {
String key(); //對象名稱
ApiReturnJsonPro[] value(); //對象屬性值
}
/**
* @ClassName: ApiReturnJsonPro
* @Description: 每一個字段的定義備註說明 (描述這個類的作用)
* @author willem
* @date 2020年3月5日 15:30:25
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiReturnJsonPro {
String key(); //key
String example() default "";
Class<?> dataType() default String.class;
String description() default "";
}
- 在Swagger2中將該字段封裝成一個model存進Swagger2容器中,繼承OperationModelsProviderPlugin類,實現如下方法:
public void apply(RequestMappingContext context) {
// TODO Auto-generated method stub
if (context.getReturnType().isInstanceOf(Map.class)) {
// 根據參數上的ApiJsonObject註解中的參數動態生成Class
Optional<ApiReturnJson> optional = context.findAnnotation(ApiReturnJson.class);
ApiReturnJsonPro[] properties = null;
String name = null;
try {
Method method = Swagger2.class.getMethod("restApi");//系統默認取該處的全局變量
ApiReturnJson apiReturnJson = method.getAnnotation(ApiReturnJson.class);
name = apiReturnJson.key()+"_"+context.getName();
ApiReturnJsonPro[] properties0 = apiReturnJson.value();
if (optional.isPresent()) {
name = optional.get().key(); // model名稱
ApiReturnJsonPro[] properties1 = optional.get().value();
properties = new ApiReturnJsonPro[properties1.length+properties0.length];
int k=0;
for(;k<properties0.length;k++) properties[k] = properties0[k];
for(int p=0;p<properties1.length;p++) properties[k+p] = properties1[p];
}
else properties = properties0;
} catch (Exception e) {
e.printStackTrace();
}
ResolvedType rt = typeResolver.resolve(createRefModel(properties, name));
// 像documentContext的Models中添加我們新生成的Class
context.getDocumentationContext().getAdditionalModels().add(rt);
context.operationModelsBuilder().addReturn(rt).build();
}
}
- 然後在每一個生成的接口在BuilderPlugin進行解析,並將訪問正常的model更新,將json、map等替換,繼承OperationBuilderPlugin類,實現如下方法:
public void apply(OperationContext operationContext) {
// TODO Auto-generated method stub
if(operationContext.getReturnType().isInstanceOf(Map.class)) {
//根據參數上的ApiJsonObject註解中的參數動態生成Class
Optional<ApiReturnJson> optional = operationContext.findAnnotation(ApiReturnJson.class);
try {
Method method = Swagger2.class.getMethod("restApi");//系統默認取該處的全局變量
ApiReturnJson apiReturnJson = method.getAnnotation(ApiReturnJson.class);
String name = apiReturnJson.key()+"_"+operationContext.getName();
if (optional.isPresent())
name = optional.get().key(); //model 名稱
Set<ResponseMessage> set = new HashSet<ResponseMessage>();
ModelRef mr = new ModelRef(name);
set.add(new ResponseMessage(200,"返回json用例說明",mr,null,null));
operationContext.operationBuilder().responseMessages(set);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- Controller接口註解
@ApiOperation(value = "獲取上傳文件表單name值")
@ApiImplicitParams({
@ApiImplicitParam(paramType="query", name = "uploadFileType", value = "上傳文件類型:saveHeadImg", required = true, dataType = "string",defaultValue="")
})
@ApiReturnJson(key = "getUploadFileUrl_api", value = {
@ApiReturnJsonPro(key = "uploadFileNamesVal", description = "上傳文件表單name值")
})
@GetMapping("/getUploadFileUrl")
@ResponseBody
public Result getUploadFileUrl(@RequestParam(required=true)String uploadFileType) {
AssertUtil.assertNotFalse(MyConstants.CONFIG.UPLOAD_FILE_TYPES.containsKey(uploadFileType), MyConstants.RESULT.FI1000, "uploadFileType非法");
String res = HttpUtil.httpGet(MyConstants.CONFIG.GET(SysParamKey.FILE_SYSTEM_AUTH_CODE_URL).toString());
Result result = (Result) JSONObject.toBean(JSONObject.fromObject(res), Result.class);
result.put("uploadFileNamesVal", MyConstants.CONFIG.UPLOAD_FILE_TYPES.get(uploadFileType));
return result;
}