体验spring-boot-devtools热部署,流畅且不失强大

标签: 体验 spring boot | 发表时间:2020-09-19 12:10 | 作者:小姐姐味道
出处:https://juejin.im/backend

不羡鸳鸯不羡仙,一行代码调半天。原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。

一个高级开发工程师,第一次用SpringBoot,决定打印一个经典的 HelloWorld

由于他太激动了,结果打错了一个字母,变成了 HalloWorld

哈喽?多么土多么俗多么没有档次,就像是嘴里含了个槟郎,吐不出气来,绝对需要进行改正。

结果,改成hello之后,高工发现需要重启应用才能生效。整整等了十多秒,系统才磨磨蹭蹭的启动起来。

有些东西,时间长了是好事,但对于这种代码调试场景来说,就让人无法忍受。

高工吐出嘴里的槟郎,心想,是时候开发一个加快调试速度的工具了。

这就是SBDT的由来。

spring-boot-devtools

SpringBootStringBuilderStringBuffer,俗称Java界的3个 SB。尤其是 SpringBoot,非常的好用,主要归功于它的 autoconfig,靠约定来规范开发。

但问题是,SpringBoot加载的Jar包太多、太大了,每次启动都要花费很长时间。对于SpringBoot服务来说, spring-boot-devtools就像一阵及时雨,滋润着瞪眼发呆盯着重启屏幕的同学。

虽然这个东西已经出来很长时间了,但我发现在现实项目中,大家用到的还是比较少。但它的使用非常简单。

只需要在项目的 pom文件中,加入下面的jar包即可获取 级的服务重载(热部署)。

   <dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-devtoolsartifactId>
    <scope>runtimescope>
    <optional>trueoptional>
dependency>
复制代码

由于 starter文件中默认的值就是true,所以下面yml中的配置,并不是必须的。

   spring:
  devtools:
    restart:
      enabled: true
复制代码

我们来验证一下。来的很快。

新建一个简单的controller,输出halloworld。

   @Controller
public class DemoController {
    @GetMapping("/test")
    @ResponseBody
    public String test(){
        return "halloworld";
    }
}
复制代码

修改代码,把hallo改成hello。控制台中将开始滚动输出日志,加载项目代码。此时访问浏览器,发现我们的改动生效了。

   # 日志显示
Started MbyeApplication in 1.731 seconds (JVM running for 51.115)
复制代码

控制台也输出了本次restart的时间,只花了不到2秒钟,可以说是飞快了。

为了在代码修改后,能够实时的触发编译,你需要在IDEA中做如下配置。如果这个配置不生效,就需要手动点击一下Build了(注意不是rebuild)。

为什么热部署的重新加载能够这么快呢?因为它的重新启动并不是完整的重启整个应用,而是只重启我们的应用代码。

通过配置 META-INF/spring-devtools.properties文件,可以指定每次重新启动都加载第三方jar包。不过这种场景比较少。当然,有include,旧有exclude,示例如下。

   restart.exclude.somejar=/somejar-[\\w-]+\.jar
restart.include.ajar=/ajar-[\\w-]+\.jar
复制代码

注意到一件有意思的事情。当我们使用IDEA启动的时候,控制台的输出是这样的。

   2020-09-18 21:33:59.495  INFO 4635 --- [  restartedMain] c.g.javarunfast.mbye.MbyeApplication     : Starting MbyeApplication on LYCYs-MacBook-Pro.local with PID 4635 (/target/classes started by xjjdog in /Users/xjjdog/codes/javarunfast/mbye)
2020-09-18 21:33:59.495  INFO 4635 --- [  restartedMain] c.g.javarunfast.mbye.MbyeApplication     : No active profile set, falling back to default profiles: default
2020-09-18 21:34:00.355  INFO 4635 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-09-18 21:34:00.355  INFO 4635 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2020-09-18 21:34:00.357  INFO 4635 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1ms. Found 0 Elasticsearch repository interfaces.
2020-09-18 21:34:00.362  INFO 4635 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-09-18 21:34:00.362  INFO 4635 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
复制代码

里面的启动线程是 restartedMain。但当我们使用 java -jar *jar来启动的时候,主进程并不是 restartedMain,而是 main

这是因为,线上环境开启devtools,是没有意义的。

这句话暂时这么说,因为会打脸。

更多功能

要想了解devtools有什么功能,我们先来看一下它的源码目录结构。

filewatchclasspath就不必说了,通过监听文件的变化,即可实现热启动。它原理上是使用一个独立的 ClassLoader(具体是指RestartClassLoader),来完成加载后的替换。

学习一下这部分的代码,可以对Java的类加载器有更好的理解。

LiveReload

接下来就是 livereload功能。

LiveReload在做前端开发的时候,经常会用到。

devtools也会在后台开启一个LiveReload Server,浏览器会与这个Server保持着一个长连接,当后端有 前端资源变动的时候,将会通知浏览器进行刷新,实现热部署。

下面是Chrome的 Remote Live Reload插件地址。安装即可拥有这个酷炫的功能。

   https://chrome.google.com/webstore/detail/remotelivereload/jlppknnillhjgiengoigajegdpieppei?hl=en-GB
复制代码

远程部署

这个就有意思多了。我们上面说到,线上环境开启devtools,是没有意义的,现在来打脸。

你可能自己的机器性能比较低,让代码运行在远端,本地只管代码开发。这时候,就可以使用远程热部署。

要开启这个功能,需要做的步骤有点多。

步骤一。

需要在 pom.xml中对 spring-boot-maven-plugin做如下的更改。

   <plugin>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-maven-pluginartifactId>
    <configuration>
        <excludeDevtools>falseexcludeDevtools>
    configuration>
