MapApiReader.java 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package com.qmth.distributed.print.config;
  2. import com.fasterxml.classmate.TypeResolver;
  3. import com.qmth.teachcloud.common.annotation.ApiJsonObject;
  4. import com.qmth.teachcloud.common.annotation.ApiJsonProperty;
  5. import com.qmth.teachcloud.common.contant.SystemConstant;
  6. import org.apache.ibatis.javassist.*;
  7. import org.apache.ibatis.javassist.bytecode.AnnotationsAttribute;
  8. import org.apache.ibatis.javassist.bytecode.ConstPool;
  9. import org.apache.ibatis.javassist.bytecode.annotation.Annotation;
  10. import org.apache.ibatis.javassist.bytecode.annotation.BooleanMemberValue;
  11. import org.apache.ibatis.javassist.bytecode.annotation.StringMemberValue;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.core.annotation.Order;
  16. import org.springframework.stereotype.Component;
  17. import springfox.documentation.schema.ModelRef;
  18. import springfox.documentation.service.ResolvedMethodParameter;
  19. import springfox.documentation.spi.DocumentationType;
  20. import springfox.documentation.spi.service.ParameterBuilderPlugin;
  21. import springfox.documentation.spi.service.contexts.ParameterContext;
  22. import java.util.Map;
  23. import java.util.Optional;
  24. /**
  25. * @Description: swagger2 map参数说明插件
  26. * @Param:
  27. * @return:
  28. * @Author: wangliang
  29. * @Date: 2020/4/23
  30. */
  31. @Component
  32. @Order //plugin加载顺序,默认是最后加载
  33. public class MapApiReader implements ParameterBuilderPlugin {
  34. private final static Logger log = LoggerFactory.getLogger(MapApiReader.class);
  35. @Autowired
  36. private TypeResolver typeResolver;
  37. @Override
  38. public void apply(ParameterContext parameterContext) {
  39. ResolvedMethodParameter methodParameter = parameterContext.resolvedMethodParameter();
  40. if (methodParameter.getParameterType().canCreateSubtype(Map.class) || methodParameter.getParameterType().canCreateSubtype(String.class)) { //判断是否需要修改对象ModelRef,这里我判断的是Map类型和String类型需要重新修改ModelRef对象
  41. Optional<ApiJsonObject> optional = methodParameter.findAnnotation(ApiJsonObject.class); //根据参数上的ApiJsonObject注解中的参数动态生成Class
  42. if (optional.isPresent()) {
  43. String name = optional.get().name(); //model 名称
  44. ApiJsonProperty[] properties = optional.get().value();
  45. parameterContext.getDocumentationContext().getAdditionalModels().add(typeResolver.resolve(createRefModel(properties, name))); //像documentContext的Models中添加我们新生成的Class
  46. parameterContext.parameterBuilder() //修改Map参数的ModelRef为我们动态生成的class
  47. .parameterType("body")
  48. .modelRef(new ModelRef(name))
  49. .name(name);
  50. }
  51. }
  52. }
  53. private final static String basePackage = "com.qmth.teachcloud.entity."; //动态生成的Class名
  54. /**
  55. * 根据propertys中的值动态生成含有Swagger注解的javaBeen
  56. */
  57. private Class createRefModel(ApiJsonProperty[] propertys, String name) {
  58. ClassPool pool = ClassPool.getDefault();
  59. CtClass ctClass = pool.makeClass(basePackage + name);
  60. try {
  61. for (ApiJsonProperty property : propertys) {
  62. ctClass.addField(createField(property, ctClass));
  63. }
  64. return ctClass.toClass();
  65. } catch (Exception e) {
  66. log.error(SystemConstant.LOG_ERROR, e);
  67. return null;
  68. }
  69. }
  70. /**
  71. * 根据property的值生成含有swagger apiModelProperty注解的属性
  72. */
  73. private CtField createField(ApiJsonProperty property, CtClass ctClass) throws NotFoundException, CannotCompileException {
  74. CtField ctField = new CtField(getFieldType(property.type()), property.key(), ctClass);
  75. ctField.setModifiers(Modifier.PUBLIC);
  76. ConstPool constPool = ctClass.getClassFile().getConstPool();
  77. AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
  78. Annotation ann = new Annotation("io.swagger.annotations.ApiModelProperty", constPool);
  79. ann.addMemberValue("value", new StringMemberValue(property.description(), constPool));
  80. ann.addMemberValue("required", new BooleanMemberValue(property.required(), constPool));
  81. attr.addAnnotation(ann);
  82. ctField.getFieldInfo().addAttribute(attr);
  83. return ctField;
  84. }
  85. private CtClass getFieldType(String type) throws NotFoundException {
  86. CtClass fileType = null;
  87. switch (type) {
  88. case "string":
  89. fileType = ClassPool.getDefault().get(String.class.getName());
  90. break;
  91. case "int":
  92. fileType = ClassPool.getDefault().get(Integer.class.getName());
  93. break;
  94. case "long":
  95. fileType = ClassPool.getDefault().get(Long.class.getName());
  96. break;
  97. case "boolean":
  98. fileType = ClassPool.getDefault().get(Boolean.class.getName());
  99. break;
  100. default:
  101. break;
  102. }
  103. return fileType;
  104. }
  105. @Override
  106. public boolean supports(DocumentationType delimiter) {
  107. return true;
  108. }
  109. }