欢迎光临Spring Boot时代(一)

333 阅读23分钟

SSM(Spring Spring MVC MyBatis)已经让我们的开发很简洁了,但是还存在着一些问题,一就是随着项目的扩大,Spring配置文件会有些庞大,当然我们可以拆分,但是让IOC管理的复杂依赖之间的注入似乎都变化不大,二就是各种依赖之间的版本问题,我们知道各个jar包存在依赖关系,相同的jar包依赖的jar可能都不一样,我们在开发的时候就需要小心翼翼,生怕弄错了版本,导致项目问题。这些问题都将由Spring Boot来解决。

前言

在当今的Java领域,Spring Boot是十分流行的,因为用它开发确实非常快更简单,有人甚至说可以不用学Spring,直接学Spring Boot,但是Spring Boot的底层还是Spring Framework,只不过是在Spring Framework的基础上进行了一层封装而已(以我目前的水平看是这样的),不学 Spring,直接学Spring Boot,在我看来就像是建楼不建地基,直接从第二层开始建一样。所以我希望你在看本篇之前,希望你对Spring Framework已经有一定了解了,那么怎么确认是否达到这个标准呢? 可以参看我这篇博客: 欢迎光临Spring时代(一) 上柱国IOC列传。如果这篇博客的东西你都掌握了,基本上这篇博客讲的就可以基本看懂了。

这些做的练习我都放在码云上了,有时间会在GitHub上也放一份, 地址如下:

简介

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run". 如果你想创建基于Spring的单体应用,且是生产级别的,选取Spring Boot吧,它非常简单,简单到你好像不用写代码,只用运行就可以了。 We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. Most Spring Boot applications need minimal Spring configuration. 老实说这句话我一直在究竟怎么翻译,我的第一个理解是我们为Spring 平台和第三方库设计了一个视图,能够开发者最快的开始开发,绝大部分Spring Boot程序需要的配置很少。第二个理解就我们重新审视了Spring 平台和第三方库之间的关系设计了Spring Boot框架,Spring Boot能够让开发者快速的开发,绝大部分Spring Boot 程序需要的配置文件都很少。反正两个理解相近都是在说能够让开发者快速上市,而且配置文件很少。有英语好的同学,可以在下方留言。

上面所说的视图就是我理解就是这个东西: image.png

特点

  • Create stand-alone Spring applications

创建单体Spring 程序

  • Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)

内置Tomcat、Jetty、Undertow等应用服务器(可以自己选择)

  • Provide opinionated 'starter' dependencies to simplify your build configuration (提供starter依赖集供你选择让你的pom文件更小一点)
  • Automatically configure Spring and 3rd party libraries whenever possible

尽可能的自动配置Spring和第三方库

  • Provide production-ready features such as metrics, health checks, and externalized configuration

提供一个可随时上生产环境的特性,就像一个度量仪,用于健康监测和扩展配置。 这个应该说的是Spring Boot admin,监控应用的运行状况

  • Absolutely no code generation and no requirement for XML configuration

完全没有衍生代码和xml配置文件 可能到这里你还是有些晕哈,什么是starter,什么是自动配置,没配置XMl配置文件,数据库信息我还怎么配置? 不要着急,慢慢跟着我的思路走,下面会一一讲清楚这些名词。

Spring Boot与Spring Cloud

Spring Boot似乎与微服务的概念缠绕在一起,是不是Spring Boot就是用来做微服务的呢? 写到这里,可能还会有同学会问,什么是微服务? 简单的说,微服务是一种软件架构,那什么是软件架构? 请参看我这篇文章:

如果你常看我的文章,会发现我的文章基本上是一环扣一环的,是一个有序的系统。

那Spring Cloud是什么?

Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems Spring Cloud 为开发人员提供了一系列工具集来解决在构建分布式系统中遇到的一些通用问题。 原来是个工具集啊,看起来跟微服务也没关系啊。不要着急,我们在Spring官网再仔细找找。

