整合营销服务商

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

免费咨询热线:

IDEA 社区版不支持 Tomcat?一招完美解决

IDEA 社区版不支持 Tomcat?一招完美解决

者 | 郑祎

责编 | Elle

前言

IntelliJ IDEA Community Edition(社区版)不支持Tomcat,不想花钱购买Ultimate版本,也不想使用Eclipse,尝试通过其他方式使IDEA社区版支持Tomcat。

尝试的方法

2.1. Smart Tomcat插件

在IDEA社区版(2019.2.4)中安装了Smart Tomcat插件,并使用其启动Tomcat应用,遇到了以下问题:

  1. Web应用的class文件未被自动拷贝到对应的Web应用根目录中,导致Web应用的代码未被加载,需要手工处理,使用不方便;

  2. Tomcat日志只生成了localhost_access_log.txt日志文件,没有生成catalina.log、localhost.log等日志文件,排查问题不方便。

使用Smart Tomcat插件遇到问题之后,放弃了使用该插件,没有再去分析是否因为使用方法不当。

可行方法

3.1. 说明

之后通过Gradle脚本,使IDEA社区版支持Tomcat(也支持IDEA Ultimate版)。

完成的Gradle脚本及示例Web工程代码可以从 https://github.com/Adrninistrator/IDEA-IC-Tomcat/ 、 https://gitee.com/adrninistrator/IDEA-IC-Tomcat/ 下载,脚本内容很短,有效行数不超过200行,处理也很简单。

通过上述Gradle脚本,结合IDEA的功能,在完成配置后,可以实现以下功能,能够达到与Eclipse或IDEA Ultimate版本对Tomcat支持的功能接近的效果。

  • 一键启动Tomcat并加载Web应用

  • 一键停止Tomcat(应用实例可以接收到Web容器销毁通知)

  • 一键启动可调试的Tomcat(Web应用)

  • 一键从Tomcat(Web应用)启动时开始调试

3.2. 依赖环境

  • IDEA

使用IntelliJ IDEA Community Edition 2019.2.4版本。

  • Tomcat

支持Tomcat 7、8、9版本(测试过Tomcat 7.0.55、7.0.79、8.5.20、9.0.30版本),理论上也支持Tomcat 5、6版本(未测试)。

  • Gradle

支持Gradle 4、5、6版本(测试过Gradle 4.1、4.7、5.6.4、6.0.1版本)。

  • JDK

使用JDK 1.8.0_144版本。

  • 操作系统

使用Windows 7 x64 SP1版本。

3.3. IDEA中执行Gradle脚本

假设存在以下Gradle任务:

task testTask {
doFirst {
println "测试-" + System.getProperty("arg")
}
}

3.3.1. 在Terminal中执行

在IDEA的Terminal中执行以上Gradle任务时,可以通过gradle或gradlew命令,以命令行的方式执行,并可以通过“-D”前缀指定传递给Gradle脚本的JVM参数,与执行Java程序时类似。

执行上述任务的Gradle命令示例如下所示:

gradle testTask -Darg=abc
gradlew testTask -Darg=abc

执行的结果如下所示:

> Task :testTask
测试-abc

3.3.2. 在Run/Debug Configurations中执行

打开IDEA的“Run/Debug Configurations”窗口,点击加号后,从弹出菜单中选择“Gradle”,可以新增一个配置,用于执行对应的Gradle任务。

打开“Configuration”标签页,对参数进行修改。

  • 点击“Gradle project”右侧的图标,选择当前项目;

  • 在“Tasks”右侧填入需要执行的Gradle任务名称,如“testTask”;

  • 在“VM options”右侧填入需要传递给Gradle脚本的JVM参数,如“-Darg=test_arg”,点击箭头图标可以展开编辑框。

在Run/Debug Configurations中完成配置后,可以选中对应的配置,点击执行按钮开始执行。

执行的结果在“Run”窗口中显示,如下所示:

当需要修改Run/Debug Configurations使用的Gradle时,可以打开IDEA的“File | Settings | Build, Execution, Deployment | Build Tools | Gradle”菜单,修改“Use Gradle from”选项。

3.3.2.1. 解决在Run/Debug Configurations中执行Gradle脚本中文乱码问题

在Run/Debug Configurations中执行Gradle脚本或编译过程时,输出的中文可能乱码。

或如下图所示:

进行以下设置,可以解决上述中文乱码问题。

  • 打开IDEA的“Help”“Edit Custom VM Options...”菜单;

  • 在打开的文件最后增加“-Dfile.encoding=UTF-8”;

  • 重启已打开的IDEA后生效。

3.4. 在IDEA中进行远程调试

3.4.1. 在IDEA创建远程调试配置并获取调试参数

打开IDEA的“Run/Debug Configurations”窗口,点击加号后,从弹出菜单中选择“Remote”,可以新增一个配置,用于进行远程调试。

打开“Configuration”标签页,对参数进行修改。

  • “Debugger mode”选项保持“Attach to remote JVM”

  • “Transport”选项保持“Socket”

  • “Host”参数保持“localhost”

  • “Port”参数指定被调试的Java进程监听的调试端口

  • “Use module classpath”选择被调试的Java进程对应的源代码模块

“Command line arguments for remote JVM”展示的调试参数不能编辑,会跟随上方的参数变化。

  • “Transport”选项“Socket”对应调试参数“transport=dt_socket”

  • “Port”参数对应调试参数“address=”

3.4.2. 增加调试参数后启动被调试Java进程

复制“Command line arguments for remote JVM”对应的调试参数,将其添加到被调试Java进程的JVM参数中,启动Java进程。

需要注意,IDEA调试配置中的Port参数,与被调试Java进程使用的调试参数中的address参数值需要相同,即调试器连接的端口需要与被调试Java进程监听的端口一致。

3.4.3. 在IDEA启动调试

选中对应的远程调试配置,点击调试按钮开始调试,与使用IDEA启动Java进程并调试类似。

