Spring 框架最初的Bean管理是通过XML文件来描述的。然后随着业务的增加,应用中存在了大量的XML配置,这些配置包括Spring框架自身的Bean配置,还包括其他框架的集成配置等待,到最后XML文件变得臃肿不堪,难以阅读和管理。随着Spring3.0的发布,Spring开始摆脱XML配置文件,并且在开发过程中大量使用“约定大于配置”的思想来摆脱Spring框架中各类繁复纷杂的配置。在Spring4.0发布后,Spring抽象出了Spring Boot框架。Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速,敏捷地开发新一代基于Spring框架的应用程序。也就是说,Spring Boot并不是用来替代 Spring 的解决方案,而是和Spring框架紧密结合用于提升开发者体验的工具。同时,Spring Boot还集成了大量常用的第三方库的配置,为这些第三方库提供了几乎以零配置的 “开箱即用” 的能力。这样大部分的Spring Boot应用都只需要非常少量的配置代码,让开发者专注于业务逻辑的完成。从最根本来讲,Spring Boot 就是一些依赖库的集合,它能够被任意项目的构建系统所使用。2018年3月1日,Spring Boot 2.0正式版发布。Spring Boot2基于 Java8 和 Spring Framework5。我们可以使用Spring Boot创建Java应用,并使用java -jar启动它,或者采用传统的WAR部署方式。
IDEA 全称 IntelliJ IDEA,是java编程语言的集成开发环境。IntelliJ IDEA是 JetBrains 的旗舰产品,主要分为Ultimate收费版本和Community Edition免费版本。本章节使用的是Community Edition 2020版本,大家可以去官方网站:https://www.jetbrains.com.cn/idea/download 去下载 “ideaIC-2020.3.4.exe” 。安装过程我们就不详细介绍了。
接下来,我们就使用IDEA来创建Spring Boot工程,可以使用 Maven 和 Spring Initializr 两种方法来创建。 首先,我们使用IDEA来创建一个Maven工程 “SpringBootDemo”
左边是我们的工程结构,右边是pom.xml文件内容。
在我们之前创建项目工程的时候,我们要做的第一件事情,就是导入Jar文件。其次,文件结构也需要梳理清楚,例如,src目录存放Java源码,build目录存放编译生成的.class文件,而WebContent则是www目录。这些工作难度不大,但是非常琐碎且耗时。如果每一个项目都自己搞一套配置,肯定会一团糟。我们需要的是一个标准化的Java项目管理和构建工具。Maven就是是专门为Java项目打造的管理和构建工具,要使用Maven的话,可以去Maven官网(https://maven.apache.org/)下载并安装。但是我们的Idea集成开发工具已经包含Maven了。
它的主要功能有:
1.提供了一套标准化的项目结构;
2.提供了一套标准化的构建流程(编译,测试,打包,发布……);
3.提供了一套依赖管理机制。
一个使用Maven管理的普通的Java项目,它的目录结构默认如下:
-maven-project
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ ├── java
│ └── resources
└── target
项目的根目录 maven-project 是项目工程名称,它有一个项目描述文件pom.xml,这个文件非常重要。然后,存放Java源码的目录是 src/main/java,存放资源文件的目录是 src/main/resources,存放测试源码的目录是src/test/java,存放测试资源的目录是src/test/resources,最后,所有编译、打包生成的文件都放在 target 目录里。这些就是一个Maven项目的标准目录结构。所有的目录结构都是约定好的标准结构,我们千万不要随意修改目录结构。使用标准结构不需要做任何配置,Maven就可以正常使用。在这里我们可以发现,Maven的默认工程结构与我们的JavaWeb工程结构是不一样的。它并没有代表WebContent的www目录,因为Maven的标准目录结构并不是针对Web项目制定的。我们重点来看最关键的一个项目描述文件pom.xml,它的内容长得像下面:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>SpringBootDemo</finalName>
</build>
</project>
其中,groupId类似于Java的包名,artifactId通常是项目名称,version是项目版本,一个Maven工程就是由groupId,artifactId 和 version作为唯一标识。重点就是下面的 <dependencies> 标签,它由多个子标签 <dependency> 构成,每一个 <dependency> 都代表一个Jar依赖库文件,如下就是junit库文件,版本是3.8.1
使用 <dependency>声明一个依赖库后,Maven就会自动下载这个依赖包并把它放到classpath中。也就是说,我们不需要在手动添加Jar文件到工程里面了,只需要简单做几个标签配置,我们就能在工程里面使用该Jar库文件了。对于某个依赖库,Maven只需要3个变量即可唯一确定某个jar包:
groupId: 属于组织的名称,类似Java的包名;
artifactId: 该jar包自身的名称,类似Java的类名;
version: 该jar包的版本。
通过上述3个变量,即可唯一确定某个jar包。Maven如何知道从何处下载所需的依赖?也就是相关的jar包?答案是Maven维护了一个中央仓库(repo1.maven.org),所有第三方库将自身的jar以及相关信息上传至中央仓库,Maven就可以从中央仓库把所需依赖下载到本地。我们也可以登录仓库网站(https://mvnrepository.com)去单独下载库文件(例如Spring Jar包等等)。Maven并不会每次都从中央仓库下载jar包。一个jar包一旦被下载过,就会被Maven自动缓存在本地目录(我们可以手动改变这个目录),所以,除了第一次编译时因为下载需要时间会比较慢,后续过程因为有本地缓存,并不会重复下载相同的jar包。除了可以从Maven的中央仓库下载外,还可以从Maven的镜像仓库下载。如果访问Maven的中央仓库非常慢,我们可以选择一个速度较快的Maven的镜像仓库。Maven镜像仓库定期从中央仓库同步,中国区用户可以使用阿里云提供的Maven镜像仓库。使用Maven镜像仓库需要一个配置,我们需要创建一个 settings.xml 配置文件,内容如下:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository/>
<interactiveMode/>
<offline/>
<pluginGroups/>
<servers/>
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云中央仓库</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
<mirror>
<id>central-repos</id>
<mirrorOf>central</mirrorOf>
<name>maven.apache.org中央仓库</name>
<url>http://repo.maven.apache.org/maven2</url>
</mirror>
<mirror>
<id>central-repos1</id>
<mirrorOf>central</mirrorOf>
<name>maven.org中央仓库</name>
<url>http://repo1.maven.org/maven2/</url>
</mirror>
</mirrors>
<proxies/>
<profiles/>
<activeProfiles/>
</settings>
我们如何在Idea中配置呢?菜单栏点击 “File” -> “Settings...” , 然后侧边栏选择“Build,Execution,Deployment” -> “Build Tools” -> “Maven”
上面的“settings.xml”就是默认的Maven仓库配置文件,我们可以替换掉我们自己的;然后再“Local Repository”一项中可以设置本地的库文件缓存路径,我们也可以修改到其他目录下。不要忘了勾选后面的 “Override” 重写复选框。 接下来,我们修改项目编码,点击菜单栏 File -> Settings,然后在左边找到 Editor -> File Encodings ,将 GBK 编码全部改成 UTF-8 格式,如下所示
接下来介绍 “Starter” ,Starter用于快速启动Spring应用的“启动器”,其本质是将业务相关的技术框架进行集成。这样,开发者就无须关注应用程序依赖配置的细节,大大简化了启动Spring应用的时间。Starter是Spring boot的核心,它就是一整套Jar库的集合包。常用的starter还有spring-boot-starter-web、spring-boot-starter-test、spring-boot-starter-jdbc,spring-boot-starter-redis,spring-boot-starter-data-mongodb等等。
接下来,我们就使用SpringBoot来做JavaWeb开发。我们只需要将 spring-boot-starter-web 依赖包纳入进来即可。通过Maven导入Spring Boot的starter模块,可以将许多程序依赖包自动导入工程中,省去了我们之前一个一个导入的繁琐配置。我们修改一下 “pom.xml” 文件内容,增加 spring boot web 的支持
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.13</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
添加完“spring-boot-starter-parent”和“spring-boot-starter-web”的支持之后,就可以通过Maven下载他们了。
点击最右边的“Maven”展开侧边栏,然后点击“刷新”按钮即可。 下载完毕后(红色字体变成上图中正常的灰色字体),我们可以去设置本地的库文件缓存路径查看一下
看到这里,大家就比较熟悉了,这就是 SpringFramework 框架了。
同时,在项目工程的外部库(External Libraries)列表中,就会自动添加Web相关的依赖库。
我们可以看到,Spring Boot帮我们自动导入了Spring Web相关的依赖库文件了。这里面除了我们刚刚看到的Spring框架的Jar文件之外,还有很多其他库文件,比如Tomcat库文件。为什么要引入Tomcat库文件呢?Tomcat不是我们运行的Web服务器嘛。SpringBoot对于Web开发的话,帮助我们内嵌了Tomcat服务器。也就是说,我们使用SpringBoot开发的JavaWeb项目,不需要再部署到Tomcat服务器下了,只需要一个jdk就可以启动了。因此,大家应该可以想到,我们的SpringBootWeb项目想要运行起来的话,首先要将Tomcat运行起来。Tomcat如何运行起来呢?这就又回到了我们Java程序的入口main方法了。也就是说,SpringBoot项目的是从入口main方法开始的。它的作用之一就是启动Tomcat服务器,而后再做项目相关的配置启动。
接下来,我们就在"src/main/java"下创建一个包含入口main方法的“Application”类。 首先,我们在“java”上右击,选择 “new” -> “Java Class”,输入我们的包“com.demo.Application”后回车
然后添加我们的入口main方法,如下所示
package com.demo;
public class Application {
public static void main(String[] args) {
}
}
每一个Spring Boot应用程序都有一个拥有main方法的入口类,也就是我们创建的“Application”的java类。为了能够让Spring Boot识别它,我们需要使用 “@SpringBootApplication” 注解来标记它,并且在main方法中运行当前 “Application” 类,如下所示:
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
注意,以上代码只是当前Spring Boot应用程序的启动入口。既然我们是Web程序,就应该需要添加一个Controller控制器来处理用户请求URL。
接下来,我们就创建一个HelloController的控制器,如下所示:
package com.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello spring boot!";
}
}
我们使用了@RestController注解 和 @RequestMapping注解,这两个注解从名称就能知道是做什么的了。大家注意的是我们的hello方法,它的返回类型是字符串,也就是我们的 “hello spring boot!” 。这里的字符串并不是简单的字符串,而是JSON格式的字符串。我们的工程结构如下
我们如何运行整个工程呢?
我们点击选择“Application”类文件,然后右击选择 “Run Application.main”
控制器已经打印出Tomcat运行在8080端口成功的信息了。
我们可以打开浏览器,直接访问 “http://localhost:8080/hello” 看看
与我们之前访问不同的是,这里我们不在输入“SpringBootDemo”这个繁琐的的二级目录了。另外,只要我们运行一次我们的项目工程,就会在Idea的工具栏右侧显示快捷启动方式
我们的入口类“Application.java”位于“com.demo”包路径下,而我们的控制器“HelloController.java”也位于“com.demo”包路径下。我们虽然使用注解“@RestController”标记了“HelloController.java”,但是这并不代表Spring就知道这个类是就是一个控制器,Spring还需要通过 “<context:component-scan />” 进行扫描“com.demo”这个路径才行。我们在哪里配置这个扫描器呢?注解“@RestController”显然没有这个功能,它本质是 @Controller 和 @ResponseBody 的组合注解,所以并没有扫描的功能。那最后就是我们使用的注解@SpringBootApplication了。这个注解本质是@Configuration,@EnableAutoConfiguration和@ComponentScan的组合注解。看到这个 @ComponentScan 大家应该比较清楚了,它就是刚刚我们介绍的<context:component-scan />。注解 @ComponentScan 会自动扫描指定包下的全部标记有@Component的类并将其注册成Spring Bean,当然也包括@Component的子注解 @Service,@Respository 和 @Controller。我们使用 @ComponentScan 注解入口类 Application,就代表Spring会扫描该入口类所在包路径(com.demo)下的所有@Component类(也包括com.demo.xxx子路径下)。只有这样,Spring才能扫描到我们创建的 “HelloController.java” 类并正确识别为控制器。当然,我们还可以将所有控制器放置到 “com.demo.controller” 包路径下。同时,我们还可以添加我们其他的Service层和Respository 层代码。 总之,使用SpringBoot的注解方式开发JavaWeb真是非常的简便了,而且还内置了Tomcat服务器。
如何将我们的Spring Boot应用程序打包发布出去呢? 我们需要一个打包插件spring-boot-maven-plugin,我们在pom.xml中添加这个插件。 而且还要在pom.xml 文件中指定打包类型,指定生成 的是 jar 还是 war。
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
</plugin>
</plugins>
</build>
这是SpringBoot自己提供的插件,它可以在maven的生命周期package后重新打包,生成自己的jar包结构。核心为repackage,它会在maven package之后执行,生成一个新的jar包,将之前的jar包命名为 xxx.original。也就是说,使用spring-boot-maven-plugin插件打包时,默认生成两个包:*.jar 和 *.jar.original。这样生成的 *.jar可直接运行,但不能被其他项目模块依赖。这是因为repackage将项目的class都放在了jar包 BOOT-INF/classes 文件夹中,导致其他模块不能加载jar包中的class。
我点击上图中的 “package” 按钮就开始打包我们的项目工程了
最后,在我们的当前工程“target”目录下生成JAR文件
我们直接在当前目录下运行 “cmd” ,使用java命令来运行该Jar文件。
java -jar SpringBootDemo-1.0-SNAPSHOT.jar
和我们之前在IDEA中运行差不多,然后我们可以再浏览器访问:http://localhost:8080/hello
由此可见,使用Spring Boot开发Web应用程序非常方便,部署就更加简单了。
关于Spring Boot的配置,可以在工程的 resources 文件夹中创建一个 application.properties 或 application.yml 文件。这个文件会被发布到classpath中,并且被 Spring Boot 自动读取。例如,我们希望修改tomcat的端口为80,可以使用如下方式。我们创建一个 application.properties 文件,然后录入以下内容即可。
server.port = 80
server.tomcat.uri-enconding = UTF-8
再次启动当前工程,访问路径就变成 “http://localhost/hello” 了