plugin>
复制代码

步骤二。

在yml中设置一个服务端与调试端连接的密钥。

   spring:
  devtools:
    remote:
      secret: test
复制代码

步骤三。

将SB服务打包成jar,然后启动。

   mvn -Dmaven.test.skip=true -Pdev package

java -jar -Xdebug  \
-Xrunjdwp:server=y,transport=dt_socket,suspend=n  \
mbye-0.0.1-SNAPSHOT.jar
复制代码

可以看到我们在启动的时候加入了很多参数,这就是开启远程 被调戏的意思。

步骤四。

在本地IDEA中编辑一个Java文件,并在启动变量里塞进我们的服务端地址(和应用地址一样)。

   import org.springframework.boot.devtools.RemoteSpringApplication;

/**
 * @date 2020/09/19
 */
public class Remote {
    public static void main(String[] args) {
        RemoteSpringApplication.main(new String[]{"http://localhost:8080"});
    }
}
复制代码

步骤五。

进行验证。随便编辑一个能看到效果的文件,然后点击build。

下面是IDEA开发端的截图。

下面是服务端截图。可以看到服务已经重新载入了,不过速度特别快。

    Listening for remote restart updates on /.~~spring-boot!~/restart
 Started MbyeApplication in 1.961 seconds (JVM running for 249.452)
复制代码

访问web页面,发现代码已经上传成功了。

End

其实,spring-boot-devtools,还不算是最强大的。因为它每次都会使用ClassLoader重新载入项目的class文件。如果你的项目文件特别多,那也是比较慢的。

有一个更牛的工具,叫做 jrebel,那可真是开发的利器。更棒的是,它能用在任何Java项目上,而不仅仅限制于SpringBoot项目中。不过,它有点重,而且是收费的。下次我们介绍一下它,或者你已经提前去体验了 。

作者简介: 小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。

相关 [体验 spring boot] 推荐:

体验spring-boot-devtools热部署,流畅且不失强大

- - 掘金后端
不羡鸳鸯不羡仙,一行代码调半天. 原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. 一个高级开发工程师,第一次用SpringBoot,决定打印一个经典的 HelloWorld. 由于他太激动了,结果打错了一个字母,变成了 HalloWorld. 多么土多么俗多么没有档次,就像是嘴里含了个槟郎,吐不出气来,绝对需要进行改正.

Spring boot传统部署

- - 企业架构 - ITeye博客
使用spring boot很方便,一个jar包就可以启动了,因为它里面内嵌了tomcat等服务器. 但是spring boot也提供了部署到独立服务器的方法. 如果你看文档的话,从jar转换为war包很简单,pom.xml的配置修改略去不讲. 只看source的修改,很简单,只要一个配置类,继承自SpringBootServletInitializer, 并覆盖configure方法.

值得使用的Spring Boot

- - ImportNew
2013年12月12日,Spring发布了4.0版本. 这个本来只是作为Java平台上的控制反转容器的库,经过将近10年的发展已经成为了一个巨无霸产品. 不过其依靠良好的分层设计,每个功能模块都能保持较好的独立性,是Java平台不可多得的好用的开源应用程序框架. Spring的4.0版本可以说是一个重大的更新,其全面支持Java8,并且对Groovy语言也有良好的支持.

Spring Boot配置多个DataSource

- - 廖雪峰的官方网站
使用Spring Boot时,默认情况下,配置 DataSource非常容易. Spring Boot会自动为我们配置好一个 DataSource. 如果在 application.yml中指定了 spring.datasource的相关配置,Spring Boot就会使用该配置创建一个 DataSource.

Spring boot executable jar/war 原理

- - ImportNew
spring boot里其实不仅可以直接以 Java -jar demo.jar的方式启动,还可以把jar/war变为一个可以执行的脚本来启动,比如./demo.jar. 把这个executable jar/war 链接到/etc/init.d下面,还可以变为Linux下的一个service. 只要在spring boot maven plugin里配置:.

Spring Boot Starter是什么?

- - 技术,永无止境
在工作中我们经常能看到各种各样的springboot starter,如spring-cloud-netflix、spring-cloud-alibaba等等. 这些starter究竟有什么作用呢. 在了解这些starter之前,我们需要先大概知道Spring MVC与Spring Boot的关系.

SPRING BOOT OAUTH2 + KEYCLOAK - service to service call

- - BlogJava-首页技术区
employee-service调用department-service,如果要按OAUTH2.0流程,只需要提供client-id和client-secrect即可. 在KEYCLOAK中引入service-account,即配置该employee-service时,取消standard-flow,同时激活service-account.

spring boot与spring batch、postgres及elasticsearch整合

- - 互联网 - ITeye博客
当系统有大量数据需要从数据库导入elasticsearch时,使用sping batch可以提高导入的效率. 这篇文章使用spring batch将数据从postgres导入elasticsearch. 本文使用spring data jest连接ES(也可以使用spring data elasticsearch连接ES),ES版本为5.5.3.

Spring Boot使用redis做数据缓存

- - ITeye博客
SysUser.class)); //请注意这里. 3 redis服务器配置. /** *此处的dao操作使用的是spring data jpa,使用@Cacheable可以在任意方法上,*比如@Service或者@Controller的方法上 */ public interface SysUserRepo1 extends CustomRepository {.

spring boot应用启动原理分析

- - ImportNew
在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server. 如果之前没有使用过spring boot可以通过下面的demo来感受下. 下面以这个工程为例,演示如何启动Spring boot项目:.