From 411b474b006c408012ab1ccdc5ac3bf9c6d8d25c Mon Sep 17 00:00:00 2001 From: Arunning6 Date: Sat, 16 Jun 2018 22:35:59 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../llchen/apidoc/annotation/ApiModel.java | 3 + .../apidoc/annotation/ApiModelProperty.java | 4 - .../llchen/apidoc/core/AnnotationFilter.java | 23 +++ .../llchen/apidoc/core/ApiClassBuilder.java | 12 ++ .../apidoc/core/ApiDocAnnotationBuilder.java | 16 ++ .../llchen/apidoc/core/ApiDocBuilder.java | 38 +++++ .../llchen/apidoc/core/ApiDocContext.java | 156 ++++++++++-------- .../llchen/apidoc/core/ApiMethodBuilder.java | 15 ++ .../llchen/apidoc/core/ClassFilter.java | 17 ++ .../llchen/apidoc/core/ClassFinder.java | 17 ++ .../apidoc/core/ClassPathClassFinder.java | 80 +++++++++ .../llchen/apidoc/core/ModelClassBuilder.java | 12 ++ .../apidoc/core/ModelClassBuilderImpl.java | 75 +++++++++ 13 files changed, 394 insertions(+), 74 deletions(-) create mode 100644 src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ClassFilter.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ClassFinder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java b/src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java index 676cf28..a5173af 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java +++ b/src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java @@ -1,5 +1,7 @@ package io.github.llchen.apidoc.annotation; +import org.apache.commons.lang3.StringUtils; + import java.lang.annotation.*; /** @@ -11,6 +13,7 @@ @Inherited public @interface ApiModel { + String name() default ""; /** * 数据模型描述 */ diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java b/src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java index 302511d..7c764e4 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java +++ b/src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java @@ -40,8 +40,4 @@ */ String example() default ""; - /** - * 数据类型 - */ - DataType type() default DataType.STRING; } diff --git a/src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java b/src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java new file mode 100644 index 0000000..b86497e --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java @@ -0,0 +1,23 @@ +package io.github.llchen.apidoc.core; + +import java.lang.annotation.Annotation; + +/** + * @author llchen12 + * @date 2018/6/14 + */ +public class AnnotationFilter implements ClassFilter { + + private Class annotationClass; + + public AnnotationFilter(Class annotationClass) { + this.annotationClass = annotationClass; + } + + @Override + @SuppressWarnings("unchecked") + public boolean accept(Class clazz) { + return clazz.getAnnotation(annotationClass) != null; + } + +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java new file mode 100644 index 0000000..3676d8d --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java @@ -0,0 +1,12 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.model.Document; + +/** + * @author chenliangliang + * @date 2018/6/16 + */ +public interface ApiClassBuilder { + + Document build(Class apiClass); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java new file mode 100644 index 0000000..0e5bef7 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java @@ -0,0 +1,16 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.model.Document; + +/** + * @author chenliangliang + * @date 2018/6/16 + */ +public class ApiDocAnnotationBuilder implements ApiClassBuilder { + + + @Override + public Document build(Class apiClass) { + return null; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java index ef5f293..9586971 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java +++ b/src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java @@ -8,6 +8,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.lang.reflect.Field; @@ -51,6 +52,43 @@ public void addApiDoc(ApiDoc apiDoc, Class apiDocClass, Object apiDocObject, docMap.put(document.getName(), document); } + + public void addApiDoc(Controller controller, Class apiDocClass, Object apiDocObject, ApiDocProperties properties) { + Document document = buildApiDoc(apiDoc, apiDocClass, properties); + Method[] methods = apiDocClass.getDeclaredMethods(); + List apiList = new LinkedList<>(); + for (Method method : methods) { + if (!Modifier.isPublic(method.getModifiers())) { + method.setAccessible(true); + } + Api api = method.getAnnotation(Api.class); + if (api == null) { + continue; + } + apiList.add(buildApi(api, method, document.getBasePath())); + } + document.setApiList(apiList); + docMap.put(document.getName(), document); + } + + public void addApiDoc(RestController apiDoc, Class apiDocClass, Object apiDocObject, ApiDocProperties properties) { + Document document = buildApiDoc(apiDoc, apiDocClass, properties); + Method[] methods = apiDocClass.getDeclaredMethods(); + List apiList = new LinkedList<>(); + for (Method method : methods) { + if (!Modifier.isPublic(method.getModifiers())) { + method.setAccessible(true); + } + Api api = method.getAnnotation(Api.class); + if (api == null) { + continue; + } + apiList.add(buildApi(api, method, document.getBasePath())); + } + document.setApiList(apiList); + docMap.put(document.getName(), document); + } + private Document buildApiDoc(ApiDoc apiDoc, Class apiDocClass, ApiDocProperties properties) { String docName = apiDoc.name(); diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java b/src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java index 3f13153..2d9de46 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java +++ b/src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java @@ -1,6 +1,7 @@ package io.github.llchen.apidoc.core; +import io.github.llchen.apidoc.annotation.Api; import io.github.llchen.apidoc.annotation.ApiDoc; import io.github.llchen.apidoc.annotation.ApiModel; import io.github.llchen.apidoc.config.ApiDocProperties; @@ -14,10 +15,13 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Controller; import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.RestController; import java.io.File; import java.util.HashMap; +import java.util.List; import java.util.concurrent.*; /** @@ -59,27 +63,98 @@ private void scanApi(ApplicationContext ctx) { long start = System.currentTimeMillis(); //初始化线程池 initThreadPool(ctx); - String basePath = ctx.getClass().getResource("/").getPath(); - basePath = basePath.endsWith("/") ? basePath : basePath + "/"; + ClassFinder classFinder = new ClassPathClassFinder(); + + ConcurrentHashMap> controllerClasses = new ConcurrentHashMap<>(); + ConcurrentHashMap> modelClasses = new ConcurrentHashMap<>(); + String controllerPackage = properties.getControllerPackage(); - if (StringUtils.isNotBlank(controllerPackage)) { - String modelPackage = properties.getModelPackage(); - if (StringUtils.isNotBlank(modelPackage)) { - //先扫描model - scanModel(basePath, modelPackage); - } - //扫描controller - scanController(ctx, basePath, controllerPackage); + String modelPackage = properties.getModelPackage(); + boolean controllerFlag = StringUtils.isBlank(controllerPackage); + boolean modelFlag = StringUtils.isBlank(modelPackage); + if (controllerFlag || modelFlag) { + //TODO: 全包扫描 + List> classList = classFinder.find("/"); + for (Class clazz : classList) { + if (clazz.getAnnotation(ApiDoc.class) != null) { + controllerClasses.put(clazz.getCanonicalName(), clazz); + } + + if (clazz.getAnnotation(Controller.class) != null) { + controllerClasses.put(clazz.getCanonicalName(), clazz); + } + + if (clazz.getAnnotation(RestController.class) != null) { + controllerClasses.put(clazz.getCanonicalName(), clazz); + } + if (clazz.getAnnotation(ApiModel.class) != null) { + modelClasses.put(clazz.getCanonicalName(), clazz); + } + } } else { - //TODO:全包扫描 + if (!controllerFlag){ + List> controllerClassList = classFinder.find(controllerPackage.replace(".", "/")); + for (Class clazz:controllerClassList){ + if (clazz.getAnnotation(ApiDoc.class) != null) { + controllerClasses.put(clazz.getCanonicalName(), clazz); + } + if (clazz.getAnnotation(Controller.class) != null) { + controllerClasses.put(clazz.getCanonicalName(), clazz); + } + if (clazz.getAnnotation(RestController.class) != null) { + controllerClasses.put(clazz.getCanonicalName(), clazz); + } + } + } + + if (!modelFlag){ + List> modelClassList = classFinder.find(modelPackage.replace(".", "/")); + for (Class clazz:modelClassList){ + if (clazz.getAnnotation(ApiModel.class) != null) { + modelClasses.put(clazz.getCanonicalName(), clazz); + } + } + } } + + handleModel(modelClasses); + handleController(controllerClasses); + executor.destroy(); long time = System.currentTimeMillis() - start; LOGGER.info("扫描Api完毕,耗时:" + time / 1000.0 + "秒"); } + + + private void handleController(ConcurrentHashMap> controllerClasses) { + for (Class clazz:controllerClasses.values()){ + executor.execute(()->loadApi(clazz)); + } + } + + private void loadApi(Class clazz) { + if (clazz.getAnnotation(ApiDoc.class)!=null){ + apiDocBuilder.addApiDoc(clazz.getAnnotation(ApiDoc.class),clazz,null,properties); + }else if (clazz.getAnnotation(Controller.class)!=null){ + apiDocBuilder.addApiDoc(clazz.getAnnotation(Controller.class),clazz,null,properties); + }else if (clazz.getAnnotation(RestController.class)!=null){ + apiDocBuilder.addApiDoc(clazz.getAnnotation(RestController.class),clazz,null,properties); + } + } + + private void handleModel(ConcurrentHashMap> modelClasses) { + for (Class clazz:modelClasses.values()){ + executor.execute(()->loadModel(clazz)); + } + } + + private void loadModel(Class clazz) { + apiDocBuilder.addModel(clazz.getAnnotation(ApiModel.class),clazz); + } + /** * 初始化线程池 */ @@ -106,68 +181,9 @@ private void initThreadPool(ApplicationContext ctx) { executor = new Executor(poolExecutor); } - /** - * 扫描model类 - */ - private void scanModel(String basePath, String modelPackage) { - String filePath = basePath + modelPackage.replace(".", "/"); - File dir = new File(filePath); - String[] classNames = dir.list((dir1, name) -> name.endsWith(".class")); - if (classNames != null && classNames.length > 0) { - String classFullName; - for (String className : classNames) { - classFullName = modelPackage + "." + className.substring(0, className.lastIndexOf(".")); - try { - Class aClass = Class.forName(classFullName); - ApiModel apiModel = aClass.getAnnotation(ApiModel.class); - if (apiModel != null) { - //多线程加载 - executor.execute(() -> loadModel(aClass, apiModel)); - } - } catch (ClassNotFoundException e) { - LOGGER.warn("加载类:{}失败", classFullName, e); - } - } - } - - } - private void loadModel(Class modelClass, ApiModel apiModel) { - apiDocBuilder.addModel(apiModel, modelClass); - } - /** - * 扫描controller类 - */ - private void scanController(ApplicationContext ctx, String basePath, String controllerPackage) { - String filePath = basePath + controllerPackage.replace(".", "/"); - File dir = new File(filePath); - String[] classNames = dir.list((dir1, name) -> name.endsWith(".class")); - if (classNames != null && classNames.length > 0) { - String classFullName; - for (String className : classNames) { - classFullName = controllerPackage + "." + className.substring(0, className.lastIndexOf(".")); - try { - Class aClass = Class.forName(classFullName); - ApiDoc apiDoc = aClass.getAnnotation(ApiDoc.class); - if (apiDoc != null) { - Object apiDocObject = ctx.getBean(aClass); - //多线程加载 - executor.execute(() -> loadApi(aClass, apiDocObject, apiDoc)); - } - } catch (ClassNotFoundException e) { - LOGGER.warn("加载类:{}失败", classFullName, e); - } - } - } - } - /** - * 加载api - */ - private void loadApi(Class apiDocClass, Object apiDocObject, ApiDoc apiDoc) { - apiDocBuilder.addApiDoc(apiDoc, apiDocClass, apiDocObject,properties); - } /** diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java new file mode 100644 index 0000000..a7a9c13 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java @@ -0,0 +1,15 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.model.ApiDefinition; +import io.github.llchen.apidoc.model.Document; + +import java.lang.reflect.Method; + +/** + * @author chenliangliang + * @date 2018/6/16 + */ +public interface ApiMethodBuilder { + + ApiDefinition build(Document document, Method method); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassFilter.java b/src/main/java/io/github/llchen/apidoc/core/ClassFilter.java new file mode 100644 index 0000000..a47ffae --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ClassFilter.java @@ -0,0 +1,17 @@ +package io.github.llchen.apidoc.core; + +/** + * 类过滤器 + * + * @author llchen12 + * @date 2018/6/14 + */ +public interface ClassFilter { + + /** + * 是否通过这个类 + * @param clazz 类 + * @return true->通过,false->不通过 + */ + boolean accept(Class clazz); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassFinder.java b/src/main/java/io/github/llchen/apidoc/core/ClassFinder.java new file mode 100644 index 0000000..1b7465e --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ClassFinder.java @@ -0,0 +1,17 @@ +package io.github.llchen.apidoc.core; + +import java.util.List; + +/** + * @author llchen12 + * @date 2018/6/14 + */ +public interface ClassFinder { + + /** + * + * @param path class路径 + * @return + */ + List> find(String path); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java b/src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java new file mode 100644 index 0000000..875e9f2 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java @@ -0,0 +1,80 @@ +package io.github.llchen.apidoc.core; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; + +/** + * @author chenliangliang + * @date 2018/6/16 + */ +public class ClassPathClassFinder implements ClassFinder { + + private static final Logger LOGGER = LoggerFactory.getLogger(ClassPathClassFinder.class); + + private String classPath; + + public ClassPathClassFinder() { + this.classPath = ClassPathClassFinder.class.getResource("/").getPath(); + } + + @Override + public List> find(String path) { + List> list = new LinkedList<>(); + String filePath; + if (StringUtils.isEmpty(path) || "/".equals(path)) { + filePath = classPath; + } else { + filePath = classPath + path; + } + + Set classNameSet = findClass(filePath); + for (String className : classNameSet) { + try { + list.add(Class.forName(className)); + } catch (ClassNotFoundException e) { + LOGGER.warn("加载{}类失败", className, e); + } + } + + return list; + } + + private Set findClass(String filePath) { + Set classNameSet = new HashSet<>(); + findClass(new File(filePath), classNameSet); + return classNameSet; + } + + private void findClass(File file, Set classNameSet) { + if (!file.exists()) { + return; + } + int i = this.classPath.length() - 1; + if (file.isFile()) { + String path = file.getPath(); + if (path.endsWith(".class")) { + String className = path.substring(i, path.lastIndexOf(".")) + .replace("\\", ".") + .replace("/", "."); + classNameSet.add(className); + } + } else { + File[] files = file.listFiles(); + for (File f : files) { + findClass(f, classNameSet); + } + } + } + + + public String getClassPath() { + return classPath; + } + + +} + diff --git a/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java new file mode 100644 index 0000000..ce45197 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java @@ -0,0 +1,12 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.model.ApiModelDefinition; + +/** + * @author chenliangliang + * @date 2018/6/16 + */ +public interface ModelClassBuilder { + + ApiModelDefinition build(Class modelClass); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java b/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java new file mode 100644 index 0000000..cfb42db --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java @@ -0,0 +1,75 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.DataType; +import io.github.llchen.apidoc.annotation.ApiModel; +import io.github.llchen.apidoc.annotation.ApiModelProperty; +import io.github.llchen.apidoc.model.ApiModelDefinition; +import io.github.llchen.apidoc.model.ApiModelPropertyDefinition; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Field; +import java.util.LinkedList; +import java.util.List; + +/** + * @author chenliangliang + * @date 2018/6/16 + */ +public class ModelClassBuilderImpl implements ModelClassBuilder { + + + @Override + public ApiModelDefinition build(Class modelClass) { + ApiModelDefinition apiModelDefinition = new ApiModelDefinition(); + ApiModel apiModel = modelClass.getAnnotation(ApiModel.class); + String name = apiModel.name(); + if (StringUtils.isEmpty(name)) { + name = modelClass.getSimpleName(); + } + apiModelDefinition.setName(name); + String description = apiModel.description(); + //TODO:从注释取 + apiModelDefinition.setDescription(description); + apiModelDefinition.setRemark(apiModel.remark()); + + //构建属性 + List propertyList = new LinkedList<>(); + Field[] fields = modelClass.getDeclaredFields(); + for (Field field : fields) { + propertyList.add(buildProperty(field)); + } + apiModelDefinition.setPropertyList(propertyList); + return apiModelDefinition; + } + + private ApiModelPropertyDefinition buildProperty(Field field) { + ApiModelPropertyDefinition property = new ApiModelPropertyDefinition(); + ApiModelProperty modelProperty = field.getAnnotation(ApiModelProperty.class); + if (modelProperty != null) { + String name = modelProperty.name(); + if (StringUtils.isEmpty(name)) { + name = field.getName(); + } + property.setName(name); + String description = modelProperty.description(); + //TODO:取注释 + property.setDescription(description); + String defaultValue = modelProperty.defaultValue(); + if (StringUtils.isEmpty(defaultValue)) { + //TODO:取默认值 + } + property.setDefaultValue(defaultValue); + + }else { + property.setName(field.getName()); + //TODO:取注释 + property.setDescription(""); + //TODO:取默认值 + property.setDescription(""); + } + property.setExample(modelProperty.example()); + property.setRequired(modelProperty.required() ? "是" : "否"); + property.setType(DataType.getType(field.getType())); + return property; + } +} From f2cf77352352c8f0f471b08b50aa684c863aa7b5 Mon Sep 17 00:00:00 2001 From: Arunning6 Date: Wed, 27 Jun 2018 06:59:58 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E9=87=8D=E6=9E=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../github/llchen/apidoc/annotation/Api.java | 7 +- .../config/ApiDocAutoConfiguration.java | 19 +-- .../apidoc/controller/ApiDocController.java | 1 + .../apidoc/core/AbstractClassParser.java | 26 ++++ .../llchen/apidoc/core/ApiClassBuilder.java | 12 -- .../apidoc/core/ApiDocAnnotationBuilder.java | 54 +++++++- .../llchen/apidoc/core/ApiDocClassParser.java | 64 +++++++++ .../github/llchen/apidoc/core/ApiMerger.java | 54 ++++++++ .../llchen/apidoc/core/ApiMethodParser.java | 79 +++++++++++ .../llchen/apidoc/core/ClassParser.java | 12 ++ .../apidoc/core/JavaDocMethodParser.java | 26 ++++ .../io/github/llchen/apidoc/core/Merger.java | 10 ++ .../llchen/apidoc/core/MethodFilter.java | 12 ++ .../llchen/apidoc/core/MethodParser.java | 15 +++ .../llchen/apidoc/core/ModelClassParser.java | 18 +++ .../apidoc/core/ReflectMethodParser.java | 74 +++++++++++ .../core/RequestMappingMethodParser.java | 96 ++++++++++++++ .../apidoc/core/RequestMappingWarp.java | 123 ++++++++++++++++++ .../llchen/apidoc/model/ApiDefinition.java | 1 + .../apidoc/model/ApiParamDefinition.java | 1 + .../io/github/llchen/apidoc/utils/Utils.java | 25 ++++ 21 files changed, 704 insertions(+), 25 deletions(-) create mode 100644 src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiMerger.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ClassParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/Merger.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/MethodFilter.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/MethodParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java create mode 100644 src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java create mode 100644 src/main/java/io/github/llchen/apidoc/utils/Utils.java diff --git a/src/main/java/io/github/llchen/apidoc/annotation/Api.java b/src/main/java/io/github/llchen/apidoc/annotation/Api.java index f0b8580..647355a 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/Api.java +++ b/src/main/java/io/github/llchen/apidoc/annotation/Api.java @@ -1,5 +1,8 @@ package io.github.llchen.apidoc.annotation; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.RequestMethod; + import java.lang.annotation.*; /** @@ -37,7 +40,7 @@ /** * http请求方式 */ - String[] httpMethod() default {}; + RequestMethod[] httpMethod() default {}; /** @@ -63,4 +66,6 @@ */ Class resultModel() default Void.class; + + } diff --git a/src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java b/src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java index 91cfcb7..79feb47 100644 --- a/src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java +++ b/src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java @@ -2,10 +2,12 @@ import io.github.llchen.apidoc.core.ApiDocContext; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * @author llchen12 @@ -24,14 +26,15 @@ public ApiDocAutoConfiguration(ApiDocProperties properties) { } -// @Bean -// public ThreadPoolTaskExecutor taskExecutor() { -// ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); -// taskExecutor.setCorePoolSize(5); -// taskExecutor.setMaxPoolSize(10); -// taskExecutor.setKeepAliveSeconds(60); -// return taskExecutor; -// } + @Bean + @ConditionalOnMissingBean(ThreadPoolTaskExecutor.class) + public ThreadPoolTaskExecutor taskExecutor() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.setKeepAliveSeconds(60); + return taskExecutor; + } @Bean public ApiDocContext apiDocContext() { diff --git a/src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java b/src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java index 979c53d..137b434 100644 --- a/src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java +++ b/src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java @@ -54,6 +54,7 @@ public void docToMarkdown(HttpServletResponse response) throws IOException { } + @GetMapping("/html") public void preLook(HttpServletResponse response) throws IOException { HashMap docMap = ApiDocContext.getDocMap(); diff --git a/src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java b/src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java new file mode 100644 index 0000000..2706199 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java @@ -0,0 +1,26 @@ +package io.github.llchen.apidoc.core; + +import java.lang.annotation.Annotation; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public abstract class AbstractClassParser implements ClassParser { + + + private Class annotationClass; + + protected AbstractClassParser(Class annotationClass){ + this.annotationClass=annotationClass; + } + + @Override + public R parse(Class clazz) { + A annotation = clazz.getAnnotation(annotationClass); + return parse2Obj(clazz,annotation); + } + + + protected abstract R parse2Obj(Class clazz, A annotation); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java deleted file mode 100644 index 3676d8d..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/ApiClassBuilder.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.llchen.apidoc.core; - -import io.github.llchen.apidoc.model.Document; - -/** - * @author chenliangliang - * @date 2018/6/16 - */ -public interface ApiClassBuilder { - - Document build(Class apiClass); -} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java index 0e5bef7..a590473 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java +++ b/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java @@ -1,16 +1,62 @@ package io.github.llchen.apidoc.core; +import io.github.llchen.apidoc.annotation.ApiCode; +import io.github.llchen.apidoc.annotation.ApiDoc; +import io.github.llchen.apidoc.model.ApiCodeDefinition; import io.github.llchen.apidoc.model.Document; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.LinkedList; +import java.util.List; + /** * @author chenliangliang * @date 2018/6/16 */ -public class ApiDocAnnotationBuilder implements ApiClassBuilder { +public class ApiDocAnnotationBuilder implements ApiClassBuilder { + - @Override - public Document build(Class apiClass) { - return null; + public Document build(Class apiClass, Class annotationClass) { + ApiDoc apiDoc = apiClass.getAnnotation(annotationClass); + Document document=new Document(); + String name = apiDoc.name(); + if (StringUtils.isEmpty(name)){ + name=apiClass.getSimpleName(); + } + document.setName(name); + document.setBasePath(getApiBasePath(apiDoc,apiClass)); + String description = apiDoc.description(); + if (StringUtils.isEmpty(description)){ + //TODO:取注释 + } + document.setDescription(description); + + //构建ApiCode + ApiCode[] apiCodes = apiDoc.codes(); + List codeList = new LinkedList<>(); + for (ApiCode code : apiCodes) { + codeList.add(new ApiCodeDefinition(code.code(), code.description())); + } + document.setCodeList(codeList); + return document; + } + + + private String getApiBasePath(ApiDoc apiDoc, Class apiDocClass) { + String basePath = apiDoc.basePath(); + if (StringUtils.isNotEmpty(basePath)) { + return basePath.startsWith("/") ? basePath : "/" + basePath; + } + + RequestMapping rm = apiDocClass.getAnnotation(RequestMapping.class); + if (rm != null) { + String[] value = rm.value(); + return value[0]; + } + + return ""; } } diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java b/src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java new file mode 100644 index 0000000..4e63727 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java @@ -0,0 +1,64 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.annotation.ApiCode; +import io.github.llchen.apidoc.annotation.ApiDoc; +import io.github.llchen.apidoc.model.ApiCodeDefinition; +import io.github.llchen.apidoc.model.Document; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.LinkedList; +import java.util.List; + + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ApiDocClassParser extends AbstractClassParser { + + + public ApiDocClassParser() { + super(ApiDoc.class); + } + + + @Override + protected Document parse2Obj(Class clazz, ApiDoc annotation) { + Document document = new Document(); + List codeList = new LinkedList<>(); + if (annotation == null) { + //TODO:取注释,取className + document.setName(clazz.getSimpleName()); + document.setDescription(""); + + } else { + //构建ApiCode + ApiCode[] apiCodes = annotation.codes(); + for (ApiCode code : apiCodes) { + codeList.add(new ApiCodeDefinition(code.code(), code.description())); + } + } + document.setCodeList(codeList); + document.setBasePath(getBasePath(annotation,clazz)); + return document; + } + + + + private String getBasePath(ApiDoc apiDoc, Class apiDocClass) { + if (apiDoc!=null){ + String basePath = apiDoc.basePath(); + if (StringUtils.isNotEmpty(basePath)) { + return basePath.startsWith("/") ? basePath : "/" + basePath; + } + }else { + RequestMapping rm = apiDocClass.getAnnotation(RequestMapping.class); + if (rm != null) { + String[] value = rm.value(); + return value[0]; + } + } + return ""; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiMerger.java b/src/main/java/io/github/llchen/apidoc/core/ApiMerger.java new file mode 100644 index 0000000..d6d770c --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ApiMerger.java @@ -0,0 +1,54 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.model.ApiDefinition; +import org.apache.commons.lang3.StringUtils; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ApiMerger implements Merger { + + + @Override + public ApiDefinition merge(ApiDefinition... obj) { + ApiDefinition apiDefinition=new ApiDefinition(); + String name=""; + for (ApiDefinition api:obj){ + name=api.getName(); + if (StringUtils.isNotBlank(name)){ + break; + } + } + apiDefinition.setName(name); + + String description=""; + for (ApiDefinition api:obj){ + description=api.getDescription(); + if (StringUtils.isNotBlank(description)){ + break; + } + } + apiDefinition.setDescription(description); + + String remark=""; + for (ApiDefinition api:obj){ + remark=api.getRemark(); + if (StringUtils.isNotBlank(remark)){ + break; + } + } + apiDefinition.setRemark(remark); + + String path=""; + for (ApiDefinition api:obj){ + path=api.getPath(); + if (StringUtils.isNotBlank(path)){ + break; + } + } + apiDefinition.setPath(path); + + return apiDefinition; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java b/src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java new file mode 100644 index 0000000..4a4dd68 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java @@ -0,0 +1,79 @@ +package io.github.llchen.apidoc.core; + +import com.alibaba.fastjson.JSON; +import io.github.llchen.apidoc.annotation.Api; +import io.github.llchen.apidoc.annotation.ApiParam; +import io.github.llchen.apidoc.model.ApiDefinition; +import io.github.llchen.apidoc.model.ApiParamDefinition; +import io.github.llchen.apidoc.utils.Utils; + +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ApiMethodParser implements MethodParser { + + + @Override + public int order() { + return 0; + } + + @Override + public ApiDefinition parse(Method method) { + ApiDefinition apiDefinition = new ApiDefinition(); + Api api = method.getAnnotation(Api.class); + if (api != null) { + apiDefinition.setName(api.name()); + apiDefinition.setDemoResponse(api.demoResponse()); + apiDefinition.setDescription(api.description()); + apiDefinition.setHttpMethod(Utils.requestMethod2Str(api.httpMethod())); + apiDefinition.setPath(api.path()); + apiDefinition.setRemark(api.remark()); + + String demoResponse = api.demoResponse(); + String responseExample; + try { + responseExample = JSON.toJSONString(JSON.parseObject(demoResponse), true); + } catch (Exception e) { + responseExample = demoResponse; + } + apiDefinition.setDemoResponse(responseExample); + + //构建requestParams + ApiParam[] requestParams = api.requestParams(); + List requestParamList = buildParam(requestParams); + apiDefinition.setRequestParams(requestParamList); + + //构建responseParams + ApiParam[] responseParams = api.responseParams(); + List responseParamList = buildParam(responseParams); + apiDefinition.setResponseParams(responseParamList); + + //构建model + apiDefinition.setResultClass(api.resultModel()); + + } + return apiDefinition; + } + + private List buildParam(ApiParam[] params){ + List paramList=new LinkedList<>(); + ApiParamDefinition apiParamDefinition; + for (ApiParam apiParam:params){ + apiParamDefinition = new ApiParamDefinition(); + apiParamDefinition.setName(apiParam.name()); + apiParamDefinition.setDescription(apiParam.description()); + apiParamDefinition.setExample(apiParam.example()); + apiParamDefinition.setRequired(apiParam.required() ? "是" : "否"); + apiParamDefinition.setType(apiParam.type().getValue()); + apiParamDefinition.setDefaultValue(apiParam.defaultValue()); + paramList.add(apiParamDefinition); + } + return paramList; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassParser.java b/src/main/java/io/github/llchen/apidoc/core/ClassParser.java new file mode 100644 index 0000000..9432460 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ClassParser.java @@ -0,0 +1,12 @@ +package io.github.llchen.apidoc.core; + + + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public interface ClassParser{ + + R parse(Class clazz); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java b/src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java new file mode 100644 index 0000000..2359d7e --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java @@ -0,0 +1,26 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.model.ApiDefinition; + +import java.lang.reflect.Method; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class JavaDocMethodParser implements MethodParser { + + + + @Override + public int order() { + return 3; + } + + @Override + public ApiDefinition parse(Method method) { + ApiDefinition apiDefinition=new ApiDefinition(); + + return apiDefinition; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/Merger.java b/src/main/java/io/github/llchen/apidoc/core/Merger.java new file mode 100644 index 0000000..526140b --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/Merger.java @@ -0,0 +1,10 @@ +package io.github.llchen.apidoc.core; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public interface Merger { + + R merge(T...obj); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/MethodFilter.java b/src/main/java/io/github/llchen/apidoc/core/MethodFilter.java new file mode 100644 index 0000000..00f2b2c --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/MethodFilter.java @@ -0,0 +1,12 @@ +package io.github.llchen.apidoc.core; + +import java.lang.reflect.Method; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public interface MethodFilter { + + boolean accept(Method method); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/MethodParser.java b/src/main/java/io/github/llchen/apidoc/core/MethodParser.java new file mode 100644 index 0000000..4b2f58e --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/MethodParser.java @@ -0,0 +1,15 @@ +package io.github.llchen.apidoc.core; + + +import java.lang.reflect.Method; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public interface MethodParser { + + int order(); + + R parse(Method method); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java b/src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java new file mode 100644 index 0000000..66edf0d --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java @@ -0,0 +1,18 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.annotation.ApiModel; +import io.github.llchen.apidoc.model.ApiModelDefinition; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ModelClassParser implements ClassParser { + + + @Override + public ApiModelDefinition parse(Class clazz, Class annotationClass) { + + return null; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java b/src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java new file mode 100644 index 0000000..74d68d8 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java @@ -0,0 +1,74 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.DataType; +import io.github.llchen.apidoc.model.ApiDefinition; +import io.github.llchen.apidoc.model.ApiParamDefinition; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.LinkedList; +import java.util.List; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ReflectMethodParser implements MethodParser { + + private static ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); + + @Override + public int order() { + return 2; + } + + @Override + public ApiDefinition parse(Method method) { + ApiDefinition apiDefinition = new ApiDefinition(); + apiDefinition.setName(method.getName()); + apiDefinition.setResultClass(method.getReturnType()); + apiDefinition.setRequestParams(buildRequestParams(method)); + Class returnType = method.getReturnType(); + apiDefinition.setResponseParams(buildResponseParams(returnType)); + apiDefinition.setResultClass(returnType); + return apiDefinition; + } + + + private List buildRequestParams(Method method) { + List apiParamList = new LinkedList<>(); + ApiParamDefinition apiParamDefinition; + String[] parameterNames = discoverer.getParameterNames(method); + Parameter[] parameters = method.getParameters(); + for (int i = 0, l = parameterNames.length; i < l; i++) { + Parameter parameter = parameters[i]; + apiParamDefinition = new ApiParamDefinition(); + apiParamDefinition.setName(parameterNames[i]); + apiParamDefinition.setRequired("是"); + apiParamDefinition.setClazz(parameter.getType()); + apiParamList.add(apiParamDefinition); + } + return apiParamList; + } + + private List buildResponseParams(Class returnType) { + List apiParamList = new LinkedList<>(); + ApiParamDefinition apiParamDefinition; + //反射获取 + Field[] fields = returnType.getDeclaredFields(); + for (Field field : fields) { + apiParamDefinition = new ApiParamDefinition(); + apiParamDefinition.setType(DataType.getType(field.getType())); + apiParamDefinition.setName(field.getName()); + apiParamDefinition.setRequired("是"); + apiParamDefinition.setExample(""); + apiParamDefinition.setDescription(""); + apiParamDefinition.setDefaultValue(""); + apiParamList.add(apiParamDefinition); + } + return apiParamList; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java b/src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java new file mode 100644 index 0000000..188d4ae --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java @@ -0,0 +1,96 @@ +package io.github.llchen.apidoc.core; + +import io.github.llchen.apidoc.DataType; +import io.github.llchen.apidoc.model.ApiDefinition; +import io.github.llchen.apidoc.model.ApiParamDefinition; +import io.github.llchen.apidoc.utils.Utils; +import org.springframework.web.bind.annotation.*; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class RequestMappingMethodParser implements MethodParser { + + @Override + public int order() { + return 1; + } + + @Override + public ApiDefinition parse(Method method) { + RequestMappingWarp warp; + RequestMapping rm = method.getAnnotation(RequestMapping.class); + if (rm!=null){ + warp=new RequestMappingWarp(rm); + return parse2Obj(warp); + } + + GetMapping gm = method.getAnnotation(GetMapping.class); + if (gm!=null){ + warp=new RequestMappingWarp(gm); + return parse2Obj(warp); + } + + PostMapping pm = method.getAnnotation(PostMapping.class); + if (pm!=null){ + warp=new RequestMappingWarp(pm); + return parse2Obj(warp); + } + + DeleteMapping dm = method.getAnnotation(DeleteMapping.class); + if (dm!=null){ + warp=new RequestMappingWarp(dm); + return parse2Obj(warp); + } + + PutMapping ptm = method.getAnnotation(PutMapping.class); + if (ptm!=null){ + warp=new RequestMappingWarp(ptm); + return parse2Obj(warp); + } + + return new ApiDefinition(); + } + + private ApiDefinition parse2Obj(RequestMappingWarp warp){ + ApiDefinition apiDefinition=new ApiDefinition(); + apiDefinition.setPath(getPath(warp)); + apiDefinition.setRequestParams(buildParam(warp.getParams())); + apiDefinition.setHttpMethod(Utils.requestMethod2Str(warp.getMethod())); + apiDefinition.setName(warp.getName()); + return apiDefinition; + } + + private List buildParam(String[] params) { + List paramList=new LinkedList<>(); + for (String param:params){ + ApiParamDefinition paramDefinition=new ApiParamDefinition(); + paramDefinition.setName(param); + paramDefinition.setType(DataType.STRING.getValue()); + paramDefinition.setRequired("是"); + paramList.add(paramDefinition); + } + return paramList; + } + + + private String getPath(RequestMappingWarp warp){ + String[] value = warp.getValue(); + if (value.length>0){ + return Arrays.toString(value); + } + + String[] path = warp.getPath(); + if (path.length>0){ + return Arrays.toString(path); + } + + return ""; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java b/src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java new file mode 100644 index 0000000..dba3321 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java @@ -0,0 +1,123 @@ +package io.github.llchen.apidoc.core; + +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class RequestMappingWarp { + + private String name; + private String[] value; + private String[] path; + private RequestMethod[] method; + private String[] params; + private String[] headers; + private String[] consumes; + + public RequestMappingWarp() { + } + + public RequestMappingWarp(RequestMapping m){ + this(m.name(),m.value(),m.path(),m.method(),m.params(),m.headers(),m.consumes()); + } + + public RequestMappingWarp(String name, String[] value, String[] path, RequestMethod[] method, String[] params, String[] headers, String[] consumes) { + this.name = name; + this.value = value; + this.path = path; + this.method = method; + this.params = params; + this.headers = headers; + this.consumes = consumes; + } + + public RequestMappingWarp(GetMapping m){ + this(m.name(),m.value(),m.path(),new RequestMethod[]{RequestMethod.GET},m.params(),m.headers(),m.consumes()); + } + + public RequestMappingWarp(PostMapping m){ + this(m.name(),m.value(),m.path(),new RequestMethod[]{RequestMethod.POST},m.params(),m.headers(),m.consumes()); + } + + public RequestMappingWarp(PutMapping m){ + this(m.name(),m.value(),m.path(),new RequestMethod[]{RequestMethod.PUT},m.params(),m.headers(),m.consumes()); + + } + + public RequestMappingWarp(DeleteMapping m){ + this(m.name(),m.value(),m.path(),new RequestMethod[]{RequestMethod.DELETE},m.params(),m.headers(),m.consumes()); + } + + public void setName(String name) { + this.name = name; + } + + public void setValue(String[] value) { + this.value = value; + } + + public void setPath(String[] path) { + this.path = path; + } + + public void setMethod(RequestMethod[] method) { + this.method = method; + } + + public void setParams(String[] params) { + this.params = params; + } + + public void setHeaders(String[] headers) { + this.headers = headers; + } + + public void setConsumes(String[] consumes) { + this.consumes = consumes; + } + + public String getName() { + return name; + } + + public String[] getValue() { + return value; + } + + public String[] getPath() { + return path; + } + + public RequestMethod[] getMethod() { + return method; + } + + public String[] getParams() { + return params; + } + + public String[] getHeaders() { + return headers; + } + + public String[] getConsumes() { + return consumes; + } + + @Override + public String toString() { + return "RequestMappingWarp{" + + "name='" + name + '\'' + + ", value=" + Arrays.toString(value) + + ", path=" + Arrays.toString(path) + + ", method=" + Arrays.toString(method) + + ", params=" + Arrays.toString(params) + + ", headers=" + Arrays.toString(headers) + + ", consumes=" + Arrays.toString(consumes) + + '}'; + } +} diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java b/src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java index 5054830..ecabe63 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java +++ b/src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java @@ -24,5 +24,6 @@ public class ApiDefinition implements Serializable { private List responseParams; private ApiModelDefinition resultModel; + private Class resultClass; } diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java b/src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java index 138ada0..45e762f 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java +++ b/src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java @@ -19,4 +19,5 @@ public class ApiParamDefinition implements Serializable { private String defaultValue; private ApiModelDefinition model; + private Class clazz; } diff --git a/src/main/java/io/github/llchen/apidoc/utils/Utils.java b/src/main/java/io/github/llchen/apidoc/utils/Utils.java new file mode 100644 index 0000000..ce11d54 --- /dev/null +++ b/src/main/java/io/github/llchen/apidoc/utils/Utils.java @@ -0,0 +1,25 @@ +package io.github.llchen.apidoc.utils; + +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class Utils { + + + public static String requestMethod2Str(RequestMethod ... methods){ + StringBuilder sb=new StringBuilder("["); + if (methods!=null&&methods.length>0) { + for (RequestMethod method : methods) { + sb.append(method.name()).append(","); + } + sb.deleteCharAt(sb.length()-1); + }else { + sb.append("GET,POST,PUT,DELETE"); + } + sb.append("]"); + return sb.toString(); + } +} From fba6051a071336229fd636b67a1de37076da435e Mon Sep 17 00:00:00 2001 From: llchen12 Date: Wed, 27 Jun 2018 14:04:37 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E9=87=8D=E6=9E=84=EF=BC=8C=E5=8A=A0?= =?UTF-8?q?=E5=85=A5comment=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- pom.xml | 25 +- .../github/llchen/apidoc/DataType.java | 2 +- .../github/llchen/apidoc/annotation/Api.java | 3 +- .../llchen/apidoc/annotation/ApiCode.java | 2 +- .../llchen/apidoc/annotation/ApiDoc.java | 2 +- .../llchen/apidoc/annotation/ApiModel.java | 4 +- .../apidoc/annotation/ApiModelProperty.java | 4 +- .../llchen/apidoc/annotation/ApiParam.java | 4 +- .../config/ApiDocAutoConfiguration.java | 6 +- .../apidoc/config/ApiDocProperties.java | 2 +- .../apidoc/controller/ApiDocController.java | 14 +- .../apidoc/core/AbstractClassParser.java | 10 +- .../llchen/apidoc/core/AbstractParser.java | 36 +++ .../llchen/apidoc/core/AnnotationFilter.java | 2 +- .../llchen/apidoc/core/ApiDocBuilder.java | 12 +- .../llchen/apidoc/core/ApiDocClassParser.java | 19 +- .../llchen/apidoc/core/ApiDocContext.java | 14 +- .../github/llchen/apidoc/core/ApiMerger.java | 115 +++++++ .../llchen/apidoc/core/ApiMethodParser.java | 14 +- .../llchen/apidoc/core/ClassFilter.java | 2 +- .../llchen/apidoc/core/ClassFinder.java | 2 +- .../apidoc/core/ClassPathClassFinder.java | 8 +- .../apidoc/core/DocCommentMethodParser.java | 67 ++++ .../github/llchen/apidoc/core/Merger.java | 2 +- .../llchen/apidoc/core/MethodFilter.java | 2 +- .../llchen/apidoc/core/ModelClassBuilder.java | 4 +- .../apidoc/core/ModelClassBuilderImpl.java | 12 +- .../llchen/apidoc/core/ModelClassParser.java | 17 ++ .../com/github/llchen/apidoc/core/Parser.java | 10 + .../apidoc/core/ReflectMethodParser.java | 16 +- .../core/RequestMappingMethodParser.java | 12 +- .../apidoc/core/RequestMappingWarp.java | 2 +- .../apidoc/model/ApiCodeDefinition.java | 2 +- .../llchen/apidoc/model/ApiDefinition.java | 2 +- .../apidoc/model/ApiModelDefinition.java | 2 +- .../model/ApiModelPropertyDefinition.java | 2 +- .../apidoc/model/ApiParamDefinition.java | 2 +- .../github/llchen/apidoc/model/Document.java | 4 +- .../llchen/apidoc/process/AnnotatedClass.java | 64 ++++ .../apidoc/process/AnnotatedMethod.java | 88 ++++++ .../github/llchen/apidoc/process/Comment.java | 75 +++++ .../llchen/apidoc/process/CommentParse.java | 242 +++++++++++++++ .../apidoc/process/DocCommentProcessor.java | 211 +++++++++++++ .../github/llchen/apidoc/utils/GenUtil.java | 2 +- .../llchen/apidoc/utils/MarkdownEntity.java | 2 +- .../llchen/apidoc/utils/MarkdownUtil.java | 2 +- .../github/llchen/apidoc/utils/Utils.java | 11 +- .../apidoc/core/ApiDocAnnotationBuilder.java | 62 ---- .../github/llchen/apidoc/core/ApiMerger.java | 54 ---- .../llchen/apidoc/core/ApiMethodBuilder.java | 15 - .../llchen/apidoc/core/ClassParser.java | 12 - .../apidoc/core/JavaDocMethodParser.java | 26 -- .../llchen/apidoc/core/MethodParser.java | 15 - .../llchen/apidoc/core/ModelClassParser.java | 18 -- src/main/resources/META-INF/doc-comment.json | 287 ++++++++++++++++++ .../javax.annotation.processing.Processor | 1 + src/main/resources/META-INF/spring.factories | 2 +- 58 files changed, 1347 insertions(+), 304 deletions(-) rename src/main/java/{io => com}/github/llchen/apidoc/DataType.java (96%) rename src/main/java/{io => com}/github/llchen/apidoc/annotation/Api.java (91%) rename src/main/java/{io => com}/github/llchen/apidoc/annotation/ApiCode.java (86%) rename src/main/java/{io => com}/github/llchen/apidoc/annotation/ApiDoc.java (91%) rename src/main/java/{io => com}/github/llchen/apidoc/annotation/ApiModel.java (79%) rename src/main/java/{io => com}/github/llchen/apidoc/annotation/ApiModelProperty.java (85%) rename src/main/java/{io => com}/github/llchen/apidoc/annotation/ApiParam.java (87%) rename src/main/java/{io => com}/github/llchen/apidoc/config/ApiDocAutoConfiguration.java (88%) rename src/main/java/{io => com}/github/llchen/apidoc/config/ApiDocProperties.java (96%) rename src/main/java/{io => com}/github/llchen/apidoc/controller/ApiDocController.java (86%) rename src/main/java/{io => com}/github/llchen/apidoc/core/AbstractClassParser.java (78%) create mode 100644 src/main/java/com/github/llchen/apidoc/core/AbstractParser.java rename src/main/java/{io => com}/github/llchen/apidoc/core/AnnotationFilter.java (92%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ApiDocBuilder.java (98%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ApiDocClassParser.java (73%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ApiDocContext.java (95%) create mode 100644 src/main/java/com/github/llchen/apidoc/core/ApiMerger.java rename src/main/java/{io => com}/github/llchen/apidoc/core/ApiMethodParser.java (87%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ClassFilter.java (86%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ClassFinder.java (84%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ClassPathClassFinder.java (91%) create mode 100644 src/main/java/com/github/llchen/apidoc/core/DocCommentMethodParser.java rename src/main/java/{io => com}/github/llchen/apidoc/core/Merger.java (73%) rename src/main/java/{io => com}/github/llchen/apidoc/core/MethodFilter.java (80%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ModelClassBuilder.java (60%) rename src/main/java/{io => com}/github/llchen/apidoc/core/ModelClassBuilderImpl.java (88%) create mode 100644 src/main/java/com/github/llchen/apidoc/core/ModelClassParser.java create mode 100644 src/main/java/com/github/llchen/apidoc/core/Parser.java rename src/main/java/{io => com}/github/llchen/apidoc/core/ReflectMethodParser.java (80%) rename src/main/java/{io => com}/github/llchen/apidoc/core/RequestMappingMethodParser.java (88%) rename src/main/java/{io => com}/github/llchen/apidoc/core/RequestMappingWarp.java (98%) rename src/main/java/{io => com}/github/llchen/apidoc/model/ApiCodeDefinition.java (87%) rename src/main/java/{io => com}/github/llchen/apidoc/model/ApiDefinition.java (93%) rename src/main/java/{io => com}/github/llchen/apidoc/model/ApiModelDefinition.java (89%) rename src/main/java/{io => com}/github/llchen/apidoc/model/ApiModelPropertyDefinition.java (89%) rename src/main/java/{io => com}/github/llchen/apidoc/model/ApiParamDefinition.java (91%) rename src/main/java/{io => com}/github/llchen/apidoc/model/Document.java (83%) create mode 100644 src/main/java/com/github/llchen/apidoc/process/AnnotatedClass.java create mode 100644 src/main/java/com/github/llchen/apidoc/process/AnnotatedMethod.java create mode 100644 src/main/java/com/github/llchen/apidoc/process/Comment.java create mode 100644 src/main/java/com/github/llchen/apidoc/process/CommentParse.java create mode 100644 src/main/java/com/github/llchen/apidoc/process/DocCommentProcessor.java rename src/main/java/{io => com}/github/llchen/apidoc/utils/GenUtil.java (97%) rename src/main/java/{io => com}/github/llchen/apidoc/utils/MarkdownEntity.java (98%) rename src/main/java/{io => com}/github/llchen/apidoc/utils/MarkdownUtil.java (99%) rename src/main/java/{io => com}/github/llchen/apidoc/utils/Utils.java (59%) delete mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiMerger.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/ClassParser.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/MethodParser.java delete mode 100644 src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java create mode 100644 src/main/resources/META-INF/doc-comment.json create mode 100644 src/main/resources/META-INF/services/javax.annotation.processing.Processor diff --git a/README.md b/README.md index 0fa7796..edb118d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ clone项目代码 ``` - io.github.llchen + com.github.llchen api-doc 0.1.0 diff --git a/pom.xml b/pom.xml index 146808a..9766917 100644 --- a/pom.xml +++ b/pom.xml @@ -3,9 +3,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - io.github.llchen + com.github.llchen api-doc - 0.1.0 + 0.2.0 jar api-doc @@ -26,6 +26,8 @@ 0.34.0 3.7 1.7 + 1.8 + 1.8 @@ -84,6 +86,25 @@ + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + + none + + + + + diff --git a/src/main/java/io/github/llchen/apidoc/DataType.java b/src/main/java/com/github/llchen/apidoc/DataType.java similarity index 96% rename from src/main/java/io/github/llchen/apidoc/DataType.java rename to src/main/java/com/github/llchen/apidoc/DataType.java index 9d406bd..51d578e 100644 --- a/src/main/java/io/github/llchen/apidoc/DataType.java +++ b/src/main/java/com/github/llchen/apidoc/DataType.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc; +package com.github.llchen.apidoc; /** * 数据类型 diff --git a/src/main/java/io/github/llchen/apidoc/annotation/Api.java b/src/main/java/com/github/llchen/apidoc/annotation/Api.java similarity index 91% rename from src/main/java/io/github/llchen/apidoc/annotation/Api.java rename to src/main/java/com/github/llchen/apidoc/annotation/Api.java index 647355a..810bdfd 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/Api.java +++ b/src/main/java/com/github/llchen/apidoc/annotation/Api.java @@ -1,6 +1,5 @@ -package io.github.llchen.apidoc.annotation; +package com.github.llchen.apidoc.annotation; -import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.RequestMethod; import java.lang.annotation.*; diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiCode.java b/src/main/java/com/github/llchen/apidoc/annotation/ApiCode.java similarity index 86% rename from src/main/java/io/github/llchen/apidoc/annotation/ApiCode.java rename to src/main/java/com/github/llchen/apidoc/annotation/ApiCode.java index 6bfc8c5..7a6dba2 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiCode.java +++ b/src/main/java/com/github/llchen/apidoc/annotation/ApiCode.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.annotation; +package com.github.llchen.apidoc.annotation; import java.lang.annotation.*; diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiDoc.java b/src/main/java/com/github/llchen/apidoc/annotation/ApiDoc.java similarity index 91% rename from src/main/java/io/github/llchen/apidoc/annotation/ApiDoc.java rename to src/main/java/com/github/llchen/apidoc/annotation/ApiDoc.java index 2b4ad8d..8567236 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiDoc.java +++ b/src/main/java/com/github/llchen/apidoc/annotation/ApiDoc.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.annotation; +package com.github.llchen.apidoc.annotation; import java.lang.annotation.*; diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java b/src/main/java/com/github/llchen/apidoc/annotation/ApiModel.java similarity index 79% rename from src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java rename to src/main/java/com/github/llchen/apidoc/annotation/ApiModel.java index a5173af..1cd4eff 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiModel.java +++ b/src/main/java/com/github/llchen/apidoc/annotation/ApiModel.java @@ -1,6 +1,4 @@ -package io.github.llchen.apidoc.annotation; - -import org.apache.commons.lang3.StringUtils; +package com.github.llchen.apidoc.annotation; import java.lang.annotation.*; diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java b/src/main/java/com/github/llchen/apidoc/annotation/ApiModelProperty.java similarity index 85% rename from src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java rename to src/main/java/com/github/llchen/apidoc/annotation/ApiModelProperty.java index 7c764e4..6cf503d 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiModelProperty.java +++ b/src/main/java/com/github/llchen/apidoc/annotation/ApiModelProperty.java @@ -1,8 +1,6 @@ -package io.github.llchen.apidoc.annotation; +package com.github.llchen.apidoc.annotation; -import io.github.llchen.apidoc.DataType; - import java.lang.annotation.*; /** diff --git a/src/main/java/io/github/llchen/apidoc/annotation/ApiParam.java b/src/main/java/com/github/llchen/apidoc/annotation/ApiParam.java similarity index 87% rename from src/main/java/io/github/llchen/apidoc/annotation/ApiParam.java rename to src/main/java/com/github/llchen/apidoc/annotation/ApiParam.java index 48d4424..0091e57 100644 --- a/src/main/java/io/github/llchen/apidoc/annotation/ApiParam.java +++ b/src/main/java/com/github/llchen/apidoc/annotation/ApiParam.java @@ -1,8 +1,8 @@ -package io.github.llchen.apidoc.annotation; +package com.github.llchen.apidoc.annotation; -import io.github.llchen.apidoc.DataType; +import com.github.llchen.apidoc.DataType; import java.lang.annotation.*; diff --git a/src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java b/src/main/java/com/github/llchen/apidoc/config/ApiDocAutoConfiguration.java similarity index 88% rename from src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java rename to src/main/java/com/github/llchen/apidoc/config/ApiDocAutoConfiguration.java index 79feb47..956df6d 100644 --- a/src/main/java/io/github/llchen/apidoc/config/ApiDocAutoConfiguration.java +++ b/src/main/java/com/github/llchen/apidoc/config/ApiDocAutoConfiguration.java @@ -1,7 +1,7 @@ -package io.github.llchen.apidoc.config; +package com.github.llchen.apidoc.config; -import io.github.llchen.apidoc.core.ApiDocContext; +import com.github.llchen.apidoc.core.ApiDocContext; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -14,7 +14,7 @@ * @date 2018/6/11 */ @Configuration -@ComponentScan(basePackages = "io.github.llchen.apidoc.controller") +@ComponentScan(basePackages = "com.github.llchen.apidoc.controller") @EnableConfigurationProperties(ApiDocProperties.class) public class ApiDocAutoConfiguration { diff --git a/src/main/java/io/github/llchen/apidoc/config/ApiDocProperties.java b/src/main/java/com/github/llchen/apidoc/config/ApiDocProperties.java similarity index 96% rename from src/main/java/io/github/llchen/apidoc/config/ApiDocProperties.java rename to src/main/java/com/github/llchen/apidoc/config/ApiDocProperties.java index c5f87c1..f0579be 100644 --- a/src/main/java/io/github/llchen/apidoc/config/ApiDocProperties.java +++ b/src/main/java/com/github/llchen/apidoc/config/ApiDocProperties.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.config; +package com.github.llchen.apidoc.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java b/src/main/java/com/github/llchen/apidoc/controller/ApiDocController.java similarity index 86% rename from src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java rename to src/main/java/com/github/llchen/apidoc/controller/ApiDocController.java index 137b434..ce41a45 100644 --- a/src/main/java/io/github/llchen/apidoc/controller/ApiDocController.java +++ b/src/main/java/com/github/llchen/apidoc/controller/ApiDocController.java @@ -1,12 +1,12 @@ -package io.github.llchen.apidoc.controller; +package com.github.llchen.apidoc.controller; -import io.github.llchen.apidoc.core.ApiDocContext; -import io.github.llchen.apidoc.model.ApiModelDefinition; -import io.github.llchen.apidoc.model.Document; -import io.github.llchen.apidoc.utils.GenUtil; -import io.github.llchen.apidoc.utils.MarkdownEntity; -import io.github.llchen.apidoc.utils.MarkdownUtil; +import com.github.llchen.apidoc.core.ApiDocContext; +import com.github.llchen.apidoc.model.ApiModelDefinition; +import com.github.llchen.apidoc.model.Document; +import com.github.llchen.apidoc.utils.GenUtil; +import com.github.llchen.apidoc.utils.MarkdownEntity; +import com.github.llchen.apidoc.utils.MarkdownUtil; import org.springframework.stereotype.Controller; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.GetMapping; diff --git a/src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java b/src/main/java/com/github/llchen/apidoc/core/AbstractClassParser.java similarity index 78% rename from src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java rename to src/main/java/com/github/llchen/apidoc/core/AbstractClassParser.java index 2706199..bcd2476 100644 --- a/src/main/java/io/github/llchen/apidoc/core/AbstractClassParser.java +++ b/src/main/java/com/github/llchen/apidoc/core/AbstractClassParser.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import java.lang.annotation.Annotation; @@ -6,7 +6,7 @@ * @author chenliangliang * @date 2018/6/17 */ -public abstract class AbstractClassParser implements ClassParser { +public abstract class AbstractClassParser extends AbstractParser> { private Class annotationClass; @@ -15,6 +15,12 @@ protected AbstractClassParser(Class annotationClass){ this.annotationClass=annotationClass; } + + @Override + protected int order() { + return 0; + } + @Override public R parse(Class clazz) { A annotation = clazz.getAnnotation(annotationClass); diff --git a/src/main/java/com/github/llchen/apidoc/core/AbstractParser.java b/src/main/java/com/github/llchen/apidoc/core/AbstractParser.java new file mode 100644 index 0000000..d19b782 --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/core/AbstractParser.java @@ -0,0 +1,36 @@ +package com.github.llchen.apidoc.core; + +import com.github.llchen.apidoc.process.CommentParse; + +import java.net.URL; + +/** + * @author llchen12 + * @date 2018/6/27 + */ +public abstract class AbstractParser implements Parser { + + + private static volatile CommentParse commentParse; + private static final Object LOCK = new Object(); + private static final String DOC_COMMENT_LOCATION = "/META-INF/doc-comment.json"; + + + abstract int order(); + + protected CommentParse getCommentParse() { + if (commentParse == null) { + synchronized (LOCK) { + if (commentParse == null) { + URL resource = this.getClass().getResource(DOC_COMMENT_LOCATION); + if (resource == null) { + throw new RuntimeException(DOC_COMMENT_LOCATION + " 不存在"); + } + commentParse = CommentParse.load(resource.getPath()); + } + } + } + return commentParse; + } + +} diff --git a/src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java b/src/main/java/com/github/llchen/apidoc/core/AnnotationFilter.java similarity index 92% rename from src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java rename to src/main/java/com/github/llchen/apidoc/core/AnnotationFilter.java index b86497e..c1d9fd9 100644 --- a/src/main/java/io/github/llchen/apidoc/core/AnnotationFilter.java +++ b/src/main/java/com/github/llchen/apidoc/core/AnnotationFilter.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import java.lang.annotation.Annotation; diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java b/src/main/java/com/github/llchen/apidoc/core/ApiDocBuilder.java similarity index 98% rename from src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java rename to src/main/java/com/github/llchen/apidoc/core/ApiDocBuilder.java index 9586971..8c5c584 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocBuilder.java +++ b/src/main/java/com/github/llchen/apidoc/core/ApiDocBuilder.java @@ -1,10 +1,10 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import com.alibaba.fastjson.JSON; -import io.github.llchen.apidoc.DataType; -import io.github.llchen.apidoc.annotation.*; -import io.github.llchen.apidoc.config.ApiDocProperties; -import io.github.llchen.apidoc.model.*; +import com.github.llchen.apidoc.DataType; +import com.github.llchen.apidoc.annotation.*; +import com.github.llchen.apidoc.config.ApiDocProperties; +import com.github.llchen.apidoc.model.*; import org.apache.commons.lang3.StringUtils; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; @@ -166,7 +166,7 @@ private String getApiUrl(Api api, Method method, String basePath) { private String getApiHttpMethod(Api api, Method method) { - String[] httpMethods = api.httpMethod(); + RequestMethod[] httpMethods = api.httpMethod(); if (httpMethods.length > 0) { return Arrays.toString(httpMethods); } diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java b/src/main/java/com/github/llchen/apidoc/core/ApiDocClassParser.java similarity index 73% rename from src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java rename to src/main/java/com/github/llchen/apidoc/core/ApiDocClassParser.java index 4e63727..490f387 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocClassParser.java +++ b/src/main/java/com/github/llchen/apidoc/core/ApiDocClassParser.java @@ -1,9 +1,10 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; -import io.github.llchen.apidoc.annotation.ApiCode; -import io.github.llchen.apidoc.annotation.ApiDoc; -import io.github.llchen.apidoc.model.ApiCodeDefinition; -import io.github.llchen.apidoc.model.Document; +import com.github.llchen.apidoc.annotation.ApiCode; +import com.github.llchen.apidoc.annotation.ApiDoc; +import com.github.llchen.apidoc.model.ApiCodeDefinition; +import com.github.llchen.apidoc.model.Document; +import com.github.llchen.apidoc.process.CommentParse; import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,8 +19,10 @@ public class ApiDocClassParser extends AbstractClassParser { - public ApiDocClassParser() { + private CommentParse commentParse; + public ApiDocClassParser(CommentParse commentParse) { super(ApiDoc.class); + this.commentParse=commentParse; } @@ -28,9 +31,9 @@ protected Document parse2Obj(Class clazz, ApiDoc annotation) { Document document = new Document(); List codeList = new LinkedList<>(); if (annotation == null) { - //TODO:取注释,取className + String classComment = commentParse.getClassComment(clazz); document.setName(clazz.getSimpleName()); - document.setDescription(""); + document.setDescription(classComment); } else { //构建ApiCode diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java b/src/main/java/com/github/llchen/apidoc/core/ApiDocContext.java similarity index 95% rename from src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java rename to src/main/java/com/github/llchen/apidoc/core/ApiDocContext.java index 2d9de46..084e564 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocContext.java +++ b/src/main/java/com/github/llchen/apidoc/core/ApiDocContext.java @@ -1,12 +1,11 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; -import io.github.llchen.apidoc.annotation.Api; -import io.github.llchen.apidoc.annotation.ApiDoc; -import io.github.llchen.apidoc.annotation.ApiModel; -import io.github.llchen.apidoc.config.ApiDocProperties; -import io.github.llchen.apidoc.model.ApiModelDefinition; -import io.github.llchen.apidoc.model.Document; +import com.github.llchen.apidoc.annotation.ApiDoc; +import com.github.llchen.apidoc.annotation.ApiModel; +import com.github.llchen.apidoc.config.ApiDocProperties; +import com.github.llchen.apidoc.model.ApiModelDefinition; +import com.github.llchen.apidoc.model.Document; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.slf4j.Logger; @@ -19,7 +18,6 @@ import org.springframework.util.Assert; import org.springframework.web.bind.annotation.RestController; -import java.io.File; import java.util.HashMap; import java.util.List; import java.util.concurrent.*; diff --git a/src/main/java/com/github/llchen/apidoc/core/ApiMerger.java b/src/main/java/com/github/llchen/apidoc/core/ApiMerger.java new file mode 100644 index 0000000..eb386bb --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/core/ApiMerger.java @@ -0,0 +1,115 @@ +package com.github.llchen.apidoc.core; + +import com.github.llchen.apidoc.model.ApiDefinition; +import com.github.llchen.apidoc.model.ApiModelDefinition; +import com.github.llchen.apidoc.model.ApiParamDefinition; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collections; +import java.util.List; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ApiMerger implements Merger { + + + @Override + public ApiDefinition merge(ApiDefinition... obj) { + ApiDefinition apiDefinition = new ApiDefinition(); + String name = ""; + for (ApiDefinition api : obj) { + if (StringUtils.isNotBlank(api.getName())) { + name = api.getName(); + break; + } + } + apiDefinition.setName(name); + + String description = ""; + for (ApiDefinition api : obj) { + if (StringUtils.isNotBlank(api.getDescription())) { + description =api.getDescription(); + break; + } + } + apiDefinition.setDescription(description); + + String remark = ""; + for (ApiDefinition api : obj) { + if (StringUtils.isNotBlank(api.getRemark())) { + remark = api.getRemark(); + break; + } + } + apiDefinition.setRemark(remark); + + String path = ""; + for (ApiDefinition api : obj) { + if (StringUtils.isNotBlank(api.getPath())) { + path = api.getPath(); + break; + } + } + apiDefinition.setPath(path); + + String httpMethod = ""; + for (ApiDefinition api : obj) { + if (StringUtils.isNotBlank(api.getHttpMethod())) { + httpMethod = api.getHttpMethod(); + break; + } + } + apiDefinition.setHttpMethod(httpMethod); + + String demoResponse = ""; + for (ApiDefinition api : obj) { + if (StringUtils.isNotBlank(api.getDemoResponse())) { + demoResponse = api.getDemoResponse(); + break; + } + } + apiDefinition.setDemoResponse(demoResponse); + + + List requestParams=Collections.emptyList(); + for (ApiDefinition api : obj) { + requestParams = api.getRequestParams(); + if (requestParams != null && !requestParams.isEmpty()) { + break; + } + } + apiDefinition.setRequestParams(requestParams); + + List responseParams=Collections.emptyList(); + for (ApiDefinition api : obj) { + responseParams = api.getResponseParams(); + if (responseParams != null && !responseParams.isEmpty()) { + break; + } + } + apiDefinition.setResponseParams(responseParams); + + Class resultClass=null; + for (ApiDefinition api:obj){ + resultClass=api.getResultClass(); + if (resultClass!=null){ + break; + } + } + apiDefinition.setResultClass(resultClass); + + ApiModelDefinition resultModel=null; + for (ApiDefinition api:obj){ + if (api.getResultModel()!=null){ + resultModel=api.getResultModel(); + break; + } + } + apiDefinition.setResultModel(resultModel); + + return apiDefinition; + + } +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java b/src/main/java/com/github/llchen/apidoc/core/ApiMethodParser.java similarity index 87% rename from src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java rename to src/main/java/com/github/llchen/apidoc/core/ApiMethodParser.java index 4a4dd68..cdcf1ae 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ApiMethodParser.java +++ b/src/main/java/com/github/llchen/apidoc/core/ApiMethodParser.java @@ -1,11 +1,11 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import com.alibaba.fastjson.JSON; -import io.github.llchen.apidoc.annotation.Api; -import io.github.llchen.apidoc.annotation.ApiParam; -import io.github.llchen.apidoc.model.ApiDefinition; -import io.github.llchen.apidoc.model.ApiParamDefinition; -import io.github.llchen.apidoc.utils.Utils; +import com.github.llchen.apidoc.annotation.Api; +import com.github.llchen.apidoc.annotation.ApiParam; +import com.github.llchen.apidoc.model.ApiDefinition; +import com.github.llchen.apidoc.model.ApiParamDefinition; +import com.github.llchen.apidoc.utils.Utils; import java.lang.reflect.Method; import java.util.LinkedList; @@ -15,7 +15,7 @@ * @author chenliangliang * @date 2018/6/17 */ -public class ApiMethodParser implements MethodParser { +public class ApiMethodParser extends AbstractParser { @Override diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassFilter.java b/src/main/java/com/github/llchen/apidoc/core/ClassFilter.java similarity index 86% rename from src/main/java/io/github/llchen/apidoc/core/ClassFilter.java rename to src/main/java/com/github/llchen/apidoc/core/ClassFilter.java index a47ffae..b282772 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ClassFilter.java +++ b/src/main/java/com/github/llchen/apidoc/core/ClassFilter.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; /** * 类过滤器 diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassFinder.java b/src/main/java/com/github/llchen/apidoc/core/ClassFinder.java similarity index 84% rename from src/main/java/io/github/llchen/apidoc/core/ClassFinder.java rename to src/main/java/com/github/llchen/apidoc/core/ClassFinder.java index 1b7465e..0f1415b 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ClassFinder.java +++ b/src/main/java/com/github/llchen/apidoc/core/ClassFinder.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import java.util.List; diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java b/src/main/java/com/github/llchen/apidoc/core/ClassPathClassFinder.java similarity index 91% rename from src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java rename to src/main/java/com/github/llchen/apidoc/core/ClassPathClassFinder.java index 875e9f2..2abf4ac 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ClassPathClassFinder.java +++ b/src/main/java/com/github/llchen/apidoc/core/ClassPathClassFinder.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -64,8 +64,10 @@ private void findClass(File file, Set classNameSet) { } } else { File[] files = file.listFiles(); - for (File f : files) { - findClass(f, classNameSet); + if (files != null && files.length > 0) { + for (File f : files) { + findClass(f, classNameSet); + } } } } diff --git a/src/main/java/com/github/llchen/apidoc/core/DocCommentMethodParser.java b/src/main/java/com/github/llchen/apidoc/core/DocCommentMethodParser.java new file mode 100644 index 0000000..206bc8f --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/core/DocCommentMethodParser.java @@ -0,0 +1,67 @@ +package com.github.llchen.apidoc.core; + +import com.github.llchen.apidoc.model.ApiDefinition; +import com.github.llchen.apidoc.model.ApiModelDefinition; +import com.github.llchen.apidoc.model.ApiParamDefinition; +import com.github.llchen.apidoc.process.Comment; +import com.github.llchen.apidoc.process.CommentParse; +import org.apache.commons.lang3.StringUtils; + +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class DocCommentMethodParser implements MethodParser { + + + private CommentParse commentParse; + + public DocCommentMethodParser(CommentParse commentParse) { + this.commentParse = commentParse; + } + + @Override + public int order() { + return 3; + } + + @Override + public ApiDefinition parse(Method method) { + ApiDefinition apiDefinition = new ApiDefinition(); + Comment methodComment = commentParse.getMethodComment(method); + apiDefinition.setDescription(methodComment.getComment()); + + Map params = methodComment.getParams(); + + List requestParams = buildRequestParams(params); + apiDefinition.setRequestParams(requestParams); + + String ret = methodComment.getRet(); + if (StringUtils.isNotEmpty(ret)){ + ApiModelDefinition modelDefinition=new ApiModelDefinition(); + modelDefinition.setRemark(ret); + apiDefinition.setResultModel(modelDefinition); + } + + return apiDefinition; + } + + private List buildRequestParams(Map params) { + List requestParams = new LinkedList<>(); + ApiParamDefinition paramDefinition; + for (Map.Entry entry : params.entrySet()) { + paramDefinition = new ApiParamDefinition(); + paramDefinition.setName(entry.getKey()); + paramDefinition.setDescription(entry.getValue()); + requestParams.add(paramDefinition); + } + return requestParams; + } + + +} diff --git a/src/main/java/io/github/llchen/apidoc/core/Merger.java b/src/main/java/com/github/llchen/apidoc/core/Merger.java similarity index 73% rename from src/main/java/io/github/llchen/apidoc/core/Merger.java rename to src/main/java/com/github/llchen/apidoc/core/Merger.java index 526140b..c943646 100644 --- a/src/main/java/io/github/llchen/apidoc/core/Merger.java +++ b/src/main/java/com/github/llchen/apidoc/core/Merger.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; /** * @author chenliangliang diff --git a/src/main/java/io/github/llchen/apidoc/core/MethodFilter.java b/src/main/java/com/github/llchen/apidoc/core/MethodFilter.java similarity index 80% rename from src/main/java/io/github/llchen/apidoc/core/MethodFilter.java rename to src/main/java/com/github/llchen/apidoc/core/MethodFilter.java index 00f2b2c..a80522d 100644 --- a/src/main/java/io/github/llchen/apidoc/core/MethodFilter.java +++ b/src/main/java/com/github/llchen/apidoc/core/MethodFilter.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import java.lang.reflect.Method; diff --git a/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java b/src/main/java/com/github/llchen/apidoc/core/ModelClassBuilder.java similarity index 60% rename from src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java rename to src/main/java/com/github/llchen/apidoc/core/ModelClassBuilder.java index ce45197..afb322b 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilder.java +++ b/src/main/java/com/github/llchen/apidoc/core/ModelClassBuilder.java @@ -1,6 +1,6 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; -import io.github.llchen.apidoc.model.ApiModelDefinition; +import com.github.llchen.apidoc.model.ApiModelDefinition; /** * @author chenliangliang diff --git a/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java b/src/main/java/com/github/llchen/apidoc/core/ModelClassBuilderImpl.java similarity index 88% rename from src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java rename to src/main/java/com/github/llchen/apidoc/core/ModelClassBuilderImpl.java index cfb42db..85f01ea 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ModelClassBuilderImpl.java +++ b/src/main/java/com/github/llchen/apidoc/core/ModelClassBuilderImpl.java @@ -1,10 +1,10 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; -import io.github.llchen.apidoc.DataType; -import io.github.llchen.apidoc.annotation.ApiModel; -import io.github.llchen.apidoc.annotation.ApiModelProperty; -import io.github.llchen.apidoc.model.ApiModelDefinition; -import io.github.llchen.apidoc.model.ApiModelPropertyDefinition; +import com.github.llchen.apidoc.DataType; +import com.github.llchen.apidoc.annotation.ApiModel; +import com.github.llchen.apidoc.annotation.ApiModelProperty; +import com.github.llchen.apidoc.model.ApiModelDefinition; +import com.github.llchen.apidoc.model.ApiModelPropertyDefinition; import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field; diff --git a/src/main/java/com/github/llchen/apidoc/core/ModelClassParser.java b/src/main/java/com/github/llchen/apidoc/core/ModelClassParser.java new file mode 100644 index 0000000..7293db9 --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/core/ModelClassParser.java @@ -0,0 +1,17 @@ +package com.github.llchen.apidoc.core; + +import com.github.llchen.apidoc.model.ApiModelDefinition; + +/** + * @author chenliangliang + * @date 2018/6/17 + */ +public class ModelClassParser implements ClassParser { + + + + @Override + public ApiModelDefinition parse(Class clazz) { + return null; + } +} diff --git a/src/main/java/com/github/llchen/apidoc/core/Parser.java b/src/main/java/com/github/llchen/apidoc/core/Parser.java new file mode 100644 index 0000000..d71ead4 --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/core/Parser.java @@ -0,0 +1,10 @@ +package com.github.llchen.apidoc.core; + +/** + * @author llchen12 + * @date 2018/6/27 + */ +public interface Parser { + + R parse(T t); +} diff --git a/src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java b/src/main/java/com/github/llchen/apidoc/core/ReflectMethodParser.java similarity index 80% rename from src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java rename to src/main/java/com/github/llchen/apidoc/core/ReflectMethodParser.java index 74d68d8..f4b7820 100644 --- a/src/main/java/io/github/llchen/apidoc/core/ReflectMethodParser.java +++ b/src/main/java/com/github/llchen/apidoc/core/ReflectMethodParser.java @@ -1,10 +1,9 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; -import io.github.llchen.apidoc.DataType; -import io.github.llchen.apidoc.model.ApiDefinition; -import io.github.llchen.apidoc.model.ApiParamDefinition; -import org.springframework.core.DefaultParameterNameDiscoverer; -import org.springframework.core.ParameterNameDiscoverer; +import com.github.llchen.apidoc.DataType; +import com.github.llchen.apidoc.model.ApiDefinition; +import com.github.llchen.apidoc.model.ApiParamDefinition; +import com.github.llchen.apidoc.utils.Utils; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -16,9 +15,8 @@ * @author chenliangliang * @date 2018/6/17 */ -public class ReflectMethodParser implements MethodParser { +public class ReflectMethodParser extends AbstractParser { - private static ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); @Override public int order() { @@ -41,7 +39,7 @@ public ApiDefinition parse(Method method) { private List buildRequestParams(Method method) { List apiParamList = new LinkedList<>(); ApiParamDefinition apiParamDefinition; - String[] parameterNames = discoverer.getParameterNames(method); + String[] parameterNames = Utils.getParameterNames(method); Parameter[] parameters = method.getParameters(); for (int i = 0, l = parameterNames.length; i < l; i++) { Parameter parameter = parameters[i]; diff --git a/src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java b/src/main/java/com/github/llchen/apidoc/core/RequestMappingMethodParser.java similarity index 88% rename from src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java rename to src/main/java/com/github/llchen/apidoc/core/RequestMappingMethodParser.java index 188d4ae..080d611 100644 --- a/src/main/java/io/github/llchen/apidoc/core/RequestMappingMethodParser.java +++ b/src/main/java/com/github/llchen/apidoc/core/RequestMappingMethodParser.java @@ -1,9 +1,9 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; -import io.github.llchen.apidoc.DataType; -import io.github.llchen.apidoc.model.ApiDefinition; -import io.github.llchen.apidoc.model.ApiParamDefinition; -import io.github.llchen.apidoc.utils.Utils; +import com.github.llchen.apidoc.DataType; +import com.github.llchen.apidoc.model.ApiDefinition; +import com.github.llchen.apidoc.model.ApiParamDefinition; +import com.github.llchen.apidoc.utils.Utils; import org.springframework.web.bind.annotation.*; import java.lang.reflect.Method; @@ -15,7 +15,7 @@ * @author chenliangliang * @date 2018/6/17 */ -public class RequestMappingMethodParser implements MethodParser { +public class RequestMappingMethodParser extends AbstractParser { @Override public int order() { diff --git a/src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java b/src/main/java/com/github/llchen/apidoc/core/RequestMappingWarp.java similarity index 98% rename from src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java rename to src/main/java/com/github/llchen/apidoc/core/RequestMappingWarp.java index dba3321..8eb1001 100644 --- a/src/main/java/io/github/llchen/apidoc/core/RequestMappingWarp.java +++ b/src/main/java/com/github/llchen/apidoc/core/RequestMappingWarp.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.core; +package com.github.llchen.apidoc.core; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiCodeDefinition.java b/src/main/java/com/github/llchen/apidoc/model/ApiCodeDefinition.java similarity index 87% rename from src/main/java/io/github/llchen/apidoc/model/ApiCodeDefinition.java rename to src/main/java/com/github/llchen/apidoc/model/ApiCodeDefinition.java index 2e65525..59dc316 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiCodeDefinition.java +++ b/src/main/java/com/github/llchen/apidoc/model/ApiCodeDefinition.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.model; +package com.github.llchen.apidoc.model; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java b/src/main/java/com/github/llchen/apidoc/model/ApiDefinition.java similarity index 93% rename from src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java rename to src/main/java/com/github/llchen/apidoc/model/ApiDefinition.java index ecabe63..e5a5221 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiDefinition.java +++ b/src/main/java/com/github/llchen/apidoc/model/ApiDefinition.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.model; +package com.github.llchen.apidoc.model; import lombok.Data; diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiModelDefinition.java b/src/main/java/com/github/llchen/apidoc/model/ApiModelDefinition.java similarity index 89% rename from src/main/java/io/github/llchen/apidoc/model/ApiModelDefinition.java rename to src/main/java/com/github/llchen/apidoc/model/ApiModelDefinition.java index b07087c..481b0b3 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiModelDefinition.java +++ b/src/main/java/com/github/llchen/apidoc/model/ApiModelDefinition.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.model; +package com.github.llchen.apidoc.model; import lombok.Data; diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiModelPropertyDefinition.java b/src/main/java/com/github/llchen/apidoc/model/ApiModelPropertyDefinition.java similarity index 89% rename from src/main/java/io/github/llchen/apidoc/model/ApiModelPropertyDefinition.java rename to src/main/java/com/github/llchen/apidoc/model/ApiModelPropertyDefinition.java index b2c52f6..524721f 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiModelPropertyDefinition.java +++ b/src/main/java/com/github/llchen/apidoc/model/ApiModelPropertyDefinition.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.model; +package com.github.llchen.apidoc.model; import lombok.Data; diff --git a/src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java b/src/main/java/com/github/llchen/apidoc/model/ApiParamDefinition.java similarity index 91% rename from src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java rename to src/main/java/com/github/llchen/apidoc/model/ApiParamDefinition.java index 45e762f..945d353 100644 --- a/src/main/java/io/github/llchen/apidoc/model/ApiParamDefinition.java +++ b/src/main/java/com/github/llchen/apidoc/model/ApiParamDefinition.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.model; +package com.github.llchen.apidoc.model; import lombok.Data; diff --git a/src/main/java/io/github/llchen/apidoc/model/Document.java b/src/main/java/com/github/llchen/apidoc/model/Document.java similarity index 83% rename from src/main/java/io/github/llchen/apidoc/model/Document.java rename to src/main/java/com/github/llchen/apidoc/model/Document.java index 5a33bf7..d1242ba 100644 --- a/src/main/java/io/github/llchen/apidoc/model/Document.java +++ b/src/main/java/com/github/llchen/apidoc/model/Document.java @@ -1,7 +1,7 @@ -package io.github.llchen.apidoc.model; +package com.github.llchen.apidoc.model; -import io.github.llchen.apidoc.config.ApiDocProperties; +import com.github.llchen.apidoc.config.ApiDocProperties; import lombok.Data; import java.io.Serializable; diff --git a/src/main/java/com/github/llchen/apidoc/process/AnnotatedClass.java b/src/main/java/com/github/llchen/apidoc/process/AnnotatedClass.java new file mode 100644 index 0000000..638e7e0 --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/process/AnnotatedClass.java @@ -0,0 +1,64 @@ +package com.github.llchen.apidoc.process; + +import javax.lang.model.element.TypeElement; +import java.util.LinkedList; +import java.util.List; + +/** + * @author llchen12 + * @date 2018/6/26 + */ +public class AnnotatedClass { + + private String className; + + private String doc; + + private List methods=new LinkedList<>(); + + public AnnotatedClass() { + } + + public AnnotatedClass(TypeElement typeElement, String doc){ + this.className=typeElement.getQualifiedName().toString(); + this.doc=doc; + } + + public AnnotatedClass(String className,String doc){ + this.className=className; + this.doc=doc; + } + + public void addMethod(AnnotatedMethod method){ + this.methods.add(method); + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getDoc() { + return doc; + } + + public void setDoc(String doc) { + this.doc = doc; + } + + public List getMethods() { + return methods; + } + + @Override + public String toString() { + return "AnnotatedClass{" + + "className='" + className + '\'' + + ", doc='" + doc + '\'' + + ", methods=" + methods + + '}'; + } +} diff --git a/src/main/java/com/github/llchen/apidoc/process/AnnotatedMethod.java b/src/main/java/com/github/llchen/apidoc/process/AnnotatedMethod.java new file mode 100644 index 0000000..2d1e02b --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/process/AnnotatedMethod.java @@ -0,0 +1,88 @@ +package com.github.llchen.apidoc.process; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import java.beans.Transient; +import java.util.List; + +/** + * @author llchen12 + * @date 2018/6/26 + */ +public class AnnotatedMethod { + + private String className; + private String methodName; + private String doc; + private ExecutableElement executableElement; + + public AnnotatedMethod(ExecutableElement executableElement, String doc) { + this.executableElement = executableElement; + this.methodName = generateMethodName(executableElement); + this.className = ((TypeElement) executableElement.getEnclosingElement()).getQualifiedName().toString(); + this.doc = doc; + } + + public AnnotatedMethod() { + } + + private String generateMethodName(ExecutableElement executableElement) { + StringBuilder res = new StringBuilder(); + res.append(executableElement.getSimpleName().toString()).append("("); + List parameters = executableElement.getParameters(); + for (VariableElement ele : parameters) { + res.append(ele).append(","); + } + if (res.charAt(res.length()-1)==','){ + res.deleteCharAt(res.length() - 1); + } + res.append(")"); + return res.toString(); + } + + @Transient + public String getClassName() { + return className; + } + + + + public void setClassName(String className) { + this.className = className; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getDoc() { + return doc; + } + + public void setDoc(String doc) { + this.doc = doc; + } + + @Transient + public ExecutableElement getExecutableElement() { + return executableElement; + } + + public void setExecutableElement(ExecutableElement executableElement) { + this.executableElement = executableElement; + } + + @Override + public String toString() { + return "AnnotatedMethod{" + + "className='" + className + '\'' + + ", methodName='" + methodName + '\'' + + ", doc='" + doc + '\'' + + '}'; + } +} diff --git a/src/main/java/com/github/llchen/apidoc/process/Comment.java b/src/main/java/com/github/llchen/apidoc/process/Comment.java new file mode 100644 index 0000000..794730b --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/process/Comment.java @@ -0,0 +1,75 @@ +package com.github.llchen.apidoc.process; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @author llchen12 + * @date 2018/6/26 + */ +public class Comment { + + private String comment = ""; + private Map params = new HashMap<>(); + private String ret; + private String demoResponse; + + + public Comment(String comment, String ret, String demoResponse) { + this.comment = comment; + this.ret = ret; + this.demoResponse = demoResponse; + } + + public Comment() { + + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public Map getParams() { + return Collections.unmodifiableMap(params); + } + + public void addParam(String paramName, String paramDesc) { + this.params.put(paramName, paramDesc); + } + + + public String getParam(String paramName) { + return this.params.get(paramName); + } + + public String getRet() { + return ret; + } + + public void setRet(String ret) { + this.ret = ret; + } + + public String getDemoResponse() { + return demoResponse; + } + + public void setDemoResponse(String demoResponse) { + this.demoResponse = demoResponse; + } + + @Override + public String toString() { + return "Comment{" + + "comment='" + comment + '\'' + + ", params=" + params + + ", ret='" + ret + '\'' + + ", demoResponse='" + demoResponse + '\'' + + '}'; + } +} diff --git a/src/main/java/com/github/llchen/apidoc/process/CommentParse.java b/src/main/java/com/github/llchen/apidoc/process/CommentParse.java new file mode 100644 index 0000000..8e1847e --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/process/CommentParse.java @@ -0,0 +1,242 @@ +package com.github.llchen.apidoc.process; + +import com.alibaba.fastjson.JSONObject; +import com.github.llchen.apidoc.utils.Utils; +import lombok.extern.slf4j.Slf4j; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author llchen12 + * @date 2018/6/26 + */ +@Slf4j +public class CommentParse { + + private static final int STATUS_COMMENT = 0; + private static final int STATUS_PARAM = 1; + private static final int STATUS_RETURN = 2; + private static final int STATUS_DEMORESPONSE = 3; + private static final int STATUS_OTHER=4; + + private static final String SPACE_STRING = " "; + private static final String NEWLINE_STRING = "\n"; + private static final String SEPARATE_STRING = "@"; + private static final String PARAM_STRING = "@param"; + private static final String RETURN_STRING = "@return"; + private static final String DEMORESPONSE_STRING = "@demoResponse"; + + + private Map docClassMap=new HashMap<>(64); + + + public CommentParse(String json) { + parseJson(json); + } + + + public static CommentParse load(String file){ + CommentParse commentParse=null; + try(FileInputStream fis=new FileInputStream(file); + InputStreamReader isr=new InputStreamReader(fis,"UTF-8"); + BufferedReader reader=new BufferedReader(isr)) { + + StringBuilder sb=new StringBuilder(); + String line; + while ((line=reader.readLine())!=null){ + sb.append(line); + } + commentParse=new CommentParse(sb.toString()); + }catch (IOException e){ + log.warn("加载文件{}异常:{}",file,e.getMessage()); + } + return commentParse; + } + + + + private void parseJson(String json) { + JSONObject jsonObj=JSONObject.parseObject(json); + for (String key:jsonObj.keySet()){ + try { + AnnotatedClass aClass = jsonObj.getObject(key, AnnotatedClass.class); + docClassMap.put(key,aClass); + }catch (Exception e){ + System.err.println("解析json异常:"+e.getMessage()); + } + } + } + + public AnnotatedClass getAnnotatedClass(String className) { + return this.docClassMap.get(className); + } + + public AnnotatedClass getAnnotatedClass(Class clazz) { + return getAnnotatedClass(clazz.getCanonicalName()); + } + + public String getClassComment(Class clazz){ + AnnotatedClass aClass = getAnnotatedClass(clazz); + if (aClass!=null){ + Comment comment = parseDoc(aClass.getDoc()); + return comment.getComment(); + } + return null; + } + + public AnnotatedMethod getAnnotatedMethod(String className, NamedMethod namedMethod) { + AnnotatedClass aClass = getAnnotatedClass(className); + if (aClass != null) { + List methods = aClass.getMethods(); + for (AnnotatedMethod method : methods) { + if (method.getMethodName().equals(namedMethod.getName())) { + return method; + } + } + } + return null; + } + + + public AnnotatedMethod getAnnotatedMethod(Class clazz, Method method) { + return getAnnotatedMethod(clazz.getCanonicalName(),new NamedMethod(method)); + } + + public AnnotatedMethod getAnnotatedMethod(Method method) { + return getAnnotatedMethod(method.getDeclaringClass(),method); + } + + + + public Comment getMethodComment(Method method) { + return parseDoc(getAnnotatedMethod(method).getDoc()); + } + + + public static Comment parseDoc(String doc) { + Comment comment = new Comment(); + if (doc == null || "".equals(doc.trim())) { + return comment; + } + String[] str = doc.split(NEWLINE_STRING); + int status = STATUS_COMMENT; + String temp = ""; + for (String line : str) { + line = line.trim(); + if ("".equals(line)) { + continue; + } + if (line.startsWith(SEPARATE_STRING)) { + int i = line.indexOf(SPACE_STRING); + String sp = line.substring(i + 1).trim(); + if (line.startsWith(PARAM_STRING)) { + status = STATUS_PARAM; + int dx = sp.indexOf(SPACE_STRING); + String param = sp.substring(0, dx); + String desc = sp.substring(dx + 1).trim(); + comment.addParam(param, desc); + temp = param; + } else if (line.startsWith(RETURN_STRING)) { + status = STATUS_RETURN; + comment.setRet(sp); + } else if (line.startsWith(DEMORESPONSE_STRING)) { + status = STATUS_DEMORESPONSE; + comment.setDemoResponse(sp); + }else { + status=STATUS_OTHER; + } + } else { + switch (status) { + case STATUS_COMMENT: + String cmt = comment.getComment() + SPACE_STRING + line; + comment.setComment(cmt.trim()); + break; + case STATUS_PARAM: + String desc = comment.getParam(temp) + SPACE_STRING + line; + comment.addParam(temp, desc.trim()); + break; + case STATUS_DEMORESPONSE: + String dr = comment.getDemoResponse() + SPACE_STRING + line; + comment.setDemoResponse(dr.trim()); + break; + case STATUS_RETURN: + String ret = comment.getRet() + SPACE_STRING + line; + comment.setRet(ret.trim()); + break; + default: + break; + } + } + } + return comment; + } + + + + static class NamedMethod{ + + Method method; + + + NamedMethod(Method method){ + this.method=method; + } + + String getName(){ + StringBuilder sb=new StringBuilder(); + sb.append(method.getName()).append("("); + String[] parameterNames = Utils.getParameterNames(method); + for (String paramName:parameterNames){ + sb.append(paramName).append(","); + } + int i = sb.length() - 1; + if (sb.charAt(i)==','){ + sb.deleteCharAt(i); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public String toString() { + return getName(); + } + } + + public static void main(String[] args) { + System.out.println(parseDoc(" 导航菜单\n @demoResponse {djjdjd}\n @return hdhdhd\n\n")); + + + } + + + public static String doc = "Returns the leading surrogate (a\n" + + " \n" + + " high surrogate code unit) of the\n" + + " \n" + + " surrogate pair\n" + + " representing the specified supplementary character (Unicode\n" + + " code point) in the UTF-16 encoding. If the specified character\n" + + " is not a\n" + + " supplementary character,\n" + + " an unspecified {@code char} is returned.\n" + + " \n" + + "

If\n" + + " {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)}\n" + + " is {@code true}, then\n" + + " {@link #isHighSurrogate isHighSurrogate}{@code (highSurrogate(x))} and\n" + + " {@link #toCodePoint toCodePoint}{@code (highSurrogate(x), }{@link #lowSurrogate lowSurrogate}{@code (x)) == x}\n" + + " are also always {@code true}.\n" + + " \n" + + " @param codePoint a supplementary character (Unicode code point)\n" + + " @return the leading surrogate code unit used to represent the\n" + + " character in the UTF-16 encoding\n" + + " @since 1.7"; +} diff --git a/src/main/java/com/github/llchen/apidoc/process/DocCommentProcessor.java b/src/main/java/com/github/llchen/apidoc/process/DocCommentProcessor.java new file mode 100644 index 0000000..0babb29 --- /dev/null +++ b/src/main/java/com/github/llchen/apidoc/process/DocCommentProcessor.java @@ -0,0 +1,211 @@ +package com.github.llchen.apidoc.process; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; + + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; +import javax.tools.Diagnostic; +import javax.tools.FileObject; +import javax.tools.StandardLocation; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author llchen12 + * @date 2018/6/26 + */ +@SupportedAnnotationTypes({"*"}) +public class DocCommentProcessor extends AbstractProcessor { + + + static final String METADATA_PATH = "META-INF/doc-comment.json"; + + static final String RESTCONTROLLER_ANNOTATION = "org.springframework.web.bind.annotation.RestController"; + + static final String CONTROLLER_ANNOTATION = "org.springframework.stereotype.Controller"; + + static final String REQUESTMAPPING_ANNOTATION = "org.springframework.web.bind.annotation.RequestMapping"; + + static final String GETMAPPING_ANNOTATION = "org.springframework.web.bind.annotation.GetMapping"; + + static final String POSTMAPPING_ANNOTATION = "org.springframework.web.bind.annotation.PostMapping"; + + static final String PUTMAPPING_ANNOTATION = "org.springframework.web.bind.annotation.PutMapping"; + + static final String DELETEMAPPING_ANNOTATION = "org.springframework.web.bind.annotation.DeleteMapping"; + + //private static final Map> ANNOTATION_CLASS_MAP = new HashMap<>(16); + + private Elements elementUtils; + private Messager messager; + private Filer filer; + + private Map docClassMap = new HashMap<>(64); + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + this.elementUtils = processingEnv.getElementUtils(); + this.messager = processingEnv.getMessager(); + this.filer = processingEnv.getFiler(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + + Set docClassSet = new HashSet<>(64); + TypeElement restControllerEle = elementUtils.getTypeElement(RESTCONTROLLER_ANNOTATION); + if (restControllerEle != null) { + docClassSet.addAll(roundEnv.getElementsAnnotatedWith(restControllerEle)); + } + TypeElement controllerEle = elementUtils.getTypeElement(CONTROLLER_ANNOTATION); + if (controllerEle != null) { + docClassSet.addAll(roundEnv.getElementsAnnotatedWith(controllerEle)); + } + + processDocClasses(docClassSet); + + Set docMethodSet = new HashSet<>(128); + TypeElement requestMappingEle = elementUtils.getTypeElement(REQUESTMAPPING_ANNOTATION); + if (requestMappingEle != null) { + docMethodSet.addAll(roundEnv.getElementsAnnotatedWith(requestMappingEle)); + } + TypeElement getMappingEle = elementUtils.getTypeElement(GETMAPPING_ANNOTATION); + if (requestMappingEle != null) { + docMethodSet.addAll(roundEnv.getElementsAnnotatedWith(getMappingEle)); + } + TypeElement postMappingEle = elementUtils.getTypeElement(POSTMAPPING_ANNOTATION); + if (requestMappingEle != null) { + docMethodSet.addAll(roundEnv.getElementsAnnotatedWith(postMappingEle)); + } + TypeElement putMappingEle = elementUtils.getTypeElement(PUTMAPPING_ANNOTATION); + if (requestMappingEle != null) { + docMethodSet.addAll(roundEnv.getElementsAnnotatedWith(putMappingEle)); + } + TypeElement deleteMappingEle = elementUtils.getTypeElement(DELETEMAPPING_ANNOTATION); + if (requestMappingEle != null) { + docMethodSet.addAll(roundEnv.getElementsAnnotatedWith(deleteMappingEle)); + } + + processDocMethods(docMethodSet); + + if (roundEnv.processingOver()) { + try { + writeData(); + } catch (IOException e) { + messager.printMessage(Diagnostic.Kind.WARNING, "Failed to write metadata " + e.getMessage()); + } + } + + return false; + } + + private void processDocMethods(Set docMethodSet) { + for (Element ele : docMethodSet) { + if (ele.getKind() != ElementKind.METHOD) { + continue; + } + AnnotatedMethod method = new AnnotatedMethod((ExecutableElement) ele, elementUtils.getDocComment(ele)); + String className = method.getClassName(); + AnnotatedClass aClass = docClassMap.get(className); + if (aClass == null) { + Element parent = ele.getEnclosingElement(); + aClass = new AnnotatedClass(className, elementUtils.getDocComment(parent)); + aClass.addMethod(method); + docClassMap.put(className, aClass); + } else { + aClass.addMethod(method); + } + } + } + + private void processDocClasses(Set docClassSet) { + for (Element ele : docClassSet) { + if (ele.getKind() != ElementKind.CLASS) { + continue; + } + String className = ((TypeElement) ele).getQualifiedName().toString(); + if (!docClassMap.containsKey(className)) { + AnnotatedClass annotatedClass = new AnnotatedClass(className, elementUtils.getDocComment(ele)); + docClassMap.put(className, annotatedClass); + } + } + } + + + private void writeData() throws IOException { + if (docClassMap.isEmpty()) { + return; + } + FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", METADATA_PATH); + try (OutputStream outputStream = resource.openOutputStream()) { + String json = JSON.toJSONString(docClassMap, SerializerFeature.PrettyFormat, + SerializerFeature.SkipTransientField); + outputStream.write(json.getBytes("UTF-8")); + } + } + +// private void processMethod(ExecutableElement ele) { +// if (hasAnyAnnotation(ele, REQUESTMAPPING_ANNOTATION, GETMAPPING_ANNOTATION, POSTMAPPING_ANNOTATION, +// DELETEMAPPING_ANNOTATION, PUTMAPPING_ANNOTATION)) { +// +// } +// } +// +// private void processClass(TypeElement ele) { +// //处理@Controller和@RestController注解 +// if (hasAnyAnnotation(ele, CONTROLLER_ANNOTATION, RESTCONTROLLER_ANNOTATION)) { +// +// } +// } + +// protected boolean hasAnnotation(Element e, String annotationClassName) { +// Class annotation = getAnnotationClass(annotationClassName); +// return annotation != null && e.getAnnotation(annotation) != null; +// } +// +// protected boolean hasAnyAnnotation(Element e, String... annotationClassNames) { +// if (annotationClassNames == null || annotationClassNames.length == 0) { +// return false; +// } +// +// for (String name : annotationClassNames) { +// if (hasAnnotation(e, name)) { +// return true; +// } +// } +// return false; +// } +// +// @SuppressWarnings("unchecked") +// protected Class getAnnotationClass(String annotationClassName) { +// Class aClass = ANNOTATION_CLASS_MAP.get(annotationClassName); +// if (aClass == null) { +// try { +// aClass = Class.forName(annotationClassName); +// ANNOTATION_CLASS_MAP.put(annotationClassName, aClass); +// } catch (ClassNotFoundException e) { +// messager.printMessage(Diagnostic.Kind.WARNING, annotationClassName + "不存在"); +// return null; +// } +// } +// return (Class) aClass; +// } + + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } +} diff --git a/src/main/java/io/github/llchen/apidoc/utils/GenUtil.java b/src/main/java/com/github/llchen/apidoc/utils/GenUtil.java similarity index 97% rename from src/main/java/io/github/llchen/apidoc/utils/GenUtil.java rename to src/main/java/com/github/llchen/apidoc/utils/GenUtil.java index a1befde..7f76d95 100644 --- a/src/main/java/io/github/llchen/apidoc/utils/GenUtil.java +++ b/src/main/java/com/github/llchen/apidoc/utils/GenUtil.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.utils; +package com.github.llchen.apidoc.utils; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; diff --git a/src/main/java/io/github/llchen/apidoc/utils/MarkdownEntity.java b/src/main/java/com/github/llchen/apidoc/utils/MarkdownEntity.java similarity index 98% rename from src/main/java/io/github/llchen/apidoc/utils/MarkdownEntity.java rename to src/main/java/com/github/llchen/apidoc/utils/MarkdownEntity.java index fbf0d68..8b768bb 100644 --- a/src/main/java/io/github/llchen/apidoc/utils/MarkdownEntity.java +++ b/src/main/java/com/github/llchen/apidoc/utils/MarkdownEntity.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.utils; +package com.github.llchen.apidoc.utils; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/io/github/llchen/apidoc/utils/MarkdownUtil.java b/src/main/java/com/github/llchen/apidoc/utils/MarkdownUtil.java similarity index 99% rename from src/main/java/io/github/llchen/apidoc/utils/MarkdownUtil.java rename to src/main/java/com/github/llchen/apidoc/utils/MarkdownUtil.java index ec406a0..2f2627a 100644 --- a/src/main/java/io/github/llchen/apidoc/utils/MarkdownUtil.java +++ b/src/main/java/com/github/llchen/apidoc/utils/MarkdownUtil.java @@ -1,4 +1,4 @@ -package io.github.llchen.apidoc.utils; +package com.github.llchen.apidoc.utils; import com.vladsch.flexmark.ast.Node; import com.vladsch.flexmark.ext.tables.TablesExtension; diff --git a/src/main/java/io/github/llchen/apidoc/utils/Utils.java b/src/main/java/com/github/llchen/apidoc/utils/Utils.java similarity index 59% rename from src/main/java/io/github/llchen/apidoc/utils/Utils.java rename to src/main/java/com/github/llchen/apidoc/utils/Utils.java index ce11d54..f46abf8 100644 --- a/src/main/java/io/github/llchen/apidoc/utils/Utils.java +++ b/src/main/java/com/github/llchen/apidoc/utils/Utils.java @@ -1,13 +1,18 @@ -package io.github.llchen.apidoc.utils; +package com.github.llchen.apidoc.utils; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; import org.springframework.web.bind.annotation.RequestMethod; +import java.lang.reflect.Method; + /** * @author chenliangliang * @date 2018/6/17 */ public class Utils { + private static ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); public static String requestMethod2Str(RequestMethod ... methods){ StringBuilder sb=new StringBuilder("["); @@ -22,4 +27,8 @@ public static String requestMethod2Str(RequestMethod ... methods){ sb.append("]"); return sb.toString(); } + + public static String[] getParameterNames(Method method){ + return discoverer.getParameterNames(method); + } } diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java deleted file mode 100644 index a590473..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/ApiDocAnnotationBuilder.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.github.llchen.apidoc.core; - -import io.github.llchen.apidoc.annotation.ApiCode; -import io.github.llchen.apidoc.annotation.ApiDoc; -import io.github.llchen.apidoc.model.ApiCodeDefinition; -import io.github.llchen.apidoc.model.Document; -import org.apache.commons.lang3.StringUtils; -import org.springframework.web.bind.annotation.RequestMapping; - -import java.util.LinkedList; -import java.util.List; - - -/** - * @author chenliangliang - * @date 2018/6/16 - */ -public class ApiDocAnnotationBuilder implements ApiClassBuilder { - - - @Override - public Document build(Class apiClass, Class annotationClass) { - ApiDoc apiDoc = apiClass.getAnnotation(annotationClass); - Document document=new Document(); - String name = apiDoc.name(); - if (StringUtils.isEmpty(name)){ - name=apiClass.getSimpleName(); - } - document.setName(name); - document.setBasePath(getApiBasePath(apiDoc,apiClass)); - String description = apiDoc.description(); - if (StringUtils.isEmpty(description)){ - //TODO:取注释 - } - document.setDescription(description); - - //构建ApiCode - ApiCode[] apiCodes = apiDoc.codes(); - List codeList = new LinkedList<>(); - for (ApiCode code : apiCodes) { - codeList.add(new ApiCodeDefinition(code.code(), code.description())); - } - document.setCodeList(codeList); - return document; - } - - - private String getApiBasePath(ApiDoc apiDoc, Class apiDocClass) { - String basePath = apiDoc.basePath(); - if (StringUtils.isNotEmpty(basePath)) { - return basePath.startsWith("/") ? basePath : "/" + basePath; - } - - RequestMapping rm = apiDocClass.getAnnotation(RequestMapping.class); - if (rm != null) { - String[] value = rm.value(); - return value[0]; - } - - return ""; - } -} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiMerger.java b/src/main/java/io/github/llchen/apidoc/core/ApiMerger.java deleted file mode 100644 index d6d770c..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/ApiMerger.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.llchen.apidoc.core; - -import io.github.llchen.apidoc.model.ApiDefinition; -import org.apache.commons.lang3.StringUtils; - -/** - * @author chenliangliang - * @date 2018/6/17 - */ -public class ApiMerger implements Merger { - - - @Override - public ApiDefinition merge(ApiDefinition... obj) { - ApiDefinition apiDefinition=new ApiDefinition(); - String name=""; - for (ApiDefinition api:obj){ - name=api.getName(); - if (StringUtils.isNotBlank(name)){ - break; - } - } - apiDefinition.setName(name); - - String description=""; - for (ApiDefinition api:obj){ - description=api.getDescription(); - if (StringUtils.isNotBlank(description)){ - break; - } - } - apiDefinition.setDescription(description); - - String remark=""; - for (ApiDefinition api:obj){ - remark=api.getRemark(); - if (StringUtils.isNotBlank(remark)){ - break; - } - } - apiDefinition.setRemark(remark); - - String path=""; - for (ApiDefinition api:obj){ - path=api.getPath(); - if (StringUtils.isNotBlank(path)){ - break; - } - } - apiDefinition.setPath(path); - - return apiDefinition; - } -} diff --git a/src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java b/src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java deleted file mode 100644 index a7a9c13..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/ApiMethodBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.llchen.apidoc.core; - -import io.github.llchen.apidoc.model.ApiDefinition; -import io.github.llchen.apidoc.model.Document; - -import java.lang.reflect.Method; - -/** - * @author chenliangliang - * @date 2018/6/16 - */ -public interface ApiMethodBuilder { - - ApiDefinition build(Document document, Method method); -} diff --git a/src/main/java/io/github/llchen/apidoc/core/ClassParser.java b/src/main/java/io/github/llchen/apidoc/core/ClassParser.java deleted file mode 100644 index 9432460..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/ClassParser.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.llchen.apidoc.core; - - - -/** - * @author chenliangliang - * @date 2018/6/17 - */ -public interface ClassParser{ - - R parse(Class clazz); -} diff --git a/src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java b/src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java deleted file mode 100644 index 2359d7e..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/JavaDocMethodParser.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.llchen.apidoc.core; - -import io.github.llchen.apidoc.model.ApiDefinition; - -import java.lang.reflect.Method; - -/** - * @author chenliangliang - * @date 2018/6/17 - */ -public class JavaDocMethodParser implements MethodParser { - - - - @Override - public int order() { - return 3; - } - - @Override - public ApiDefinition parse(Method method) { - ApiDefinition apiDefinition=new ApiDefinition(); - - return apiDefinition; - } -} diff --git a/src/main/java/io/github/llchen/apidoc/core/MethodParser.java b/src/main/java/io/github/llchen/apidoc/core/MethodParser.java deleted file mode 100644 index 4b2f58e..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/MethodParser.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.llchen.apidoc.core; - - -import java.lang.reflect.Method; - -/** - * @author chenliangliang - * @date 2018/6/17 - */ -public interface MethodParser { - - int order(); - - R parse(Method method); -} diff --git a/src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java b/src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java deleted file mode 100644 index 66edf0d..0000000 --- a/src/main/java/io/github/llchen/apidoc/core/ModelClassParser.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.llchen.apidoc.core; - -import io.github.llchen.apidoc.annotation.ApiModel; -import io.github.llchen.apidoc.model.ApiModelDefinition; - -/** - * @author chenliangliang - * @date 2018/6/17 - */ -public class ModelClassParser implements ClassParser { - - - @Override - public ApiModelDefinition parse(Class clazz, Class annotationClass) { - - return null; - } -} diff --git a/src/main/resources/META-INF/doc-comment.json b/src/main/resources/META-INF/doc-comment.json new file mode 100644 index 0000000..88df7ac --- /dev/null +++ b/src/main/resources/META-INF/doc-comment.json @@ -0,0 +1,287 @@ +{ + "com.hfutonline.mly.modules.news.controller.ArticleTagController":{ + "className":"com.hfutonline.mly.modules.news.controller.ArticleTagController", + "doc":" \n\n @author chenliangliang\n @date 2018-02-21 15:42:00\n", + "methods":[] + }, + "com.hfutonline.mly.modules.news.controller.CatalogController":{ + "className":"com.hfutonline.mly.modules.news.controller.CatalogController", + "doc":" 栏目\n\n @author chenliangliang\n @date 2018-02-21 15:42:00\n", + "methods":[{ + "doc":" 信息\n", + "methodName":"info(id)" + },{ + "doc":" 保存\n", + "methodName":"save(catalog)" + },{ + "doc":" 删除\n", + "methodName":"delete(ids)" + },{ + "methodName":"select()" + },{ + "doc":" 修改\n", + "methodName":"update(catalog)" + },{ + "doc":" 列表\n", + "methodName":"list(params)" + }] + }, + "com.hfutonline.mly.modules.news.controller.TagController":{ + "className":"com.hfutonline.mly.modules.news.controller.TagController", + "doc":" 标签管理\n\n @author chenliangliang\n @date 2018-02-21 15:41:59\n", + "methods":[{ + "doc":" 信息\n", + "methodName":"info(id)" + },{ + "doc":" 修改\n", + "methodName":"update(tag)" + },{ + "doc":" 标签列表\n", + "methodName":"select()" + },{ + "doc":" 删除\n", + "methodName":"delete(ids)" + },{ + "doc":" 保存\n", + "methodName":"save(tag)" + },{ + "doc":" 列表\n", + "methodName":"list(params)" + }] + }, + "com.hfutonline.mly.modules.sys.controller.SysUserController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysUserController", + "doc":"

\n 系统用户 前端控制器\n

\n\n @author chenliangliang\n @since 2018-02-18\n", + "methods":[{ + "doc":" 获取用户信息\n @param userId 用户id\n @return 用户详细信息\n", + "methodName":"info(userId)" + },{ + "doc":" 获取登录的用户信息\n", + "methodName":"info()" + },{ + "doc":" 修改登录用户密码\n", + "methodName":"password(password,newPassword)" + },{ + "doc":" 保存用户\n", + "methodName":"save(user)" + },{ + "doc":" 所有用户列表\n", + "methodName":"list(params)" + },{ + "doc":" 修改用户\n", + "methodName":"update(user)" + },{ + "doc":" 删除用户\n", + "methodName":"delete(userIds)" + }] + }, + "com.hfutonline.mly.modules.sys.controller.SysLoginController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysLoginController", + "doc":" 登录相关\n \n @author chenliangliang\n @date 2018/2/18\n", + "methods":[{ + "doc":" 退出\n", + "methodName":"logout()" + },{ + "methodName":"registerPage()" + },{ + "methodName":"captcha(request,response)" + },{ + "doc":" 登录\n", + "methodName":"login(username,password,captcha,session)" + },{ + "methodName":"register(name,pw,model)" + }] + }, + "com.hfutonline.mly.modules.web.controller.ServerController":{ + "className":"com.hfutonline.mly.modules.web.controller.ServerController", + "doc":" 服务器表\n\n @author chenliangliang\n @date 2018-02-25 19:42:13\n", + "methods":[{ + "doc":" 修改\n", + "methodName":"update(server)" + },{ + "doc":" 信息\n", + "methodName":"info(id)" + },{ + "doc":" 服务器列表\n", + "methodName":"select()" + },{ + "doc":" 删除\n", + "methodName":"delete(ids)" + },{ + "doc":" 保存\n", + "methodName":"save(server)" + },{ + "doc":" 列表\n", + "methodName":"list(params)" + }] + }, + "com.hfutonline.mly.modules.web.controller.AppController":{ + "className":"com.hfutonline.mly.modules.web.controller.AppController", + "doc":" 应用表\n\n @author chenliangliang\n @date 2018-02-25 21:25:16\n", + "methods":[{ + "doc":" 信息\n", + "methodName":"info(id)" + },{ + "doc":" 修改\n", + "methodName":"update(app)" + },{ + "methodName":"manageCatalog(app)" + },{ + "doc":" 删除\n", + "methodName":"delete(ids)" + },{ + "methodName":"manageCatalog(appId)" + },{ + "doc":" 注册应用\n", + "methodName":"register(app)" + },{ + "doc":" 列表\n", + "methodName":"list(params)" + }] + }, + "com.hfutonline.mly.modules.news.controller.ArticleController":{ + "className":"com.hfutonline.mly.modules.news.controller.ArticleController", + "doc":" 文章管理\n\n @author chenliangliang\n @date 2018-02-21 15:42:00\n", + "methods":[{ + "methodName":"detail(id)" + },{ + "doc":" 删除\n", + "methodName":"delete(ids)" + },{ + "doc":" 修改\n", + "methodName":"update(article)" + },{ + "doc":" 审核文章\n", + "methodName":"audit(id)" + },{ + "doc":" 列表\n", + "methodName":"list(params)" + },{ + "doc":" 保存\n", + "methodName":"save(article)" + }] + }, + "com.hfutonline.mly.modules.sys.controller.SysUserRoleController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysUserRoleController", + "doc":"

\n 用户与角色对应关系 前端控制器\n

\n\n @author chenliangliang\n @since 2018-02-18\n", + "methods":[] + }, + "com.hfutonline.mly.modules.sys.controller.SysPageController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysPageController", + "doc":"系统页面视图\n\n @author chenliangliang\n @date 2018/2/18\n", + "methods":[{ + "methodName":"main()" + },{ + "methodName":"notFound()" + },{ + "methodName":"index(model)" + },{ + "methodName":"upload()" + },{ + "methodName":"module(module,url)" + },{ + "methodName":"login()" + }] + }, + "com.hfutonline.mly.modules.web.controller.AppCatalogController":{ + "className":"com.hfutonline.mly.modules.web.controller.AppCatalogController", + "doc":" \n\n @author chenliangliang\n @date 2018-02-25 21:25:16\n", + "methods":[] + }, + "com.hfutonline.mly.modules.sys.controller.SysRoleMenuController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysRoleMenuController", + "doc":"

\n 角色与菜单对应关系 前端控制器\n

\n\n @author chenliangliang\n @since 2018-02-18\n", + "methods":[] + }, + "com.hfutonline.mly.modules.news.controller.CatalogTagController":{ + "className":"com.hfutonline.mly.modules.news.controller.CatalogTagController", + "doc":" \n\n @author chenliangliang\n @date 2018-02-25 21:20:50\n", + "methods":[{ + "doc":" 保存\n", + "methodName":"save(catalogTag)" + },{ + "doc":" 信息\n", + "methodName":"info(id)" + },{ + "doc":" 删除\n", + "methodName":"delete(ids)" + },{ + "doc":" 列表\n", + "methodName":"list(params)" + },{ + "doc":" 修改\n", + "methodName":"update(catalogTag)" + }] + }, + "com.hfutonline.mly.modules.sys.controller.SysRoleController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysRoleController", + "doc":"

\n 角色 前端控制器\n

\n\n @author chenliangliang\n @since 2018-02-18\n", + "methods":[{ + "doc":" 保存角色\n", + "methodName":"save(role)" + },{ + "doc":" 删除角色\n", + "methodName":"delete(roleIds)" + },{ + "doc":" 修改角色\n", + "methodName":"update(role)" + },{ + "doc":" 角色列表\n", + "methodName":"select()" + },{ + "doc":" 角色列表\n", + "methodName":"list(params)" + },{ + "doc":" 角色信息\n", + "methodName":"info(roleId)" + }] + }, + "com.hfutonline.mly.modules.web.controller.AppServerController":{ + "className":"com.hfutonline.mly.modules.web.controller.AppServerController", + "doc":" \n\n @author chenliangliang\n @date 2018-02-25 21:25:16\n", + "methods":[] + }, + "com.hfutonline.mly.modules.api.controller.ArticleApi":{ + "className":"com.hfutonline.mly.modules.api.controller.ArticleApi", + "doc":" @author chenliangliang\n @date 2018/2/28\n", + "methods":[{ + "methodName":"getArticleTitle(catalogId,page,size)" + },{ + "methodName":"getArticleDetail(id)" + }] + }, + "com.hfutonline.mly.modules.sys.controller.SysLogController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysLogController", + "doc":"

\n 系统日志 前端控制器\n

\n\n @author chenliangliang\n @since 2018-02-18\n", + "methods":[{ + "doc":" 列表\n", + "methodName":"list(params)" + }] + }, + "com.hfutonline.mly.modules.sys.controller.SysMenuController":{ + "className":"com.hfutonline.mly.modules.sys.controller.SysMenuController", + "doc":"

\n 菜单管理 前端控制器\n

\n\n @author chenliangliang\n @since 2018-02-18\n", + "methods":[{ + "doc":" 菜单信息\n", + "methodName":"info(menuId)" + },{ + "doc":" 保存\n", + "methodName":"save(menu)" + },{ + "doc":" 所有菜单列表\n", + "methodName":"list()" + },{ + "doc":" 修改\n", + "methodName":"update(menu)" + },{ + "doc":" 选择菜单(添加、修改菜单)\n", + "methodName":"select()" + },{ + "doc":" 删除\n", + "methodName":"delete(menuId)" + },{ + "doc":" 导航菜单\n @demoResponse {djjdjd}\n @return hdhdhd\n\n", + "methodName":"nav()" + }] + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000..00bae2b --- /dev/null +++ b/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +com.github.llchen.apidoc.process.DocCommentProcessor \ No newline at end of file diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index 41e8b0e..7909149 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -1,3 +1,3 @@ # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -io.github.llchen.apidoc.config.ApiDocAutoConfiguration \ No newline at end of file +com.github.llchen.apidoc.config.ApiDocAutoConfiguration \ No newline at end of file