Spring Boot 学习笔记

参考资料

Spring Boot 简介

Spring Boot 使创建基于 Spring 的应用程序变得轻松,只需要做到“just run”就能创建一个独立的、产品级别的 Spring 应用程序。官方为 Spring 平台及第三方库提供了相对固定的搭配,所以开始的时候会轻松很多。大部分的 SpringBoot 应用程序都只需要很少的 Spring 配置。

可以使用 SpringBoot 创建应用程序,通过 java -jar 命令或者传统的 war 包部署方式来启动它。也提供了一个命令行工具来运行“spring 脚本”。

SpringBoot 的目标是:

  • 从根本上提供更加快速和简便的 Spring 开发体验。
  • 开箱即用,但定制开发也很便捷。
  • 提供一些大型项目常用的非功能性特性(例如:嵌入式服务、安全、监控、健康检查、外部配置)。
  • 不用生成代码,没有 xml 配置。

使用 Maven 进行配置

Spring Boot 依赖的 groupId 是 org.springframework.boot。通常情况下,MavenPOM 文件继承自 spring-boot-starter-parent 项目,并且声明一些“Starters”。Spring Boot 也提供了一些创建可执行 jar 文件的 Maven 插件。

继承 spring-boot-starter-parent 项目是不错的使用 Spring Boot 的方式,但是有时候可能还是有不适配的问题。有些时候您可能需要继承子不同的父 POM,或者仅仅是和我们的默认配置有所区别。查看Section 13.2.2, “Using Spring Boot without the parent POM”,这是使用了导入方式的一种解决方案。

经典的 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>
<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.example<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>myproject<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>0.0.1-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">parent</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-parent<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.5.2.RELEASE<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
	<span class="hljs-comment">&lt;!--web应用基本环境配置 --&gt;</span>
	<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
		<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
		<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
	<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>

</project>

java 代码

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;

@SpringBootApplication
public class MainApplicion {

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception {
	SpringApplication.run(MainApplicion.class, <span class="hljs-string">"--server.port=8081"</span>);
}

}

import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@Controller
public class SampleController {

	@ResponseBody
	@RequestMapping(value = "/")
	String home() {
		return "Hello World!";
	}

}

运行

直接执行 main 方法。

或者生成可执行的 jar 包,如果要生成可执行的 jar 包,需要把 spring-boot-maven-plugin 添加到 pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

打包mvn package,运行java -jar target/myproject-0.0.1-SNAPSHOT.jar

打开浏览器http://localhost:8081/,即可看到Hello World!

附:不使用 parent POM 的配置方式

<dependencyManagement>
     <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.5.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

使用 Spring Boot CLI

介绍

Spring Boot CLI 是一个命令行工具,如果想要快速获取一个 Spring 样品程序,可以使用到它。Spring Boot CLI 是一个命令行工具,如果想要快速获取一个 Spring 样品程序,可以使用到它。有了它,您可以运行 Groovy 脚本,这意味着您可以使用熟练的类 Java 语法,而不是超多的样板代码。

使用 CLI 这个命令行工具来做 Spring Boot 开发并不是必须的,但它确实是一个开发 Spring 应用程序最快捷的方式。

下载地址

http://repo.spring.io/snapshot/org/springframework/boot/spring-boot-cli/

使用

windows 的话,下载解压即可。

快速开始 Spring CLI 实例

新建一个文件,文件名是 app.groovy:

@RestController
class ThisWillActuallyRun {
<span class="hljs-meta">@RequestMapping("/")</span>
String <span class="hljs-title function_">home</span><span class="hljs-params">()</span> {
    <span class="hljs-string">"Hello World!"</span>
}

}

运行

spring run app.groovy

打开浏览器http://localhost:8080,即可看到Hello World!

使用 @SpringBootApplication 注解

许多使用 Spring Boot 的开发者总是有带有 @Configuration, @EnableAutoConfiguration 和 @ComponentScan 注解的主类。由于这些注解很频繁地被用在一起,基于最佳实践,Spring Boot 提供了一个方便的注解 @SpringBootApplication 来替代。