Microservice architectures are the ‘new normal’. Building small, self-contained, ready to run applications can bring great flexibility and added resilience to your code. Spring Boot’s many purpose-built features make it easy to build and run your microservices in production at scale. 微服务架构正在成为新常态,组建一个个微小的、包含容器的、运行起来简单的能够给你的系统带来高灵活性和强扩展性。 Spring Boot的许多构建特性能够让开发者在大型项目中组建和部署微服务简单起来。

And don’t forget, no microservice architecture is complete without Spring Cloud ‒ easing administration and boosting your fault-tolerance. 但是不要忘了,在Java领域,没有Spring Cloud的任何微服务架构都是不完整的,因为缺少容错能力和管理麻烦。

所以Spring Boot和Spring Cloud是可以用来组建微服务,实现微服务架构的。Spring Boot用来做开发服务,只是加快你开发Spring 应用程序的速度,不一定非得用来做微服务。Spring Cloud用来做服务治理和Spring Boot能够做到无缝集成。 到此两者的关系应该讲清楚了。

如何创建一个Spring Boot工程

版本号选讲

数字版本号参看知乎的这个问题: 软件的版本号是如何确定的? 直接想看官方约定的,请去这个网址: semver.org/lang/zh-CN/ 这里讲的是英文大版本号,像GA之类的:

  • GA

General Availability,正式发布的版本,官方开始推荐广泛使用,国外有的用GA来表示release版本。

  • RELEASE

正式发布版,官方推荐使用的版本,有的用GA来表示。比如spring。

  • Stable

稳定版,开源软件有的会用stable来表示正式发布的版本。比如Nginx。

  • Final

最终版,也是正式发布版的一种表示方法。比如Hibernate。

  • RC

Release Candidate,发行候选版本,基本不再加入新的功能,主要修复bug。是最终发布成正式版的前一个版本,将bug修改完就可以发布成正式版了。

  • alpha

α是希腊字母的第一个,表示最早的版本,内部测试版,一般不向外部发布,bug会比较多,功能也不全,一般只有测试人员使用。 Beta β是希腊字母的第二个,公开测试版,比alpha版本晚些,主要会有“粉丝用户”测试使用,该版本仍然存在很多bug,但比alpha版本稳定一些。这个阶段版本还会不断增加新功能。分为Beta1、Beta2等,直到逐渐稳定下来进入RC版本。 我们介绍的是常见的,然后还有一些,如果还想了解请参看后文的参考资料中的文章。

方式一: Spring Initializr

image.png image.png image.png image.png image.png image.png image.png image.png

不用配置Tomcat,直接运行我们看下效果: image.png 然后我们写个Controller试试看: image.png 代码如下:

RestController
public class HelloWorld {
    @GetMapping(value = "/hello")
    public String test() {
        return "hello";
    }
}

输入url: http://localhost:8080/hello 结果: image.png 下面会讲什么不用之前那么一堆,就能直接编写Controller。

方式二: 直接引入依赖

  1. 新建一个maven工程,如果你不懂maven,请参看: Maven学习笔记
  2. image.png
  3. image.png
  4. 2.3.9的Spring Boot将对应starter的pom展示移除了,如果你想复制的话,可以进入这个网址:

docs.spring.io/spring-boot…

试了好几次,访问pom是进入GitHub,但是总是失败。Spring Boot 的starter依赖总是以spring-boot-starter开头,我们不用写版本号,因为继承了父依赖。我们直接这么写就行了:

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

然后建一个包和类: image.png

@SpringBootApplication
public class StudySpringBoot {
    public static void main(String[] args) {
        SpringApplication.run(StudySpringBoot.class, args);
    }
}

运行结果: image.png 同样的控制器代码:

image.png

同样的运行结果: image.png

分析一下这个Hello World

上面我们已经通过两种方式建立了一个Spring Boot工程,非常快的就搭建起来了一个web工程,Spring MVC的那些麻烦配置都被扔掉了,我们很快就可以开始开发。这是什么原理呢? 下面我们就来探究一下。

pom文件变小了

image.png

image.png

