【Spring Boot官方文档原文理解翻译-持续更新中】

文章目录

  • 【Spring Boot官方文档原文理解翻译-持续更新中】
  • Chapter 4. Getting Started
    • 4.1. Introducing Spring Boot
    • 4.2. System Requirements
      • 4.2.1. Servlet Containers
    • 4.3. Installing Spring Boot
      • 4.3.1. Installation Instructions for the Java Developer
        • 4.3.1.1. Maven Installation
      • 4.3.2. Installing the Spring Boot CLI
        • Manual Installation
        • Installation with SDKMAN!
        • OSX Homebrew Installation
        • Command-line Completion
    • 4.4. Developing Your First Spring Boot Application
  • Chapter 6. Developing with Spring Boot
    • 6.1. Build Systems
      • 6.1.1. Dependency Management
      • 6.1.2. Maven
      • 6.1.3. Gradle
      • 6.1.4. Ant
      • 6.1.5. Starters
    • 6.2. Structuring Your Code
      • 6.2.1. Using the “default” Package
      • 6.2.2. Locating the Main Application Class
    • 6.3. Configuration Classes
      • 6.3.1. Importing Additional Configuration Classes
      • 6.3.2. Importing XML Configuration
    • 6.4. Auto-configuration
      • 6.4.1. Gradually Replacing Auto-configuration
      • 6.4.2. Disabling Specific Auto-configuration Classes
    • 6.6. Using the @SpringBootApplication Annotation
  • Chapter 8. Web
    • 8.1. Servlet Web Applications
      • 8.1.1. The “Spring Web MVC Framework”
        • Spring MVC Auto-configuration
        • HttpMessageConverters
        • MessageCodesResolver
        • Static Content
        • Welcome Page
        • Custom Favicon
        • Path Matching and Content Negotiation
        • ConfigurableWebBindingInitializer
        • Template Engines
        • Error Handling
      • 8.1.2. JAX-RS and Jersey
        • JSP Limitations
  • Chapter 13. Production-ready Features
    • Spring MVC Metrics
  • Chapter 17. “How-to” Guides
    • 17.1. Spring Boot Application
    • 17.3. Embedded Web Servers
      • 17.3.1. Use Another Web Server
      • 17.7.2. Configure Log4j for Logging
      • 17.16.9. Build an Executable Archive from Ant without Using spring-boot-antlib
  • Appendices
    • Appendix A: Common Application Properties
      • A.11. Server Properties

Chapter 4. Getting Started

如果你想要入门 Spring Boot 或是 Spring,就从阅读这一部分开始吧。它会回答这些基础的 “ 是什么 ?”、“ 怎么做 ?” 和 “ 为什么 ?” 等这类问题,并且包含了 Spring Boot 的介绍和使用说明。稍后我们将指导您搭建第一个 Spring Boot 应用,并且谈论一些核心原则。

4.1. Introducing Spring Boot

Spring Boot 帮助您创建一个单例的、生产级的且基于 Spring 的应用程序。我们对 Spring 平台和第三方库保持中立,所以您可以以最少的麻烦开始,大多数的 Spring Boot 应用甚至只需要很少的(几乎没有的)Spring 配置。

您可以通过 Spring Boot 创建的 Java 应用程序,这些程序通过 java -jar 命令或者传统 war 包依赖启动,除此之外,我们还提供了一个运行 “ spring scripts ” 的命令行工具。

我们的主要目标是:

4.2. System Requirements

Spring Boot 2.7.2 需要 Java 8 支持并且兼容包含 Java 18 在内的更高 JDK 版本。Spring Framework 5.3.22 或者更高版本也需要。

为下列搭建工具提供了显式支持:

Build Tool Vesion
Maven 3.5+
Gradle 6.8.x, 6.9.x, 和 7.x

4.2.1. Servlet Containers

Spring Boot 支持下列的内置 servlet 容器:

Name Servlet Version
Tomcat 9.0 4.0
Jetty 9.4 3.1
Jetty 10.0 4.0
Undertow 2.0 4.0

此外,您也可以把 Spring Boot 应用部署在任何兼容 servlet 3.1+ 版本的容器中

4.3. Installing Spring Boot

Spring Boot 可与 “ classic ” Java 开发工具一起使用或者作为命令行工具安装,如果您不想用这两种方式 没关系,您只需要有 Java SDK v1.8 或更高版本。在开始之前,使用下列命令检查电脑当前安装的 Java 版本

$ java -version

如果您是 Java 开发菜鸟或者只是想尝试一下 Spring Boot 框架,您最好先试试 Spring Boot CLI (Spring Boot 命令行接口),除此之外,最好阅读一下 “ classic ” 的安装指导。

4.3.1. Installation Instructions for the Java Developer

您可以像使用任何 Java 标准库那样使用 Spring Boot,为此,请包含适当版本的 spring-boot-*.jar 文件在您的类路径上。因为 Spring Boot 不需要任何指定的集成工具,所以您可以使用任何 IDE (全称是Intergration Development Environment,意为集成开发环境)或者编辑器。此外,Spring Boot 平平无奇,所以您可以像运行其他的 Java 程序一样去运行和调试 Spring Boot 应用。

虽然您可以复制 Spring jar 包,但是我们通常建议使用支持依赖管理的搭建工具(例如 Maven 或者 Gradle)

4.3.1.1. Maven Installation

Spring Boot 兼容 Apache Maven 3.3+ 版本。如果您还没有安装 Maven 的话,建议您按照 maven.apache.org 站点上的说明进行安装和配置。

TIP

在大多数的操作系统上,Maven 可与包管理器一起安装,如果您使用 OSX Homebrew 包管理器的话,尝试 brew install maven 命令安装Maven。Ubuntu 用户运行 sudo apt-get install maven 命令安装 Maven。带有 Chocolatey 软件的 Windows 用户可以从高级(管理员)提示符中运行 choco install maven 安装 Maven。

Spring Boot 依赖使用 org.springframework.boot.groupId。通俗地说,您的 Maven POM 文件继承 spring-boot-starter-parent 项目并且声明一个或多个 “ 启动器 ” 的依赖。此外,Spring Boot 也提供了可选的 Maven 插件来创建可执行 jar 包

4.3.2. Installing the Spring Boot CLI

Spring Boot CLI (Command Line Interface:命令行接口) 是一个命令行工具,用于快速使用 Spring 原型。它允许运行 Groovy 脚本,这意味着只需很少的样板代码,因为您熟悉 Java 语法。

您不一定需要通过 CLI 使用 Spring Boot,但是它是一个快捷的方法,无需 IDE 也可以脱离后台获取 Spring 应用

Manual Installation

您可以从 Spring 软件仓库下载 Spring CLI 发行版:

  • spring-boot-cli-2.7.2-bin.zip

  • spring-boot-cli-2.7.2-bin.tar.gz

此外,还提供最新的快照发行版本。

下载后,从解压缩开始按照 INSTALL.txt 指导文件进行操作。综上所述,这是一个 .zip 文件中 bin/ 目录 下的spring 脚本(spring.bat 适用于Windows操作系统)。此外,java -jar 命令可以与 .jar 文件一起使用(脚本有助于您正确设置 classpath 目录)

