Spring Boot学习 一 开始
注:
本文需要一定的Spring及Linux/unix操作基础。
本文所有源代码均可在https://github.com/favorstack/spring-boot-demo下载。
一 简介
随着微服务的盛行,Spring Boot几乎成为了Java界的标配。从Spring官网首页也可以看出其地位,并且在其项目列表中已跃升至第一位。
Spring Boot的出现并非用于替代Spring Framework,相反,它用于简化Spring的开发,将Spring中的“约定优于配置”发挥到了极致,其核心仍然是Spring Framework,并将各种第三方框架与Spring平台完美地整合到了一起,目的一如当初创建Spring时一样,简化Java企业开发,让我们更容易的创建独立的,可用于生产级的Spring应用。换句话说,Spring Boot可以让我们更专注于业务。
目前Spring Boot的迭代依然很快,当前的GA
版本为2.1.6
,本文及后后续均以该版本为基础。
二 系统要求
Spring Boot 2.1.6 要求Java8+,兼容Java11;并且要求Spring Framework5.1.8+。
构建工具要求:
构建工具 | 版本 |
---|---|
Maven | 3.3+ |
Gradle | 4.4+ |
支持以下内嵌Servlet容器:
Name | Servlet Version |
---|---|
Tomcat 9.0 | 4.0 |
Jetty 9.4 | 3.1 |
Undertow 2.0 | 4.0 |
也可以将Spring Boot应用程序部署到任何兼容Servlet 3.1+的容器
三 安装配置Spring Boot开发环境
Spring Boot提供了多种不同的安装方式,有针对刚接触Java开发的Spring Boot CLI (Command Line Interface),也有经典的Java应用安装方式。我们将采用第二种。
3.1 检查Java版本
由于Spring Boot是Java应用,所以首先需要配置Java环境,可以参考这一篇文章。
安装完毕执行以下命令检查:
$ java -version
3.2 检查Maven版本
本文将使用Maven作为构建管理工具,关于Maven的安装和配置,请参考这里。
安装完毕执行以下命令检查:
$ mvn -v
一个基本的Spring Boot maven pom文件如下:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.favorstack</groupId>
<artifactId>myfirstboot-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- 从Spring Boot继承默认配置 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<!-- 为web应用添加依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- 打包为可执行jar文件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
四 第一个Spring Boot应用
首先,在任意目录下创建一个目录,例如:myfirstboot-app
,然后在该目录下创建一个pom
文件:
$ mkdir myfirstboot-app && touch myfirstboot-app/pom.xml
4.1 引入SpringBoot Starter默认配置
编辑刚才创建的pom
文件并加入以下内容:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.favorstack</groupId>
<artifactId>myfirstboot-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- 从Spring Boot继承默认配置 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<!-- 其他内容 -->
</project>
4.2 打包
现在我们可以在myfirstboot-app
目录下执行mvn clean package
命令来构建一下:
$ cd myfirstboot-app && mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< io.favorstack:myfirstboot-app >--------------------
[INFO] Building myfirstboot-app 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ myfirstboot-app ---
[INFO] Deleting /Users/lin/tmp/bootdemo/myfirstboot-app/target
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ myfirstboot-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/lin/tmp/bootdemo/myfirstboot-app/src/main/resources
[INFO] skip non existing resourceDirectory /Users/lin/tmp/bootdemo/myfirstboot-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ myfirstboot-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/lin/tmp/bootdemo/myfirstboot-app/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ myfirstboot-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/lin/tmp/bootdemo/myfirstboot-app/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ myfirstboot-app ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ myfirstboot-app ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ myfirstboot-app ---
[WARNING] JAR will be empty - no content was marked for inclusion!
[INFO] Building jar: /Users/lin/tmp/bootdemo/myfirstboot-app/target/myfirstboot-app-1.0.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.421 s
[INFO] Finished at: 2019-07-17T12:19:05+08:00
[INFO] ------------------------------------------------------------------------
构建成功,不过我们发现会有一个警告,提示jar包为空:[WARNING] JAR will be empty - no content was marked for inclusion!
,现在先不用管它,因为我们尚未用到任何依赖。
spring-boot-starter-parent 可以让接下来的其他boot依赖省掉版本标签。例如下面的web依赖无需再指定版本。
可以使用mvn dependency:tree
来分析当前pom中的所有依赖:
$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< io.favorstack:myfirstboot-app >--------------------
[INFO] Building myfirstboot-app 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ myfirstboot-app ---
[INFO] io.favorstack:myfirstboot-app:jar:1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.487 s
[INFO] Finished at: 2019-07-17T12:44:58+08:00
[INFO] ------------------------------------------------------------------------
4.3 添加一个web应用依赖
Spring Boot提供了许多开发特定应用的“Starters”依赖项,比如,我们要开发一个web应用,可以在pom
中加入以下web依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
现在,再次执行mvn dependency:tree
,我们会发现多了许多依赖:
$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< io.favorstack:myfirstboot-app >--------------------
[INFO] Building myfirstboot-app 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ myfirstboot-app ---
[INFO] io.favorstack:myfirstboot-app:jar:1.0.0-SNAPSHOT
[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:2.1.6.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter:jar:2.1.6.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot:jar:2.1.6.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.6.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.6.RELEASE:compile
[INFO] | | +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] | | | +- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] | | | \- org.slf4j:slf4j-api:jar:1.7.26:compile
[INFO] | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.2:compile
[INFO] | | | \- org.apache.logging.log4j:log4j-api:jar:2.11.2:compile
[INFO] | | \- org.slf4j:jul-to-slf4j:jar:1.7.26:compile
[INFO] | +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] | +- org.springframework:spring-core:jar:5.1.8.RELEASE:compile
[INFO] | | \- org.springframework:spring-jcl:jar:5.1.8.RELEASE:compile
[INFO] | \- org.yaml:snakeyaml:jar:1.23:runtime
[INFO] +- org.springframework.boot:spring-boot-starter-json:jar:2.1.6.RELEASE:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.9:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO] | | \- com.fasterxml.jackson.core:jackson-core:jar:2.9.9:compile
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.9:compile
[INFO] | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.9:compile
[INFO] | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.9:compile
[INFO] +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.1.6.RELEASE:compile
[INFO] | +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.21:compile
[INFO] | +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.21:compile
[INFO] | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.21:compile
[INFO] +- org.hibernate.validator:hibernate-validator:jar:6.0.17.Final:compile
[INFO] | +- javax.validation:validation-api:jar:2.0.1.Final:compile
[INFO] | +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile
[INFO] | \- com.fasterxml:classmate:jar:1.4.0:compile
[INFO] +- org.springframework:spring-web:jar:5.1.8.RELEASE:compile
[INFO] | \- org.springframework:spring-beans:jar:5.1.8.RELEASE:compile
[INFO] \- org.springframework:spring-webmvc:jar:5.1.8.RELEASE:compile
[INFO] +- org.springframework:spring-aop:jar:5.1.8.RELEASE:compile
[INFO] +- org.springframework:spring-context:jar:5.1.8.RELEASE:compile
[INFO] \- org.springframework:spring-expression:jar:5.1.8.RELEASE:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.938 s
[INFO] Finished at: 2019-07-17T12:50:12+08:00
[INFO] ------------------------------------------------------------------------
主要有spring-boot-starter-web,spring-boot-starter-json,spring-boot-starter-tomcat,hibernate-validator,spring-web,spring-webmvc等。
4.4 Hello world示例代码
由于我们使用Maven构建管理我们的应用,所以源代码的目录结构需要遵循Maven风格的目录结构:
1). 首先在pom
文件同级下创建src/main/java
目录,并创建一个Example.java
文件:
$ mkdir -p src/main/java && touch src/main/java/Example.java
2). 然后在刚才创建的Example.java
文件中编写以下代码:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableAutoConfiguration
public class Example {
@RequestMapping("/")
String home() {
return "Hello world!";
}
public static void main(String[] args) {
SpringApplication.run(Example.class, args);
}
}
3). 运行:
直接执行mvn spring-boot:run
命令即可启动,启动完毕,可以直接在浏览器中访问localhost:8080,没问题的话,应该能看到如下内容了:
Hello world!
run定义于spring-boot-starter-parent这个pom
4). 停止:
直接在终端中按ctrl+c
即可。
4.4.1 @EnableAutoConfiguration注解
@EnableAutoConfiguration
注解可以让Spring Boot根据我们所添加的jar依赖来猜测我们想如何配置Spring应用上下文。例如我们添加了spring-boot-starter-web
之后,会将Tomcat和SpringMVC的相关依赖一块引入,它会因此推测出我们是在开发一个web应用,并自动按web应用需要的配置来配置好,我们无需再去配置要扫描哪些包,哪些配置文件之类,当然,配置都是按默认值来的,比如Tomcat端口8080,这也体现了约定优于配置
的思想,除非你想要更改默认配置,否则无需关注。
另外还有一个注解@SpringBootApplication,该注解等价于同时声明@Configuration,@EnableAutoConfiguration,@ComponentScan这三个注解。
通常推荐将@EnableAutoConfiguration注解放到根包中(如果没有使用@SpringBootApplication的话),这样所有的子包和类都可以被搜索到。
4.4.2 main方法
该方法就是一个Java应用程序的标准入口main
方法。该方法通过调用run
方法来将执行权委托给Spring Boot的SpringApplication
类,最终由SpringApplication
类来引导我们的应用,并在此过程中完成spring及Tomcat容器的配置和启动。另外,该类的run
方法需要两个参数,第一个为一个类,告知SpringApplication
哪个类是要加载的主要的Spring组件;第二个为命令行参数列表。
4.5 生成可执行jar包
与普通的jar包不同的是,可执行jar包中会包含代码运行所需要的所有依赖,这种jar包通常体积很大(内嵌了许多其他jar包),所以又被称为fat-jar(这个词很形象)。
更多关于Spring Boot可执行jar包的内容可以参考executable-jar。
1). 首先在pom
加入依赖:
<build>
<plugins>
<!-- 打包为可执行jar文件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
spring-boot-starter-parent
的POM中包含了<executions>
配置,绑定了repackage
目标。如果不使用该parent POM,那么需要自己手动声明该配置,详见 plugin documentation
2). 打包:
$ mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< io.favorstack:myfirstboot-app >--------------------
[INFO] Building myfirstboot-app 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ myfirstboot-app ---
[INFO] Deleting /Users/lin/tmp/bootdemo/myfirstboot-app/target
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ myfirstboot-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/lin/tmp/bootdemo/myfirstboot-app/src/main/resources
[INFO] skip non existing resourceDirectory /Users/lin/tmp/bootdemo/myfirstboot-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ myfirstboot-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/lin/tmp/bootdemo/myfirstboot-app/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ myfirstboot-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/lin/tmp/bootdemo/myfirstboot-app/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ myfirstboot-app ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ myfirstboot-app ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ myfirstboot-app ---
[INFO] Building jar: /Users/lin/tmp/bootdemo/myfirstboot-app/target/myfirstboot-app-1.0.0-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.6.RELEASE:repackage (repackage) @ myfirstboot-app ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.529 s
[INFO] Finished at: 2019-07-17T13:00:19+08:00
[INFO] ------------------------------------------------------------------------
3). 运行程序:
java -jar target/myfirstboot-app-1.0.0-SNAPSHOT.jar
4). 停止:
同样直接在终端中按ctrl+c
即可。
5). 如果查看target
目录下的编译打包结果会发现有两个jar包:
$ ll target/
total 32808
drwxr-xr-x 8 lin staff 256 7 17 13:16 ./
drwxr-xr-x 5 lin staff 160 7 17 13:16 ../
drwxr-xr-x 4 lin staff 128 7 17 13:16 classes/
drwxr-xr-x 3 lin staff 96 7 17 13:16 generated-sources/
drwxr-xr-x 3 lin staff 96 7 17 13:16 maven-archiver/
drwxr-xr-x 3 lin staff 96 7 17 13:16 maven-status/
-rw-r--r-- 1 lin staff 16791006 7 17 13:16 myfirstboot-app-1.0.0-SNAPSHOT.jar
-rw-r--r-- 1 lin staff 2472 7 17 13:16 myfirstboot-app-1.0.0-SNAPSHOT.jar.original
其中体积较大的myfirstboot-app-1.0.0-SNAPSHOT.jar
为Spring Boot插件重新打包的jar,这个即为可执行jar包;另一个myfirstboot-app-1.0.0-SNAPSHOT.jar.original
是Maven打包的原始jar,只包含我们自己编写的代码,体积较小,不能单独运行。
可以使用jar tvf target/myfirstboot-app-1.0.0-SNAPSHOT.jar
命令查看jar包的内部结构。
4.6 注意事项
需要注意的是,原本我们开发的是一个Java web应用,但似乎这里的可执行jar包并没有接触到Servlet容器相关的东西,千万不要以为这是Spring Boot提供了该运行时环境的能力,只不过是Spring Boot默认把Servlet容器引入进来给我们简化掉这一操作罢了,即便不使用Spring Boot,你也同样可以编写这种内嵌Servlet容器形式的web应用,如嵌入Tomcat,Jetty等,但这要额外写更多的代码。
五 Spring Initializr
最后,Spring Boot还提供了一个Initializr
工具,用于生成Spring Boot基本的项目结构。可以直接访问https://start.spring.io/来打开该页面:
根据需要选择好各个选项后,点击下边的Cenerate the project
按钮即可下载打包好的项目结构。
不管是之前我们手动创建的项目结构,还是用Initalizr
导出的,此时都可以导入你喜欢的IDE中继续开发,当然,一些IDE也提供了直接初始化Spring Boot项目的功能,例如Idea:
参考:
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/getting-started-system-requirements.html
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/getting-started-installing-spring-boot.html
https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/getting-started-first-application.html
版权声明:知识共享署名-非商用-非衍生 (CC BY-NC-ND 3.0) 转载请注明出处