@SpringBootApplication 等价于使用 @Configuration, @EnableAutoConfiguration 和 @ComponentScan 默认属性的情况。

Starters

Starters 是 Spring boot 提供的便利,可以一站式的对依赖进入引入,命名格式为“spring-boot-starter-*”,如“spring-boot-starter-test”则集成了 JUnit 跟 Mockito,用于跑测试用例。

开发工具

Spring Boot 包含一系列工具,可以使应用开发的过程更方便一点。spring-boot-devtools 模块可以包含进任何工程,用来提供额外的程序调试特性。为了添加工具支持,简单的添加模块依赖到你的构建系统中:

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

当 classpath 中的文件修改时,使用 spring-boot-devtools 的应用会自动重启。当使用 IDE 开发时,这是一个很有用的功能,因为代码改变时它能快速的进行反馈。默认情况下,会监控 classpath 指向的文件夹中任何条目的变化。注意某些资源例如静态资源和视图模板不需要重启应用。作为 DevTools 监视器 classpath 中的资源,触发重启的唯一方式是更新 classpath。

Spring Boot 提供的 restart 技术是通过两个类加载器进行工作的。加载进基类加载器的类不能改变(例如,那些第三方 jar 包)。那些你正在开发的类加载进重启类加载器中。当应用重启时,丢弃旧的重启类加载器并创建一个新的。这种方法意味着应用重启是比“cold starts” 更快,因为基类加载器已经存在并可用。