image.png 那这里可能有同学就会问了,我也不需要这么多啊,你给我引入了,不是影响我启动速度吗? 不用担心,这是按需引入,Spring Boot会根据你pom中引入的starter来自动按需引入,我们看一下我们引入的web starter。

image.png

image.png 所以不用担心父依赖引入的东西全部被引入。Spring Boot 将我们的库和开发场景做成了一个个starter,我们不用再费心开发的时候去一个一个引入了,比如你开发的是web程序就找web-starter,Spring Boot提供的starter如下:

image.png 这样我们就只用根据场景去选择starter了,这样就不用担心jar包版本不匹配的问题了。这也就是上面我们讲的Spring Boot的第 三个特点: Provide opinionated 'starter' dependencies to simplify your build configuration。提供starter,让你的pom文件更简单。

自动配置的原理

下面我们来研究为什么我们不用配置DispatchServlet、扫描包、注解驱动等Spring MVC配置,就能直接写Controller,其实我们也可以猜的到,我们不配,那就是Spring Boot帮我们配置,这也就叫自动配置。 这里我把启动程序贴一下:

@SpringBootApplication
public class BootApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootApplication.class, args);
    }
}

这是一个普通的main函数,我们首先研究上面的@SpringBootApplication这个注解。

image.png 然后我们看到了三个值得注意的注解:

  • @ComponentScan

这个注解我们熟悉,在欢迎光临Spring时代(一) 上柱国IOC列传我们介绍过了,你看学Spring Boot之前,学Spring是必要的吧。 自动扫描不用配的原因找到了。

  • @EnableAutoConfiguration @EnableAutoConfiguration概览:

image.png@EnableAutoConfiguration又发现了两个自定义注解:

@AutoConfigurationPackage
// 将AutoConfigurationImportSelector这个类加入到IOC容器中
@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector 字面意思是自动配置引入选择器,估计就是这个类根据starter执行按需引入这个功能的。我们研究一下AutoConfigurationImportSelector这个类: image.png 还记得Deferred意为延缓,还记得ImportSelector这个接口的作用吗? 该接口的selectImports方法,返回的值就能够加入到IOC容器中。不记得的再翻一翻在欢迎光临Spring时代(一) 上柱国IOC列传。 我们接着打断点研究一下:

image.png 注意也不知道是IDEA的bug还是怎么回事,我在99行打断点,启动的时候进不来,但是我在getAutoConfigurationEntry这个方法中打断点就进来了,我当时很奇怪,难道是高版本的Spring Boot改了流程? 但是看了很多视频,发现人家在这里打断点就行,所以最后确定是我IDEA的问题。 我们接着来研究:

image.png

image.png 最终是WebMvcAutoConfiguration来帮我们搞定自动配置的,我们大致看一下这个类:

image.png 又出现了五个新的Spring Boot自定义注解:

@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })

我们先看上面三个@ConditionalOn开头的,这好像跟条件注解有点像,对它本质上就是条件注解。你可以接着点进入看,发现里面有@Conditional 其实不用翻注释我们直接从名字上就能推断出来:

  • @ConditionalOnWebApplication: 是一个web应用程序且引入的依赖中有Servlet时,算是满足条件。
  • @ConditionalOnClass: 引入的依赖中有Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class这三个类条件成立
  • @ConditionalOnMissingBean: missing有缺失的意思,仅在容器中没有该类的属性,才向IOC容器中注入。 组合在一起就是这三个条件成立,自动加载WebMvcAutoConfiguration,然后开始自动配置。 这里再补充一下,这些自动配置类都是从哪里获得的呢? 我们想一下这个问题,我们总不能写在代码里,没增加一个自动配置类,我就要该代码吧。其实这个也是配置文件中的,还是在AutoConfigurationImportSelector的selectImports方法中:

image.png image.png

image.png

image.png 总有些元数据是程序需要通过配置文件来获取的。 接着我们来看@AutoConfigurationPackage注解,基本上这个注解一看完,我们就对Spring Boot的自动配置原理有一个清晰的理解了。 image.png 我们接着打断点看一下这个类做了什么:

image.png 然后我们在看下AutoConfigurationPackage上的注释:

Registers packages with {@link AutoConfigurationPackages}. When no {@link #basePackages base packages} or {@link #basePackageClasses base package classes} are specified, the package of the annotated class is registered. 当在@AutoConfigurationPackage没指定base packages或base package classes这个属性时,打上该注解的类所在的包或者子包的类,有对应注解的,就会被加入到IOC容器中。这不是跟@ComponentScan注解的作用重合了吗? 看到这里我表示不解,我怀疑是不是记错@ComponentScan注解的作用了,我打算看下AutoConfigurationPackages这个类的注释: Class for storing auto-configuration packages for reference later (e.g. by JPA entity scanner). 大意是: 该类为存储自动配置包的引用供之后引用,比如JPA实体对应扫描器。 有点不知所以,

总结一下

到现在我们已经大致上对Spring Boot有一个大致的理解了,为什么Spring Boot做Web不需要配置Servlet那一大堆东西,因为Spring Boot的自动配置类已经帮我们配置了,Spring Boot 根据条件注解和starter来确定要启用哪个自动配置类。为什么能让我们pom变小,因为Spring Boot把我们的开发场景变成了starter,如果我们要开发web,那么首先就要引入web starter。如果是MyBatis那就有 myBatis-starter。 Spring Boot的执行流程图:

image.png

无法被舍弃的配置文件

尽管做了大量的自动配置,大大减少了Spring Boot配置文件的体积,但是总是有些配置我们不想硬编码,比如数据库连接、端口等。所以Spring Boot也提供了加载配置文件的方式,Spring Boot支持了一种新的配置文件,我们称之为yaml,通过缩进来表达K,V对,而且要求k和v之间要一个空格的距离。 Spring Boot目前主要支持的配置文件有两种:

  • application.properties k,v对
  • application.yml 缩进

默认情况下 application.properties 的优先级高于application.yml。

@ConfigurationProperties

我们目前借助org.springframework.boot.autoconfigure.web.ServerProperties来讲解Spring Boot加载配置文件的思想,我们先大致看一下这个类:

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {

	/**
	 * Server HTTP port. 端口
	 */
	private Integer port;

	/**
	 * Network address to which the server should bind. 地址
	 */
	private InetAddress address;

	@NestedConfigurationProperty
	private final ErrorProperties error = new ErrorProperties();

	/**
	 * Strategy for handling X-Forwarded-* headers.
	 */
	private ForwardHeadersStrategy forwardHeadersStrategy;

	/**
	 * Value to use for the Server response header (if empty, no header is sent).
	 */
	private String serverHeader;

	/**
	 * Maximum size of the HTTP message header.
	 */
	private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8);

	/**
	 * Type of shutdown that the server will support.
	 */
	private Shutdown shutdown = Shutdown.IMMEDIATE;

	@NestedConfigurationProperty
	private Ssl ssl;

	@NestedConfigurationProperty
	private final Compression compression = new Compression();

	@NestedConfigurationProperty
	private final Http2 http2 = new Http2();

	private final Servlet servlet = new Servlet();

	private final Tomcat tomcat = new Tomcat();

	private final Jetty jetty = new Jetty();

	private final Netty netty = new Netty();

	private final Undertow undertow = new Undertow();
	}

ServerProperties 中还有一个静态内部类,我们也拿出来看一下,这里我就直接贴部分源码了:

	public static class Servlet {
    /**
		 * Servlet context init parameters.
		 */
		private final Map<String, String> contextParameters = new HashMap<>();

		/**
		 * Context path of the application.
		 */
		private String contextPath;

		/**
		 * Display name of the application.
		 */
		private String applicationDisplayName = "application";
}

在上面我们注意到有一个@ConfigurationProperties注解,我们进去看他的注释,碰见英文不要排斥,开发常用的单词就那么多,不行还有百度翻译。

Annotation for externalized configuration. Add this to a class definition or a @Bean method in a @Configuration class if you want to bind and validate some external Properties (e.g. from a .properties file).

