• [技术干货] JMeter安装教程
    注意事项:1)解压之后压缩包叫apache-jmeter-4.0.zip,如是src.zip后缀的都不对,打开之后会报错不可用,因为里面缺少我们下一步将要配置的环境变量.jar文件。2)对应的jdk版本不可太低,一般jmeter3.0的对应jdk1.7,jmeter4.0对应jdk1.8以上,否者启用jmeter也会报错。3)一定要确保环境变量配置正确(包括jdk的与jmeter的环境变量配置)。一、下载与安装1、JMeter下载/安装官网:https://jmeter.apache.org镜像地址:https://mirrors.cloud.tencent.com/apache/jmeter/binaries/apache-jmeter-5.6.zip2、Jdk下载镜像地址:Index of java-local/jdk/8u202-b083、配置环境变量 电脑桌面----》“计算机”图标----》鼠标右键选择“属性”----》点击高级系统设置----》高级---》环境变量页面新建jmeter 配置路径第一步添加jmeter路径变量:JMETER_HOME值:F:\soft\apache-jmeter-5.6\apache-jmeter-5.6   (拷贝你的解压路径即可)第二步添加classpath路径新建或编辑CLASSPATH配置classpath变量,没有的话也要按照上面步骤进行新建,有的话直接进行选中,点击编辑即可。变量值固定为:%JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;%JMETER_HOME%\lib\jorphan.jar;%JMETER_HOME%\lib/logkit-2.0.jar;  做完之后一定要保存,不确定的话可以直接点击确定按钮直到退到我的电脑页面基本配置完成,然后验证一下是否配置正确,是否可用。确认安装是否成功,双击jmeter.bat或者以管理员方式运行。注意:运行成功以后的CMD界面和JMeter主界面都不要关闭。要想使用这个相应时间首先需要安装3 Basic Graphs插件下载官方地址:https://jmeter-plugins.org/install/Install/ 将下载的plugins-manager.jar包复制到Jmeter安装目录,lib/ext下面重启jmeter后技能使用Plugins Manager插件安装到这一步我发现,好像直接在plugins manager->available plugins中直接搜然后下载即可。
  • [技术干货] Java+BS +saas云HIS系统源码SpringBoot+itext + POI + ureport2数字化医院系统源码
    Java+BS +saas云HIS系统源码SpringBoot+itext + POI + ureport2数字化医院系统源码医院云HIS系统是一种运用云计算、大数据、物联网等新兴信息技术的业务和技术平台。它按照现代医疗卫生管理要求,在特定区域内以数字化形式收集、存储、传递和处理医疗卫生行业的数据。通过云HIS系统,可以实现区域内医疗卫生信息资源的集中统管、统一调配、按需服务,为居民、医疗机构、卫生管理机关和其他机构提供云服务。云HIS系统的主要功能包括门诊收费管理、住院收费管理、门诊医生工作站、住院医生工作站、住院护士工作站、辅助检查科室管理、药房药品管理、药库药品管理以及报表查询等,以满足诊所业务中看诊、收费、发药、药库管理、经营分析等多环节的工作需要。云HIS药物管理系统门诊发/退药:门诊发退药,发退药历史记录可查询住院发药:住院患者发药住院汇总发药:住院处方明细可以汇总,按汇总单发药住院退药:住院退药之前需先进行审核,审核通过才能退药药物信息管理:对药品信息(基础信息、厂商信息、医嘱信息、医保信息)集中管理;可一键导入上传药品信息;可下载所有药品信息;可设置与药品外部系统进行关联入出库管理:药房药库出入库操作;出入库单据打印;出入库历史记录查询药物调拨:药房药库调拨操作,支持跨域调拨;调拨单据打印;调拨历史记录查询药物盘点:药房药库盘点操作;盘点明细查询;历史盘点记录查询药品控制:对药品信息和药品的使用情况、有效期、是否能使用、是否恢复冻结药品的状态进行控制管理;定时检查药品期效,逾期则消息栏通知提醒;药品拆分:药品拆分后,按拆分最小单位计费云HIS经济管理系统挂号统计:统计门诊挂号信息,支持多种查询方式门诊费用管理:门诊收费,支持医保结算、医保撤销;门诊收费流水查询,可进行退费、发票重打补打操作;门诊收费日结,可进行预结操作,可查看历史交账;门诊冲正交易业务;预约管理:预约挂号服务;统计预约挂号信息,支持多种查询方式排班管理:对在职的员工进行排班,可设置班次、查看本月排班情况患者管理:门诊患者信息集中管理,可查看患者个人详情、诊断历史、挂号收费记录等。住院登记:住院患者信息登记,自费登记或医保登记床位管理:住院科室床位信息管理预缴金管理:住院患者预缴金信息管理住院清单:住院患者处方明细、一日清单明细;住院清单可打印出院结算:住院患者进行出院结算,可医保结算结算报表:统计不同类型患者的结算信息票据管理:管理系统使用的发票、查询票据的使用情况、统计票据的使用或报损的情况住院费用管理:住院患者产生费用每日定时自动计费;住院患者药品和项目退费、住院患者结算明细查询云HIS报表管理系统门诊收入汇总:对门诊收入汇总,可按时间段查询住院收入汇总:对住院收入汇总,可按时间段查询收费统计报表:门诊收费统计,可按患者类型查询收费明细报表:门诊收费明细,可按患者类型查询缴款日报:每日收费后结转的金额数,用于财务每日和月末的统计审核门诊收费汇总:汇总门诊收费员每月的收费总额,用于月末统计账目住院科室日志:统计每月的出入院人数,和人次数,用来概览医院整体运行情况住院结算汇总:汇总住院收费员每月的收费总额,用于月末统计账目医疗项目统计:统计门诊或住院各科室开立的医疗项目的数量、产生费用检查项目统计:对所有患者检查项目的信息统计检验项目统计:对所有患者检验项目的信息统计月末收支汇总:汇总各科室阶段性的药品收支情况、支持结转操作、汇总票据打印药品进销存统计:可查询药品的进销存详情云HIS系统管理机构信息:管理医疗机构的基础信息科室管理:医疗机构各个科室基础信息管理员工管理:医疗机构所有员工基础信息管理;可设置角色,登录密码角色管理:机构角色定义及角色菜单使用权限的分配字典管理:机构部分字典信息集中管理(如门诊项目、收费项目等)参数设置:快捷操作参数设置、收费规则灵活设置等报表模板管理:可浏览系统所有的报表单据模板医嘱模板管理:住院医嘱模板管理;门诊处方模板管理
  • [问题求助] CodeArts Snap插件报错
    idea版本2023.3.2报错信息:com.intellij.diagnostic.PluginException: 4372 ms to call on EDT LoginMenuAction#Update@MainMenu (com.huawei.hdn.toolkitplatform.action.LoginMenuAction). Revise AnAction.getActionUpdateThread property [Plugin: com.huawei.hdn.toolkitPlatform]     at com.intellij.diagnostic.PluginProblemReporterImpl.createPluginExceptionByClass(PluginProblemReporterImpl.java:23)     at com.intellij.diagnostic.PluginException.createByClass(PluginException.java:89)     at com.intellij.openapi.actionSystem.impl.ActionUpdater.computeOnEdt(ActionUpdater.kt:223)     at com.intellij.openapi.actionSystem.impl.ActionUpdater.access$computeOnEdt(ActionUpdater.kt:71)     at com.intellij.openapi.actionSystem.impl.ActionUpdater$computeOnEdt$1.invokeSuspend(ActionUpdater.kt)     at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)     at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)     at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)     at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)     at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)     at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)     at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)     at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)     Suppressed: java.lang.Throwable: EDT-trace-at-313-ms (5/5) 后面的报错很长,超过5000字符,不能发帖
  • [问题求助] CodeArts Snap异常。
    每次打开idea的设置,然后关闭后,都会出现这个异常的信息。idea的版本是2023.3.2com.intellij.diagnostic.PluginException: No display name specified in plugin descriptor XML file for configurable com.huawei.codeelf.common.settings.configurable.CodeElfConfigurable; specify it using 'displayName' or 'key' attribute to avoid necessity to load the configurable class when Settings dialog is opened [Plugin: com.huawei.codearts.snap]     at com.intellij.openapi.options.ex.ConfigurableWrapper.getDisplayName(ConfigurableWrapper.java:156)     at com.intellij.openapi.options.ex.Weighted.lambda$static$0(Weighted.java:26)     at java.base/java.util.TimSort.binarySort(TimSort.java:296)     at java.base/java.util.TimSort.sort(TimSort.java:221)     at java.base/java.util.Arrays.sort(Arrays.java:1307)     at java.base/java.util.ArrayList.sort(ArrayList.java:1721)     at com.intellij.openapi.options.ex.SortedConfigurableGroup.buildConfigurables(SortedConfigurableGroup.java:41)     at com.intellij.openapi.options.SearchableConfigurable$Parent$Abstract.getConfigurables(SearchableConfigurable.java:75)     at com.intellij.openapi.options.ex.EpBasedConfigurableGroup.<init>(EpBasedConfigurableGroup.kt:110)     at com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil.getConfigurableGroup(ConfigurableExtensionPointUtil.java:119)     at com.intellij.ide.actions.ShowSettingsUtilImpl$Companion.getConfigurableGroups(ShowSettingsUtilImpl.kt:48)     at com.intellij.ide.actions.ShowSettingsUtilImpl.getConfigurableGroups(ShowSettingsUtilImpl.kt)     at com.intellij.ide.actions.ShowSettingsAction.perform(ShowSettingsAction.java:61)     at com.intellij.ide.actions.ShowSettingsAction.actionPerformed(ShowSettingsAction.java:48)     at com.intellij.openapi.actionSystem.ex.ActionUtil.doPerformActionOrShowPopup(ActionUtil.java:344)     at com.intellij.openapi.actionSystem.ex.ActionUtil.lambda$performActionDumbAwareWithCallbacks$4(ActionUtil.java:318)     at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareWithCallbacks(ActionUtil.java:381)     at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAwareWithCallbacks(ActionUtil.java:318)     at com.intellij.openapi.actionSystem.ex.ActionUtil.invokeAction(ActionUtil.java:553)     at com.intellij.ui.popup.ActionPopupStep.performAction(ActionPopupStep.java:258)     at com.intellij.ui.popup.ActionPopupStep.lambda$onChosen$3(ActionPopupStep.java:235)     at com.intellij.ui.popup.AbstractPopup.lambda$dispose$18(AbstractPopup.java:1733)     at com.intellij.openapi.wm.impl.FocusManagerImpl.lambda$doWhenFocusSettlesDown$3(FocusManagerImpl.java:169)     at com.intellij.util.ui.EdtInvocationManager.invokeLaterIfNeeded(EdtInvocationManager.java:33)     at com.intellij.ide.IdeEventQueue.ifFocusEventsInTheQueue(IdeEventQueue.kt:220)     at com.intellij.ide.IdeEventQueue.executeWhenAllFocusEventsLeftTheQueue(IdeEventQueue.kt:186)     at com.intellij.openapi.wm.impl.FocusManagerImpl.doWhenFocusSettlesDown(FocusManagerImpl.java:165)     at com.intellij.openapi.wm.impl.FocusManagerImpl.doWhenFocusSettlesDown(FocusManagerImpl.java:159)     at com.intellij.ui.popup.AbstractPopup.dispose(AbstractPopup.java:1731)     at com.intellij.ui.popup.WizardPopup.dispose(WizardPopup.java:161)     at com.intellij.ui.popup.list.ListPopupImpl.dispose(ListPopupImpl.java:407)     at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.dispose(PopupFactoryImpl.java:293)     at com.intellij.openapi.util.ObjectTree.runWithTrace(ObjectTree.java:130)     at com.intellij.openapi.util.ObjectTree.executeAll(ObjectTree.java:162)     at com.intellij.openapi.util.Disposer.dispose(Disposer.java:250)     at com.intellij.openapi.util.Disposer.dispose(Disposer.java:238)     at com.intellij.ui.popup.WizardPopup.disposeAllParents(WizardPopup.java:269)     at com.intellij.ui.popup.list.ListPopupImpl.disposePopup(ListPopupImpl.java:518)     at com.intellij.ui.popup.list.ListPopupImpl.handleNextStep(ListPopupImpl.java:542)     at com.intellij.ui.popup.list.ListPopupImpl._handleSelect(ListPopupImpl.java:505)     at com.intellij.ui.popup.list.ListPopupImpl.handleSelect(ListPopupImpl.java:449)     at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.handleSelect(PopupFactoryImpl.java:305)     at com.intellij.ui.popup.list.ListPopupImpl$MyMouseListener.mouseReleased(ListPopupImpl.java:745)     at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:298)     at java.desktop/java.awt.Component.processMouseEvent(Component.java:6657)     at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3385)     at com.intellij.ui.popup.list.ListPopupImpl$MyList.processMouseEvent(ListPopupImpl.java:810)     at java.desktop/java.awt.Component.processEvent(Component.java:6422)     at java.desktop/java.awt.Container.processEvent(Container.java:2266)     at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5027)     at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)     at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)     at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4969)     at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4583)     at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4524)     at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)     at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2809)     at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)     at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:794)     at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)     at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)     at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)     at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)     at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)     at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:766)     at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:764)     at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)     at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)     at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:763)     at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:695)     at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.kt:635)     at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$10(IdeEventQueue.kt:580)     at com.intellij.openapi.application.impl.RwLockHolder.runWithEnabledImplicitRead(RwLockHolder.kt:75)     at com.intellij.openapi.application.impl.RwLockHolder.runWithImplicitRead(RwLockHolder.kt:67)     at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:580)     at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:72)     at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:355)     at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:354)     at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:793)     at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:354)     at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:349)     at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:1014)     at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:114)     at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1014)     at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:349)     at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:848)     at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:391)     at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)     at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)     at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)     at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)     at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)     at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92) 
  • [其他] idea快捷键汇总
     IntelliJ IDEA开发中常用的快捷键有很多,以下是一些常见且使用频率较高的快捷键:  - **编辑类快捷键**:通过`psvm + Tab`可以快速生成main方法,`sout + tab`用于生成输出语句。此外,`Ctrl+X`和`Ctrl+Y`分别用于删除一行和复制一行代码。对于注释代码,可以使用`Ctrl+/`或`Ctrl+Shift+/`。如果误操作了,可以通过`Ctrl + Z`进行撤销,多次撤销可以使用`Ctrl + Shift + Z`。  - **调试快捷键**:在debug过程中,可以使用`F7`单步执行,`F8`逐行执行,`Shift + F8`跳出当前方法。而`Alt + M`则可以一键修复doc comment。  - **搜索快捷键**:查找文件内内容,可以使用`Ctrl + E`;而全局搜索则可以用`Ctrl + Shift + N`。  - **窗口管理快捷键**:切换不同的窗口可以使用`Alt + Left`和`Alt + Right`,并且对于隐藏的窗口,可以使用`Alt + Tab`进行切换。  以上只是其中一部分常用快捷键,实际上IntelliJ IDEA提供了非常多的快捷键以帮助开发者提升编程效率。你可以根据自己的需求和使用习惯去学习和掌握更多的快捷键。 
  • [其他] idea各个版本的区别
     IntelliJ IDEA是由JetBrains公司开发的一款卓越的Java集成开发环境(IDE),它有社区版和专业版两个主要版本。  1. 社区版(Community):这是免费的版本,基于开源代码构建,适用于纯JVM和Android开发。它拥有大部分开发所需的基本功能,但并不支持前端css和js的技术支持。  2. 专业版(Ultimate):这个版本是付费的,可用于web端和企业端的开发使用。它支持众多的前端和后端框架和技术,提供了更全面的分析和数据库工具、HTTP客户端等高级功能。  在版本更新方面,从v2022.2开始,所有IntelliJ IDEA更新都附带了JetBrains Runtime 17 (JBR 17),这带来了显着的IDE性能改进、更好的安全性、由于Metal API而在macOS上增强的渲染性能等等。  然而,需要注意的是,新版本可能会对电脑配置有较高的要求,例如某些用户反映在升级到最新版本后出现了操作延迟和卡顿的问题。因此,在选择使用何种版本时,应根据自己的实际需求和电脑配置进行权衡。 
  • [其他] 在idea中如何接入gitgpt插件
     在 IntelliJ IDEA 中接入 GitGPT 插件的步骤如下:  1. 打开 IntelliJ IDEA,点击菜单栏的 "File"(文件)> "Settings"(设置)。  2. 在设置窗口左侧导航栏中,选择 "Plugins"(插件)。  3. 在插件页面右上角,点击 "Marketplace"(市场)标签,搜索 "GitGPT"。  4. 在搜索结果中找到 "GitGPT" 插件,点击 "Install"(安装)按钮进行安装。  5. 安装完成后,重启 IntelliJ IDEA 生效。  注意:目前并没有名为 "GitGPT" 的插件,请确保你搜索的插件名称是正确的。如果你需要接入某个特定的插件,请提供正确的插件名称。 
  • [技术干货] IDEA 插件开发入门教程【转载】
    IntelliJ IDEA 是目前最好用的 JAVA 开发 IDE,它本身的功能已经非常强大了,但是每个人的需求不一样,有些需求 IDEA 本身无法满足,于是我们就需要自己开发插件来解决。工欲善其事,必先利其器,想要提高开发效率,我们可以借助 IDEA 提供的插件功能来满足我们的需求。如果没有我需要的功能怎么办?很简单,我们自己造一个!插件能做什么?IDEA 的插件几乎可以做任何事情,因为它把 IDE 本身的能力都封装好开放出来了。主要的插件功能包含以下四种:自定义语言支持:如果有 IDEA 暂时不支持的语言,你可以自己写一个插件来支持,例如 Go 语言原来的支持就是通过插件做的,后来单独做了一个 Goland。官方有自定义语言插件支持的教程。框架支持:例如Struts 2 的框架支持工具集成:可以给 IDEA 的自带功能进行增强,例如对 Git 的操作增加 CodeReview 的功能。参考Gerrit用户界面:自定义的插件改变用户界面。参考BackgroundImage我为了减少重复代码的编写,写了一个代码生成的插件【IDEA代码生成插件CodeMaker】,支持自定义代码生成的模板。Hello world 插件依照惯例,我们从 Hello world 开始。新建一个 Gradle 的插件工程有些教程推荐用 IDEA 默认的插件工程来开始,但是我比较推荐用 Gradle 来管理整个插件工程,后面的依赖管理会很方便,否则都得靠手动管理。点击新建工程,选择 Gradle接下来填写项目属性配置 Gradle,用默认配置就行新建完工程之后,IDEA 会自动开始解析项目依赖,因为它要下载一个几百兆的 SDK 依赖包,所以会比较久,打开科学上网能快一点。Gradle 依赖解析完成之后,项目结构如下图,其中 plugin.xml 是插件的配置,build.gradle 是项目依赖的配置(类比 pom.xml)。下面就是默认生成的 plugin.xml<idea-plugin> <!--插件id--> <id>com.xiaokai.test.demo</id> <!--插件名称--> <name>Demo</name> <!--开发者信息--> <vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor> <!--插件说明--> <description><![CDATA[ Enter short description for your plugin here.<br> <em>most HTML tags may be used</em> ]]></description> <!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html on how to target different products --> <!-- uncomment to enable plugin in all products <depends>com.intellij.modules.lang</depends> --> <!--依赖的其他插件能力--> <extensions defaultExtensionNs="com.intellij"> <!-- Add your extensions here --> </extensions> <!--插件动作--> <actions> <!-- Add your actions here --> </actions></idea-plugin>创建一个 ActionAction 是 IDEA 中对事件响应的处理器,它的 actionPerformed 就像是 JS 中的 onClick 方法。可以看出来,插件的开发本质上跟 web、Android 的开发没有什么不同,因为都是事件驱动的编程。我们可以直接使用 IDEA 提供的 Action 生成器点击 OK 之后会在 src 生成类文件:package com.xiaokai.test;import com.intellij.openapi.actionSystem.AnAction;import com.intellij.openapi.actionSystem.AnActionEvent;public class HelloWorldAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { // TODO: insert action logic here }}同时,动作的信息也会注册到 plugin.xml 中 <!--插件动作--> <actions> <!-- Add your actions here --> <action id="demo.hello.world" class="com.xiaokai.test.HelloWorldAction" text="HelloWorld" description="Say Hello World"> <add-to-group group-id="GenerateGroup" anchor="last"/> </action> </actions>弹出对话框创建完 Action 之后我们就要开始往里面写逻辑了,既然是 Hello World 教学,那我们就来试一下最简单的弹出对话框。 @Override public void actionPerformed(AnActionEvent e) { //获取当前在操作的工程上下文 Project project = e.getData(PlatformDataKeys.PROJECT); //获取当前操作的类文件 PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE); //获取当前类文件的路径 String classPath = psiFile.getVirtualFile().getPath(); String title = "Hello World!"; //显示对话框 Messages.showMessageDialog(project, classPath, title, Messages.getInformationIcon()); }代码写完之后,打开 Gradle 的界面,点击 runIde 就会启动一个安装了插件的 IDEA,然后就可以进行测试。你还可以右键启动 Debug 模式,这样还能进行断点。可以看到,我们右键打开 Generate 菜单之后,里面最后一项就是我们添加的 Action,进阶的教程如果想学习更多的原理和设计理念可以看IntelliJ Platform SDK的官方文档。不过老实说,它的文档写的挺差的,基本上就是简单讲了一下概念和原理,没有深入的分析。所以如果要深入研究还得靠自己。最靠谱的学习方式就是看别人写的插件,举个例子,你想知道怎么样实现自动生成代码,你就去找支持这个功能的插件,看他的源码是怎么写的。我当时写CodeMaker的时候也是靠自己啃源码之后写出来的。下面我简单介绍一下我用过的一些 API,这些 API 基本都没有文档说明,全靠代码相传。判断当前光标选择的元素是什么 //获取当前事件触发时,光标所在的元素 PsiElement psiElement = anActionEvent.getData(LangDataKeys.PSI_ELEMENT); //如果光标选择的不是类,弹出对话框提醒 if (psiElement == null || !(psiElement instanceof PsiClass)) { Messages.showMessageDialog(project, "Please focus on a class", "Generate Failed", null); return; }获取当前类文件的所有类对象一个类文件中可能会有内部类,所以读取的时候返回的是一个列表 public static List<PsiClass> getClasses(PsiElement element) { List<PsiClass> elements = Lists.newArrayList(); List<PsiClass> classElements = PsiTreeUtil.getChildrenOfTypeAsList(element, PsiClass.class); elements.addAll(classElements); for (PsiClass classElement : classElements) { //这里用了递归的方式获取内部类 elements.addAll(getClasses(classElement)); } return elements; }格式化代码 public static void reformatJavaFile(PsiElement theElement) { CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(theElement.getProject()); try { codeStyleManager.reformat(theElement); } catch (Exception e) { LOGGER.error("reformat code failed", e); } }使用粘贴板 CopyPasteManager.getInstance() .setContents(new SimpleTransferable(table.toString(), DataFlavor.allHtmlFlavor));原文链接:IDEA 插件开发入门教程 - 知乎 (zhihu.com)