某些资源当它们改变时不一定需要触发重启。默认不触发重启的有/META-INF/maven, /META-INF/resources ,/resources ,/static ,/public or /templates。修改默认行为,可修改配置spring.devtools.restart.exclude=static/**,public/**;如果是在默认的基础上进行添加不触发行为,可使用spring.devtools.restart.additional-exclude

启动失败

如果你的应用启动失败,注册 FailureAnalyzers 有可能会提供专门的错误信息和解决这个问题的具体行动。例如,如果你启动一个 8080 端口的 web 应用并且这个端口已经被占用,你应该会看到类似于下面的内容:

***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

如果没有任何失败分析器的话,可以开启 debug(默认的
日志级别是INFO),属性名为“org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer”,如果是通过java -jar运行的,还可以使用--debug进行开启,如java -jar myproject-0.0.1-SNAPSHOT.jar --debug

自定义 Banner

默认情况下,Spring Boot 的打印内容如下

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.2.RELEASE)

如果要修改,可在 classpath 下创建一个文件,名称为“banner.txt”,编写自己要的内容即可。

关闭 banner

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(MySpringConfiguration.class);
    app.setBannerMode(Banner.Mode.OFF);
    app.run(args);
}

应用事件与监听器

在 ApplicationContext 创建之前实际上会触发一些事件,因此你不能使用 @Bean 来注册这些监听器。你可以通过SpringApplication.addListeners()SpringApplicationBuilder.listeners()来注册这些监听器。
如果你想自动注册这些监听器,不管上下文的创建方式,你可以在你的工程中添加 META-INF/spring.factories 文件,并通过 org.springframework.context.ApplicationListener 作为 key 来引用你的监听器。

当应用运行时,运用的发送顺序

  1. ApplicationStartingEvent
  2. ApplicationEnvironmentPreparedEvent
  3. ApplicationPreparedEvent
  4. ApplicationReadyEvent
  5. ApplicationFailedEvent

web 环境

SpringApplication将试图创建一个正确类型的ApplicationContext。如果是 web 应用,创建一个AnnotationConfigEmbeddedWebApplicationContext ,否则创建一个AnnotationConfigApplicationContext

访问应用参数

启动应用时,我们会通过SpringApplication.run(args)添加启动参数 args,我们可通过注入org.springframework.boot.ApplicationArguments来获取启动参数。

在应用启动过程中做一些事

实现ApplicationRunnerCommandLineRunner接口。

应用退出拦截

使用 @PreDestroy 注解或实现org.springframework.boot.ExitCodeGenerator接口

可变配置

可通过“application.properties”(或 YAML 变量)对默认配置进行修改。

通过命令行对配置进行修改,即SpringApplication.run(MainApplicion.class, args)中的args参数,如--server.port=9000则启动端口变成了 9000。

配置随机数

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

把配置文件中的配置绑定到 Bean 中,可使用@value,还可以使用@ConfigurationProperties,如下

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
@ConfigurationProperties(prefix="my")
public class Config {
<span class="hljs-keyword">private</span> List&lt;String&gt; servers = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;String&gt;();

<span class="hljs-keyword">public</span> List&lt;String&gt; <span class="hljs-title function_">getServers</span><span class="hljs-params">()</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.servers;
}

}

profile(不同环境读取不同配置)

不同环境的配置设置一个配置文件,例如:dev 环境下的配置配置在 application-dev.properties 中;pro 环境下的配置配置在 application-pro.properties 中。

各个环境公共的配置写在 application.properties 中。

各个模块独有的配置配置在自己的 application-{xxx}.properties 文件中。

指定某一环境运行,使用spring.profiles.active进行配置

SpringApplication.run(MainApplicion.class, "--spring.profiles.active=dev");

日志

说明

默认日志框架是“Commons Logging”,但如果是用“Starters”,那么默认日志框架是“Logback”

默认打印级别是INFO,若要开启,有两种方式

java -jar myapp.jar --debug

在 application.properties 中添加debug=true

文件输出

默认是只打打印在控制台上,不输出到文件,可配置。

可在 application.properties 中配置logging.filelogging.path

日志级别

格式:logging.level.*=LEVEL,LEVEL 的取值有(TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)

自定义日志格式

根据不同的日志框架,编写不同的配置文件

Logging System Customization
Customization logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

开发 web 应用

Spring MVC 框架

使用HttpMessageConverter转换 HTTP 中的 requests 和 responses

使用 @JsonComponent 注解来实现 JSON 的序列号跟反序列化

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Serializer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">JsonSerializer</span>&lt;SomeObject&gt; {
    <span class="hljs-comment">// ...</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Deserializer</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">JsonDeserializer</span>&lt;SomeObject&gt; {
    <span class="hljs-comment">// ...</span>
}

}

静态资源

默认配置的 /** 映射到 /static (或 /public、/resources、/META-INF/resources),上面的 static、public、resources 等目录都在 classpath: 下面(如 src/main/resources/static)。

优先级顺序为:META/resources > resources > static > public

如:src/main/resources/static/js/test.js 的访问路径为 http://localhost:8080/js/test.js

注意:不要使用src/main/webapp文件夹,因为打成 jar 包时,这个文件夹不会被打包进去。

当我们的资源内容发生改变时,由于浏览器缓存,用户本地的资源还是旧资源,为了防止这种情况发生导致的问题。Spring 在解决这种问题方面,提供了 2 种解决方式:资源名称 md5 方式、资源名称 md5 方式。

错误处理

自定义错误页面

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- static/
             +- error/
             |   +- 404.html
             |   +- 5xx.ftl
             +- <other public assets>

嵌入的 Servlet 容器支持

可使用 @WebServlet, @WebFilter, @WebListener 注解,还有 @ServletComponentScan 注解扫描来支持 Servlet、Filter、Listener

JSP 支持

可参考代码:https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-samples/spring-boot-sample-web-jsp

1、打包方式需要改成 war。

2、添加必要的依赖

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>
<!-- Provided -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-tomcat</artifactId>
	<scope>provided</scope>
</dependency>
<dependency>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-jasper</artifactId>
	<scope>provided</scope>
</dependency>

3、新建文件夹src/main/webapp/WEB-INF/jsp/

4、application.properties 文件添加配置

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

5、创建 Controller 跟 jsp 文件

其他特性

  • Security
  • SQL databases
  • NoSQL technologies
  • Caching
  • Messaging
  • Validation
  • Sending email
  • JTA
  • JMX
  • Testing