Installation with SDKMAN!

SDKMAN!(软件开发工具管理员)用于管理多个版本的各种二进制软件开发工具包,其中包含 Groovy 和 Spring Boot CLI。从 sdkman.io 站点中获取 SDKMAN 并且使用下列命令安装 Spring Boot:

$ sdk install springboot
$ spring --version
Spring CLI v2.7.2

如果您想为 CLI 开发功能并且想要访问自己构建的版本,那么请使用下列命令:

$ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-bootcli-2.7.2-bin/spring-2.7.2/
$ sdk default springboot dev
$ spring --version
Spring CLI v2.7.2

前面的指导安装了一个名为 dev 的本地 spring 实例。因为它指向了您的搭建目标位置,所以每次重构 Spring Boot 时,Spring 都是最新的。

您可以运行下列命令进行查看:

$ sdk ls springboot
================================================================================
Available Springboot Versions
================================================================================
> + dev
* 2.7.2
================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

OSX Homebrew Installation

如果您在 Mac 上使用 HomeBrew,可以使用下列命令安装 Spring Boot CLI:

$ brew tap spring-io/tap
$ brew install spring-boot

Homebrew 将 spring 安装到 /usr/local/bin 目录。

NOTE

如果您没有看到公式,那么您安装的 brew 可能已经过时。在这种情况下,运行 brew update 并且再试一次

Command-line Completion

Spring Boot CLI 包含 BASH 和 zsh 的 shell 命令脚本,您可以在任何 shell 中使用 source 命令脚本(也叫spring)或者…

4.4. Developing Your First Spring Boot Application

依赖管理 并且可以发布到 “ Maven Central ” 仓库(Maven 中心仓库)的依赖自动化搭建系统,最好使用 Maven 或者 Gradle。当然也可以让 Spring Boot 与其他的自动化搭建系统一起工作(例如:Ant),不过对比前面两种,我们对其他的自动化搭建系统支持力度不大。

6.1.1. Dependency Management

所有的 Spring Boot 的发行版本都提供了它所支持的一个依赖管理列表。在实践中,您不需要为这些依赖提供版本号,Spring Boot 将会为您自动管理。因为当您更新升级 Spring Boot 时,这些依赖也会同时进行更新升级,所以您无须担心。

NOTE

如果您有需要的话,可以指定某个依赖的版本号并且覆盖 Spring Boot 推荐的依赖版本号

依赖管理列表包含了所有可以和 Spring 模块一起使用的第三方库的依赖细化列表。这个列表可以作为一个标准的材料清单 (spring-boot dependencies),用于 Maven 或者 Gradle

Warning

所有的 Spring Boot 的发行版本都和 Spring 框架的一个基础版本相关联,强烈建议您不要指定其版本号

6.1.2. Maven

要了解如何使用 Spring Boot 和 Maven,请查看 Spring Boot 的 Maven 插件文档:

  • 参考 (HTML 和 PDF)

  • API

6.1.3. Gradle

要了解如何使用 Spring Boot 和 Gradle,请查看 Spring Boot 的 Gradle 插件文档:

  • 参考 (HTML 和 PDF)

  • API

6.1.4. Ant

搭建 Spring Boot 项目可以使用 Apache 的 Ant + lvy。spring-boot-antlib模块也有助于 Ant 创建可执行的 jar 包。

要声明依赖关系,一个典型的ivy.xml文件如下所示:

<ivy-module version="2.0"><info organisation="org.springframework.boot" module="spring-boot-sample-ant" /><configurations><conf name="compile" description="everything needed to compile this module" /><conf name="runtime" extends="compile" description="everything needed to run
this module" /></configurations><dependencies><dependency org="org.springframework.boot" name="spring-boot-starter"rev="${spring-boot.version}" conf="compile" /></dependencies>
</ivy-module>

一个典型的build.xml文件如下所示:

<projectxmlns:ivy="antlib:org.apache.ivy.ant"xmlns:spring-boot="antlib:org.springframework.boot.ant"name="myapp" default="build"><property name="spring-boot.version" value="2.7.2" /><target name="resolve" description="--> retrieve dependencies with ivy"><ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" /></target><target name="classpaths" depends="resolve"><path id="compile.classpath"><fileset dir="lib/compile" includes="*.jar" /></path></target><target name="init" depends="classpaths"><mkdir dir="build/classes" /></target><target name="compile" depends="init" description="compile"><javac srcdir="src/main/java" destdir="build/classes"
classpathref="compile.classpath" /></target><target name="build" depends="compile"><spring-boot:exejar destfile="build/myapp.jar" classes="build/classes"><spring-boot:lib><fileset dir="lib/runtime" /></spring-boot:lib></spring-boot:exejar></target>
</project>

TIP

如果您不想使用spring-boot-antlib模块,请查看 “How-to Guides” 中的 Build an Executable Archive from Ant without Using spring-boot-antlib

6.1.5. Starters

启动器是一套方便的依赖描述符,可以将其包含在应用程序中。您可以获得所有 Spring 和其相关技术的一站式服务,而不需要查找示例代码并且复制粘贴大量的依赖描述符。 例如,如果您想要使用 Spring 和 JPA 访问数据库,请在项目中包含 spring-boot-starter-data-jpa启动器

启动器包含许多快速启动和运行项目所需的依赖,并且具有一致的受支持的托管依赖传递关系

在一个名称里的东西是什么?

所有的官方启动器都遵循一个类似的命名模板: spring-boot-starter-** 是一个独特的应用类型。这种命名结构旨在当需要找到启动器时提供帮助。大部分的 IDE 中集成的 Maven 允许按名称查找依赖,例如,安装了合适的 Eclipse 或者是 Spring Tools 插件后,在 POM 编辑器中按 ctrl + space 键入 “ spring-boot-starter ” 可以获得完整的依赖列表。

正如 “ Creating Your Own Starter ” (创建自己的启动器)所言,第三方启动器不应该以 spring-boot 开头,因为这是为 Spring Boot 官方依赖所保留的。当然,一个第三方启动器常常会以项目的名称作为开头(所以一般不用担心)。比如,一个叫做 thirdpartproject 的第三方项目将会毫无疑问地以 thirdpartproject-spring-boot-starter 命名。

Spring Boot 的org.springframework.boot分组提供下面的应用启动器:

表1.Spring Boot 应用启动器

Name Description
spring-boot-starter Spring Boot 的核心启动器,包含自动配置支持,日志记录和 YAML
spring-boot-starter-activemq 专为 JMS(Java消息服务:是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。)使用Apache的ActiveMQ消息队列发送消息而生的启动器
spring-boot-starter-amqp 用于 Spring 的 AMQP(AMQP:即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议)和Rabbit MQ(RabbitMQ:这是一个开源消息代理软件。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。)的启动器
spring-boot-starter-aop 用于 Spring AOP 切面方向的编程和 AspectJ 的启动器
spring-boot-starter-artemis 专为 JMS 使用 Apache 的 Artemis 而生的启动器
spring-boot-starter-batch 用于 Spring 批处理任务的启动器
spring-boot-starter-cache 用于 Spring 框架缓存支持的启动器
spring-boot-starter-data-cassandra 用于 Cassandra 分布式数据库(Cassandra:是一套开源分布式NoSQL数据库系统。它最初由Facebook开发,用于储存收件箱等简单格式数据,集GoogleBigTable的数据模型与Amazon Dynamo的完全分布式的架构于一身Facebook于2008将 Cassandra 开源,此后,由于Cassandra良好的可扩展性,被Digg、Twitter等知名[Web 2.0](https://baike.baidu.com/item/Web 2.0)网站所采纳,成为了一种流行的分布式结构化数据存储方案。)和String Data Cassandra的启动器
spring-boot-starter-data-cassandra-reactive 用于 Cassandra 分布式数据库和 String Data Cassandra Reactive 的启动器
spring-boot-starter-data-couchbase 专为使用 Couchbase 面向文档数据库(CouchBase:是一款开源的、分布式的、面向文档的NoSQL数据库,主要用于分布式缓存和数据存储领域。能够通过manage cache提供快速的亚毫米级别的k-v存储操作,并且提供快速的查询和其功能强大的能够指定SQL-like查询的查询引擎。)和 Spring Data Couchbase 而生的启动器
spring-boot-starter-data-couchbase-reactive 用于 Cassandra 分布式数据库和 String Data Cassandra Reactive 的启动器
spring-boot-starter-data-elasticsearch 用于 Elasticsearch 搜索(Elasticsearch:是位于 Elastic Stack 核心的分布式搜索和分析引擎。Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监控堆栈。Elasticsearch 是索引、搜索和分析魔法发生的地方。)、分析引擎和Spring Data Elasticsearch的启动器
spring-boot-starter-data-jdbc 用于Spring Data JDBC(JDBC:全称Java Database Connectivity,也即Java数据库连接,简称JDBC。它是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。)的启动器
spring-boot-starter-data-jpa 用于 Spring Data JPA(JPA:JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。)与Hibernate(Hibernate:是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JavaEE架构中取代CMP,完成数据持久化的重任。)的启动器
spring-boot-starter-data-ldap 用于 Spring Data LDAP(LDAP:全称Lightweight Directory Access Protocol, 意为轻型目录访问协议,它是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。)的启动器
spring-boot-starter-data-mongodb 用于 MongoDB 面向文档数据库(MongoDB:是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。)和 Spring Data MongoDB 的启动器
spring-boot-starter-data-mongodb-reactive 用于 MongoD B面向文档数据库和 Spring Data MongoDB Reactive 的启动器
spring-boot-starter-data-neo4j 用于Neo4j图形数据库(Neo4j:是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。)和Spring Data Neo4j的启动器
spring-boot-starter-data-r2dbc 用 于Spring Data R2DBC 的启动器
spring-boot-starter-data-redis 用于 Spring Data Redis 存储 Redis 键值对与和 Lettuce client 的启动器
spring-boot-starter-data-redis-reactive 用于 Spring Data Redis reactive 存储 Redis 键值对和 Lettuce client 的启动器
spring-boot-starter-data-rest 专为 Spring Data REST 在 Rest 上公开 Spring Data 仓库而生的启动器
spring-boot-starter-freemarker 专为使用FreeMarker视图(FreeMarker:是一款模板引擎, 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网络、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。)搭建 MVC 网络应用而生的启动器
spring-boot-starter-graphql 用于 Spring GraphQL 搭建 GraphQL 应用的启动器
spring-boot-starter-groovy-templates 用于 Groovy 模板视图(Groovy:是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy也可以使用其他非Java语言编写的库。)搭建MVC网络应用的启动器
spring-boot-starter-hateoas 用于 Spring MVC 搭建基于超媒体和 Restful 风格的网络应用和 Spring HATEOAS 的启动器
spring-boot-starter-integration 用于 Spring Integration 的启动器
spring-boot-starter-jdbc 用于 HikariCP 连接池使用 JDBC 的启动器
spring-boot-starter-jersey 用于 JAX-RS 和 Jersey 搭建 Restful 风格的网络应用的启动器。此外,也可以选用spring-boot-starter-web
spring-boot-starter-jooq 用于 JDBC 使用 jOOQ 访问 SQL 数据库的启动器。此外,也可以选用 spring-bootstarter-data-jpa 或者是spring-boot-starter-jdbc
spring-boot-starter-json 用于读写JSON(JSON:全称JavaScript Object Notation, JS对象简谱,这是一种轻量级的数据交换格式。它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。)的启动器
spring-boot-starter-jta-atomikos 专为JTA事务(JTA:即Java Transaction API,JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JDBC驱动程序的JTA支持极大地增强了数据访问能力。)使用Atomikos(Atomikos: 是一个为Java平台提供增值服务的并且开源类事务管理器。)而生的启动器
spring-boot-starter-mail 用于 Java 和 Spring 框架的邮件发送支持的启动器
spring-boot-starter-mustache 用于 Mustache 视图搭建网络应用的启动器
spring-boot-starter-oauth2-client 用于 Spring Security 的 OAuth2(OAuth2:是一种授权框架,提供了一套详细的授权机制(指导)。用户或应用可以通过公开的或私有的设置,授权第三方应用访问特定资源。)或 OpenID 连接客户端特性使用的启动器
spring-boot-starter-oauth2-resource-server 用于 Spring Security 的 OAuth2 资源服务器特性使用的启动器
spring-boot-starter-quartz 用于 Spring Quartz 的启动器
spring-boot-starter-rsocket 用于搭建 RSocket 客户端和服务器的启动器
spring-boot-starter-security 用于 Spring Security 的启动器
spring-boot-starter-test 用于使用包含JUnit Jupiter、Hamcrest 和 Mockito 的依赖代码库测试Spring Boot应用的启动器
spring-boot-starter-thymeleaf 用于 Thymeleaf 视图搭建 MVC 网络应用的启动器
spring-boot-starter-validation 用于使用 Java Bean 验证与 Hibernate 验证器的启动器
spring-boot-starter-web 用于使用 Spring MVC 搭建包含 Restful 风格的网络应用的启动器。使用 Tomcat 作为默认嵌入式容器
spring-boot-starter-web-services 用于 Spring 网络服务的启动器
spring-boot-starter-webflux 用于使用 Spring 框架的 Reactive 网络支持搭建 WebFlux 应用的启动器
spring-boot-starter-websocket 用于使用 Spring 框架的 WebSocket 支持搭建 WebSocket 应用的启动器

除了上面提到的应用启动器,下列启动器常常用于添加 生产就绪 特性:

表2.Spring Boot生产启动器

Name Description
spring-boot-starter-actuator 用于使用Spring Boot的Actuator提供生产就绪特性帮助监督和管理您的应用的启动器

最后,Spring Boot还包含了以下启动器,如果您想排除或者更换指定技术面的话会用到:

表3.Spring Boot技术启动器

Name Description
spring-boot-starter-jetty 用于使用 Jetty 作为内置的 servlet 容器的启动器,也可选用spring-boot-starter-tomcat启动器
spring-boot-starter-log4j2 用于使用 Log4j2 的日志记录的启动器,也可选用spring-boot-starter-logging启动器
spring-boot-starter-logging 用于使用Logback记录日志的启动器,它也是 Spring 默认日志记录启动器
spring-boot-starter-reactor-netty 用于使用 Reactor Netty 作为内置的 reactive HTTP 服务器的启动器
spring-boot-starter-tomcat 用于使用 Tomcat 作为内置的 servlet 容器的启动器,也是spring-boot-starter-web中使用的默认servlet容器启动器
spring-boot-starter-undertow 用于使用 Undertow(Undertow:是一个采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。)作为内置servlet容器的启动器,也可选用spring-boot-starter-tomcat启动器

要了解如何交换技术面,请查看 swapping web serverlogging system 文档

TIP

对于社区贡献的启动器列表,请查看Github上的spring-boot-starters模块中的 README 文件

6.2. Structuring Your Code

Spring Boot 不需要使用任何指定的布局代码来工作,然而,也有些最佳实践是有所帮助的

@SpringBootApplication 注解 常常用于放置在主类上,并且暗中为某些项目定义了一个基础的 “ 搜索包 ” 。例如,如果您编写一个JPA应用,@SpringBootApplication 注释的包将用于定位 @Entity 项。此外,使用根路径包也允许组件扫描仅用于您的项目。

TIP

如果不想使用@SpringBootApplication注解, 它导入的@EnableAutoConfiguration@ComponentScan注解也定义了那些行为(这里的行为指的是组件扫描,自动配置等功能),因此换成这两个注解也是可行的

下面的示例代码展示了一个典型的布局:

com+- example+- myapplication+- MyApplication.java|+- customer| +- Customer.java| +- CustomerController.java| +- CustomerService.java| +- CustomerRepository.java|+- order+- Order.java+- OrderController.java+- OrderService.java+- OrderRepository.java

MyApplication.java 文件将会声明 main 方法,以及基本的 @SpringBootApplication 注解,如下所示:

Java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}}

Kotlin

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {runApplication<MyApplication>(*args)
}

6.3. Configuration Classes

Spring Boot 偏爱基于 Java 的配置,虽然 XML 文件源也可以使用 SpringApplication,但是我们通常建议您的主要来源应当是一个独立的 @Configuration 类。通常地,定义 main 方法的类是一个好的 @Configuration 的候选者

TIP

(虽然)网络上有许多使用 XML 配置 的 Spring Boot 发布示例,(但是)如果可能的话,我们始终建议您使用基于 Java 的相同配置。比如查找 Enable* 开头的注释是一个好的开端

6.3.1. Importing Additional Configuration Classes

您不需要把所有的 @Configuration 放在一个独立的类中,@Import 注解常常用于导入其他的配置类。此外,您还可以使用 @ComponentScan 注解,它会自动装配所有包含 @Configuration 注解的类将其作为 Spring 的组件

6.3.2. Importing XML Configuration

如果您必须要使用基于 XML 的配置,那么我们也建议您先从 @Configuration 类开始,接着使用 @ImportResource 注解加载 XML 配置文件

6.4. Auto-configuration

Spring Boot 自动配置基于添加的 jar 包依赖试图自动构建 Spring 应用程序。例如,如果 HSQLDB (Hyper SQL Database) 在类路径下且没有手动配置任何数据库连接的 bean,那么 Spring Boot 会自动在内存中配置数据库。

通过向其中一个 @Configuration 配置类中添加 @EnableAutoConfiguration 或者 @SpringBootApplication 注解来选择加入自动配置。

TIP

您应该只添加一个 @SpringBootApplication 或者 @EnableAutoConfiguration 注解,通常建议只将其中一个添加到您的 @Configuration 类中

6.4.1. Gradually Replacing Auto-configuration

自动配置是非侵入式的,在任何时候,都可以自定义配置更换特定的自动配置。例如:如果您添加自定义的 DataSource 的 bean,那么默认内置的数据库就会失效.

如果需要了解当前应用的自动配置及其原因,打开应用程序 --debug 开关,这样做可以启用核心日志器作日志调试并且会将情况输出到控制台。

6.4.2. Disabling Specific Auto-configuration Classes

如果发现应用程序中有不想使用的自动配置类,可以使用 @SpringBootAplication 注解的排除属性来禁用他们,如下所示:

Java

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
}

Kotlin

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
@SpringBootApplication(exclude = [DataSourceAutoConfiguration::class])
class MyApplication

如果该类不在类路径下,还可以使用注解的 excludeName 属性并且指定类的全限定名。如果您更喜欢使用 @EnableAutoConfiguration 而不是 @SpringBootApplication 注解,excludeexcludeName 属性也能使用。顺便一提,使用 spring.autoconfigure.exclude 属性,还能排除自动配置类的列表

TIP

排除 (不需要的自动配置类) 不仅可以在注解上而且还能使用属性

NOTE

虽然自动配置类是公共的,但是这些 API 的公共部分只能用于禁用自动配置类。这些类的实际内容,就类似于嵌套配置类或者 bean 方法,只供内部使用,所以我们并不推荐直接使用这些内容

6.6. Using the @SpringBootApplication Annotation

Chapter 8. Web

Spring Boot 非常适合网络应用开发,您可以使用内置的 Tomcat、Jetty、Undertow 或 Netty 创建独立的 HTTP 服务器。多数的网络应用使用 spring-boot-starter-web 模块快速启动和运行。(除此之外)您也可以选择使用 spring-boot-starter-webflux 模块搭建 reactive 网络应用。

如果您还没有开发过 Spring Boot 网络应用,可以按照 Getting started 章节中的示例进行开发。

8.1. Servlet Web Applications

如果想搭建基于 servlet 的网络应用,您可以利用 Spring Boot 的 Spring MVC 或 Jersey 的自动配置实现

8.1.1. The “Spring Web MVC Framework”

Spring Web MVC framework(通常被称为 “ Spring MVC ”)是一个强大的 “ model view controller (模型-视图-控制器)” 的网络框架。Spring MVC 可以让您创建特殊的 @Controller@RestController 的 bean 处理接收的 HTTP 请求,在控制器中的方法使用 @RequestMapping 注解映射 HTTP 请求。

下列代码展示了提供 JSON 数据的典型 @RestController

Java

import java.util.List;import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/users")
public class MyRestController {private final UserRepository userRepository;private final CustomerRepository customerRepository;public MyRestController(UserRepository userRepository, CustomerRepositorycustomerRepository) {this.userRepository = userRepository;this.customerRepository = customerRepository;}@GetMapping("/{userId}")public User getUser(@PathVariable Long userId) {return this.userRepository.findById(userId).get();}@GetMapping("/{userId}/customers")public List<Customer> getUserCustomers(@PathVariable Long userId) {return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get();}@DeleteMapping("/{userId}")public void deleteUser(@PathVariable Long userId) {this.userRepository.deleteById(userId);}
}

Kotlin

import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController@RestController
@RequestMapping("/users")
class MyRestController(private val userRepository: UserRepository, private val
customerRepository: CustomerRepository) {@GetMapping("/{userId}")fun getUser(@PathVariable userId: Long): User {return userRepository.findById(userId).get()}@GetMapping("/{userId}/customers")fun getUserCustomers(@PathVariable userId: Long): List<Customer> {returnuserRepository.findById(userId).map(customerRepository::findByUser).get()}@DeleteMapping("/{userId}")fun deleteUser(@PathVariable userId: Long) {userRepository.deleteById(userId)}
}

“WebMvc.fn” 即功能变体,从实际的请求处理中分离路由配置,如下所示:

Java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.function.RequestPredicate;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;import static org.springframework.web.servlet.function.RequestPredicates.accept;
import static org.springframework.web.servlet.function.RouterFunctions.route;@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);@Beanpublic RouterFunction<ServerResponse> routerFunction(MyUserHandler userHandler) {return route().GET("/{user}", ACCEPT_JSON, userHandler::getUser).GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers).DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser).build();}
}

Kotlin

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.web.servlet.function.RequestPredicates.accept
import org.springframework.web.servlet.function.RouterFunction
import org.springframework.web.servlet.function.RouterFunctions
import org.springframework.web.servlet.function.ServerResponse@Configuration(proxyBeanMethods = false)
class MyRoutingConfiguration {@Beanfun routerFunction(userHandler: MyUserHandler): RouterFunction<ServerResponse> {return RouterFunctions.route().GET("/{user}", ACCEPT_JSON, userHandler::getUser).GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers).DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser).build()}companion object {private val ACCEPT_JSON = accept(MediaType.APPLICATION_JSON)}
}

Java

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;@Component
public class MyUserHandler {public ServerResponse getUser(ServerRequest request) {...return ServerResponse.ok().build();}public ServerResponse getUserCustomers(ServerRequest request) {...return ServerResponse.ok().build();}public ServerResponse deleteUser(ServerRequest request) {...return ServerResponse.ok().build();}
}

Kotlin

import org.springframework.stereotype.Component
import org.springframework.web.servlet.function.ServerRequest
import org.springframework.web.servlet.function.ServerResponse@Component
class MyUserHandler {fun getUser(request: ServerRequest?): ServerResponse {return ServerResponse.ok().build()}fun getUserCustomers(request: ServerRequest?): ServerResponse {return ServerResponse.ok().build()}fun deleteUser(request: ServerRequest?): ServerResponse {return ServerResponse.ok().build()}
}

Spring MVC 是 Spring 核心框架的一部分,详情信息可以在 参考文档 中获取。此外,在 spring.io/guides 中的一些指南也有提及。

TIP

您可以以模块化路由器的定义来定义任意数量 RounterFunction 的 bean,如果需要应用优先级可对 bean 进行排序。

Spring MVC Auto-configuration

Spring Boot 为 Spring MVC 提供适用于大多数应用程序的自动配置

自动配置基于 Spring 的默认值添加下列功能:

  • 包含 ContentNegotiatingViewResolverBeanNameViewResolver 的 bean

  • 支持静态资源服务,包括WebJars(后面的章节将会介绍到)

  • CoverterGenericConverterFormatter 的 bean 自动注册

  • 支持 HttpMessageConverters(后面的章节将会介绍到)

  • MessageCodesResolver 的自动注册(后面的章节将会介绍到)

  • 支持静态 index.html 文件

  • 自动填充 ConfigurableWebBindingInitializer 的 bean(后面的章节将会介绍到)

如果您想要保留这些自定义的 Spring Boot MVC 功能并且获取更多(例如:拦截器,格式化器,视图控制器和其他),添加自己的 WebMvcConfiugurer 类型的 @Configurarion 配置类的同时,@EnableWebMvc 配置的会消失。

如果您想提供定制的 RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver 的实例,并且始终保留自定义的 Spring Boot MVC 功能。您需要声明 一个 WebMvcRegistrations 类型的 bean ,并且使用它来提供这些定制组件的实例。

如果您想完全掌控 Spring MVC,使用 @EnableWebMvc 注解并添加自己的 @Configuration 配置类,或者直接添加自己的 @Configuration 配置类,就像@EnableWebMvc 的 Javadoc 中描述的 @DelegatingWebMvcConfiguration 一样。

NOTE

Spring MVC 使用不同的 ConversionService ,他们会被用来从application.propertiesapplication.yaml 配置文件中读取并转换值。这意味着 PeriodDurationDataSize 不可用并且 @DurationUnit@DataSizeUnit 注解将会被忽略

如果您想定制 Spring MVC 使用的 ConversionService,提供一个带 addFormatters 方法的 WebMvcConfigurer 的 bean。在这个方法中,您可以注册任何您喜欢的转换器,也可以委托给ApplicationConversionService 类提供的静态方法

HttpMessageConverters

Spring MVC 使用 HttpMessageConverter 接口转换 HTTP 请求和响应。合理的默认值是可以做到开箱即用的,例如,对象可以自动地转为 JSON(使用 Jackson 库)或 XML(如果 Jackson 的 XML 扩展可用的话,使用 Jackson 的 XML 扩展,否则使用 JAXB)。在默认情况下,String 使用 UTF-8 编码。

如果您需要添加或定制转换器,使用 Spring Boot 的 HttpMessageConverters 类,如下所示:
Java

import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;@Configuration(proxyBeanMethods = false)
public class MyHttpMessageConvertersConfiguration {@Beanpublic HttpMessageConverters customConverters() {HttpMessageConverter<?> additional = new AdditionalHttpMessageConverter();HttpMessageConverter<?> another = new AnotherHttpMessageConverter();return new HttpMessageConverters(additional, another);}
}

Kotlin

import org.springframework.boot.autoconfigure.http.HttpMessageConverters
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.converter.HttpMessageConverter@Configuration(proxyBeanMethods = false)
class MyHttpMessageConvertersConfiguration {@Beanfun customConverters(): HttpMessageConverters {val additional: HttpMessageConverter<*> = AdditionalHttpMessageConverter()val another: HttpMessageConverter<*> = AnotherHttpMessageConverter()return HttpMessageConverters(additional, another)}
}

任何存在于上下文中的 HttpMessageConverter 的 bean 都被添加到转换器列表,您可以以相同的方式重写默认的转换器。

MessageCodesResolver

Spring MVC 有一个策略,从绑定错误:MessageCodesResolver 中翻译错误信息并生成错误码。如果您设置了 spring.mvc.message-codes-resolver-format 属性的值为 PREFIX_ERROR_CODEPOSTFIX_ERROR_CODE,那么 Spring Boot 创建会为你创建 MessageCodesResolver (详细信息请查看 DefaultMessageCodesResolver.Format 中的枚举)

Static Content

在默认情况下,Spring Boot 从 classpath 路径下的 /static (或 /publicresources/META-INF/resources )目录 或者 ServletContext 的根目录中提供静态内容,Spring MVC 中使用了 ResourceHttpRequestHandler 便于通过添加自己 WebMvcConfigurer 类并且重写 addResourceHandlers 方法来修改(默认的静态资源处理)逻辑。

独立的网络应用程序中,容器中默认的 servlet 也被启用并作为一条退路,如果 Spring 决定不处理它的话,则从 ServletContext 的根目录提供内容。大多数时间下不会发生这种情况(除非你修改了缺省的 MVC 配置),因为 Spring 总是通过 DispatcherServlet 来处理请求。

虽然在默认情况下,资源映射会在 /** 路径上,但是我们可以调换 spring.mvc.static-path-pattern 属性。对于实例,可以实现移动所有资源到 /resources/** 路径,如下所示:
Properties

spring.mvc.static-path-pattern=/resources/**

Yaml

spring:mvc:static-path-pattern: "/resources/**"

您可以使用 spring.web.resources.static-locations 属性 (使用目录位置列表用更换默认值) 自定义静态资源路径,而 servlet 根内容路径 “ / ” 自动添加为位置

除了前面提及的 “ 标准 ” 静态资源位置之外,还有一种特别的情况是 Webjars 的内容。如果他们是以 Webjars 格式打包,任何 /webjars/** 路径上的资源都将从 jar 文件中提供。

TIP

如果您的应用程序打包成 jar 包,则不使用 src/main/webapp 目录。尽管此目录是一个通俗的标准,但是它仅与 war 包一起工作,并且即使您生成了 jar 包它也会通过大多数的构建工具默默忽视掉生成的 jar 包

Spring Boot 还支持 Spring MVC 提供的先进资源处理功能,允许例如缓存清除的静态资源或使用与版本无关的URL Webjars 文件这类情况。

要使用版本无关的 URL Webjars 文件,请添加 webjars-locator-core 依赖,然后声明您的 Webjar 文件。以 jQuery 为例,添加 "/webjars/jquery/jquery.min.js" 文件会导致 "/webjars/jquery/x.y.z/jquery.min.js" 中的 x.y.z 是 Webjar 的版本

NOTE

如果您使用 JBoss,需要声明 webjars-locator-jboss-vfs 依赖代替 webjars-locator-core,否则,所有的 Webjar 包都会被解析为 404

要使用缓存清除,以下配置为所有的静态资源配置缓存清除的方案,高效地在 URL 中添加内容哈希 ,例如 < link href="/css/spring2a2d595e6ed9a0b24f027f2b63b134d6.css" / >

Properties

spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**

Yaml

spring:web:resources:chain:strategy:content:enabled: truepaths: "/**"

NOTE

运行时在模板中链接重写的资源,都要感谢 ResourceUrlEncodingFilter 自动配置的 Thymeleaf 和 FreeMarker 模板引擎。您应当在使用 JSP 时手动声明此过滤器,目前其它模板引擎不自动支持,但是可以自定义模板 宏/助手 以及支持 ResourceUrlProvier 的使用

使用 JavaScript 模块加载器动态加载资源时,重命名文件不是一种选择。这就是为什么也支持其他策略并且可以组合的原因。 一个 “固定的” 策略在 URL 中添加静态版本字符串而不更改文件名,如下所示:

Properties

spring.web.resources.chain.strategy.content.enabled=true
spring.web.resources.chain.strategy.content.paths=/**
spring.web.resources.chain.strategy.fixed.enabled=true
spring.web.resources.chain.strategy.fixed.paths=/js/lib/
spring.web.resources.chain.strategy.fixed.version=v12

Yaml

spring:web:resources:chain:strategy:content:enabled: truepaths: "/**"fixed:enabled: truepaths: "/js/lib/"version: "v12"

有了这个配置,位于 "/js/lib" 下的JavaScript 模块会使用固定的版本策略 ("v12/js/lib/mymodule.js"),而其他资源仍然使用此内容 (< link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css" / >)

有关于更多支持选项,请参阅 WebProperties.Resources 获取

TIP

此功能已在专门的博客文章和 Spring 框架的参考文档)中进行了详细描述

Welcome Page

Spring Boot 支持 静态和模板化的欢迎页面,它首先在配置的静态内容位置下寻找 index.html 文件,如果找不到,它就会寻找 index 模板。如果找到任意一个,它就会自动将其作为应用程序的欢迎页面

Custom Favicon

类似于其他的静态资源,Spring Boot 在配置的静态内容位置下查找 favicon.ico 图标文件,如果存在这样的文件,它会自动将其作为应用程序的图标。

Path Matching and Content Negotiation

Spring MVC 可以通过查看请求路径将传入的 HTTP 请求映射到处理器,并且将其与应用程序中定义的映射相匹配(例如,控制器方法上的@GetMapping 注解)

Spring Boot 默认选择禁用后缀模式匹配,意味着像 "GET /projects/spring-boot.json" 的请求将不会匹配 @GetMapping("/projects/spring-boot") 映射。这被认为是 Spring MVC 应用程序的最佳实践。此特性在主要用于过去未正确发送 " Accept " 请求头的 HTTP 客户端;我们需要确保发送正确的内容类型到客户端。如今,内容协商更可靠。

还有其他的方法可以替代后缀匹配的使用,处理始终不能正确接受 “ Accept” 239 请求头的 HTTP 客户端,使用查询参数确保像 "GET /projects/spring-boot?format=json" 的请求可以将请求映射到 @GetMapping("/projects/spring-boot") :

Properties

spring.mvc.contentnegotiation.favor-parameter=true

Yaml

spring:mvc:contentnegotiation:favor-parameter: true

或者,如果你喜欢的话,可以使用以下配置自定义不同的参数名称:

Properties

spring.mvc.contentnegotiation.favor-parameter=true
spring.mvc.contentnegotiation.parameter-name=myparam

Yaml

spring:mvc:contentnegotiation:favor-parameter: trueparameter-name: "myparam"

虽然大多数标准的媒体类型支持开箱即用,不过您也可以定义一种新的类型:

Properties

spring.mvc.contentnegotiation.media-types.markdown=text/markdown

Yaml

spring:mvc:contentnegotiation:media-types:markdown: "text/markdown"

后缀模式的匹配已经弃用并且在未来的版本中将会被移除。如果您理解警告并且仍然想要让您的应用使用后缀模式进行匹配,那么需要以下配置:

Properties

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true

Yaml

spring:mvc:contentnegotiation:favor-path-extension: truepathmatch:use-suffix-pattern: true

或者,与其打开所有后缀模式,不如仅支持注册后缀模式这样来的更安全些:

Properties

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true

Yaml

spring:mvc:contentnegotiation:favor-path-extension: truepathmatch:use-registered-suffix-pattern: true

作为 Spring Framework 5.3,Spring MVC 支持一些匹配请求路径到控制器处理器的实现策略,原先仅支持 AntPathMatcher 策略,但是现在也提供 PathPatternParser。Spring Boot 现在提供配置属性选择以及新策略的挑选:

Properties

spring.mvc.pathmatch.matching-strategy=path-pattern-parser

Yaml

spring:mvc:pathmatch:matching-strategy: "path-pattern-parser"

有关于为什么要考虑到这个新的实现,请参阅 dedicated blog post

NOTE

PathPatternParser 是优化的实现但是限制了某些可变路径模式的用法并且不兼容后缀模式的匹配 (spring.mvc.pathmatch.use-suffix-pattern, spring.mvc.pathmatch.use-registeredsuffix-pattern) 或用 servlet 前缀映射的 DispatcherServlet (spring.mvc.servlet.path)。

ConfigurableWebBindingInitializer

Spring MVC 使用 WebBindingInitializer 为特定请求初始化 WebDataBinder ,如果您创建自己的 ConfigurableWebBindingInitializer @Bean, 那么 Spring Boot 会自动配置 Spring MVC 来使用它。

“ Server Properties ”

TIP

自定义 ErrorController 的基类是 BasicErrorController ,如果想要为新的内容类型 (默认专门处理 text/html 并且为所有的其他内容提供回调方法 ) 添加处理器,那就少不了它。为此,需要扩展 BasicErrorController 类,添加一个带有 @RequestMapping 注解和 produces 属性的公开方法,并且创建一个新的内容类型的 bean。

您也可以定义一个带有 @ControllerAdvice 注解的类将 JSON 文件自定义为返回特殊的控制器或异常类型,如下所示:

Java

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
importorg.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice(basePackageClasses = SomeController.class)
public class MyControllerAdvice extends ResponseEntityExceptionHandler {@ResponseBody@ExceptionHandler(MyException.class)public ResponseEntity<?> handleControllerException(HttpServletRequest request,Throwable ex) {HttpStatus status = getStatus(request);return new ResponseEntity<>(new MyErrorBody(status.value(), ex.getMessage()),status);}private HttpStatus getStatus(HttpServletRequest request) {Integer code = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);HttpStatus status = HttpStatus.resolve(code);return (status != null) ? status : HttpStatus.INTERNAL_SERVER_ERROR;}
}

Kotlin

import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseBody
import
org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler
import javax.servlet.RequestDispatcher
import javax.servlet.http.HttpServletRequest
@ControllerAdvice(basePackageClasses = [SomeController::class])
class MyControllerAdvice : ResponseEntityExceptionHandler() {@ResponseBody@ExceptionHandler(MyException::class)fun handleControllerException(request: HttpServletRequest, ex: Throwable):ResponseEntity<*> {val status = getStatus(request)return ResponseEntity(MyErrorBody(status.value(), ex.message), status)}private fun getStatus(request: HttpServletRequest): HttpStatus {val code = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE) as Intval status = HttpStatus.resolve(code)return status ?: HttpStatus.INTERNAL_SERVER_ERROR}
}

在上面的示例中,如果在同一包裹中定义的 SomeController 抛出 MyException 异常,会使用 MyErrorBody 的 POJO 的 JSON 形式而不是 ErrorAttributes

在某些情况下,控制器层级的错误处理不会被 度量设施 记录。此外,应用程序可以通过设置将异常作为请求的属性:

Java

import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
@Controller
public class MyController {@ExceptionHandler(CustomException.class)String handleCustomException(HttpServletRequest request, CustomException ex) {request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex);return "errorView";}
}

Kotlin

import org.springframework.boot.web.servlet.error.ErrorAttributes
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.ExceptionHandler
import javax.servlet.http.HttpServletRequest
@Controller
class MyController {@ExceptionHandler(CustomException::class)fun handleCustomException(request: HttpServletRequest, ex: CustomException?):String {request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex)return "errorView"}
}

Custom Error Pages

如果您想对于指定的状态码展示自定义的 HTML 错误页面,那么您应当添加文件到 /error 目录下,并且错误页面也可以是 静态 HTML 文件(也就是说,能被添加到任何的静态资源目录下)或通过使用模板生成。此外,文件的名称应当是确切的状态码或序列掩码。

例如,要映射 404 为静态 HTML 文件,您的目录结构应当如下所示:

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

要使用 FreeMarker 模板映射 所有的 5xx 错误。您的目录结构应当如下所示:

src/+- main/+- java/|     + <source code>+- resources/+- templates/+- error/| +- 5xx.ftlh+- <other templates>

对于很多复杂的映射,您也可以添加实现 ErrorViewResolver 接口的 bean,如下所示:

Java

import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.ModelAndView;
public class MyErrorViewResolver implements ErrorViewResolver {@Overridepublic ModelAndView resolveErrorView(HttpServletRequest request, HttpStatusstatus, Map<String, Object> model) {// Use the request or status to optionally return a ModelAndViewif (status == HttpStatus.INSUFFICIENT_STORAGE) {// We could add custom model values herenew ModelAndView("myview");}return null;}
}

Kotlin

import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver
import org.springframework.http.HttpStatus
import org.springframework.web.servlet.ModelAndView
import javax.servlet.http.HttpServletRequest
class MyErrorViewResolver : ErrorViewResolver {override fun resolveErrorView(request: HttpServletRequest, status: HttpStatus,model: Map<String, Any>): ModelAndView? {// Use the request or status to optionally return a ModelAndViewif (status == HttpStatus.INSUFFICIENT_STORAGE) {// We could add custom model values herereturn ModelAndView("myview")}return null}
}

您也可以使用常规的 Spring MVC 功能例如 @ExceptionHandler 方法 以及@ControllerAdvice 注解,然后,ErrorController 类将会获取任何未处理的异常

Mapping Error Pages outside of Spring MVC

对于未使用 Spring MVC 的应用程序,您可以直接使用 ErrorPageResiter 接口注册 ErrorPages。此抽象与底层内置的 servlet 容器一起工作即使您没有 Spring MVC DispatchServlet

Java

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@Configuration(proxyBeanMethods = false)
public class MyErrorPagesConfiguration {@Beanpublic ErrorPageRegistrar errorPageRegistrar() {return this::registerErrorPages;}private void registerErrorPages(ErrorPageRegistry registry) {registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));}
}

Kotlin

import org.springframework.boot.web.server.ErrorPage
import org.springframework.boot.web.server.ErrorPageRegistrar
import org.springframework.boot.web.server.ErrorPageRegistry
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpStatus
@Configuration(proxyBeanMethods = false)
class MyErrorPagesConfiguration {@Beanfun errorPageRegistrar(): ErrorPageRegistrar {return ErrorPageRegistrar { registry: ErrorPageRegistry ->registerErrorPages(registry) }}private fun registerErrorPages(registry: ErrorPageRegistry) {registry.addErrorPages(ErrorPage(HttpStatus.BAD_REQUEST, "/400"))}
}

NOTE

如果 错误页面 与最终通过 过滤器 处理的路径一起注册,那么 过滤器 必须明确地注册为 错误 分派器,如下所示:

Java

import java.util.EnumSet;
import javax.servlet.DispatcherType;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyFilterConfiguration {@Beanpublic FilterRegistrationBean<MyFilter> myFilter() {FilterRegistrationBean<MyFilter> registration = newFilterRegistrationBean<>(new MyFilter());// 省略实际业务中的代码逻辑registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));return registration;}
}

Kotlin

import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.EnumSet
import javax.servlet.DispatcherType
@Configuration(proxyBeanMethods = false)
class MyFilterConfiguration {@Beanfun myFilter(): FilterRegistrationBean<MyFilter> {val registration = FilterRegistrationBean(MyFilter())// ...registration.setDispatcherTypes(EnumSet.allOf(DispatcherType::class.java))return registration}
}

注意,默认的 FilterRegisterBean 不包含 错误 分派器类型。

Error handling in a war deployment

当部署到 servlet 容器中时,Spring Boot 使用错误页面过滤器转发带有错误状态的请求到对应的错误页面。这是必要的,因为 servlet 规范确实如此,不提供用于注册错误页面的 API,它只依赖于部署的容器、war 文件和应用程序使用的技术,以及一些也许是必要的额外配置。

如果响应没有预先提交的话,错误页面过滤器仅转发请求到正确的错误页面。在默认情况下,WebSphere 应用程序服务器 8.0 以及更高版本提供成功完成 servlet 的服务方法时的响应

8.1.2. JAX-RS and Jersey

JSP Limitations

Chapter 13. Production-ready Features

Spring MVC Metrics

Chapter 17. “How-to” Guides

本文回答了在使用 Spring Boot 时,经常出现的例如 “ 我该怎么做 ” 这类普通问题。它的覆盖范围可能并不详细,但是确实涵盖了很多内容。

如果您有我们没有覆盖到的具体问题,那么您也许需要检查 stackoverflow.com 站点,看看是否有人已经提供了回答。同时这也是一个询问问题的好地方(问的时候请带上 spring-boot 标签)

如果您想要添加问题的回答到 “ How to ” 中,我们也非常荣幸地欢迎您扩展这个章节,只要给我们发送一个拉取代码请求即可

17.1. Spring Boot Application

本节包含了与 Spring Boot 应用相关的话题

17.3. Embedded Web Servers

每个 Spring Boot 网络应用都包含了一个内置的网络服务器,但也就是这个特性 “ 十分厉害 ” ,产生了大量的 “ how-to ” 问题,包括类似于如何去改变内置服务器并且配置它这样的问题等等。如果你对此也有疑问的话,可以从本文开始,因为我们在这里回答了这些问题。

17.3.1. Use Another Web Server

大部分的 Spring Boot 启动器都包含了默认的内置容器

  • 对于 servlet 栈应用,spring-boot-starter-web 通过 spring-boot-starter-tomcat 包含了 Tomcat 网络应用服务器,但我们可以使用 spring-boot-starter-jetty 或者 spring-boot-starter-undertow 进行替换
  • 对于 reactive 栈应用,spring-boot-starter-webflux 通过 spring-boot-starter-reactor-netty 包含了 Reactor Netty 框架,但我们可以使用 spring-boot-starter-tomcatspring-boot-starter-jetty、或者 spring-boot-starter-undertow 进行替换

17.7.2. Configure Log4j for Logging

17.16.9. Build an Executable Archive from Ant without Using spring-boot-antlib

Appendices

Appendix A: Common Application Properties

A.11. Server Properties

【Spring Boot官方文档原文理解翻译-持续更新中】相关推荐

  1. Spring Boot 官方文档学习(一)入门及使用

    Spring Boot 官方文档学习(一)入门及使用 个人说明:本文内容都是从为知笔记上复制过来的,样式难免走样,以后再修改吧.另外,本文可以看作官方文档的选择性的翻译(大部分),以及个人使用经验及问 ...

  2. Spring Boot 官方文档摘要

    Spring Boot 官方文档摘要 一.Develop Your First Spring Boot Application Spring Boot 依赖于 groupId 为 org.spring ...

  3. Spring系列 官方文档(中文翻译)

    以下所有文档均包含多个版本,并支持多语言(英文及中文),后端福利. Spring Framework 中文文档 Spring Boot 中文文档 Spring Cloud 中文文档 Spring Se ...

  4. Spring Boot 官方文档中文版

    目前为最新版 2.5.5. 其他spring文档不断更新中 目前为最新版 2.5.5. 其他spring文档不断更新中 总目录 Spring Boot Reference Documentation ...

  5. 《Spring Boot官方文档》16. 自动配置

    16. 自动配置 Spring Boot的自动配置会尝试根据你添加进来的jar依赖来自动配置你的Spring应用.例如,如果HSQLDB在你的classpath路径上,你没有手动配置任何数据库连接实体 ...

  6. Spring Boot Restful框架搭建和使用【持续更新中】

    2019独角兽企业重金招聘Python工程师标准>>> 1 Spring Boot Restful框架搭建 项目源码地址 2 SpringBoot框架使用技巧记录 2.1 pagea ...

  7. Redis分布式锁(Redlock官方文档的理解)

    Redis分布式锁(Redlock官方文档的理解) 我github博客原文 官网解释 分布式锁在许多不同进程下需要对共享资源进行互斥操作的环境下,十分需要 Redis作者提出了 Redlock 算法 ...

  8. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  9. Android官方文档training中英文翻译目录大全:29篇已翻译,45篇未翻译

    Android官方文档training中英文翻译目录大全:29篇已翻译,45篇未翻译 1. Getting Started Building Your First App: 原文: https://d ...

最新文章

  1. 【图像处理】透视变换 Perspective Transformation
  2. Linux2.6内核PCI驱动程序开发
  3. php 获取对象中的元素个数组长度,php数组长度怎么获取
  4. 训练 yolo 模型
  5. hihocoder 第113周 Fibonacci(动态规划)
  6. 2018年第九届蓝桥杯 第五题:快速排序 (满分9分)
  7. Android开发之获取常用android设备参数信息
  8. Quartz 之入门示例
  9. MongoDB 初学
  10. Android笔记 解析xml文件demo
  11. mysql从文本导入表_[Mysql] 用load data将文本文件数据导入到表
  12. python进阶与数据操控_python进阶(mysql:表操作、数据操作、数据类型)(示例代码)...
  13. LintCode_13 字符串查找
  14. setuna软件使用问题:Win10(专业版)在使用setuna时,启动快捷键(Ctrl+A)截屏后屏幕会放大
  15. MATLAB 人脸识别矩阵(矩阵、相似度)
  16. 计算机领域媒体的分类有,多媒体信息主要有几种类型
  17. selenium录制百度3D地图
  18. 计算机中开方的符号,开方符号-平方根符号怎么打?平方根符号在word和Excel中怎么打?上面 爱问知识人...
  19. ecap捕捉epwm波形的占空比及频率(总结)
  20. 树莓派 3B+/4B 连接“手机热点“或“WiFi“ 后无法上网(必解)

热门文章

  1. 基于图像处理的缺陷检测系统 matlab的设计
  2. 【MySQL】数据库 -- select详解
  3. 《Hadoop.The.Definitive.Guide.4th.Edition.2015.3》学习笔记
  4. 玖逸云黑免费无加密版本源码-亲测可用
  5. BASIS--更换SAP登录背景和个性化的设置
  6. C++ functional头文件
  7. latex 中文正文双栏模板_LaTeX学习指南(一)
  8. libtool的使用
  9. 不动点求数列通项原理_不动点法和数列通项公式
  10. ipad上能安装mysql_CentOS以RPM方式安装MYSQL