JAVA自动生成接口文档的实现

Java (32) 2024-01-31 16:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说JAVA自动生成接口文档的实现,希望能够帮助你!!!。

原理

利用反射提取类、方法、方法参数、方法返回值及参数或返回值中的对象属性信息生成接口文档。

流程

1.获取待生成接口文档的相关类(对外接口类)

可以利用spring工具类和自定义注解获取相关bean。

applicationContext.getBeansWithAnnotation(OpenApi.class);

2.利用反射获取类及方法相关信息

Class c = bean.getClass();
//获取开放api名称
OpenApi openApi = (OpenApi) c.getAnnotation(OpenApi.class);
String openApiName = openApi.value();
//遍历方法
Method[] methods = c.getDeclaredMethods();
if (ArrayUtil.isNotEmpty(methods)) {
    for (Method method : methods) {
        if (method.isAnnotationPresent(OpenApiMethod.class)) {
            //获取开放api方法名称
            OpenApiMethod openApiMethod = method.getAnnotation(OpenApiMethod.class);
            String openApiMethodName = openApiMethod.value();

            //获取方法参数类型
            Type[] types = method.getGenericParameterTypes();

            //获取方法参数
            Parameter[] parameters = method.getParameters();

3.递归获取参数或返回值对象中的属性信息

/**
 * 获取指定类型里的属性信息
 *
 * @return 属性信息
 */
private List<Property> getProperties(Type type) {
    List<Property> properties = null;
    if (type instanceof Class) {
        if (ClassUtil.isBasicType((Class) type)) {
            //基本类型直接返回
            return null;
        }
        for (Class ignoreType : ignoreAddPropertyTypes) {
            //忽略的类型(及其子类)直接返回
            if (ignoreType.isAssignableFrom((Class) type)) {
                return null;
            }
        }
        if (((Class) type).isArray()) {
            //数组类型则获取元素的属性
            Class elementType = ((Class) type).getComponentType();
            return getProperties(elementType);
        }

        properties = new ArrayList<>();
        Field[] fields = ReflectUtil.getFields((Class) type);
        for (Field field : fields) {
            Property property = new Property();
            property.setName(field.getName());
            property.setType(field.getGenericType().getTypeName());
            //递归设置属性
            property.setProperties(getProperties(field.getGenericType()));

            if (field.isAnnotationPresent(OpenApiDoc.class)) {
                OpenApiDoc apiDoc = field.getAnnotation(OpenApiDoc.class);
                property.setCnName(apiDoc.cnName());
                property.setDescribe(apiDoc.describe());
                if (apiDoc.ignore()) {
                    //取消文档的生成
                    continue;
                }
            }

            properties.add(property);
        }
    } else if (type instanceof ParameterizedType) {
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Class rawType = (Class) parameterizedType.getRawType();
        //集合泛型类(Collection/List/Set等)
        if (Collection.class.isAssignableFrom(rawType)) {
            //取第一个泛型参数(集合元素)的属性
            Type elementType = parameterizedType.getActualTypeArguments()[0];
            return getProperties(elementType);
        }
        //Map泛型类(HashMap、Hashtable、TreeMap等)
        if (Map.class.isAssignableFrom(rawType)) {
            properties = getMapProperties(parameterizedType);
        }
    }
    return properties;
}

4.包装类、方法、参数、属性等相关信息为接口文档数据

JAVA自动生成接口文档的实现_https://bianchenghao6.com/blog_Java_第1张

5.前端获取json数据展示到网页上

JAVA自动生成接口文档的实现_https://bianchenghao6.com/blog_Java_第2张

JAVA自动生成接口文档的实现_https://bianchenghao6.com/blog_Java_第3张

JAVA自动生成接口文档的实现_https://bianchenghao6.com/blog_Java_第4张

附录

完整源代码请见我的开源项目openapi中的openapi-server-sdk模块中的文档功能:

GitHub - hdwang123/openapi: 开放接口sdk(openapi-sdk)

目前已经支持常见类型接口文档的生成,包括基本类型(Long,Integer,Byte,long,int...)、String、数组类型、普通JAVA对象、集合泛型类型(List<T>,Set<T>...)、Map泛型类型(Map<K,V>...)等

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复