springboot 2.0.8 整合swager

混江龙づ霸主 提交于 2020-03-17 12:45:40

某厂面试归来,发现自己落伍了!>>>

1、引入swager pom依賴

  <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
        </dependency>
        <!-- swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
         <dependency>
           	 <groupId>org.javassist</groupId>
 			 <artifactId>javassist</artifactId>
 			 <version>3.26.0-GA</version>
        </dependency>

其中 commons-lang3,javasist是swager依赖的  

2、Swagger2Config 配置类

package com.topnet.quick.frame.swager;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

/**
 * @author litianxiang
 */
@Configuration
public class Swagger2Config {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.topnet.quick.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                // 页面标题
                .title("API文档")
                // 创建人
                .contact(new Contact("litianxiang", "http://localhost:9082", "litianxiang@topnet.net.cn"))
                // 版本号
                .version("1.0")
                // 描述
                .description("API 描述")
                .build();
    }
}

3、访问地址:http://localhost:9002/quick/swagger-ui.html#/auto-controller

以上swager就配置结束了,但是,如果想swager支持requestBody map类型,需要增加下面三个类

4、ApiJsonProperty.java 属性描述

package com.topnet.quick.frame.swager;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonProperty {
	 String key();  //key
	 
	    String example() default "";
	 
	    String type() default "string";  //支持string 和 int
	 
	    String description() default "";
 }

5、ApiJsonObject.java 对象描述

package com.topnet.quick.frame.swager;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonObject {
	
	ApiJsonProperty[] value(); //对象属性值
	 
    String name();  //对象名称

}

6、SwagerRequestBodyMapPlugin.java 解析ApiJsonProperty、ApiJsonObject注解,生成接口文档

package com.topnet.quick.frame.swager;

 import java.lang.reflect.Modifier;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Optional;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.IntegerMemberValue;
import javassist.bytecode.annotation.StringMemberValue;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.ParameterContext;

/**
 * @author lpf
 *swager 生成requestBody map 类型的接口数据
 */
@Component
@Order 
public class SwagerRequestBodyMapPlugin implements ParameterBuilderPlugin {
	@Autowired
	private TypeResolver typeResolver;

	@Override
	public boolean supports(DocumentationType delimiter) {
		// TODO Auto-generated method stub
		return true;
	}

	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);
            }
        }
	}
	private final static String basePackage = "com.topnet.quick.frame.swager.invalid.";  //动态生成的Class名
    /**
     * 根据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;
        }
    }
    private CtField createField(ApiJsonProperty property, CtClass ctClass) throws    Exception {
        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));
        if (ctField.getType().subclassOf(ClassPool.getDefault().get(String.class.getName())))
            ann.addMemberValue("example", new StringMemberValue(property.example(), constPool));
        if (ctField.getType().subclassOf(ClassPool.getDefault().get(Integer.class.getName())))
            ann.addMemberValue("example", new IntegerMemberValue(Integer.parseInt(property.example()), constPool));
 
        attr.addAnnotation(ann);
        ctField.getFieldInfo().addAttribute(attr);
 
        return ctField;
    }
 
    private CtClass getFieldType(String type) throws Exception {
        CtClass fileType = null;
        switch (type) {
            case "string":
                fileType = ClassPool.getDefault().get(String.class.getName());
                break;
            case "int":
                fileType = ClassPool.getDefault().get(Integer.class.getName());
                break;
        }
        return fileType;
    }

 
 
	
}

7、使用

 @ApiOperation(value = "保存或更新", notes = "保存或更新")
    @RequestMapping(value = "/put", method = RequestMethod.POST)
    @ResponseBody
    public Result saveOrUpdate( @ApiJsonObject(name = "param", value = {@ApiJsonProperty(key = "id", example = "123", description = "编号"),@ApiJsonProperty(key = "autoDatesoureId", example = "123", description = "数据源编号")})  @RequestBody Map para) {
        return Result.success(autoService.saveOrUpdate(para));
    }

8、这样就可以看到接口协议了

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!