当前位置:   article > 正文

Swagger2文档生成 扩展支持 Map JSONObject 传参_swagger2 jsonobject

swagger2 jsonobject

本功能在 Swagger 2.7.0   和   2.9.2 版本 测试通过 ,保证可正常使用,

有问题联系471801687@qq.com

关于Swagger2本身不支持Map/JSONObject传参 生成文档,在网上找了很多,大多是自定义注解,借助第三方插件动态生成类,或者重写Swagger2的多数文件,显得很复杂,而且要看很多代码,跟踪才能了解并修改为自己的,而且还时好时坏,但是这些资料又给我带来了新的灵感。

大体思路,

1、新建一个静态Map,存储自己新建的model变量(不需要创建实体类)

2、自定义注解,实现配置参数信息

3、继承Swagger的部分builder类,根据注解 创建自己的 model 塞入 静态Map

4、添加Swagger Aop切面,将静态Map 合并到 Swagger的model中返回

下面是实现代码 

  1. import com.cloud.utils.util.baseenum.DataType;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * @author: fengyuan
  8. * @date 2021-6-3 17:23:28
  9. * @Description TODO Swagger2配置
  10. */
  11. @Target(ElementType.ANNOTATION_TYPE)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface PropFy2 {
  14. String name(); // key
  15. String eg() default "";// 示例
  16. DataType type() default DataType.String; // 支持string、int、double
  17. String desc() default "";// 参数描述
  18. boolean required() default false; // 是否必传
  19. }
  1. import com.cloud.utils.util.baseenum.DataType;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * @author: fengyuan
  8. * @date 2021-6-3 17:23:28
  9. * @Description TODO Swagger2配置
  10. */
  11. @Target(ElementType.ANNOTATION_TYPE)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface PropFy {
  14. String name(); // key
  15. String eg() default "";// 示例
  16. DataType type() default DataType.String; // 支持string、int、double
  17. String desc() default "";// 参数描述
  18. boolean required() default false; // 是否必传
  19. PropFy2[] map() default {};
  20. }
  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. /**
  6. * @author: fengyuan
  7. * @date 2021-6-3 17:23:28
  8. * @Description TODO Swagger2配置
  9. */
  10. @Target({ElementType.METHOD})
  11. @Retention(RetentionPolicy.RUNTIME)
  12. public @interface ResObjFY {
  13. PropFy[] value() default {}; //请求属性值
  14. }
  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. /**
  6. * @author: fengyuan
  7. * @date 2021-6-3 17:23:28
  8. * @Description TODO Swagger2配置
  9. */
  10. @Target({ElementType.PARAMETER})
  11. @Retention(RetentionPolicy.RUNTIME)
  12. public @interface ReqObjFy {
  13. PropFy[] value(); //对象属性值
  14. }
  1. //随便找个地方
  2. public static Map<String, Model> modelMap = new HashMap<>();
  1. //此为创建Model的方法,深度支持2级
  2. import com.cloud.utils.util.baseenum.DataType;
  3. import com.cloud.utils.utilabstract.BasePubFun;
  4. import io.swagger.models.ModelImpl;
  5. import io.swagger.models.properties.*;
  6. import org.apache.commons.lang3.StringUtils;
  7. import java.util.LinkedHashMap;
  8. import java.util.Map;
  9. /**
  10. * @author: fengyuan
  11. * @date 2021-6-3 15:17:49
  12. * @Description TODO Swagger2配置公共方法
  13. */
  14. public class SwaggerFun {
  15. public static String createModelRst(String name, PropFy[] pros) {
  16. createModel(name, pros);
  17. Map<String, Property> proMap = new LinkedHashMap<>();
  18. Property code = new StringProperty();
  19. code.setName("code");
  20. code.setDescription("状态'10000'成功,其他失败");
  21. code.setExample((Object) "10000");
  22. proMap.put("code", code);
  23. Property msg = new StringProperty();
  24. msg.setName("msg");
  25. msg.setDescription("提示");
  26. proMap.put("msg", msg);
  27. Property msgext = new StringProperty();
  28. msgext.setName("msgext");
  29. msgext.setDescription("详情");
  30. proMap.put("msgext", msgext);
  31. Property result = new RefProperty(name);
  32. result.setName("result");
  33. result.setDescription("结果集");
  34. proMap.put("result", result);
  35. Property success = new BooleanProperty();
  36. success.setName("success");
  37. success.setDescription("状态 true成功 false失败");
  38. proMap.put("success", success);
  39. //创建model
  40. String rstName = BasePubFun.format("RstData<{}>", name);
  41. ModelImpl model = new ModelImpl();
  42. model.setName(rstName);
  43. model.setProperties(proMap);
  44. model.setType("object");
  45. SwaggerFy.modelMap.put(rstName, model);
  46. return model.getName();
  47. }
  48. public static void createModel(String name, PropFy[] pros) {
  49. Map<String, Property> proMap = new LinkedHashMap<>();
  50. for (PropFy pro : pros) {
  51. Property property = null;
  52. try {
  53. if (DataType.String.equals(pro.type())) {
  54. property = new StringProperty();
  55. property.setExample(StringUtils.isBlank(pro.eg()) ? "" : (Object) pro.eg());
  56. } else if (DataType.Long.equals(pro.type())) {
  57. property = new LongProperty();
  58. property.setExample(StringUtils.isBlank(pro.eg()) ? 0L : Long.valueOf(pro.eg()));
  59. } else if (DataType.Integer.equals(pro.type())) {
  60. property = new IntegerProperty();
  61. property.setExample(StringUtils.isBlank(pro.eg()) ? 0 : Integer.valueOf(pro.eg()));
  62. } else if (DataType.Date.equals(pro.type())) {
  63. property = new DateProperty();
  64. property.setExample(StringUtils.isBlank(pro.eg()) ? "" : Boolean.valueOf(pro.eg()));
  65. } else if (DataType.Boolean.equals(pro.type())) {
  66. property = new BooleanProperty();
  67. property.setExample(StringUtils.isBlank(pro.eg()) ? "" : Boolean.valueOf(pro.eg()));
  68. } else if (DataType.Map.equals(pro.type())) {
  69. String tempName = name + "_" + pro.name();
  70. createModel(tempName, pro.map());
  71. property = new RefProperty(tempName);
  72. } else {
  73. property = new StringProperty();
  74. property.setExample((Object) pro.eg());
  75. }
  76. } catch (Exception e) {
  77. }
  78. property.setDescription(pro.desc());
  79. property.setRequired(pro.required());
  80. property.setName(pro.name());
  81. proMap.put(pro.name(), property);
  82. }
  83. ModelImpl model = new ModelImpl();
  84. model.setName(name);
  85. model.setProperties(proMap);
  86. model.setType("object");
  87. SwaggerFy.modelMap.put(name, model);
  88. }
  89. private static void createModel(String name, PropFy2[] pros) {
  90. Map<String, Property> proMap = new LinkedHashMap<>();
  91. for (PropFy2 pro : pros) {
  92. Property property = null;
  93. if (DataType.String.equals(pro.type())) {
  94. property = new StringProperty();
  95. property.setExample(StringUtils.isBlank(pro.eg()) ? "" : (Object) pro.eg());
  96. } else if (DataType.Long.equals(pro.type())) {
  97. property = new LongProperty();
  98. property.setExample(StringUtils.isBlank(pro.eg()) ? 0L : Long.valueOf(pro.eg()));
  99. } else if (DataType.Integer.equals(pro.type())) {
  100. property = new IntegerProperty();
  101. property.setExample(StringUtils.isBlank(pro.eg()) ? 0 : Integer.valueOf(pro.eg()));
  102. } else if (DataType.Date.equals(pro.type())) {
  103. property = new DateProperty();
  104. property.setExample(StringUtils.isBlank(pro.eg()) ? "" : Boolean.valueOf(pro.eg()));
  105. } else if (DataType.Boolean.equals(pro.type())) {
  106. property = new BooleanProperty();
  107. property.setExample(!StringUtils.isBlank(pro.eg()) && Boolean.valueOf(pro.eg()));
  108. }
  109. property.setDescription(pro.desc());
  110. property.setRequired(pro.required());
  111. property.setName(pro.name());
  112. proMap.put(pro.name(), property);
  113. }
  114. ModelImpl model = new ModelImpl();
  115. model.setName(name);
  116. model.setProperties(proMap);
  117. model.setType("object");
  118. SwaggerFy.modelMap.put(name, model);
  119. }
  120. }
  1. import com.alibaba.fastjson.JSONObject;
  2. import com.google.common.base.Optional;
  3. import org.springframework.core.annotation.Order;
  4. import org.springframework.stereotype.Component;
  5. import springfox.documentation.schema.ModelRef;
  6. import springfox.documentation.service.ResolvedMethodParameter;
  7. import springfox.documentation.spi.DocumentationType;
  8. import springfox.documentation.spi.service.ParameterBuilderPlugin;
  9. import springfox.documentation.spi.service.contexts.ParameterContext;
  10. import java.util.Map;
  11. /**
  12. * @author: fengyuan
  13. * @date 2021-6-3 15:17:49
  14. * @Description TODO Swagger2配置
  15. */
  16. @Component
  17. @Order // plugin加载顺序,默认是最后加载
  18. public class ParamReqPlugin implements ParameterBuilderPlugin {
  19. @Override
  20. public void apply(ParameterContext parameterContext) {
  21. ResolvedMethodParameter methodParameter = parameterContext.resolvedMethodParameter();
  22. // 判断是否需要修改对象ModelRef,这里我判断的是Map类型和JSONObject类型需要重新修改ModelRef对象
  23. if (!methodParameter.getParameterType().canCreateSubtype(Map.class) && methodParameter.getParameterType().canCreateSubtype(JSONObject.class)) {
  24. return;
  25. }
  26. Optional<ReqObjFy> optional = methodParameter.findAnnotation(ReqObjFy.class);
  27. if (!optional.isPresent()) {
  28. return;
  29. }
  30. String name = parameterContext.getOperationContext().requestMappingPattern().replace("/", "_").substring(1);
  31. SwaggerFun.createModel(name, optional.get().value());
  32. parameterContext.parameterBuilder().parameterType("body").modelRef(new ModelRef(name)).name(name);
  33. }
  34. @Override
  35. public boolean supports(DocumentationType delimiter) {
  36. return true;
  37. }
  38. }
  1. import com.cloud.utils.dto.RstData;
  2. import com.fasterxml.classmate.ResolvedType;
  3. import com.google.common.base.Optional;
  4. import org.springframework.core.annotation.Order;
  5. import org.springframework.stereotype.Component;
  6. import springfox.documentation.builders.ResponseMessageBuilder;
  7. import springfox.documentation.schema.ModelRef;
  8. import springfox.documentation.service.ResponseMessage;
  9. import springfox.documentation.spi.DocumentationType;
  10. import springfox.documentation.spi.service.OperationBuilderPlugin;
  11. import springfox.documentation.spi.service.contexts.OperationContext;
  12. import java.util.HashSet;
  13. /**
  14. * @author: fengyuan
  15. * @date 2021-6-3 15:17:49
  16. * @Description TODO Swagger2配置
  17. */
  18. @Component
  19. @Order // plugin加载顺序,默认是最后加载
  20. public class ParamResPlugin implements OperationBuilderPlugin {
  21. @Override
  22. public void apply(OperationContext operationContext) {
  23. ResolvedType returnType = operationContext.getReturnType();
  24. // 判断是否需要修改对象ModelRef,这里我判断的是RstData类型需要重新修改ModelRef对象
  25. if (!returnType.canCreateSubtype(RstData.class)) {
  26. return;
  27. }
  28. Optional<ResObjFY> optional = operationContext.findAnnotation(ResObjFY.class);
  29. if (!optional.isPresent()) {
  30. return;
  31. }
  32. String name = operationContext.requestMappingPattern().replace("/", "_").substring(1) + "_rst";
  33. String rstName = SwaggerFun.createModelRst(name, optional.get().value());
  34. ResponseMessage responseMessage = new ResponseMessageBuilder()
  35. .code(200).responseModel(new ModelRef(rstName))
  36. .build();
  37. HashSet<ResponseMessage> responseMessages = new HashSet<>();
  38. responseMessages.add(responseMessage);
  39. operationContext.operationBuilder().responseMessages(responseMessages);
  40. }
  41. @Override
  42. public boolean supports(DocumentationType delimiter) {
  43. return true;
  44. }
  45. }
  1. import io.swagger.models.Swagger;
  2. import org.aspectj.lang.ProceedingJoinPoint;
  3. import org.aspectj.lang.annotation.Around;
  4. import org.aspectj.lang.annotation.Aspect;
  5. import org.aspectj.lang.annotation.Pointcut;
  6. import org.springframework.stereotype.Component;
  7. /**
  8. * @author: fengyuan
  9. * @date 2021-6-3 17:23:28
  10. * @Description TODO Swagger2配置
  11. */
  12. @Aspect
  13. @Component
  14. public class SwaggerAop {
  15. @Pointcut(value = "execution(public * springfox.documentation.swagger2.mappers.ServiceModelToSwagger2MapperImpl.mapDocumentation(..))")
  16. public void point() {
  17. }
  18. @Around("point()")
  19. public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
  20. Swagger swagger = (Swagger) proceedingJoinPoint.proceed();
  21. swagger.getDefinitions().putAll(SwaggerFy.modelMap);
  22. return swagger;
  23. }
  24. }
  1. @PostMapping(value = "demo")
  2. @ApiOperation("请求参数配置方式,支持二级")
  3. @ResObjFY({
  4. @PropFy(name = "id", eg = "123", desc = "主键", type = DataType.Long, required = true),
  5. @PropFy(name = "row", desc = "具体数据", type = DataType.Map, map = {
  6. @PropFy2(name = "idCard", eg = "610126198911111111", desc = "身份证号", type = DataType.String, required = true),
  7. @PropFy2(name = "name", eg = "张三", desc = "姓名", required = true),
  8. @PropFy2(name = "sex", eg = "1", desc = "性别 1男 2女", type = DataType.Integer),
  9. })
  10. })
  11. public RstData demo(
  12. @ReqObjFy({
  13. @PropFy(name = "id", eg = "123", desc = "主键", type = DataType.Long, required = true),
  14. @PropFy(name = "row", desc = "具体数据", type = DataType.Map, map = {
  15. @PropFy2(name = "idCard", eg = "610126198911111111", desc = "身份证号", type = DataType.String, required = true),
  16. @PropFy2(name = "name", eg = "张三", desc = "姓名", required = true),
  17. @PropFy2(name = "sex", eg = "1", desc = "性别 1男 2女", type = DataType.Integer),
  18. })
  19. })
  20. @RequestBody Map<String, Object> params) {
  21. return RstData.success(params);
  22. }

效果图 

2.7.0

2.9.2

下面为Swagger扩展Ui的依赖及效果图
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/897710
推荐阅读
相关标签
  

闽ICP备14008679号