该注解用来引入外部的配置文件,具体的水就是如果你想要为配置类或配置类形式的Java Bean(也就是加上了@Configuration的类、加上@bean的注解)设置一些从外部文件的值(比如properties配置文件),那么你就可以使用这个注解。

我的解读: 虽然Spring Boot尽量减少了配置文件,但是有些配置文件还是需要引入,引入了,怎么绑定到对应的对象上呢,那就是通过@ConfigurationProperties这个注解来引入。

Binding is either performed by calling setters on the annotated class or, if @ConstructorBinding is in use, by binding to the constructor parameters. 这个绑定是通过调用带有注解的类的方法是通过set方法,如果构造函数上有@ConstructorBinding,那么就通过构造函数来完成绑定。

我的解读: 如果有@ConstructorBinding,这个那就调用构造函数绑定值,如果没有那就调Set方法。

Note that contrary to @Value, SpEL expressions are not evaluated since property values are externalized. 注意相对于@Value注解,SpEL表达式不会对这种额外的配置求值。 @Value表达式是Spring EL表达式,这个可以自行查下相关资料,这里就不做介绍了。

那么问题又来了,怎么匹配呢? 我这么多属性怎么对应到配置文件对应的值呢? 我们接着看@ConfigurationProperties这个注解的源码,其实注解是一个语法糖,本篇也算是Java 的稍微高级一点的知识,我这里默认你已经对Java已经比较了解了。

答案就是@ConfigurationProperties中的value属性,别名是prefix,prefix意味前缀。所以匹配的规则就是前缀加上属性名。 ServerProperties上面的@ConfigurationProperties的prefix是server,里面有一个端口属性,所以我们在properties就应该这么写:

server.port=8884
server.servlet.context-path=/studyBoot

然后我们启动一下项目,看一下配置是否成功: image.png 在yaml中的配置方法注意是缩进加空格:

server:
  port: 8882
  servlet:
    context-path: /study

yaml就相当于把propertis中的.改成了缩进,=号变成了空格。注意这个规律。 ServerProperties 还有别的属性这里就不一一细讲了。我们再来做几个联系来体会一下 @ConfigurationProperties这个注解的用处。

@Getter //  Lombok插件
@Setter //  Lombok插件
@NoArgsConstructor //  Lombok插件
@ToString //  Lombok插件 不懂 百度一下
@Component
@ConfigurationProperties(prefix = "student")
public class Student {
    private int age;
    private String name;
    private boolean sex;
    private String[] locations;
    private StudentCard car;
}
@NoArgsConstructor
@Setter
@Getter
@ToString
public class StudentCard {
    private String cardNo;
}

yaml中的配置:

student:
 age: 23
 name: zs
 sex: true
 locations:
   - 上海
 car:
   cardNo: 8888

我们测试一下:

@RunWith(SpringRunner.class)
@SpringBootTest
class BootApplicationTests {
	@Autowired
	private Student student;
	@Test
	void contextLoads() {
		System.out.println(student);
	}
}

测试结果:

image.png 平时写yaml这种靠缩进的也比较头疼,好在IDEA有强大的提示,但是有的时候我是更喜欢写properties文件格式的,然后转成yaml。之前项目做过一个多数据源的,我在yaml里配置,怎么都不成功,然后那个时候IDEA没这个多数据源的提示,当时着实让我头疼了一把,如果你觉得这个头疼,有在线将properties转成yaml的工具。

@PropertySource简介

上面我们讲的取值与赋值都是走的Spring Boot默认的配置文件: application.properties,application.yml。在Spring Boot中properties的优先级要高于yaml。但是假如有些配置文件,我们不想写入默认文件中想单独抽出来加载应该怎么办呢? 实际上就是通过@PropertySource来完成的。我们还是能看源码上的注释,就尽量看源码上的注释。

Annotation providing a convenient and declarative mechanism for adding a @link org.springframework.core.env.PropertySource PropertySource} to Spring's {@link org.springframework.core.env.Environment Environment}. To be used in conjunction with @{@link Configuration} classes. @PropertySource 注解和Spring的环境变量配合一块使用,用于配置类之上。

