运行 Spring Boot 应用的几种方式

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 你好看官,里面请!今天笔者讲的是运行 Spring Boot 应用的几种方式。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。

运行 Spring Boot 应用的几种方式

如果觉得写的还可以,点个赞支持一下笔者呗!你的点赞和关注会让我更快更新哦。笔者会持续更新关于Java和大数据有关的文章。目前集中精力在更新java框架的内容。


1. 前言

在 Spring Boot 出现之前,部署通常是将打好的 War 包放到 Tomcat(或其他 Web 容器)的 WebApps 目录下,然后启动 Tomcat。

2. War 与 Jar

Spring Boot 推荐我们使用 Jar 的方式打包和运行我们的工程(也是默认方式)。通过这段时间对于 Spring Boot 的了解,我们已经发现了一个规律 —— 采用 Spring Boot 推荐的方式(约定优于配置)通常都非常简单(基本上不需要额外的工作)。当然 Spring Boot 也会给我们自定义的自由,需要做一点额外的配置而已。

2.1 Jar

采用 Jar 的方式打包应用,我们不需要做任何额外的事情,按部就班的通过 Maven 打包就行了。执行完打包命令,在 target 目录就会生成一个 Jar 文件,如:helloworld-0.0.1-SNAPSHOT.jar。然后使用 java -jar 命令来启动就可以了。

打开系统命令行工具,将路径切换到 Jar 文件所在的目录,然后执行:

java -jar helloworld-0.0.1-SNAPSHOT.jar

接下来就可以看到熟悉的启动日志了,等应用启动完成以后,就可以访问我们写的接口了,很简单。

2.2 War

Spring Boot 让人喜爱的地方除了它为我们做了 N 多自动配置,还有另外一个可爱之处,就是能够非常方便的使用自定义配置。完美的兼顾了方便与灵活,Spring Boot 具有这样既贴心又开放的 “性格”,不由得你不喜欢。

下面我们就通过自定义配置,将 Spring Boot 工程以传统的 War 方式进行打包。我们只需要修改两个文件即可 ——SpringbootApplication(项目主类)和 pom 文件。

修改主类

修改项目主类:

@SpringBootApplication
public class SpringbootApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(SpringbootApplication.class);
    }
}

主类需要继承 SpringBootServletInitializer,然后重写 configure () 方法,这样主类就修改完了。

修改 pom 文件

pom 文件中需要修改三个地方:

  1. 修改打包方式
  2. 修改依赖项
  3. 设置 War 文件名

具体代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    ......
    <!-- 修改成 war -->
    <packaging>war</packaging>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 移除内置 Tomcat -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 添加 Tomcat 依赖,用于在 IDE 中运行项目 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        ......
    </dependencies>
    <build>
        <!-- 设置 war 文件名 -->
        <finalName>springboot</finalName>
      ......
    </build>
</project>

接下来使用 Maven 进行打包,打包完成后将 War 文件复制到 Tomcat 的 Webapps 目录下,然后运行 startup 脚本(Tomcat 的启动脚本在 bin 目录下)搞定。

3. DevTools

DevTools 是 Spring Boot 1.3 版本引入的一组开发者工具,目的是为了提高开发效率。其中一个很重要的功能就是,当代码修改后会自动帮我们重启应用。就这个?比我自己重启也强不到哪去呀!如果只是将原来的手动变成了自动,那真的就没啥好说的了。

自动重启优势所在

为了提升重启的速度,Spring Boot 将资源分成了两类:一类是不变对象(例如项目依赖的 Jar 包);另一类是可变对象(也就是我们应用中的类或者资源文件)。然后用基础类加载器来加载不变对象,用重启类加载器来加载可变对象。

那么重启的时候就可以只加载可变对象了。这样一来,启动速度势必会比加载所有资源的方式更快。理论上,项目依赖的第三方资源越多(项目越大),这种机制的优势也就越明显。

3.1 添加依赖

引入 DevTools 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

3.2 设置 IDE

想要使用 Spring Boot 的自动重启功能,需要对 IDE 进行一些设置。我们以 IDEA 为例,需要开启自动构建和自动编译。

开启自动构建

file -> Settings(Mac:IntelliJ IDEA -> Preferences) -> Compiler -> Build Project automatically

快捷键(打开设置对话框):

  • Win:Ctrl + Alt + S
  • Mac:Command + ,

网络异常,图片无法展示
|

Build Project automatically 选项后面有一行小字 ——only works while not running/debugging,勾选了自动构建以后,告诉我只能在非运行(调试)的情况下起作用。IDEA 你是在逗我吗?我们要的就是运行时起作用呀!所以,我们还得再做一个设置。

开启自动编译

Help -> Find Action -> Registry…

快捷键:

  • Win:Ctrl + Alt + Shift + /
  • Mac:Command + Option + Shift + /

网络异常,图片无法展示
|

勾选 compiler.autoMake.allow.when.app.running

网络异常,图片无法展示
|

可以看到这一项是允许应用在运行期进行自动编译的。

经过以上步骤后,在修改完类或者 application.yml 文件,应用就可以自动重启了。

3.3 自定义规则

如果你想要定制自动重启的策略,可以通过以下配置项来实现:

# 是否启用自动重启,默认值 true
spring.devtools.restart.enabled
# 不在监控范围的目录,默认值去 DevToolsProperties 类中查看
spring.devtools.restart.exclude
# 用来设置不需要监控的路径(会与 spring.devtools.restart.exclude 叠加)
spring.devtools.restart.additional-exclude
# 用来设置 classpath 以外的监控路径
spring.devtools.restart.additional-paths
# 监控 classpath 下文件修改的时间间隔,单位毫秒,默认值 1000
spring.devtools.restart.poll-interval
# classpath 下文件无更新的等待时间(超过这个时间没有任何更新就开始进行重启),单位毫秒,默认值 400
spring.devtools.restart.quiet-period
# 设置一个用于触发重启的文件,如果不设置,那么 classpath 只要有更改就可以触发重启
spring.devtools.restart.trigger-file

4. 类加载机制

我们都知道,Java 程序需要被 JVM 将编译后的字节码加载到内存,之后才能够运行和使用。JVM 将字节码加载进内存再到形成 JVM 可用的 Java 类型,这一过程就是 Java 的类加载。DevTools 的自动重启正是借助了这种灵活的加载机制才得以实现。

4.1 加载过程

类加载的过程中,JVM 做了很多工作,这些工作可以分为五个阶段:

网络异常,图片无法展示
|

如上图所示,整个类加载的过程包含加载、验证、准备、解析、初始化。下面我们分别看看这五个阶段都做了什么。

加载

加载是「类加载」的第一个阶段(注意,不要混淆 加载类加载 这两个概念)。在这一阶段,JVM 做了三件事:

  1. 通过类的全限定名(如:java.lang.String)获取类的二进制字节流
  2. 将类的字节流转化成方法区(JVM 内存模型中的一个分区)的运行时数据结构
  3. 在内存中生成一个对应的 java.lang.Class 对象(就是 foo.getClass () 方法获得的那个类类型对象)

二进制字节流不仅可以来自文件系统(class 文件),还可以来自网络或者运行时动态生成。

验证

验证阶段理解起来比较简单,就是验证所加载的内容是否符合 Java 类的规范。比如:

  • 是否以 CAFEBABE 开头
  • 版本号是否在当前虚拟机的处理范围
  • 常量池符合规范
  • 是否有父类以及父类是否允许被继承
  • 语法验证

目的就是为了保证 JVM 的安全,不能什么东西都直接往 JVM 内存里放。就好比我们坐火车、飞机之前都要安检是一个道理。

准备

准备阶段做的事情比较简单,就是为类变量分配内存,并为类变量设置初始值。这里有两个需要注意的地方,一是,类变量指的是 static 修饰的静态变量;二是,设置初始值指的是如有代码:public static int num = 100,在准备阶段会将 num 的值设置为 0,而不是 100(将 num 设置为 100 是初始化阶段要做的事情)。

但如果是 public static final int num = 100,那么 num 在准备阶段会被设置成 100

解析

在解析阶段,JVM 会将常量池中的符号引用替换成直接引用。Java 虚拟机规范中并没有严格规定解析阶段的执行时机,只是要求在在执行 16 个特定的指令之前执行。

这 16 个特定的指令是:anewarray、checkcast、getfield、getstatic、instanceof、invokedynamic、invokeinterface、invokespecial、invokestatic、invokevirtual、ldc、lde_w、multianewarray、new、putfield、putstatic

解析主要针对:类、接口、字段、类中的方法、接口中的方法、方法类型、方法句柄和调用点限定符,这 7 类符号引用进行。最后,要说明一点,就是这一段不需要懂,了解一下就行,哈哈哈!

初始化

初始化是类加载的最后一步。在这一阶段 JVM 会为静态变量赋值、执行静态代码块。在讲准备阶段时,示例中的 num 将被赋值为 100。

这里有个知识点需要掌握:只有在父类初始化完成以后,才会初始化子类。也就是说,在为父类初始化完静态资源以后,才会处理子类的静态资源。

public class Father {
    public static int a = 1;
    static {
        a++;
    }
}
public class Son extends Father {
    public static int b = a;
    public static void main(String[] args) {
        System.out.println(b);
    }
}

上面代码输出 b 的值是 2,而不是 1。这一点经常会在笔试题中遇到。

5. 总结

OK,在这一节,我们学习了 Spring Boot 的两种打包方式(Jar 和 War);还学习了使用 DevTools 设置应用自动重启;最后又简要分析了类的加载机制和每个阶段分别作了什么。又是一次理论与实践的结合。

相关文章
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
115 62
|
20天前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
44 14
|
18天前
|
XML 前端开发 安全
Spring MVC:深入理解与应用实践
Spring MVC是Spring框架提供的一个用于构建Web应用程序的Model-View-Controller(MVC)实现。它通过分离业务逻辑、数据、显示来组织代码,使得Web应用程序的开发变得更加简洁和高效。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring MVC,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
45 2
|
26天前
|
JSON 安全 算法
Spring Boot 应用如何实现 JWT 认证?
Spring Boot 应用如何实现 JWT 认证?
60 8
|
1月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
24天前
|
消息中间件 Java Kafka
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
Spring Boot 与 Apache Kafka 集成详解:构建高效消息驱动应用
36 1
|
1月前
|
Dubbo Java 应用服务中间件
深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案
本文深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案。通过检查GraalVM版本兼容性、配置反射列表、使用代理类、检查配置文件、禁用不支持的功能、查看日志文件、使用GraalVM诊断工具和调整GraalVM配置等步骤,帮助开发者快速定位并解决问题,确保服务的正常运行。
49 1
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
81 2
|
25天前
|
安全 Java 应用服务中间件
如何将Spring Boot应用程序运行到自定义端口
如何将Spring Boot应用程序运行到自定义端口
39 0
|
1月前
|
Java Docker 微服务
利用Docker容器化部署Spring Boot应用
利用Docker容器化部署Spring Boot应用
49 0
下一篇
DataWorks