调试启动成功后,在“Debug”“Console”窗口提示“Connected to the target VM”,如下所示。

点击停止按钮可以停止调试,IDEA的“Debug”窗口会出现类似“Disconnected from the target VM, address: 'localhost:5555', transport: 'socket'”的提示。

停止被调试Java进程时,IDEA启动的调试会自动结束。

停止调试后,不会使被调试的Java进程退出。

当对Tomcat进行调试时,停止调试后在Tomcat窗口会出现类似“Listening for transport dt_socket at address: 5555”提示。

以上调试方法也支持非Web应用,以及远程的Java进程。

3.5. runTomcat.gradle脚本使用方法

将runTomcat.gradle脚本拷贝至Java Web应用工程中,在build.gradle脚本中添加“apply from: 'runTomcat.gradle'”。

3.5.1. 任务及参数说明

runTomcat.gradle脚本中提供了名称为“startTomcat”的任务,用于启动Tomcat并加载Web应用。

在脚本中使用了以下参数。

3.5.1.1. 环境变量

  • TOMCAT_HOME_4IDEA

  • TOMCAT_INSTANCE_4IDEA

3.5.1.2. JVM参数

  • appName

  • noBuild

  • contextPath

  • arg4Tomcat

3.5.2. 环境配置

在使用提供的Gradle脚本runTomcat.gradle时,首先需要完成环境配置,“TOMCAT_HOME_4IDEA”环境变量配置需要增加,“TOMCAT_INSTANCE_4IDEA”环境变量的配置可选。

在完成环境变量配置后,需要重启已打开的IDEA后生效。

为了验证环境变量配置是否已生效,可在IDEA的Terminal中执行“echo %TOMCAT_HOME_4IDEA%”,当配置完成时会输出对应的环境变量值,未配置或未生效时会输出“%TOMCAT_HOME_4IDEA%”。

3.5.3. 使用场景

3.5.3.1. 正常启动Tomcat进程

正常启动Tomcat进程,加载示例工程中的Web应用的Gradle命令如下所示:

gradlew startTomcat -DappName=test-tomcat -Darg4Tomcat="-DtestValue=aaabbbccc -Dlog.home=E:\desktop\log-test"

在以上示例中,指定当前应用对应的Tomcat实例的名称,以及Web应用的上下文路径,均为“test-tomcat”,指定启动Tomcat时使用的JVM参数为“"-DtestValue=aaabbbccc -Dlog.home=E:\desktop\log-test"”。

第一次执行上述Gradle命令时(或删除了当前应用对应的Tomcat实例的目录后),Gradle脚本输出的结果如下所示:

> Configure project :
noBuild参数值:

> Task :clean
> Task :compileJava
> Task :processResources
> Task :classes

> Task :startTomcat
appName参数值: test-tomcat
contextPath参数值: test-tomcat
arg4Tomcat参数值: -DtestValue=aaabbbccc -Dlog.home=E:\desktop\log-test
tomcatDir参数值: C:\program\apache-tomcat-7.0.55
instanceDir参数值: C:\Users\user\.tomcat_idea
当前路径: E:\IDEA-IC-Tomcat
当前应用使用的Tomcat实例目录: C:\Users\user\.tomcat_idea\test-tomcat
生成Web应用所需文件
生成Web应用所需文件-完成
判断是否需要创建Tomcat实例
创建Tomcat实例
文件不存在: C:\Users\user\.tomcat_idea\test-tomcat\conf\Catalina\localhost\test-tomcat.xml
写入文件: C:\Users\user\.tomcat_idea\test-tomcat\conf\Catalina\localhost\test-tomcat.xml
生成bat停止脚本文件: C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-stop.bat
文件不存在: C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-stop.bat
写入文件: C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-stop.bat
生成bat启动脚本文件: C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-start.bat
文件不存在: C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-start.bat
写入文件: C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-start.bat

当以上Gradle脚本执行成功后,会启动Tomcat,Tomcat进程会产生单独的命令行窗口。

使用浏览器访问示例工程的Controller,URL为“ http://localhost:8080/test-tomcat/testrest/get ”,输出结果为当前时间戳及“testValue”对应的JVM参数值,访问结果如下所示:

3.5.3.2. 使用Tomcat实例启动脚本启动Tomcat进程

runTomcat.gradle脚本的“startTomcat”任务执行时,会在当前Web应用对应的Tomcat实例目录生成启动脚本,如前文输出的示例“C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-start.bat”。

当不需要对Web应用重新编译时,可以直接执行上述启动脚本,启动Tomcat进程,加载Web应用。

3.5.3.3. 停止Tomcat进程

在示例工程中,TestPostConstructLazyFalse.preDestroy方法使用了@PreDestroy注解,该方法会在应用停止阶段执行,会在当前目录生成名称为“preDestroy-”及当前时间戳的目录。

3.5.3.3.1. 直接关闭Tomcat窗口(应用实例无法接收到Web容器销毁通知)

将Tomcat窗口关闭,可以停止Tomcat进程。

通过该方法停止Tomcat进程,会使Tomcat进程直接结束,应用实例无法接收到Web容器销毁通知,示例工程的TestPostConstructLazyFalse.preDestroy方法不会执行,当前目录不会生成目录。

3.5.3.3.2. 使用Tomcat实例停止脚本停止Tomcat进程(应用实例可以接收到Web容器销毁通知)

runTomcat.gradle脚本的“startTomcat”任务执行时,会在当前Web应用对应的Tomcat实例目录生成停止脚本,如前文输出的示例“C:\Users\user\.tomcat_idea\test-tomcat\test-tomcat-stop.bat”。

执行上述停止脚本,会执行Tomcat提供的stop命令,可以停止Tomcat进程,应用实例可以接收到Web容器销毁通知,示例工程的TestPostConstructLazyFalse.preDestroy方法会执行,当前目录会生成目录,如下所示。

