一、遇到问题

目前使用Swagger2形成接口文档时,当系统设计的接口返回的类型不是实体对象时,Swagger2无法在接口文档页面中显示返回结果字段说明,比如返回json、map等可以存储key-val形式的类型;均无法在接口文档页面上显示返回的字段备注说明,所以怎么才能像实体对象一样显示正常的model字段说明是我们这次需要解决的问题;

二、实现思路

1、首先告诉Swagger2该接口需要返回的字段具体有哪些

定义两个注解,方便来定义返回json或者map的固定参数;如:

/** 
* @ClassName: ApiReturnJson 
* @Description: 返回对象的定义 (描述这个类的作用) 
* @author TangCai
* @date 2019年2月22日 下午4:56:33  
*/
  	
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiReturnJson {
	String key();  //对象名称
    ApiReturnJsonPro[] value(); //对象属性值
}
/** 
* @ClassName: ApiReturnJsonPro 
* @Description: 每一个字段的定义备注说明 (描述这个类的作用) 
* @author TangCai
* @date 2019年2月22日 下午4:57:09  
*/
  	
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiReturnJsonPro {
 
    String key();  //key
 
    String example() default "";
 
    Class<?> dataType() default String.class;
 
    String description() default "";
}

 

2、在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();
		}
	}

 

3、然后在每一个生成的接口在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();
			}
		}
	}

 

三、运行结果

注解样式:

@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;
	}

接口页面结果:

GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 4 个月前
8c391e04 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