代码中还有示例,我们照着做就行,首先我们准备一个properties文件:

testbean.name=myTestBean

然后准备配置类和一个javaBean:

@Getter
@Setter
@NoArgsConstructor
@ToString
public class TestBean {
    private String name;
}

@Configuration
@PropertySource(value = "classpath:app.properties")
public class SpringBootConfig {
    private Environment env;

    @Autowired
    public void setEnv(Environment env) {
        this.env = env;
    }

    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
    }
}

测试一下:

@RunWith(SpringRunner.class)
@SpringBootTest
class BootApplicationTests {

	@Autowired
	private TestBean bean;

	@Test
	void contextLoads() {
		System.out.println(bean);
	}
}

测试结果: image.png

@ImportResource 还是需要配置文件

虽然配置类已经很强大了,但是有些还是无法移植到配置类中,在@ImportResource中有这样一段注释:

but where some XML functionality such as namespaces is still necessary. 但是有些XML的功能比如命名空间仍然是必须的。好像是跟groovy这门语言有关系,因为Spring 不只属于Java,要讨论下去似乎要站在Spring整体的角度去考虑,这又是一个庞大的课题,这里我们就姑且将其他理解为引入xml配置文件的吧。 具体怎么用呢? 还是在配置文件中做一个Java Bean,然后在Spring Boot的启动主类上加载它就行。 首先我们准备一个配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 这里只是做个示例,实际上这个更适合配置类-->	
    <bean id = "testBean" class = "com.example.boot.pojo.TestBean">
        <property name="name" value="zd"/>
    </bean>
</beans>

然后在主类上引入:

@SpringBootApplication
@ImportResource(locations = "classpath:spring-mvc.xml")
public class BootApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootApplication.class, args);
    }
}

测试代码:

@RunWith(SpringRunner.class)
@SpringBootTest
class BootApplicationTests {

    @Autowired
    private TestBean bean;
    @Test
    void contextLoads() {
        System.out.println(bean);
    }
}

测试结果:

image.png

配置文件位置

熟悉maven的人可能清楚,maven约定了目录结构,resources我们称之为资源文件夹,我们会把配置文件放在这个位置。 Spring Boot启动的时候就会默认的加载application.properties文件,如果没有则会去找yaml。properties的优先级要始终高于yaml。但是如果两者同时存在,相互冲突的配置向,以properties的配置为主。如果不冲突,则相互补充(想是合并在了一个配置文件一样)。

假如你的项目大的过分,达到需要把配置文件拆分之后,也需要单独放置一个文件夹的话,那么Spring Boot会默认从这四处寻找配置文件:

  • file: 项目根路径/config(此时config文件夹与资源文件夹平级)
  • file: 项目根目录
  • classpath: 资源文件位置/config
  • classpath: 资源文件位置/项目根目录 优先级从上达到下。

环境切换

我们之前一直强调过我们有开发(dev)、测试(uat)、生产环境(prod),对应的也有三套配置文件,那我们该怎么配才能让做到让应用程序在不同的环境使用不同的配置文件呢? Spring Boot 也考虑到了,你说贴心不贴心。 如果有properties文件,会优先选取properties文件进行读取。

在主配置文件中指定激活环境。

我们以properties为例,yaml是同样的,这里不再做对应的展示。首先我们建立一个开发环境中的配置文件,文件名指定为: application-dev.properties,里面指定端口:

server.port=8885

然后在主配置文件里选取激活的文件环境:

server:
  port: 8882
  servlet:
    context-path: /study
Spring:
  profiles: dev

注意这个dev就和开发环境中的配置文件对上了,通过application-环境。 再启动的时候,你就发现端口是8882了。

运行参数

Spring Boot web应用是做成一个jar包的,java 中启动一个jar包通过的指令是java -jar xxx.jar,其实这后面也可以跟运行参数。

