运用Spring Boot

start.spring.io可以直接下载Spring Boot项目

|
|   pom.xml
|
|
\---src
    +---main
    |   +---java
    |   |   \---com
    |   |       \---zdx
    |   |           \---readinglist
    |   |                   ReadingListApplication.java
    |   |
    |   \---resources
    |       |   application.properties
    |       |
    |       +---static
    |       \---templates
    \---test
        \---java
            \---com
                \---zdx
                    \---readinglist
                            ReadingListApplicationTests.java

查看初始化Spring Boot 新项目

  • 目录结构遵循传统Maven项目的布局
  • 主要的应用代码位于src/main/java
  • 资源文件位于src/main/resources
  • 测试代码在src/test/java
  • 如果有测试资源的话,应在src/test/resources

主要的文件:

  • ReadingListApplication.java应用程序的启动引导类(bootstrap class),也是主要的Spring配置类。
  • application.properties用于配置应用程序和Spring Boot的属性。
  • ReadingListApplicationTests.java一个基本的集成测试类。

启动引导Spring

ReadingListApplication.java在Spring中有两个作用:

  1. 配置
  2. 启动引导

虽然Spring Boot的自动配置免除了很多Spring配置,但你还需要进行少量配置来启用自动配置

默认情况下只有一行配置代码:

package com.zdx.readinglist;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//开启组件扫描和自动配置
public class ReadingListApplication {

    public static void main(String[] args) {
        //负责启动引导应用程序
        SpringApplication.run(ReadingListApplication.class, args);
    }

}
  • @SpringBootApplication开启了Spring的组件扫描和Spring Boot的自动配置功能,但实际上@SpringBootApplication将三个有用的注解组合在了一起:
    • @Configuration 标明该类使用Spring基于Java的配置...
    • @ComponentScan 启用组件扫描,这样自定义的Web控制器类和其他组件才会被自动发现并注册为Spring应用程序上下文里面的Bean
    • @EnableAutoConfiguration 也被称为@Abracadabra :就是这一行配置开启了Spring Boot自动配置

配置应用程序的属性

默认生成的application.properties文件是一个空文件

如果application.properties存在就会被加载,无需指定

application.properties使用例子:

server.port=8000

加上这一行,嵌入式Tomcat的监听端口就变成了8000

Spring Boot 项目构建过程解析

Spring Boot为Gradle 和 Maven提供了构建插件 以便辅助构建Spring Boot项目...

选择Maven会替你生成一个pom.xml文件,其中使用了Spring Boot的Maven插件

<?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>

    <!--从 spring-boot-starter parent继承版本号-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zdx</groupId>
    <artifactId>readinglist</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Reading List</name>
    <description>Reading List Demo</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <!-- 起步依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!--运用Spring Boot插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • 构建插件的主要功能是把项目打包成一个可执行的超级JAR(uber-JAR),包括把应用程序的所有依赖打入JAR文件内,并为JAR添加一个描述文件,其中的内容能让你用java -jar来运行应用程序。

  • 除了构建插件,还将spring-boot-starter-parent作为上一级,这样一来就能利用Maven的依赖管理功能继承很多常用库的依赖版本,在你声明依赖时就不用再去指定版本号了。请注意,这个pom.xml里的<dependency>都没有指定版本

起步依赖

首先,假设不存在起步依赖,用Spring MVC的话,我们得晓得以下几点:

  1. 需要哪个Spring依赖
  2. Thymeleaf的Group和Artifact ID
  3. 用哪个版本的Spring Data JPA
  4. 兼容问题

而这只不过是开发一个Spring Web应用程序,使用Thymeleaf视图,通过JPA进行数据持久化.但是在敲代码前,我们需要明白,要支持我们的项目,需要往POM.XML中加入哪些东西.

可能有以下几个:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>2.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
         <version>2.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
        <version>2.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.1.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <version>2.1.7.RELEASE</version>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.17</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.1.7.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-test</artifactId>
        <version>5.1.6.RELEASE</version>
        <scope>test</scope>
    </dependency>
</dependencies>

这段依赖列表不错,应该能正常工作,但任何得知?在一行代码都没写的情况下,我们离开始构建还有很长的路要走

  • 让我们退一步再想想,我们要做什么。我们要构建一个拥有如下功能的应用程序。
    • 这是一个Web应用程序。
    • 它用了Thymeleaf
    • 它通过Spring Data JPA在关系型数据库里持久化数据

如果我们只在构建文件里指定这些功能,让构建过程自己搞明白我们要什么东西,岂不是更简单?这正是Spring Boot起步依赖的功能

覆盖起步依赖引入的传递依赖

以Spring Boot的Web起步依赖为例,它传递依赖了Jackson JSON库。如果你正在构建一个生产或消费JSON资源表述的REST服务,那它会很有用。但是,要构建传统的面向人类用户的Web应用程序,你可能用不上Jackson。虽然把它加进来也不会有什么坏处,但排除掉它的传递依赖,可以为你的项目瘦身.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.fasterxml.jackson.core</groupId>
        </exclusion>
    </exclusions>
</dependency>

另一方面,也许项目需要Jackson,但你需要用另一个版本的Jackson来进行构建,而不是Web起步依赖里的那个。假设Web起步依赖引用了Jackson 2.3.4,但你需要使用2.4.3。在Maven里,你可以直接在pom.xml中表达诉求,就像这样:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.3</version>
</dependency>

使用自动配置

在向应用程序加入Spring Boot时,有个名为spring-boot-autoconfigure的JAR文件,其中包含了很多配置类。每个配置类都在应用程序的Classpath里,都有机会为应用程序的配置添砖加瓦。这些配置类里有用于Thymeleaf的配置,有用于Spring Data JPA的配置,有用于Spiring MVC的配置,还有很多其他东西的配置,你可以自己选择是否在Spring应用程序里使用它们。

所有这些配置如此与众不同,原因在于它们利用了Spring的条件化配置,这是Spring 4.0引入的新特性。条件化配置允许配置存在于应用程序中,但在满足某些特定条件之前都忽略这个配置。

在Spring里可以很方便地编写你自己的条件,你所要做的就是实现Condition接口,覆盖它的matches()方法。举例来说,下面这个简单的条件类只有在Classpath里存在JdbcTemplate时才会生效...

public class JdbcTemplateCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        try {
            context.getClassLoader().loadClass("org.springframework.jdbc.core.JdbcTemplate");
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}

而当你用Java来声明Bean的时候,可以使用这个自定义条件类:

@Conditional(JdbcTemplateCondition.class)
public MyService myService() {
    ...
}

在这个例子里,只有当JdbcTemplateCondition类的条件成立时才会创建MyService这个Bean。也就是说MyService Bean创建的条件是Classpath里有JdbcTemplate。否则,这个Bean的声明就会被忽略掉。

这些配置类构成了Spring Boot的自动配置。 Spring Boot运用条件化配置的方法是,定义多个特殊的条件化注解,并将它们用到配置类上

09-06 14:28