整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

package-info.java文件详解

package-info.java文件详解

、pacakge-info.java介绍

pacakge-info.java是一个Java文件,可以添加到任何的Java源码包中。pacakge-info.java的目标是提供一个包级的文档说明或者是包级的注释。

pacakge-info.java文件中,唯一要求包含的内容是包的声明语句,比如:

package com.ch.service;

二、包文档

在Java 5之前,包级的文档是package.html,是通过JavaDoc生成的。而在Java 5以上版本,包的描述以及相关的文档都可以写入pacakge-info.java文件,它也用于JavaDoc的生成。比如:

/**
* dev1.ch包描述<br>
* 基于Apache DbUtils库封装的工具库,简化开发
* @author Li Qiang<br>
* date: 2015.5.13
* @since 1.7
* @version 1.0
*
*/
package dev1.ch;

上面的说明通过JavaDoc生成如下:

这里写图片描述

点击dev1.ch程序包的链接后显示:

这里写图片描述

三、包注释

注释对于程序员来说非常重要,pacakge-info.java文件包含了包级的注释。我们还可以使用ElementType来自定义注释。

包注释当然是ElementType.PACKAGE了,除此之外,还有:

  • ElementType.TYPE (class, interface, enum)
  • ElementType.FIELD (instance variable)
  • ElementType.METHOD ElementType.PARAMETER
  • ElementType.CONSTRUCTOR
  • ElementType.LOCAL_VARIABLE
  • ElementType.ANNOTATION_TYPE (应用于另一个注解上)

比如,想让包中的所有类型过时(Deprecate),你可以注释每一个单独的类型(类、接口、枚举等),如下所示:

@DEPRECATED
PUBLIC CLASS CONTACT {
}

或者是可以在package-info.java包声明文件中使用@Deprecated注释,它可以让包中的一切均过时。

@Deprecated

package dev1.ch.domain;

四、把package-info.java添加到包中

可以手动在包目录下创建package-info.java文件,也可以通过Eclipse工具实现这一点。

写在最后:

码字不易看到最后了,那就点个关注呗,只收藏不点关注的都是在耍流氓!

关注并私信我“架构”,免费送一套Java架构资料,先到先得!

馨提示:这是一篇私有的package客户端查询的平台搭建文章,牵扯到python中的Django框架,虽和Flutter相关,但客户端的代码并没有关联,请您根据需要进行阅读。

公有的package,对于一个Flutter开发者而言,再熟悉不过,比如常见的网络库dio,存储库shared_preferences等等,我们都可以在官网进行查找和使用,中文地址:https://flutter.cn/,很方便的就可以找到package网址,如下图所示:

点击打开之后,如下图,我们就可以查找想要的三方库。

在一些特定的环境下,自己公司封装的库,不适合于发布到公有的仓库中,那么就需要搭建一套私有的仓库,和Android中的私有Maven是一个道理,私有的服务端仓库,搭建起来很是简单,因为官方已经给我们提供了,地址是:https://github.com/dart-archive/pub_server,我们只需要按照流程,就可以完美的实现,在这里就不过多介绍,本篇重在于解决如何查看,也就是客户端查看,而不是上传,请各位老铁须知

私有的package存储服务搭建好之后,一般来说就足够了,只需要把使用方式整理成一个文档即可,但是,如果上传的package足够多,而且公司的开发人员又足够多,那么开发一个针对性的查看平台类似于官网提供的查看就很有必要了。

目前客户端查看实现的方案,有官网提供,当然也有一些三方提供,大家可以根据自己公司需求进行选择性使用,这里采用的是自己从0到1开发,旨在一个简单易用。


本篇的内容大概如下:


1、最终的实现效果一览

2、采用哪种语言作为接口开发

3、前端UI设计以及搭建

4、如何获取package对应的相关信息

5、路由设置和页面返回

6、相关总结


一、最终的实现效果一览

UI效果主打简洁,和官网的风格,简单的保持一致,内容区域只展示基本的内容,别的什么也不展示,以动画的形式,展示左右结构,只有简单的检索和列表展示及简单的内容展示。

首页


搜索页面



内容展示页面

右侧为测试内容,点击想要的Item后,以动画的形式滑入。


二、采用哪种语言作为接口开发

既然作为一个客户端查看,难免需要一个服务端作为支持,不然内容从哪来?服务端主要负责提供package检索和内容的返回,客户端负责内容展示,基于这是一个比较小得项目,选择一个轻量级的语言比较好,一开始选的是php,奈何最近一段时间对python比较感兴趣,于是就选择使用python作为服务端语言,使用的是比较成熟的Django框架。

关于Django框架,这里不做过多介绍,后续准备了相关文章进行着重的概述,所以啊铁子们,需要注意,虽是开发的Flutter的私有package查看,但是呢,用的是python,这个大家一定要熟知。

三、前端UI设计以及搭建

关于前端的UI,确实没什么好设计的,都是遵循着极简的模式,能多简单就多简单,一共三个页面,都是html文件,第一个是首页,第二个是搜索和内容展示页,第三个是上传package介绍页。这里着重介绍下搜索和内容展示页面。

搜索和内容展示页面,搜索的时候是以列表的形式展示,点击相关Item后,左边展示列表,右边展示内容,有一个动态切换的效果,这里简单的做了一个小动画。

  $(".list_name").each(function () {
                $(this).click(function () {
                    //点击之后查看详情
                    $(".list_div").animate({marginLeft: "5%", width: "40%"});
                    setTimeout(function () {
                        $(".list_content").css("display", "block");
                        $(".list_content").animate({right: "5%"});
                    }, 300);
                    //请求接口信息
                    $.get("../queryReadMe?fileName=gwm_lib", function (data) {
                        let content=data.data;

                        var converter=new showdown.Converter();
                        var html=converter.makeHtml(content);
                        $(".list_text").html(html);
                    });
                });
            });


为了支持md文件加载,这里使用了一个第三方showdown.min.js,当然了在实际的开发中,大家可以随意。


关于填充内容,使用的是Django的模板,主要用于分离文档的表现形式和内容,和Vue使用起来很像。


<div class="pub_div">
    <div class="pub_input_div">
        <input class="pub_input" placeholder="Search packages"/>
        <img src="../static/img/pub_search.png" class="pub_search"/>
    </div>
    <!--搜索结果页-->
    <div class="list_div">
        {% if count > 0 %}
            {% for search in searchList %}
                <div class="list_item">
                    <div class="list_name">{{ search.name }}</div>
                    <div class="list_author">
                        最新版本:<span style="font-style: italic;color: #7a8dc5;">{{ search.version }}</span>
                        作者:{{ search.author }}
                    </div>
                    <div class="list_description">{{ search.description }}</div>
                    <div class="list_time">
                        {{ search.time }}
                    </div>
                </div>
            {% endfor %}
        {% else %}
            <div class="list_no">暂时没有数据</div>
        {% endif %}
    </div>
    <!--使用详情-->
    <div class="list_content">
        <div class="list_text">

        </div>
    </div>
</div>


四、如何获取package对应的相关信息

当服务端搭建完成之后,便可以按照相关流程,上传自己的package,无论谁去上传,最终都会存到一个路径下,比如,我做为测试用的,所有的package都上传到了E盘下的tmp目录下的package-db。

在package-db目录下,存放的就是所有上传到私服的package,目前做为测试,仅上传了一个,我们继续打开:

每个package下存放的就是各个对应的版本号,再往下,就是存放的资源了。


知道了上传的基本目录结构后,一个问题就来了,如何拿到package的相关信息呢?比如名字,时间,版本号,作者,如何使用等?

其实大家,可以发现,在每个版本号的里面都有一个yaml文件,而这个yaml文件里就是我们上传到package时所填的一些信息,如下所示:

我们只需要逐行读取信息就可以拿到了,拿到信息之后,我们就可以用一个数组存储起来,组成我们需要的列表了。

只提供package而不提供如何使用,显然是不科学的,形同鸡肋,会让人懵逼,最终会造成,你这个package怎么使用?方法怎么调?属性怎么使用?没有一个简单的使用说明,会让人望而却步。

但是,使用方式如何获取呢?当我们开源一个库,为了让别人了解如何使用,一般都会在哪里书写呢?README啊,是不是,随便去github上扒拉一个不错的开源,相信都会有一个README文件,同样的,我们再上传package时,尽量也书写一下README文件,在README里书写相关使用方式或步骤即可,有了README文件,在上传的时候就会跟着一起上传,如下图,它是在tar.gz压缩包里:



压缩文件目录:



打开README文件,是不是发现和上边的截图内容展示一样,没错,所谓的package使用方式,就是通过读取压缩文件里的README内容而来的。




通过以上的分析,我们便可以拿到我们想要的内容,如,名字,版本号,描述,作者,上传时间,使用方式等等,具体的代码如下:


# Flutter私有库查询列表页面
def package(request):
    key=request.GET.get("key")
    packagePath="E:\\tmp\\package-db"
    rootPath=os.listdir(packagePath)
    # 遍历,查找一样的
    endList=[]
    for path in rootPath:
        if path.find(key) !=-1:
            # 继续寻找,找到最大的一个版本号
            versionPath=packagePath + "\\" + path
            versionList=os.listdir(versionPath)
            # 找出最大的一个版本号
            versionDir=versionList[len(versionList) - 1]
            # 遍历Yaml文件后,读取内容
            versionYamlPath=versionPath + "\\" + versionDir + "\\pubspec.yaml"
            # 读取内容
            file=open(versionYamlPath, "r", encoding="UTF-8")
            lines=file.readlines()  # 读取所有的行数
            name=lines[0].replace("\n", "").replace("name: ", "")  # 名字
            description=lines[1].replace("\n", "").replace("description: ", "")  # 描述信息
            version=lines[2].replace("\n", "").replace("version: ", "")  # 版本号
            author=lines[3].replace("\n", "").replace("author: ", "")  # 作者
            c_time=os.path.getctime(versionYamlPath)
            e_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(c_time))
            json={"name": name, "version": version, "description": description, "author": author, "time": e_time}
            endList.append(json)
    cou=len(endList)
    return render(request, "flutter/pubList.html", {"searchList": endList, "count": cou})



五、路由设置和页面返回


每个Django框架都有一个对应的urls文件,也就是路由文件,在这个文件里,我们可以设置我们跳转的页面,请求的接口等信息。

path('flutter/pub', index.pub),  # Flutter私有库查询首页面
path('flutter/package', index.package),  # Flutter私有库查询列表页面
path('flutter/packageUpload', index.packageUpload),  # Flutter私有库如何上传页面


路由指向的页面配置


# Flutter私有库查询首页面
def pub(request):
    return render(request, "flutter/pub.html")


# Flutter私有库如何上传页面
def packageUpload(request):
    return render(request, "flutter/pubUpload.html")

六、相关总结

基于Django框架,就简单的实现了一个客户端的package查询页面,前边也说过,不一定非得要使用python来作为服务端,使用php或者Java又或者其他语言都是可行的,最主要的就是选择一个自己熟悉的语言,这样写起来才比较顺手。

还有需要注意的是,如果官网和一些三方提供的package查询,能够满足我们的需求,我们也可以直接使用,没有必要再从0到1进行开发。

按照往常的文章风格,最后我都会贴出来源码或者开源地址,但是呢,实在是过于简单,如果大家了解了Django后,就会发现这些都是基本的知识点,所以就不贴了,但是主要的代码,都在文中介绍了。

ackage-info.java 介绍

pacakge-info.java 是一个 Java 文件目标是提供一个包级的文档说明及包级的注释。在 Java 5 之前,包级的文档是 package.html,是通过 JavaDoc 生成的。而在 Java 5 之后版本,包的描述以及相关的文档都可以写入 pacakge-info.java 文件

创建 package-info.java

pacakge-info.java 不能随便被创建,会报 This is not a valid Java qualified name 错误,类名无效,因为类名不能包括 -,那么怎么创建这个文件呢

创建一个普通的文件,文件名设置为 package-info.java 即可,或者从其它项目中复制一个

pacakge-info.java 只需要声明 package

package com.test;

package-info.java 用途

提供包级别的注释

package-info.java 添加注释

/**
 * 测试 package-info 的包注释功能
 * 
 * @author mimi
 * @since 1.0.0-RELEASE
 * @version 2.0.0-RELEASE
 */
package com.test;

执行 javadoc 之后查看效果图

  • 如何在 idea 中执行 javadoc

Tools -> Generate JavaDoc,选择 Output directory,在 Othre Command line arguments 中填入 -encoding utf-8 -charset UTF-8,用于解决中文乱码问题

提供包级别的注解

自定义一个注解

@Target(ElementType.PACKAGE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PackageAnnotation {
}

在 package-info.java 上添加注解,注解加在 package 之上,注解的地方与平常用的注解稍有不同

@PackageAnnotation
package com.test;

获取包注解

public class Test {
    public static void main(String[] args) {
        System.out.println("Package Annotation:");
        Arrays.stream(Test.class.getPackage().getAnnotations())
                .forEach(System.out::println);
        System.out.println();
        System.out.println("Class Annotation:");
        Arrays.stream(Test.class.getAnnotations())
                .forEach(System.out::println);
    }
}

输入结果如下,通过包可以获取到包的注解。

Package Annotation:
@com.test.PackageAnnotation()

Class Annotation:


@Deprecated 的使用

@Deprecated 可以作用在一个类,一个方法或者一个变量上,意味着被标记的元素是过时的,在之后的版本可能不再支持,不建议使用。但如果是一整个功能下线,@Deprecated 也可以作用在包上,将整个包标记为过时。

@Deprecated
package com.test;

提供包级别的变量

package-info.java 中只能声明 default 默认访问权限的类,只能包内访问,其它包包括子包都不可访问。

package com.test;
class Constant {
    static final String PACKAGE_NAME="Test";
}

同一个包下使用