使用Spring Boot快速构建应用

Spring Boot于2014年4月发布1.0.0版本, 用于创建Spring 4.0项目, 简化了Spring中繁琐的配置, 提高了开发效率



Spring Boot简介

  • Spring Boot致力于快速构建应用, 去掉了Spring的繁琐配置, 使创建Spring应用就像写一个main函数一样方便.
  • 直接嵌入TomcatJetty服务器, 不需要部署 WAR 文件, 可以直接run
  • XML配置(也支持导入XML配置)
  • 构建Spring4应用, 最好使用高版本环境(JDK8, Maven3.2+, Servlet3.0+)
  • 提供了maven插件, 可把应用及所需要的所有依赖包内嵌到一个jar包中
  • 提供了一个命令行工具Spring Boot CLI(安装方法)
  • 支持Groovy编程语言

CLI和Groovy示例

Spring Boot CLI是一个命令行工具, 可以快速搭建Spring原型, 支持Groovy脚本.
我们通过CLI使用Groovy脚本创建一个最简单的Web应用, 创建一个app.groovy文件, 内容如下:

@RestController
class ThisWillActuallyRun {
    @RequestMapping("/")
    String home() {
        "Hello World!"
    }
}

然后在shell中运行下面命令:

$ spring run app.groovy

则已经运行了一个Spring web应用(首次运行需要下载依赖包, 比较慢), 访问127.0.0.1:8080就会看到输出内容Hello World!


快速创建一个应用

通过Maven创建一个Spring Boot应用, 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.example.project</groupId>
    <artifactId>spring_boot</artifactId>
    <version>1.0</version>

    <!-- 继承spring-boot-starter-parent是最快的方式, 后面有不继承该怎么写 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.1.RELEASE</version>
    </parent>
    <!-- 这一个依赖就够了 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

可以通过mvn dependency:tree来看看都用到了哪些jar包

src/main/java/目录下创建一个类src/main/java/Example.java:

@RestController
@EnableAutoConfiguration
public class Example {
    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Example.class, args);
    }
}

到此整个应用就创建完毕, 可以直接运行main方法启动容器, 访问127.0.0.1:8080


运行容器的方式

  • 像上面那样直接运行main方法
  • 通过mvn spring-boot:run命令运行
  • 创建可执行jar包运行

通过插件spring-boot-maven-plugin可将应用及依赖打成jar包, 如果没有继承spring-boot-starter-parent则需要主动添加一下这个插件, 并且parent中的<executions>需要自己进行配置

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
        </plugin>
    </plugins>
</build>

通过命令mvn package打包, 将会得到target/spring_boot-1.0.jar文件, 可通过命令jar tvf target/myproject-1.0.jar查看该jar包的结构. 除此之外, 还有个文件target/spring_boot-1.0.jar.original, 这是Spring Boot重新打包之前, Maven创建的原始jar文件

使用命令java -jar target/spring_boot-1.0.jar即可运行


依赖管理

上面都是以继承spring-boot-starter-parent的形式进行一来管理, 这个parent里有如下内容:

  • 指定了Java的版本, 和编码(不继承parent可自己指定)
  • 配置, 除了接受原有的Spring形式的`${…​}`, 还支持了Maven的`@..@`形式(不继承parent可自己指定)
  • 包依赖管理, 继承自spring-boot-dependencies(不继承parent的形式就是引入这个pom)
  • 插件配置(不继承parent需要自己配置)

因此, 如果不继承spring-boot-starter-parent, 我们的pom文件可以这么写:

    <properties>
        <java.version>1.8</java.version>
        <resource.delimiter>@</resource.delimiter> <!-- delimiter that doesn't clash with Spring ${} placeholders -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <tomcat.version>7.0.57</tomcat.version> <!-- 配置你的tomcat版本 -->
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.4.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- 如果是通过parent方式继承spring-boot-starter-parent则不用配置此插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

目录结构及配置

官方建议项目有一个标准的目录结构, 就像其他Spring项目一样, 包名采用一个反转的域名, 结构类似于下面这样:

com.example.myproject
         +- Application.java
         |
         +- service
         |   +- CustomerService.java
         |
         +- controller
             +- CustomerController.java

其中Application.java的内容如下:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

该项目中Application.java为main类, 将main类放到其他类所在包的顶层(root package), 并将@EnableAutoConfiguration注解加main类上, 这样就隐式地定义了一个基础包扫描路径, 所以采用root package时, @ComponentScan注解就不需要添加basePackage属性了

解释下这几个注解的意思:

  • @Configuration: 表示一个配置类, 类似于原来的一个xml文件
  • @EnableAutoConfiguration: Spring Boot的自动配置会根据所添加的jar包依赖自动配置Spring应用, 通常项目中只有一个@EnableAutoConfiguration注解, 并建议将它加到主配置类(primary @Configuration)上
  • @ComponentScan: 包扫描路径, 采用root package形式会自动收集root package包下所有组件, 包括配置类(@Configuration类)

由于平时配置main类时, 频繁的一起使用@Configuration、@EnableAutoConfiguration、@ComponentScan这三个注解, 因此Spring Boot提供了一个简单的注解SpringBootApplication来代替这三个注解, 其效果与这三个注解一起使用的效果完全一样

另外, 还有几个有用的用法:

  • @Import: 导入其他配置类
  • @ImportResource: 引入XML形式的配置
  • @EnableAutoConfiguration(exclude={XXXConfiguration.class})排除某些配置, 若配置类不在classpath中, 可以使用excludeName属性指定全限定名