3.5.3.4. 调试Web应用

以下在IDEA创建远程调试配置并获取调试参数的过程,可以参考前文对应内容。

3.5.3.4.1. 进程启动后调试

  • 启动Tomcat进程

获取到调试参数如下所示:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5555

在执行Gradle “startTomcat”任务时,添加以上参数至arg4Tomcat参数中(可添加到IDEA的“Run/Debug Configurations”的Gradle配置中),如下所示:

gradlew -DappName=test-tomcat
-Darg4Tomcat="-DtestValue=aaabbbccc -Dlog.home=E:\desktop\log-test -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5555"

执行以上Gradle命令后,启动Tomcat进程。

  • 启动IDEA调试

之后可以在IDEA中启动调试。

对URI“/testrest/get”对应的TestRestController.get方法设置断点,通过浏览器访问后,IDEA调试器进入断点,可在“Debug”“Debugger”窗口查看。

3.5.3.4.2. 从进程启动开始调试(操作两次)

以上使用的调试参数中的suspend参数值为“n”,被调试的进程在启动时不会暂停线程,会正常启动。只支持先启动被调试进程,再进行调试。

当需要从进程启动开始调试时,需要将调试参数中的suspend参数值设为“y”,被调试的进程在启动时会暂停线程,等待调试器连接address指定的端口后,才会继续启动。

  • 启动Tomcat进程

当需要从进程启动开始调试时,调试参数示例如下。

-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5555

将Gradle任务“startTomcat”的“arg4Tomcat”参数中配置的“suspend”参数设置为“y”,再通过该命令启动Tomcat,Tomcat窗口只显示“Listening for transport dt_socket at address: 5555”,未显示其他内容,即Tomcat进程此时在等待调试器连接address参数对应的端口,未完成启动。

  • 启动IDEA调试

在Web应用初始化阶段会执行的代码设置断点,例如在示例工程的带有@PostConstruct注解的TestPostConstructLazyFalse.postConstruct方法设置断点。

在IDEA启动调试,查看Tomcat窗口日志已更新,说明Tomcat进程已启动。

查看IDEA调试窗口,已进入以上设置的断点,证明可以从Web应用启动开始调试。

3.5.3.4.3. 从进程启动开始调试(一键完成)

以上从进程启动开始调试的操作需要先启动Tomcat进程,再启动IDEA调试,可以优化为一键完成。

打开IDEA的“Run/Debug Configurations”窗口,选择“Remote”配置,点击“Before launch: Activate tool window”下方的加号按钮,选择“Run Gradle task”。

弹出“Select Gradle Task”窗口,“Gradle project”“Tasks”“VM options”参数配置,可参考在IDEA添加Gradle配置,通过“startTomcat”任务启动Tomcat进程的步骤,需要确保“VM options”参数填写的“arg4Tomcat”参数中的调试参数“suspend”为“y”。

“Before launch: Activate tool window”下方的列表会出现配置的Gradle任务。

完成以上配置后,在启动IDEA调试之前,会执行指定的Gradle任务“startTomcat”,以“suspend=y”的调试参数启动Tomcat进程。可以实现一键从进程启动开始调试,与IDEA Ultimate版或Eclipse对Web应用从启动开始调试的效果类似。

3.5.3.4.4. 调试Tomcat的类

当需要对Tomcat的类进行调试时,需要将Tomcat的lib目录添加至IDEA的Web应用工程的依赖中,否则调试时无法查看Tomcat的类。

打开IDEA的“Project Structure”窗口,选择“Project Settings”“Modules”标签页,在打开的窗口中选择Web项目主模块,选择“Dependencies”标签页,点击加号按钮,选择“JARs or directories...”菜单。

在弹出的窗口,选择当前使用的Tomcat的安装目录的lib目录。

完成添加后,Tomcat的lib目录会出现在“Dependencies”标签页的最下方。

当刷新Gradle后,项目配置会重置,以上添加的依赖会被清理,需要重新添加。

完成以上配置后,在Tomcat的org.apache.catalina.startup.HostConfig$DeployDescriptor类run方法设置断点,从进程启动开始调试,可以在IDEA的Debug窗口看到已进入断点。该方法是Tomcat启动时执行的第一个Tomcat的类的方法。

3.6. 其他说明

  • 生成Web应用所需文件调整

runTomcat.gradle脚本中buildFiles4WebApp方法用于生成Web应用所需文件,拷贝的目录与文件可以根据实际情况调整。

  • 调试端口需要确保未被监听

被调试Java进程的调试参数中指定的adderss参数对应的调试端口,需要确保未被监听,否则被调试Java进程会启动失败,窗口会自动消失,Tomcat的提示如下。

  • 重新创建Tomcat实例

当因为需要修改使用的Tomcat版本,或其他原因,导致需要重新创建Web应用使用的Tomcat实例时,需要将对应的Tomcat实例目录删除,如“C:\Users\user.tomcat_idea\test-tomcat”,之后再执行Gradle的startTomcat任务。

  • Tomcat实例目录配置修改与日志查看

当前Web应用对应的Tomcat实例目录,在执行Gradle “startTomcat”任务时会输出,如“C:\Users\user.tomcat_idea\test-tomcat”。

当需要修改当前Web应用对应的Tomcat使用的HTTP服务端口、SSL配置、线程池数量等参数时,可以修改Tomcat实例目录的“conf\server.xml”文件,说明略。

当需要同时启动多个Tomcat进程分别加载不同的Web应用时,需要先修改对应Tomcat实例的“conf\server.xml”文件中的监听端口,避免不同的Tomcat实例使用同一个端口导致不可用。

Tomcat实例目录的“logs”目录保存了Tomcat日志文件,使用默认配置时,包括“catalina.log”“localhost.log”“localhost_access_log.txt”“host-manager.log”“manager.log”等。

3.7. 原理说明

通过runTomcat.gradle脚本启动Tomcat进程并加载Web应用,与Eclipse或IDEA Ultimate(2018.3及之前版本)的原理类似,如下所示。

3.7.1. 生成Web应用所需文件

当noBuild参数未指定或为空时,会先执行Gradle的classes任务完成编译,再执行buildFiles4WebApp方法,完成以下操作:

  • 将编译生成的class文件拷贝至“build/tomcat/WEB-INF/classes”目录中

  • 将“src/main/resources/”目录(配置文件)拷贝至“build/tomcat/WEB-INF/classes”目录中

  • 将“src/main/webapp/”目录(静态资源与WEB-INF/web.xml文件)拷贝至“build/tomcat”目录中

  • 将依赖的jar包拷贝至“build/tomcat/WEB-INF/lib”目录中

3.7.2. 生成Tomcat实例

判断当前应用使用的Tomcat实例目录是否已存在,若已存在时则不再处理。

当前应用使用的Tomcat实例目录不存在时,进行以下操作生成Tomcat实例:

在“TOMCAT_INSTANCE_4IDEA”环境变量参数值对应的目录,或当前用户目录的“.tomcat_idea”目录中,创建当前Web应用使用的Tomcat实例目录,使用Gradle “startTomcat”任务执行时的“appName”参数值作为目录名称;

将“TOMCAT_HOME_4IDEA”环境变量参数值指定的,需要使用的Tomcat安装目录的bin、conf目录拷贝至当前Web应用使用的Tomcat实例目录中;

在当前Web应用使用的Tomcat实例目录创建logs、temp、work目录。

3.7.3. 处理Tomcat上下文描述符文件

上下文描述符是一个XML文件,其中包含与Tomcat相关的上下文配置,例如命名资源或会话管理器配置等。当Tomcat启动时,上下文描述符会被首先部署。可参考 https://tomcat.apache.org/tomcat-7.0-doc/deployer-howto.html 。

上下文描述符需要保存在当前Web应用使用的Tomcat实例目录的“conf\Catalina\localhost”目录中,当前Web应用的上下文路径与上下文描述符文件名相同(不含.xml后缀),上下文路径的大小写与文件名的大小写一致。

runTomcat.gradle脚本会检查当前Web应用对应的Tomcat实例的上下文描述符,若文件已存在且内容不需要修改,则不执行写入操作;若文件不存在或文件内容需要修改,则执行文件写入操作。

3.7.4. 生成Tomcat实例启动/停止脚本

Tomcat实例启动/停止脚本会保存在当前Web应用对应的Tomcat实例目录中。

runTomcat.gradle脚本会检查对应的脚本文件,在需要写入时进行写入操作。

在启动脚本中会调用Tomcat实例目录的“bin\startup.bat”脚本;在停止脚本中会调用Tomcat实例目录的“bin\shutdown.bat”脚本。

3.7.5. 启动Tomcat

runTomcat.gradle脚本会执行生成的Tomcat实例启动脚本,以启动Tomcat。

3.7.6. 调试Web应用

以上的远程调试使用了JDWP(Java Debug Wire Protocol),可参考 https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/jdwp-spec.html ,JDWP是用于调试器与其调试的Java虚拟机之间的通信协议。

JPDA(The Java Platform Debugger Architecture)包含三个接口,供调试器在桌面系统的开发环境中使用。JDWP属于其中一个,JPDA的说明可参考 https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/ 。

在JPDA连接和调用详细信息(https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/conninv.html )中,说明当suspend参数为“y”时,VMStartEvent会使用SUSPEND_ALL作为暂停策略;当suspend参数为“n”时,VMStartEvent会使用SUSPEND_NONE作为暂停策略。

参考

https://docs.oracle.com/javase/8/docs/jdk/api/jpda/jdi/com/sun/jdi/request/EventRequest.html ,说明SUSPEND_ALL在事件发生时会暂停全部线程;SUSPEND_NONE在事件发生时不会暂停线程。

根据以上说明可知,当Java进程的调试参数中的suspend参数为“y”时,在启动时会暂时全部线程;suspend参数为“n”时,在启动时不会暂时线程。

作者:郑祎,Java后台开发

ive Templates 是什么,听上去感觉挺玄乎的。有的同学用过之后觉得简直太好用了,不能说大大提高了开发效率吧,至少也是小小的提高一下,节省了很多敲重复代码的时间。有的同学用过之后说:没什么用,奇技淫巧罢了。

就算你没听过这个概念,但是或多或少你可能都用到过一点,就算没有用过的话,也可能见到过一些,没吃过猪肉可能也见过猪跑,就像下面这样的操作。

总结一下呢,它就类似于一种快捷指令(神奇代码),只要你在 IDEA 中输入特定的字母组合,IDEA 就会帮你在当前输入的位置插入一段预先定义好的代码,代码可以是固定的,也可以定义一些上下文变量,适用于那些常用的、使用频率较高的声明或重复代码段。

比如声明静态 finalString,再不用 Live Tmeplates 的情况下,我们会手动在 IDEA 中依次敲出 "public static final String" 这一行代码,当然可能借助 IDEA 的智能提示,每个单词只需要敲前两个字母。在使用了 Live Tmeplates 的情况下, 我们只需要敲出 psfs这四个字母,然后按回车键,IDEA 就会帮我们在 psfs这个位置插入 "public static final String" 这一行。

没用过的同学是不是赶紧打开 IDEA 试一下呢?在设置界面,输入 Live Templates,然后找到右侧的 Java就可以看到内置的模板。不光有 Java 的,对于多种文件类型都有支持,比如 SQL 、JavaScript、JSP 、Kotlin 等。

下面介绍几个 IDEA 内置的、常用的模板。

常用的 Live Templates

main 和 psvm

main 方法插入,虽然我们已经可以很熟练的盲打出下面这一段代码,但是只敲四个字母是不是会更快呢。

public static void main(String[] args){
}

变量声明

下面一些是常用的变量声明

psfs

public static final String 

psfi

public static final int 

prsf

private static final 

St

String 

控制台输出

下面是控制台输出,还有一些,不一一列举了。

sout

文本输出,最常用到的。

System.out.println();

souf

带格式化的文本输出。

System.out.printf();

循环迭代

fori

输入完,按回车后,光标会在 i<的位置,等待输入临界值。

    for (int i=0; i < ; i++) {

    }

iter

用 forEach 的方式循环,在一个数组或者列表变量下方使用。

List<String> array=new ArrayList<>();
for (String s1 : array) {

}

itco

用迭代器的方式迭代,同样是在一个列表变量下方使用。

List<String> array=new ArrayList<>();
for (Iterator<String> iterator=array.iterator(); iterator.hasNext(); ) {
  String next=iterator.next();
}

Surround Templates

这种模板是在选中一段代码后,然后使用快捷键 option+command+j调出提示框,然后选择一个模板类型。

这个快捷键是 MAC 系统下的,如果你用的是 windows,可以通过点击 code菜单项,找到 Sorround With,看看快捷键是什么。

C

实现一个 Callable

Callable<Object> callable=new Callable<Object>() {
  public Object call() throws Exception {
    System.out.println("hello");
  }
};

RL 和 WL

插入一段读锁或写锁加解锁代码。

// 要先声明一个读写锁实例
ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
readWriteLock.readLock().lock();
try {
  System.out.println("hello");
} finally {
  readWriteLock.readLock().unlock();
}

自定义 Template

有时候我们经常会高频词的使用一段相似的代码, 比如做网络开发的同学,会经常用到 Socket 相关的初始化代码。

对于这种我们自己经常要写的某些类似的代码段,就可以抽取出一个 Template 出来,方便我们使用。

下面我就实现一个自定的 Template,来看一下是不是大大简化了重复性劳动。有的同学可能觉得无所谓的事儿,复制、粘贴也挺省事儿。见仁见智吧,觉得有用的可以尝试一下,觉得鸡肋的也无所谓,反正也不影响最后的功能实现。

比如我最新在做一些系统优化的工作,这个过程中,我会频繁的用 commons-lang3StopWatch来看某些方法或者某些代码段的执行时间。比如下面的代码段:

StopWatch stopWatch=new StopWatch("代码段");
stopWatch.start();
try {
  Thread.sleep(1000);
} catch (InterruptedException e) {
  throw new RuntimeException(e);
}
stopWatch.stop();
System.out.printf("执行时间 %s%n",stopWatch.toString());

由于我比较懒,所以我不想每次都敲重复的内容,连粘贴复制都不想。所以就想到了 Live Template。

1、打开 IDEA 的设置窗口,找到 Editor 下的 Live Templates,在右侧找到 Java,点击最右侧的加号。

2、输入这个 Template 的名字,到时候可以在编辑器中通过输入这个名字来插入这个模板。

输入描述,帮助我们记忆。

最后输入模板的内容。

我给这个模板起名为 watch,模板内容如下:

StopWatch stopWatch=new StopWatch("$MESSAGE$");
stopWatch.start();
$SELECTION$
stopWatch.stop();
System.out.printf("执行时间 %s%n",stopWatch.toString());

$SELECTION$表示选中的部分,我们要监控的正好是某个方法或者某个代码段,所以正好可以用 Surround Templates,并且在内容中用了 $SELECTION$,模板就默认为 Surround Templates了。

$MESSAGE$就是一个占位符的作用,当我们插入这个模板后,光标会定位到这个占位符,我们就可以在需要定制的地方输入我们想要的内容了。在这里呢,由于我的一个方法中可能用到多个 StopWatch,所以正好在这儿占位,给不同的 StopWatch 赋予不同的名字。

可以通过下面的演示看一下效果。

Live Template 支持的变量

有一些情况下,我们希望插入的内容不只是固定不变的代码段,而是希望加入一些上下文相关的内容,比如当前方法的入参,比如当前类名,比如当前方法名等。用下面这个例子说明一下。

有一个内置的模板叫做 soutm,它的描述是这样的:Prints current class and method names to System.out,打印当前类和方法名,我们看一下效果,直接将当前类和方法名 Study.main填充到了println参数位置上。

模板内容是这样的,其中用到了两个变量是表示当前类名的 $CLASS_NAME$和表示当前方法名的$METHOD_NAME$

System.out.println("$CLASS_NAME$.$METHOD_NAME$");

更多的可用变量可以到 IDEA 官网查看,看到这些变量后,可能会打开你的思路,更近一步的为你提高开发效率。不过不用这些变量也没关系,上面这写其实差不多也够用了。

官网地址:https://www.jetbrains.com/help/idea/template-variables.html#predefined_functions

原文:https://mp.weixin.qq.com/s/Dur9IeuasDjpAyHye0pR8Q

如果感觉本文对你有帮助,点赞关注支持一下

欲善其事,必先利其器。在Java开发中挑选一款好的Ide环境能大大提升我们的开发效率,IntelliJ IDEA正是一个不二选择。本教程会介绍怎么对idea进行配置、使用idea进行debug和经常使用的快捷键,最后会推荐几个牛逼的idea插件,大大提升开发体验和效率。

一、安装

IntelliJ IDEA 有旗舰版和社区版本之分,其中旗舰版(Ultimate Edition)为收费版本,有 30 天试用期。如果你是学生、老师、开源项目参与者都可以向官网免费试用旗舰版。社区版(Community Edition)为免费版本,功能较旗舰版少了很多。

收费版本比Community的免费版本多了很多功能,这些功能可以大大提升我们的开发效率。下载完成后需要自己安装激活。

关于怎么永久激活可以见地址:

https://www.yuque.com/docs/share/12a88ca7-c665-45ad-82bc-8bfbc1718567?# 《IntelliJ IDEA2022.2最新最细指导教程》


  • 申请免费版本:https://www.jetbrains.com/idea/buy/
  • 旗舰版和社区版差异细节:https://www.jetbrains.com/idea/features/editions_comparison_matrix.html

系统要求:

  • JDK 版本:Apple Java 6 或 Oracle Java 7 以上
  • 内存:最低要求 1 G,推荐 2 G 以上
  • 硬盘:最低要求 2 G
  • 显示器:最低要求 1024 X 768 分辨率


IntelliJ IDEA 相关核心文件和目录介绍:

  • IntelliJ IDEA 的安装目录并不复杂,上图为最常改动的 bin 目录,经常会改动的文件或是必须介绍就是如图红色框中的几个。
  • idea64.exe 文件是 IntelliJ IDEA 64 位的可行执行文件,要求必须电脑上装有 JDK 64 位版本。64 位的系统也是建议使用该文件。
  • idea64.exe.vmoptions 文件是 IntelliJ IDEA 64 位的可执行文件的 VM 配置文件,具体配置修改会下面进行专门讲解。
  • idea.properties 文件是 IntelliJ IDEA 的一些属性配置文件,具体配置修改会下面进行专门讲解。

  • 强烈推荐不要直接修改安装目录下的这几个配置文件,因为 IDEA 升级/重装可能会导致修改完全失效!

  • 强烈推荐使用 IDEA 自带菜单中的 Help -> Edit Custom VM Options 和 Help -> Edit Custom Properties 来进行参数个性化配置!

二、配置、

2.1 样式主题配置

第一次安装完IDEA之后,第一步往往需要设置一个合适自己的样式主题,这部分配置主要包括:

  • 整体的主题配置;
  • 菜单栏字体大小样式配置;
  • 代码区字体大小样式配置;
  • 输出控制台字体大小样式配置。

1. 主题和菜单栏配置

如上图,File>>Settings>>Appearance&Behavior>>Appearance,进入主题设置页面。选择我们喜欢的主题,这个可以根据个人爱好自己选择。然后图中"override default fonts by"这栏,选择字体,字体大小自己选择。注意,这个配置只会影响主题和最上面菜单栏的显示。

2. 代码区字体大小样式配置

如上图,进入Color Scheme Font标签页进行代码编辑区的字体样式设置。

3. 输出控制台字体大小样式配置

2.2 设置编码字符集

2.3 配置JDK

1. 项目编译的JDK版本


2. 配置Project的Jdk版本

项目的SDK默认会被项目中的每个module使用,当然我们也可以为每个module配置专有的SDK类型和版本。

3. 配置每个module依赖的JDK版本

每个module会默认使用project配置的jdk版本,当然我们也可以自己指定。

4. 检查平台的JDK版本(也就是你电脑上安装的JDK)

我们在给project创建jdk的时候其实用的就是这个jdk。

2.4 键盘习惯配置

如果你之前用惯的是Eclipse,可能用不惯IDEA的快捷键.没事,idea可以将快捷键设置为eclipse模式。你之前用的是windows电脑,现在转为mac了,idea也提供了相应的转换设置。

通过keyman标签还可以设置快捷键,但是个人不建议改变IDEA默认的快捷键设置。

2.5 构建工具配置

常用的构建工具有Maven和Gradle。我们可以选其一。

2.6 自动编译配置

具体步骤:顶部工具栏 File ->Other Settings -> Default Settings -> Auto Import

说明:开启自动编译之后,结合Ctrl+Shift+F9 会有热更新效果。

三. 调试技巧

3.1 Debug界面&基本功能

首先看下IDEA中Debug模式下的界面,随着idea版本的更新Debug模式的图标设计虽有微调改动,但是功能大体相通。

 上图爬虫的图标就是Debug模式运行键,绿色三角形图标是正常的Run模式
  
 如下是在IDEA中启动Debug模式,进入断点后的界面,我这里是Windows,可能和Mac的图标等会有些不一样。就简单说下图中标注的8个地方:

① 以Debug模式启动服务,左边的一个按钮则是以Run模式启动。在开发中,我一般会直接启动Debug模式,方便随时调试代码。

② 断点:在左边行号栏单击左键,或者快捷键Ctrl+F8 打上/取消断点,断点行的颜色可自己去设置。

③ Debug窗口:访问请求到达第一个断点后,会自动激活Debug窗口。如果没有自动激活,可以去设置里设置。

④ 调试按钮:调试的主要功能就对应着几个按钮,鼠标悬停在按钮上可以查看对应的快捷键。在菜单栏Run里可以找到同样的对应的功能。

⑤ 服务按钮:可以在这里关闭/启动服务,设置断点等。

⑥ 方法调用栈:这里显示了该线程调试所经过的所有方法,勾选右上角的[Show All Frames]按钮,就不会显示其它类库的方法了,否则这里会有一大堆的方法。

⑦ Variables:在变量区可以查看当前断点之前的当前方法内的变量。

⑧ Watches:查看变量,可以将Variables区中的变量拖到Watches中查看

在设置里勾选Show debug window on breakpoint,则请求进入到断点后自动激活Debug窗口

如果你的IDEA底部没有显示工具栏或状态栏,可以在View里打开,显示出工具栏会方便我们使用。可以自己去尝试下这四个选项。

在菜单栏Run里有调试对应的功能,同时可以查看对应的快捷键。

3.2 基本用法&快捷键

Debug调试的功能主要对应着图中两组按钮:

1、首先说第一组按钮,从左到右依次如下:

> Show Execution Point (Alt + F10):如果你的光标在其它行或其它页面,点击这个按钮可跳转到当前代码执行的行。

> Step Over (F8):步过,一行一行地往下走,如果这一行上有方法不会进入方法。

> Step Into (F7):步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法。

> Force Step Into (Alt + Shift + F7):强制步入,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法。