比如java -jar xxx.jar ----spring.profiles.active=uat ,然后Spring Boot 在启动的时候就会去加载名为application-uat.properties文件,在IDEA中我们可以实现对应的效果:

image.png

image.png 然后你会发现运行参数的优先级最高,主配置文件中我们制定的是dev环境,运行参数中我们制定的是uat环境。

VM参数

JVM参数,我们通常用来限制JVM的内存,因为JVM一向是有多大内存就吃多大内存。一般的命令格式 java -参数 。 我们也可以通过这个来设置启动环境,在IDEA如下配置就可以:

image.png 也可以达到同样的效果。

Spring Boot整合的思想

总纲

上面我们讲Spring Boot把我们开发的各种场景做成了各种各样的starter,我们开发的时候只需要按需引入即可。引入之后,在配置文件中配置必要的文件参数,Spring Boot就能让自动配置类完成自动整合。所以总这里总结一下Spring Boot开发的一般步骤:

  • 根据场景去找starter

Spring 官方出的starter依赖名通常以spring-boot-starter开头,可以去上面放的官网中去找找看。 如果不属于Spring Boot,那么starter通常spring-boot-starter在后面,比如mybatis-spring-boot-starter

  • 根据启动器在配置文件中配置参数。

整合MyBatis

首先我们仔细想一下MyBatis需要什么? 首先肯定需要mybatis-spring-boot-starter,这里面是MyBatis帮我们做的,里面已经集成了一些必要的。但是我们想想,这个启动器不应该集成的:

  • 数据库连接池

如果这个集成了,岂不是还要关注市面上连接池的动向。

  • 数据库驱动

这个也应该让开发者自己选择,毕竟数据库不少,驱动版本也不少。starter集成那么多,又耦合起来了。 然后我们引入依赖:

 <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.22</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

然后怎么配参数: 我们依然去百度搜索看看有没有官方文档: image.png 点进去看一下: image.png 里面有对应的示例,这里我们就简单的整合一下就可以了,理解这个思想很重要。 在整合MyBatis之前,我们还得先搞定连接池,这次选定的连接池Druid,还是先去百度搜搜看看有没有官方文档,一般都有,告诉你参数应该怎么配。 image.png image.png 我们直接从官网复制: server.port=8884

server.servlet.context-path=/studyBoot
mybatis.mapper-locations=classpath*:com/example/boot/mapper/*.xml 
spring.datasource.druid.url=jdbc:mysql://192.168.2.129:3306/study?useUnicode=true&characterEncoding=utf-8
spring.datasource.druid.username=root
spring.datasource.druid.password=RrXMoWG8+6gl
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver

注意看官网要看仔细,想想我们SSM整合中我们配Mapper.xml也配置了Mapper.xml对应的接口。 image.png 上面说的是Spring Boot会自动将打上@Mapper接口的注解去和mapper-locations中指定的xml做关联。 如果你想定制可以用@MapperScan,里面指定你想扫描的包。 具体的代码,可以去GitHub看。

整合Redis

接着我们来做个练习尝试在Spring Boot 整合Redis。第一步去找Redis 对应的starter:

image.png 我们点进去看一下:

image.png 我大意了,没有闪,我万万没想到Spring Boot 自己做了Redis的starter,所以大家以后整合第三方库,还是先去Spring Boot的starter表找一下,没有再按照 库-Spring-Boot-Starter去百度找官方文档。我们上面搜到的那个是在Spring的基础上又封装了一层,我们本次就只整合Spring提供的。 我们上面看到MyBatis的配置类是MybatisProperties,那么我们也可以类比猜想一下,Redis的配置类就是RedisProperties,其实我在整合的时候就是这么想的,然后一搜果然是。 我们来配一下:

spring.redis.host=192.168.2.129:6379
spring.redis.password=foobared

然后我们在Spring 配置类中配置一下RedisTemplate就行了。

总结一下

本篇基本上介绍了Spring Boot的基本使用和基本原理,算上我之前的几篇文章,整体算是基本圆满了。如果想学习框架不妨跟着我的文章走,先后顺序依次是:

参考资料