为提高线上代码的质量,我们在项目持续集成的过程中,会对提交编译打包的代码进行静态代码扫描。我们预置了一些开发语言的语法规则(bug、漏洞、代码风格等),在静态代码扫描时,会对代码进行扫描,并将不符合规则的的代码标记出来。如果扫出的代码问题很严重,则会阻断上线,开发人员必须对问题代码进行修改。为方便对问题代码的修改,我们使用了静扫插件。该插件会在开发人员的编码过程中,对编写的代码进行扫描和分析,并将代码中与指定规则不符合的代码标记出来,提示开发人员修改。这样可以让开发人员快速发现问题,并及时修改。
但此时会面临一个问题,不同的业务线,对于代码的要求可能是不一样的,如何让这些规则匹配到所有的业务线。于是使用了规则集,把不同业务线的规则放到不同的规则集中,让业务线使用各自的规则集。为此我们开发了58EE插件,通过这个插件来修改规则集。
58EE插件有Eclipse和IDEA两个版本,并同时支持Mac OS和Windows。
下面我们就以IDEA为例,带大家了解下如何开发IDE插件。
1、配置JDK
点击File -> Project Structure,打开ProjectStructure面板。
在Project Structure面板中点击SDKs,之后点击加号,选择JDK。
选中JDK所在的路径,点击OK。
2、配置插件开发SDK
在Project Structure面板中点击SDKs,之后点击加号,选择IntelliJ Platform Plugin SDK。
选中IDEA的安装目录,点击OK。
3、启用Plugin DevKit插件
在Settings面板的Plugins中找到Plugin DevKit,确保此插件处于开启状态。一般IDEA中会自带此插件。
插件工程有两种形式,一种是DevKit,一种是Gradle。DevKit结构简单,上手快,Gradle依赖管理方便。官方推荐使用Gradle。对于插件开发选用哪种工程,一般根据插件的功能需求来确定。功能简单,依赖较少就用DevKit;功能复杂,依赖较多就用Gradle。
创建DevKit工程
在创建工程时选择IntelliJ Platform Plugin。
点击Next,填写工程名,点击Finish。
创建Gradle工程
在创建工程时选择Gradle,勾选Java和IntelliJPlatform Plugin。
点击Next,填写项目相关信息,建立项目。(注意Gradle工程需要在IDEA中配置Gradle)
pluginxml
在resources/META-INF目录下有个pluginxml文件,这是插件工程的配置文件。
以上内容是pluginxml中的基本配置内容,随着插件功能的增加,配置文件的内容也会越来越多。其它的配置项会在之后的功能开发模块介绍。
buildgradle
现在,我们开发一个插件小功能,在IDEA中新增一个按钮,点击该按钮d出一个Hello World的提示窗。
创建Action
在pluginxml中添加Action配置。
编写该Action的实现类。继承AnAction类,重写actionPerformed()方法。
运行调试
打开运行配置面板,点击加号,选择Plugin。
填写相关参数。VM Options为JVM参数,Use classpath of module为运行的插件项目,选择此次编写的插件,点击OK。
点击运行或调试按钮,则会启动一个新的IDEA,在此IDEA中会应用此插件工程。
开发者可以在新打开的这个IDEA中查看插件的使用效果。点击File,在最后一项出现HelloWorld。
点击HelloWorld,d出提示框。
DevKit打包
在菜单栏点击Build -> Prepare Plugin Module ‘xxx’ For Deployment,之后会在项目所在目录生成插件的zip压缩包。
Gradle打包
在Gradle窗口中点击双击clean,clean结束后双击build。
Build完成后,会在工程目录中生成build文件夹。
在build文件下的distributions目录中可以看到此插件打包后的文件。
插件安装方式
IDEA上的插件有两种安装方式:本地安装和在线安装。如果有插件的文件包,可以选择本地安装;如果你有插件的安装地址,就可以选择在线安装。
本地安装
本地安装有两种方式。一种是直接将插件zip文件解压后的文件夹放到IDEA安装目录的plugins目录中。
另一种方式是在IDEA中安装。在Setting面板的Plugins中点击Install plugin from disk。
选择本地的插件文件,点击OK。
在线安装
如果要安装官方插件仓库中的插件,则再插件面板中点击Browse repositories。
在d出的窗口中点击Repository单选框,选择插件所在的仓库。也可以在搜索框中输入插件的名称进行搜索。
找到插件后选中该插件,点击右方的Install进行安装。
注:安装完插件后,须重启IDEA才能使插件生效。
建立插件仓库
如果开发的是一个开源插件,想要全世界的人都可以使用这个插件,那么可以把这个插件发布到JetBrains的插件仓库。如果只想让这个插件在一定范围内使用,比如在公司内部使用,那么可以建立一个插件仓库。使用者通过访问这个插件仓库来安装插件。
创建一个任意名称的xml文件,在文件中写入以下内容。
其中,plugins标签中的每一项plugin代表一个插件。
id为插件工程配置文件pluginxml中定义的id;
url为该插件的下载地址;
version为插件的版本号,需要和pluginxml中的版本号对应;
如果插件要升级版本,则将url改为新版本插件的地址,version改为新的版本号。改完后使用者直接在IDEA上就可以升级。
写完这个xml文件后,把这个文件放到服务器上,文件的地址就是插件仓库的地址。在IDEA中添加自定义的插件仓库。在插件面板中点击Browse repositories。
点击下方的Manage repositories。
在d出的自定义插件仓库面板中,点击右方的加号。
输入xml文件的地址。
点击Check Now,如果d出成功的提示窗,则表示插件仓库能够被IDEA识别。
如果d出错误信息,则表示这个插件仓库检测失败,需重新检测仓库地址或xml文件编写是否有误。
在插件进行在线安装时,选择添加的自定义仓库,就可以看到这个仓库中的所有插件,选择需要的插件进行安装。
安装完插件后,如果该插件发布了新的版本,则Install按钮会变成Update按钮。用户点击该按钮就可以升级到新版本的插件。
插件组件是插件集成的基础概念。
插件组件的类型
插件有三种类型的组件,应用级组件(Application Component)、项目级组件(Project Component)、模块级组件(Module Component)。
应用级组件会在IDEA启动的时候创建和初始化,其生命周期伴随整个IDEA进程。在插件中只能有一个应用级组件。使用应用级组件,需在pluginxml中定义<application-components>标签,其实现类必须实现ApplicationComponent接口。在使用时可以通过ApplicationManager来获取Application实例,再通过Application实例的getComponent(Class)方法来获取应用级组件
在每个Project实例创建时,由IDEA自动为该实例创建一个项目级组件。在pluginxml中需使用<Project-components>标签定义,其实现类需要实现ProjectComponent接口,使用时通过Project实例的getComponent(Class)方法获取。
当Project中有Module被创建时,IDEA会自动为其创建一个模块级组件。在pluginxml中需使用<Project-components>标签定义,其实现类需要实现ModuleComponent接口,使用时通过Module实例的getComponent(Class)方法获取。
定义的每个组件,无论哪种类型,都有一个唯一的名字,用来作为外部,便于其它组件检索。通过组件的getComponentName()方法返回。组件的名字,推荐使用“插件名组件名”的方式来命名。
Component的周期方法
组件接口中有多个方法,会在组件生命周期的不同阶段执行。
ApplicationComponent中有initComponent()和disposeComponent()方法。initComponent()方法会在组件创建的时候被调用,disposeComponent()方法会在组件销毁的时候被调用。
ProjectComponent比ApplicationComponent多了两个方法,projectOpened()和projectClosed()。projectOpened()会在一个项目已经加载完成是调用,projectClosed()会在一个项目关闭后执行。
ModuleComponent比ProjectComponent多了一个moduleAdded()方法,会在模块已经被添加到project时执行。
如果开发者想开发一个图形界面,并嵌入到IDEA的面板中,则需要对IDEA中的组件进行扩展。
扩展和扩展点
扩展Setting面板
下面将展示插件在Setting面板中增加一项配置。
在pluginxml添加扩展信息。
接着写实现类,实现类必须实现Configurable接口,并重写改接口的方法。
createComponent()方法返回一个封装为JComponent对象的图形界面。开发者使用Java中的Swing进行图形界面的开发,并在此方法返回。使用时,当用户在Setting面板中点击此设置项,IDEA则会调用此方法,在面板中展示此界面。比如,输入return newJButton(“ok”),则会在面板中显示一个名称为ok的按钮。
isModified()方法则是用于监听界面中的内容是否有修改,当界面发生变化时会调用此方法。返回值为true时,Setting面板的Apply按钮可以点击;当返回值为false时,Apply按钮置灰,不能被点击。
apply()方法会在用户点击Apply按钮时执行,插件对于用户的响应 *** 作就可以放到此方法中进行。
reset()方法会在用户点击Cancel按钮时执行,可以用来还原设置。
disposeUIResources()方法会在当前界面消失的时候执行。比如当用户切换到其它设置项或Setting面板关闭时,会调用此方法。
运行效果
运行此插件,在Setting面板的Other Setting中可以看到此插件增加的设置项。
在用户使用插件的过程中,插件有时需要保存用户本次 *** 作的数据。比如用户上次选择的某个选项,在用户再次打开插件的时候,需要显示用户上次的选择。此时则需要将用户每次选择的数据进行持久化。IDEA提供了两种持久化的方式:PropertiesComponent和PersistentStateComponent。PropertiesComponent *** 作简单,适合保存简单、少量的的数据;PersistentStateComponent *** 作复杂,适合保存复杂、量多的数据。
PropertiesComponent
PropertiesComponent会把所有数据,以key-value的形式保存到一个IDEA的公共空间,所以定义的key必须是唯一的,建议使用项目名作为前缀。使用时,通过setValue()方法将数据保存到propertiesComponent中。
获取数据时,通过getValue()方法获取。
PersistentStateComponent
PersistentStateComponent的方式则会在本地新建一个xml文件,将插件数据保存到这个xml文件中。使用前需要先写一个PersistentStateComponent接口的实现类,用于定义xml文件。
以上的代码中,@State用于配置xml文件,name用于指定组件名称,storages用于指定文件保存的位置。在IDEA 2016以后的版本中,直接在@Storage注解为value属性赋值,值为xml文件的文件名,即@Storage(value = “filenamexml”)。value属性可以省略,直接填写文件名,插件使用时会在IDEA的用户目录中自动生成这个文件。
而在IDEA 2016及之前的版本,需要在@Storage注解中给id和file属性赋值(例如: @Storage(id = "rulesGroup", file="$APP_CONFIG$/rulesGroupxml"), $APP_CONFIG$ 为IDEA安装后的默认用户路径)。
持久化数据在xml文件中以key-value的形式保存,实现类中的属性名就是key。
以上的PersistentStateComponent实现类是将保存数据的属性定义在了实现类自身,当保存的数据较多时,对应的属性也会很多,类中的代码管理会显得混乱。这时可以在该实现类中定义一个内部类,把属性写到这个内部类中。
代码中的getState()方法,会在保存设置(比如settings窗口失去焦点,关闭IDEA)的时候调用。如果用户没有修改内容,则不会保存。loadState()方法会在创建组件或xml文件被外部改变的时候调用。
如果没有对实现类中属性进行封装,使用时可以直接对属性进行 *** 作。
建议对属性进行封装,通过get和set方法来或者属性值。
IDEA插件开发的技术点还有很多,比如进度条、PSI等。由于文章篇幅的限制,以上内容只是对其部分内容进行举例。希望能在以后为大家分享更多的IDEA插件开发技术。
一 Idea打包jar
因为本人用的开发环境是IntelliJ IDEA,开始的时候研究了一下利用这个开发工具进行打包
首先按F4或者点击IDEA右上角这地方
进入项目结构管理器
选择这里面的Artifacts。开始我完全不知道Artifacts是什么东西,后来查阅了点资料:Artifacts是maven中的一个概念,表示某个module要如何打包,例如war exploded、war、jar、ear等等这种打包形式;意思我理解的就是Artifacts就是告诉我们的程序因该如何打包这个项目。
之后新建一个Artifacts
这有两个选项选择第二个,从模块中引入,点击进去后会有一些设置,如下:
module是你需要打成jar包的项目
MainClass是运行的主函数,如果不需要运行则可以不选择
jarfilesfromlibraries是项目打包的方式,下面选项大致的含义:
1:extracttothetargetjar:把所有文件倒入进一个jar包里
2:copytothe。。。。:把项目的依赖包导出和项目一个目录,通过MANIFESTMF文件来引用jar包。
这里如果你的项目需要打成一个可运行的jar包推荐第二种,反之第一种。
设置完之后,就会新建一个xxx:jar,并进入进入xxx:jar的编辑页面
在我们需要进行一个输出目录布局的设置,我们可以看到,已经编译好的项目的jar文件(我的是eachendjar)和其他导入的jar包混到一起的,很杂,我是点击outputlayout下最左边的文件夹图标新建了一个lib文件,把其他jar包拖拽进来(建议,也可以直接点OK完成)
但是我们这样做的话依赖的jar包的目录就会产生变化,这时候我们需要选中我们项目,在下方然后修改MANIFESTMF中的Class Path
修改成OK
到了这一步后Artifacts是写好了,保存之后就可以用来生成jar文件
点击build Artifacts后选择你刚刚生成的artifacts
build后就会在out的目录下生成对应的jar文件
最后进入项目目录输入命令java -jar XXXjar就可以跑起来了如下
二gradle打包jar
本以为项目打成jar包并且可以完美运行了后,这事就差不多完了,可是项目组长说:你这样打包是可以,但是如果其他人用Eclipes来开发的话,就不管用了。。。。。。哎,好不容易搞出来的一个方法被pass掉了,无奈之下就只有另换方法。
因为项目我是用的gradle构建的,第一时间想起了用gradle打包。
利用gradle进行打包其实非常非常简单,但是因为我平常只是简单用它来导包,以及构建项目,它的基本的一些东西不是很清楚,所以走了些弯路花了大半天的时间才搞出来,所以说有时候需要了解一下你所用的东西的一些基础和原理。
在build,gradle中首先需要加上
apply plugin: 'java'
apply plugin: 'idea'
来定义你自己项目使用的插件,apply plugin: 'idea'用于把项目构建成idea项目,apply plugin: 'java'用于添加Java插件,以及一些内置任务,打包jar就要用到这里的插件。
version = '10'
repositories {
mavenCentral()
}
这里用来声明版本号以及添加maven中心仓库地址
dependencies {
compile 。。。。。。。
}
这里来添加项目所需要的依赖包
jar {
String someString = ''
configurationsruntimeeach {someString = someString + " lib//"+itname} //遍历项目的所有依赖的jar包赋值给变量someString
manifest {
attributes 'Main-Class': 'comeachdubboMainEnd'
attributes 'Class-Path': someString
}
}
打包的时候,这个地方很重要,用来设置jar文件的相关属性,这个地方把我坑了有点久,最后补了下gradle的基础知识,就搞出来了,这篇博客写gradle基础写的还可以,推荐给大家看看>
因为项目为插件工程,每次编译需要使用“/gradlew pushPlugin”自动push到壳工程,但是我的不行,就不行
错误如下:
一脸懵逼,完全看不懂
按照提示尝试找找错误原因,然后一顿 *** 作,猛如虎:
/gradlew --stacktrace
/gradlew --info
/gradlew --scan
这个错误感觉有点意思,可能是病灶的根源,仔细一看,确实,经过几分钟仔细研究,终于知道了:
解决方案:
1、我首先去把as的jre配置地方改成系统的,发现,改不了,放弃
2as不让改,还不能改自己的么,改本地的环境变量,把java_home的jre换成as的jre地址,
结果,编译的特别丝滑
问题解决了,但是总觉得怪怪了,因为本地jre环境被改了,不舒服,哈哈,原因很简单啊,本地jdk以后升级就不行了,第二种方法只是暂时解决了,并不完美,所以还得再想想
终极解决:
编写了一个脚本文件,主要作用有俩个,第一是临时替换本地jre的地址,指向到as的。第二是直接编译,然后push;
脚本如下:
ps:把地址换成自己as的jre地址就可以,注意分隔符的方向
运行编译,完美编译, 丝滑
这两个有什么区别?
概括一句话:根据gradle中现有的签名配置进行自动签名打包
通常debug和dev环境是系统自行配置的debug-sing签名,不需要手动进行配置,但是release环境是对外发布的环境,必须要求手动在gradle中进行签名配置才可以打包(后边说)
所以在gradle配置好了签名的情况下,直接点击 Build APK(s) 就可以进行打包
一句话概括:通过手动选择签名文件进行签名打包
这种方式则不需要在gradle中进行配置,直接选择你已经创建好的签名文件,输入对应的密码等信息,就可以进行打包
然后就可以进行打包了
debug 和 dev 等测试/开发环境 因为系统自动配置了debug-sing 可以直接使用 Build APK(s) 进行打包。
但是release环境需要对外发布,所以需要手动在gradle中进行签名配置才可以使用 Build APK(s) ,或着自己选择 Generate Signed Bundle or APK 通过签名文件进行打包(效果和gradle中配置好了签名文件完全相同)
那么就有以下两个问题:
在 Generate Signed Bundle or APK 中选择 Create new
在module的gradleandroid中输入:
然后在配置环境的buildTypes中,想使用 signingConfigs 签名配置的环境加上一句话: signingConfig signingConfigsrelease
这样,就在gradle中配置好了签名,可以直接使用 Build APK(s) 进行打包
注意这里的 minifyEnabled true 也就是要使用混淆文件(一般测试环境为false 编译更快)。如果release环境打包,没有配置好混淆文件的话,会导致apk安装之后,秒退。(如果没有签名强行打包,则无法安装)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)