SpringBoot简介

316 阅读6分钟

简介

SpringBoot是用来简化Spring应用的初始搭建和开发过程的新框架,该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置;它内置Tomcat或Jetty等Servlet容器,并提供自动配置的“starter”项目对象模型以简化Maven配置.

SpringBoot框架有两个重要的策略:开箱即用和约定优于配置。

  • 开箱即用:指在开发过程中,通过在MAVEN项目的pom文件中添加相关依赖包,然后使用对应注解来代替繁琐的XML配置文件以管理对象的生命周期。

  • 约定优于配置:通过约定来减少配置。框架应假定合理默认值(在大部分情况下,你会发现使用框架提供的默认值会让你的项目开发起来效率更快)。

    比如当我们导入一个 spring-boot-starter-web 后,就约定我们是在一个web开发环境,然后自动帮我们导入 Spring MVC 的相关依赖。(而不是Struct2之类的)

第一个SpringBoot

本例的SpringBoot版本为2.2.0,IDEA版本2019.3.1

创建后的项目结构为:

依赖文件:

<?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.on1</groupId>
    <artifactId>springbootMaaven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.2.0.RELEASE</version>
        <relativePath/>
    </parent>

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

    </dependencies>

    <!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
    <build>
        <plugins>

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

        </plugins>
    </build>

</project>

在maven的安装目录的settings.xml文件夹下添加阿里云镜像:

 <mirrors>
	<!-- 阿里云镜像 -->
	<mirror> 
	    <id>alimaven</id> 
		<name>aliyun maven</name> 
		<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
		<mirrorOf>central</mirrorOf> 
	</mirror>

</mirrors>

类:

package com.on1;

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

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}
@Controller
public class HelloController {
    @ResponseBody
    @RequestMapping("/halo")
    public String hello() {
        return "hello world";
    }
}

运行MainApplication程序后,访问 http://localhost:8080/hello

我们还可以将整个工程打包:点击pachage

然后就会可以多出的打包的jar包

Spring Initializer

IDE支持使用Spring的项目创建向导来快速创建一个SpringBoot项目,创建步骤如下:

步骤1

步骤2

完成后的项目结构图如下:

删除掉.gitignore,mvnw,mvnw.cmd后,将原来项目的两个类拷贝进来:

解释一下resources文件夹的目录结构:

  • static:保存所有的静态资源,如js css images;
  • templates:保存所有模板页面,可以使用模板引擎
  • application.properties:SpringBoot应用的配置文件,可以修改一下默认配置。比如可以通过server.port=8081来修改端口

简介流程

相关依赖

在前面我们往项目里的pom.xml导入了一个父项目依赖:

<parent>
 <!-- 项目的父工程是org.springframework.boot-->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/> 
</parent>

而org.springframework.boot也有一个父项目,

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.0.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
  </parent>

之后我们导入的spring-boot相关依赖默认不需要写版本。

然后我们导入了一个依赖:

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

spring-boot-starter是一个场景启动器,它帮我们导入了web模块正常运行所依赖的组件。如果我们希望某些特定功能,比如redis,只需在项目里引入这些starter相关场景的依赖即可。

主程序类

//该注解表示该类是主配置类,通过运行该方法启动SpringBoot应用。
@SpringBootApplication
public class HaloworldQuickstartApplication {
    public static void main(String[] args) {
        SpringApplication.run(HaloworldQuickstartApplication.class, args);
    }
}

SpringBootApplication注解

@Target({ElementType.TYPE})     //可以给一个类型进行注解,比如类、接口、枚举
//可以保留到程序运行的时候,它会被加载进入到 JVM 中
@Retention(RetentionPolicy.RUNTIME)
@Documented             //将注解中的元素加入文档javadoc中
@Inherited              //被该注解注释的类的子类也会拥有注解@SpringBootTest
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

@SpringBootConfiguration注解

该注解标注的类表示是一个SpringBoot的配置类

@Configuration
public @interface SpringBootConfiguration {
}

@EnableAutoConfiguration注解

该注解负责开启自动配置功能

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage注解

该注解负责将主配置类的所在包(本例的com.on1.haloworldquickstart)及下面所有子包里面的所有组件扫描到Spring容器

// Spring底层注解@Import负责给容器导入组件
// 导入的组件由Registrar类指定
@Import({Registrar.class})  
public @interface AutoConfigurationPackage {
}
@Import({AutoConfigurationImportSelector.class})

点进AutoConfigurationImportSelector类。搜索方法public String[] selectImports()。 其中configurationss数组是容器中需要导入的组件,此处我们通过debug来看一下数组的值:

这些组件名都是类似xxxAutoConfiguration的形式,即自动配置类。因此 AutoConfigurationImportSelector类会往容器里导入许多的自动配置类,这样就避免了我们手动编写配置注入功能组件等的工作。

自动配置类从何得来?

由上图可看出是通过getCandidateConfigurations()方法来获取候选配置文件,

该方法的第一个参数值是EnableAutoConfiguration.class,第二个参数则是类加载器classLoader。

该方法负责从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,比如下图:

它将这些值作为自动配置类导入容器中,这样自动配置类就会生效,从而帮我们进行自动配置工作。

HttpEncodingAutoConfiguration类为例,该类负责Http编码的自动配置。

@Configuration      //这是一个配置类
//将配置文件的值与HttpEncodingProperties绑定
@EnableConfigurationProperties({HttpEncodingProperties.class})
//基于Spring底层Condition注解,若当前应用是Web应用,则整个配置类里的配置就生效
@ConditionalOnWebApplication
//判断当前项目有无过滤器类CharacterEncodingFilter
@ConditionalOnClass({CharacterEncodingFilter.class})
//判断配置文件中是否存在某个配置(不存在则判断也是成立的)
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {

    //封装了配置文件的相关属性的配置类,通过这个配置对象来从容器里取出想要的组件
    private final Encoding properties;
 
    @Bean
    @ConditionalOnMissingBean({CharacterEncodingFilter.class})
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
        return filter;
    }
    
    // 省略其他属性及方法
}
//从配置文件中获取指定值与bean属性进行绑定
//我们能配置属性都是来源于这些xxxProperties,
//比如我们可以主配置文件里配置:
// spring.http.encoding.charset=utf-8
// spring.http.encoding.force=true
// spring.http.encoding.enabled=true
@ConfigurationProperties(       
    prefix = "spring.http.encoding"
)
public class HttpProperties {
    public static class Encoding {
            public static final Charset DEFAULT_CHARSET;
            private Charset charset;
            private Boolean force;
            // 省略其他属性及方法
    }
}

@Conditional派生注解

前面我们看到了许多@Conditional的扩展注解,下图是其扩展注解及作用。

@Conditional注解表示必须是@Conditional派生注解指定的条件成立,才往容器里添加组件,配置类里的所有内容才能生效。

查看哪些自动配置类生效

我们可以在主配置文件中添加语句:

debug=true

来让控制台打印自动配置报告。成功匹配的配置类如下图所示

没有成功匹配的配置类如下图所示: