原创

Swagger与SpringBoot整合

首先引入

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version> 2.7.0  </version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>

相关SpringBoot的就不在列举,后面有时间单独讲

一般配置为如下代码:

/**
* Swagger配置
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {

@Bean
public Docket createRestApi() {
//添加head参数start
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<Parameter>();
tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
//添加head参数end
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//加了ApiOperation注解的类,才生成接口文档
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
//head参数.securitySchemes(security())
.globalOperationParameters(pars)/*.securitySchemes(security())*/;
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("XX平台")
.description("test")
.termsOfServiceUrl("")//可以给网址地址,或者是测试环境地址等
.version("1.0.0")
.build();
}

// private List<ApiKey> security() {
// return newArrayList(
// new ApiKey("token", "token", "header")
// );
// }


接口传入单个参数实例:

@PostMapping(value = "/demo")
@ApiOperation(value = "获取资产", notes = "入参单个参数")
public R demo(
@ApiParam(value = "ID", name = "Id", required = false) @RequestParam(value = "Id", required = false) Long Id
) {

return R.ok();
}
传入对象时需要在对应对象中使用@ApiModel和@ApiModelProperty(value = "分类id"),例如:
@ApiModel
public class TClassifyTecEntity implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 主键id
*/
@TableId
@ApiModelProperty(value = "主键id")
private Long ctId;
/**
* 分类id
*/
@ApiModelProperty(value = "分类id")
private Long classifyId;

/**
* 设置:主键id
*/
public void setCtId(Long ctId) {
this.ctId = ctId;
}
/**
* 获取:主键id
*/
public Long getCtId() {
return ctId;
}
/**
* 设置:分类id
*/
public void setClassifyId(Long classifyId) {
this.classifyId = classifyId;
}
/**
* 获取:分类id
*/
public Long getClassifyId() {
return classifyId;
}


接口写法如下:
    @RequestMapping("/getTest")
@ApiOperation(value = "测试对象参数",notes = "测试对象参数TClassifyTecEntity" ,httpMethod = "POST", produces = MediaType. APPLICATION_JSON_VALUE)
public R getTest(@RequestBody TClassifyTecEntity tclassifyTec){



return R.ok();
}

API效果如下:


当参数使用对象不能满足,或者是过多时,使用map时则需要配置如下:
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonObject {
ApiJsonProperty[] value(); //对象属性值
String name(); //对象名称
}
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonProperty {

String key(); // key

String example() default "";// 示例

String type() default "string"; // 支持string、int、double

String description() default "";// 参数描述

boolean required() default true; // 是否必传
}
/**
*
* @Title: MapReaderForApi.java
* @Description: 将map入参匹配到swagger文档的工具类
* @version 1.0
*/
@Component
@Order // plugin加载顺序,默认是最后加载
public class MapReaderForApi implements ParameterBuilderPlugin{
@Autowired
private TypeResolver typeResolver;

private final static String basePackage = "com.*.*."; // 动态生成的虚拟DTO路径,需要使用代码时,改为自己的即可
@Override
public boolean supports(DocumentationType delimiter) {
// TODO Auto-generated method stub
return true;
}

@Override
public void apply(ParameterContext parameterContext) {
ResolvedMethodParameter methodParameter = parameterContext.resolvedMethodParameter();

if (methodParameter.getParameterType().canCreateSubtype(Map.class)
|| methodParameter.getParameterType().canCreateSubtype(String.class)) { // 判断是否需要修改对象ModelRef,这里我判断的是Map类型和String类型需要重新修改ModelRef对象
Optional<ApiJsonObject> optional = methodParameter.findAnnotation(ApiJsonObject.class); // 根据参数上的ApiJsonObject注解中的参数动态生成Class
if (optional.isPresent()) {
String name = optional.get().name(); // model 名称
ApiJsonProperty[] properties = optional.get().value();

parameterContext.getDocumentationContext().getAdditionalModels()
.add(typeResolver.resolve(createRefModel(properties, name))); // 向documentContext的Models中添加我们新生成的Class

parameterContext.parameterBuilder() // 修改Map参数的ModelRef为我们动态生成的class
.parameterType("body").modelRef(new ModelRef(name)).name(name);
}
}
}
/**
* 根据propertys中的值动态生成含有Swagger注解的javaBeen
*/
private Class createRefModel(ApiJsonProperty[] propertys, String name) {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass(basePackage + name);

try {
for (ApiJsonProperty property : propertys) {
ctClass.addField(createField(property, ctClass));
}
return ctClass.toClass();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据property的值生成含有swagger apiModelProperty注解的属性
*/
private CtField createField(ApiJsonProperty property, CtClass ctClass)
throws NotFoundException, CannotCompileException {
CtField ctField = new CtField(getFieldType(property.type()), property.key(), ctClass);
ctField.setModifiers(Modifier.PUBLIC);

ConstPool constPool = ctClass.getClassFile().getConstPool();

AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
Annotation ann = new Annotation("io.swagger.annotations.ApiModelProperty", constPool);
ann.addMemberValue("value", new StringMemberValue(property.description(), constPool));
// string类型
if (ctField.getType().subclassOf(ClassPool.getDefault().get(String.class.getName())))
ann.addMemberValue("example", new StringMemberValue(property.example(), constPool));
// int类型
if (ctField.getType().subclassOf(ClassPool.getDefault().get(Integer.class.getName())))
ann.addMemberValue("example", new IntegerMemberValue(Integer.parseInt(property.example()), constPool));
// double类型
if (ctField.getType().subclassOf(ClassPool.getDefault().get(Double.class.getName())))
ann.addMemberValue("example", new DoubleMemberValue(Double.parseDouble(property.example()), constPool));

ann.addMemberValue("required", new BooleanMemberValue(property.required(), constPool));

attr.addAnnotation(ann);
ctField.getFieldInfo().addAttribute(attr);

return ctField;
}
/**
*
* @Title: MapApiReader.java
* @Description: 参数类型,后续可以增加多少类型
* @date
*/
private CtClass getFieldType(String type) throws NotFoundException {
CtClass fileType = null;
switch (type) {
case "string":
fileType = ClassPool.getDefault().get(String.class.getName());
break;
case "int":
fileType = ClassPool.getDefault().get(Integer.class.getName());
case "double":
fileType = ClassPool.getDefault().get(Double.class.getName());
break;
}
return fileType;
}
}

以上配置完成后接口如下书写即可:

}
@PostMapping(value = "/demo")
@ApiOperation(value = "获取资产", notes = "入参为map,userId必传")
public R valuationValue(@ApiJsonObject(name = "RequestModel", value = {
@ApiJsonProperty(key = "userId", example = "001", description = "用户Id必传", type = "string", required = true),
@ApiJsonProperty(key = "indexs", example = "1,2", description = "指标编号非必传", type = "string", required = false),
@ApiJsonProperty(key = "queryDate", example = "2018-12-24", description = "查询日期非必传", type = "string", required = false) })
@RequestBody Map<String, Object> params) {


return R.ok();
}


以上是Swagger的一些使用方法,还请多多指教!









正文到此结束