自开发添加swagger map类型参数说明

1 添加maven

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

2 添加ApiJsonObject类

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();  //对象名称
}

3 添加属性类ApiJsonProperty

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、double

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

	boolean required() default true; // 是否必传

}

3 添加swagger读取自定义信息类MapReaderForApi

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

import javassist.*;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.BooleanMemberValue;
import javassist.bytecode.annotation.DoubleMemberValue;
import javassist.bytecode.annotation.IntegerMemberValue;
import javassist.bytecode.annotation.StringMemberValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
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;

import java.util.Map;

/**
 * 
 * @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.xsy.dto."; // 动态生成的虚拟DTO Class的包路径

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

	@Override
	public boolean supports(DocumentationType delimiter) {
		return true;
	}
}

4 使用DemoController

    @PostMapping(value = "/demo")
	@ApiOperation(value = "获取资产", notes = "入参为map,userId必传")
	public String valuationValue(@ApiJsonObject(name = "RequestModel", value = {
			@ApiJsonProperty(key = "userId", example = "xsy123", 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) {
		log.info(String.format("Method[%s], args[%s]", "demo", params.toString()));
		
		return "";
	}

 

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Swagger是一个用于描述和自动生成API文档的工具,可以帮助开发人员快速生成接口文档,提高API开发效率。针对Map类型参数的解析,可以使用Swagger提供的注解来描述。 首先,我们需要在pom.xml文件中添加Swagger的依赖: ```xml <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${springfox.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${springfox.version}</version> </dependency> ``` 其中,`${springfox.version}`是Swagger的版本号。 接着,在Spring Boot应用程序中,我们需要创建一个Swagger配置类,用于配置Swagger的基本信息,例如接口文档的标题、描述、版本号等等。示例代码如下: ```java @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.example.demo")) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Swagger Demo") .description("This is a demo application for Swagger") .version("1.0.0") .build(); } } ``` 在上面的代码中,我们创建了一个`Docket`对象,用于配置Swagger的基本信息,包括扫描的API接口、文档的标题、描述和版本号。其中,`RequestHandlerSelectors`和`PathSelectors`用于指定扫描的包和路径。 接着,我们可以在Controller中使用Swagger提供的注解来描述接口和参数。针对Map类型参数,可以使用`@ApiParam`注解来描述Map中的键值对。示例代码如下: ```java @ApiOperation("添加用户") @ApiImplicitParams({ @ApiImplicitParam(name = "username", value = "用户名", required = true, dataType = "string", paramType = "query"), @ApiImplicitParam(name = "age", value = "年龄", required = true, dataType = "int", paramType = "query"), @ApiImplicitParam(name = "address", value = "地址", required = true, dataType = "map[string,string]", paramType = "query") }) @PostMapping("/user") public String addUser(@RequestParam String username, @RequestParam int age, @ApiParam("地址") @RequestParam Map<String, String> address) { // 处理添加用户的逻辑 return "添加用户成功"; } ``` 在上面的代码中,我们使用`@ApiImplicitParams`注解来描述接口的参数,其中`@ApiImplicitParam`用于描述具体的参数信息,包括参数名称、描述、数据类型、是否必填等等。针对Map类型参数,我们使用`map[string,string]`来描述Map的键值对,其中`string`表示Map的键和值都是字符串类型。 同时,在方法的参数中,我们使用`@ApiParam`注解来描述Map类型参数的具体信息,包括参数名称和描述。这样,Swagger就能正确解析Map类型参数,并生成相应的接口文档。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值