> Step Out (Shift + F8):步出,从步入的方法内退出到方法调用处,此时方法已执行完毕,只是还没有完成赋值。

> Drop Frame (默认无):回退断点,后面章节详细说明。

> Run to Cursor (Alt + F9):运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点。

> Evaluate Expression (Alt + F8):计算表达式,后面章节详细说明。

2、第二组按钮,共从上到下依次如下:

> Rerun ‘xxxx’:重新运行程序,会关闭服务后重新启动程序。

> Update ‘tech’ application (Ctrl + F5):更新程序,一般在你的代码有改动后可执行这个功能。

> Resume Program (F9):恢复程序,比如,你在第20行和25行有两个断点,当前运行至第20行,按F9,则运行到下一个断点(即第25行),再按F9,则运行完整个流程,因为后面已经没有断点了。

> Pause Program:暂停程序,启用Debug。

> Stop ‘xxx’ (Ctrl + F2):连续按两下,关闭程序。有时候你会发现关闭服务再启动时,报端口被占用,这是因为没完全关闭服务的原因,你就需要查杀所有JVM进程了。

> View Breakpoints (Ctrl + Shift + F8):查看所有断点,后面章节会涉及到。

> Mute Breakpoints:静哑断点,哑的断点,选择这个后,所有断点变为灰色,断点失效,按F9则可以直接运行完程序。再次点击,断点变为红色,有效。如果只想使某一个断点失效,可以在断点上右键取消Enabled。

更新程序,On ‘Update’ actions,执行更新操作时所做的事情,一般选择’Update classes and resources’,即更新类和资源文件。

一般配合热部署插件会更好用,如JRebel,这样就不用每次更改代码后还要去重新启动服务。

下面的On frame deactivation,在IDEA窗口失去焦点时触发,即一般你从idea切换到浏览器的时候,idea会自动帮你做的事情,一般可以设置Do nothing,频繁切换会比较消耗资源的。

常用的调试快捷键如下:

Run Shift + F10 运行最近一次运行的函数、Debug Shift + F9 运行debug最近一次运行的函数

Run Alt + Shift + F10 初次运行指定的函数
Debug Alt + Shift + F9 初次debug运行指定的函数
Stop Ctrl + F2 停止项目
Step Over F8 越过当前函数
Forcce Step Over Alt + Shift + F8 强制越过
Step Into F7 步入当前函数
Force Step Into Alt + Shift + F7 强行进入当前函数
Smart Step Into Shift + F7 只能进入当前函数
Step out Shift + F8 步出
Resume Program F9 恢复程序
Evaluate Expression Alt + F8 计算表达式


3.3 变量查看

在Debug过程中,跟踪查看变量的变化是非常必要的,这里就简单说下IDEA中可以查看变量的几个地方,相信大部分人都了解。

1、如下,在IDEA中,参数所在行后面会显示当前变量的值。

  2、光标悬停到参数上,显示当前变量信息。点击打开详情如图。我一般会使用这种方式,快捷方便。



  3、在Variables里查看,这里显示当前方法里的所有变量。



  4、右键添加到watch, 可以查看值

3.4 计算表达式

在前面提到的计算表达式的按钮,Evaluate Expression (Alt + F8) 。可以使用这个操作在调试过程中计算某个表达式的值,而不用再去打印信息。
求值计算功能在我们debug过程中,可以很方便的查看程序中所有变量的值,也可以临时修改程序中变量的值,这个功能能在一定程度上辅助我们进行代码调试。


  1、按Alt + F8或按钮,或者,你可以选中某个表达式再Alt + F8,弹出计算表达式的窗口,如下,回车或点击Evaluate计算表达式的值。

这个表达式不仅可以是一般变量或参数,也可以是方法,当你的一行代码中调用了几个方法时,就可以通过这种方式查看查看某个方法的返回值。

3.5 智能步入

想想,一行代码里有好几个方法,怎么只选择某一个方法进入。之前提到过使用Step Into (Alt + F7) 或者 Force Step Into (Alt + Shift + F7)进入到方法内部,但这两个操作会根据方法调用顺序依次进入,这比较麻烦。

那么智能步入就很方便了,智能步入,这个功能在Run里可以看到,Smart Step Into (Shift + F7),如图

  按Shift + F7,会自动定位到当前断点行,并列出需要进入的方法,如图点击方法进入方法内部。

如果只有一个方法,则直接进入,类似Force Step Into。

3.6 断点条件设置

条件断点就是当满足某个条件(通常是表达式)时,debug断点才会生效;这在循环中debug是非常有用的;例如我们想要在循环体中调试:当某个变量满足某个条件时,需要断点调试,来查看详细的执行流程及变化情况。通过设置断点条件,在满足条件时,才停在断点处,否则直接运行。

通常,当我们在遍历一个比较大的集合或数组时,在循环内设置了一个断点,难道我们要一个一个去看变量的值?那肯定很累,说不定你还错过这个值得重新来一次。

1、在断点上右键直接设置当前断点的条件,如图,当name为eamon:23时,程序执行到断点处停下来。

有了条件断点,这样一来,那些不相关和我们不关心的代码就可以直接跳过了。

2、点击View Breakpoints (Ctrl + Shift + F8),查看所有断点。

Java Line Breakpoints 显示了所有的断点,在右边勾选Condition,设置断点的条件。

勾选Log message to console,则会将当前断点行输出到控制台,如图

勾选Evaluate and log,可以在执行这行代码是计算表达式的值,并将结果输出到控制台。

3、再说说右边的Filters过滤,这些一般情况下不常用,简单说下意思。

Instance filters:实例过滤,输入实例ID。

Class filters:类过滤,根据类名过滤

Pass count:用于循环中,如果断点在循环中,可以设置该值,循环多少次后停在断点处,之后的循环都会停在断点处。

4、异常断点,通过设置异常断点,在程序中出现需要拦截的异常时,会自动定位到异常行。

如图,点击+号添加Java Exception Breakpoints,添加异常断点。然后输入需要断点的异常类,之后可以在Java Exception Breakpoints里看到添加的异常断点。

3.7 多线程调试

一般情况下我们调试的时候是在一个线程中的,一步一步往下走。但有时候你会发现在Debug的时候,想发起另外一个请求都无法进行了?

那是因为IDEA在Debug时默认阻塞级别是ALL,会阻塞其它线程,只有在当前调试线程走完时才会走其它线程。可以在View Breakpoints里选择Thread,如图,然后点击Make Default设置为默认选项。

切换线程,在Frames的下拉列表里,可以切换当前的线程,如下我这里有两个Debug的线程,切换另外一个则进入另一个Debug的线程。

3.10 中断Debug

想要在Debug的时候,中断请求,不要再走剩余的流程了?

有些时候,我们看到传入的参数有误后,不想走后面的流程了,尤其是后面的流程要删除数据库数据,这种情况可以通过Force Return,即强制返回来避免后续的流程。

点击Force Return,弹出Return Value的窗口,我这个方法的返回类型为Map,所以,我这里直接返回 results,来强制返回,从而不再进行后续的流程。或者你可以new HashMap<>()。

四、常用快捷键

IntelliJ IDEA 于 2001 年 1 月诞生,并在 3.0 版本之后屡次获得各类大奖,从而奠定了它在 IDEA 中地位。而IDEA的快捷键能大大提升我们的开发效率和编程体验,让开发者为之着迷。

4.1 搜索相关

  • alt+F7(右键“find usage”)/ctr+鼠标左击:查找当前类、方法和变量在哪些地方使用过;
  • ctrl+N: 查找类;
  • ctrl+N+:行号(比如String:10 指跳转到String类的第10行 )
  • ctrl+F/alt+f3:在当前编辑的文档中查找;
  • ctrl+shitf+F :在所有文件中查找;
  • ctrl+shift+N :查找文件;
  • double shift:search everywhere;
  • search struct:按照模板搜索代码。

4.2 代码编辑相关

  • alt+insert:插入构造函数,setter/getter方法;
  • ctrl+alt+space :自动补全代码;
  • ctrl+shift+enter:补全代码
  • ctrl+/ :代码注释;
  • ctrl+shirt+/ : 代码注释;
  • ctrl+X:剪切行;
  • ctrl+D:赋值行;
  • ctrl+W:智能选中相关代码;
  • ctrl+alt+t : 选中代码块 可以添加try catch if-else块
  • ctrl+J :提示缩写
  • alt+J: 逐个选中并高亮一个变量
  • shift+F6: rename变量和方法等;
  • ctrl+P:显示一个方法的参数情况
  • ctrl+O :重载一个父类或接口的方法
  • alt+1 -->ctrl+shift+> : 首先alt+1定位project,然后再调整分割线
  • F11:添加书签,收藏关键业务代码
  • shift+F11:显示书签
  • ctrl+enter:重命名书签
  • ctrl+z/ctrl+shift+z
  • ctrl+shift+f7结合f3:ctrl+shift+f7可以高亮某个变量,而且随着鼠标的移动,这个高亮是不会消失的(这个很重要)。然后使用f3找到下一个使用该变量的地方。
  • ctrl+shift+. 折叠代码块,ctrl++号;还原代码块;
  • CTRL+SHIFT+F7:把光标放在某个元素中,按下快捷键之后,IDE将高亮显示所选元素所有出现过的地方。

4.3 导航相关

  • ctrl+反点号 : 基础设置;
  • Ctrl+Shift+V :使用最近复制过的文本;
  • ctrl+tab :历史tab导航;
  • ctrl+E :最近浏览过的文件;
  • ctrl+shift+e :最近编辑过的文件;
  • ctrl + F12 :列举类的成员变量和方法;
  • ctrl + H : 查看类的继承关系
  • Ctrl+Shift+Backspace(Go to | Last Edit Location)让你调转到代码中所做改变的最后一个地方,多按几次Ctrl-Shift-Backspace查看更深的修改历史;
  • ctrl+alt+< / ctrl+alt+> : 可以在前两次操作之间切换,有点像浏览器的前进后退功能
  • Ctrl-Alt-Down/Ctrl-Alt-Up快捷键则可以在编译器错误信息或者查找操作结果间跳转;
  • ESC :将焦点移到编辑器窗口
  • shift+esc :将焦点移动到编辑器窗口,并且关闭工具窗口
  • F12 打开上次使用的工具窗口
  • alt+home:浏览导航栏;
  • ctrl+]或者ctrl+[:括号匹配:这个也非常有用,因为代码太长,某个for循环,可能已经撑满整个屏幕了。这个时候,找到某个大括号对应的另外一边就很费劲。你可以将光标定位在某个大括号一边,然后使用ctrl+]或者ctrl+[来回定位即可。

这边贴上一个思维导图:

五、插件推荐

  • 阿里巴巴规约插件;
  • Key promoter(快捷键提示);
  • jrebel(热部署);
  • findbugs(帮助寻找代码可能潜在的bug);
  • grep console;
  • .ignore(生成各种ignore文件);
  • lombok(支持各种注解,省略代码);
  • GsonFormat(一键根据json文本生成java类);
  • Maven Helper;
  • VisualVM Launcher;(jvm调优必备工具);
  • MyBatisCodeHelperPro(mybatis代码自动生成插件);
  • Rainbow Brackets(彩虹颜色的括号,代码看起来比较舒服);
  • Translation(翻译插件);
  • String Manipulation(提供强大的文本转换操作);
  • Nyan progress bar(进度条);
  • Background Image Plus(背景图插件);
  • activate-power-mode OR Power mode II(字节跳动插件);
  • JUnitGenerator(单元测试生成工具);
  • SequenceDiagram(时序图生成工具);
  • ledis(Redis可视化工具
  • easyCode