Spring Boot的前世此生以及它和Spring Cloud的关系详解。

2021年11月25日 阅读数:14
这篇文章主要向大家介绍Spring Boot的前世此生以及它和Spring Cloud的关系详解。,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

要了解Spring Boot的发展背景,还得从2004年Spring Framework1.0版本发布开始提及,不过你们都是从开始学习Java就使用Spring Framework了,因此就不作过多展开。html

随着使用Spring Framework进行开发的企业和我的愈来愈多,Spring 也慢慢从一个单一简洁的小框架编程了一个大而全的开源软件,Spring Framework的边界不断进行扩张,到了如今Spring 几乎能够作任何事情。目前市面上绝大部分的开源组件和中间件,都有Spring对应组件的支持,java

大家若是去关注Spring目前的官网,你会发现他的slogan是:Spring makes Java Simple。它让Java的开发变得更加简单。mysql

虽然Spring的组件代码是轻量级的,可是它的配置倒是重量级的,Spring 每集成一个开源软件,就须要增长一些基础配置,慢慢的随着咱们开发的项目愈来愈庞大,每每须要集成不少开源软件,所以后期使用 Spirng 开发大型项目须要引入不少配置文件,太多的配置很是难以理解,并容易配置出错,这个给开发人员带来了很多的负担。web

你们想象一个场景,就是假如你须要用spring开发一个简单的Hello World Web应用程序,应该要作哪些动做呢?spring

  • 建立一个项目结构,必然包含依赖Maven或者Gradle的构建文件。
  • 至少须要添加spring mvc和servlet api的依赖
  • 一个web.xml,声明spring的DispatcherServlet
  • 一个启用了Spring MVC的spring 配置
  • 一个控制器类,“以HelloWord”为响应的http请求
  • 一个用于部署应用程序的web应用服务器,好比Tomcat

在整个过程当中,咱们发现只有一个东西和Hello Word功能相关,那就是控制器(controller),剩下的都是Spring 开发的Web应用程序必需要的通用模版,既然全部Spring Web应用程序都要用到他们,那为何还要你来提供这些东西呢?sql

因此,直到2012年10月份,一个叫Mike Youngstrom(扬斯特罗姆)在Spring Jira中建立了一个功能请求,要求在Spring Framework中支持无容器Web应用程序体系结构,他谈到了在主容器引导 spring 容器内配置 Web 容器服务。shell

https://jira.spring.io/browse...数据库

I think that Spring's web application architecture can be significantly simplified if it were to provided tools and a reference architecture that leveraged the Spring component and configuration model from top to bottom. Embedding and unifying the configuration of those common web container services within a Spring Container bootstrapped from a simple main() method.
我认为,若是要提供从上到下充分利用Spring组件和配置模型的工具和参考体系结构,则能够大大简化Spring的Web应用程序体系结构。在经过简单main()方法引导的Spring容器中嵌入和统一那些通用Web容器服务的配置。

并且Spring 开发团队也意识到了这些问题,急须要一套软件来解决这个问题,而这个时候微服务的概念也慢慢的起来,快速开发微小独立的应用也变得很急迫。express

而Spring刚好处在这样一个交叉点上,因此顺势而为在2013年初的时候,开始投入Spring Boot项目的研发,直到2014年4月,Spring Boot1.0版本发布。从那之后,Spring Boot开启了一些列的迭代和升级的过程。编程

通过7年时间的发展,到目前为止,Spring Boot最新稳定版为2.6.0版本。

Spring Boot的发展

Spring Boot刚出生的时候,引发了不少开源社区的关注,而且也有我的和企业开始尝试使用Spring Boot。 其实直到2016年,Spring Boot才真正在国内被使用起来。我以前在挖财的时候,2015年公司就开始采用Spring Boot来构建基于Dubbo的微服务架构。到如今,Spring Boot几乎是全部公司的第一选择。

Build Anything

Spring Boot被官方定位为“BUILD ANYTHING”,Spring Boot官方的概述是这么描述Spring Boot的。

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
// 经过Spring Boot能够轻松的建立独立的、生产级别的基于Spring 生态下的应用,你只须要运行便可。
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 Framework生态的开发者快速高效的构建一个基于Spring以及spring 生态体系的应用。

为了让你们对这句话的理解更加深入,咱们来作两个小实验,一个是基于传统的Spring MVC框架构建一个项目、另外一种是使用Spring Boot。

Spring MVC With Spring Boot

经过Spring MVC项目搭建过程来对比Spring Boot的差别和优点。

Spring MVC项目搭建过程

  • 建立一个maven-webapp项目
  • 添加jar包依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    spring-context
    spring-context-support
    spring-core
    spring-expression
    spring-web
    spring-webmvc
  • 修改web.xml文件

    <context-param><!--配置上下文配置路径-->
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
    <!--配置Spring MVC的请求拦截-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dispatcher-servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-patter>
    </servlet-mapping>
  • 在resources目录下添加dispatcher-servlet.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!-- 扫描 controller -->
    <context:component-scan base-package="com.gupaoedu.controller" />
    <!--开启注解驱动-->
    <mvc:annotation-driven/>
    <!-- 定义视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
  • 建立一个Controller

    @Controller
    public class HelloController {
    
        @RequestMapping(method = RequestMethod.GET,path = "/index")
        public String index(Model model){
            model.addAttribute("key","Hello Gupao");
            return "index";
        }
    }
  • 修改默认的index.jsp,设置el表达式的解析

    <%@ page language="java" contentType="text/html; charset=utf-8"
             pageEncoding="utf-8" isELIgnored="false" %>
    ${key}
  • 运行项目

Spring Boot搭建过程

直接基于start.spring.io这个脚手架搭建便可。

思考和总结

我们再回到最开始Spring Boot的定义部分,Spring Boot可以帮助使用Spring Framework生态的开发者快速高效的构建一个基于Spring以及spring 生态体系的应用。

再对比两种构建过程,彷佛也可以理解Spring Boot的做用了吧。固然它的做用不只于此,后续会逐步揭开它的真实面目。

经过上面这个案例咱们发现,若是没有spring boot,要去构建一个Spring MVC的web应用,须要作的事情不少

  • 引入jar包
  • 修改web.xml,添加监听和拦截
  • 建立spring mvc核心配置文件dispatcher-servlet.xml
  • 建立controller
  • 部署到tomcat

这个过程若是不熟悉,极可能须要1~2个小时,若是是新手,可能须要更长时间。可是spring boot,无论是新手仍是老手,都可以分分钟解决问题。

理解约定优于配置

咱们知道,Spring Boot是约定因为配置理念下的产物,那么什么是约定因为配置呢?

约定优于配置是一种软件设计的范式,主要是为了减小软件开发人员需作决定的数量,得到简单的好处,而又不失灵活性。

简单来讲,就是你所使用的工具默认会提供一种约定,若是这个约定和你的期待相符合,就能够省略那些基础的配置,不然,你就须要经过相关配置来达到你所期待的方式。

约定优于配置有不少地方体现,举个例子,好比交通讯号灯,红灯停、绿灯行,这个是一个交通规范。你能够在红灯的时候不停,由于此时没有一个障碍物阻碍你。可是若是你们都按照这个约定来执行,那么无论是交通的顺畅度仍是安全性都比较好。

而相对于技术层面来讲,约定有不少地方体现,好比一个公司,会有专门的文档格式、代码提交规范、接口命名规范、数据库规范等等。这些规定的意义都是让整个项目的可读性和可维护性更强。

Spring Boot Web应用中约定优于配置的体现

那么在前面的案例中,咱们能够思考一下,Spring Boot为何可以把本来繁琐又麻烦的工做省略掉呢? 实际上这些工做并非真正意义上省略了,只是Spring Boot帮咱们默认实现了。

而这个时候咱们反过来思考一下,Spring Boot Web应用中,相对Spring MVC框架的构建而言,它的约定因为配置体如今哪些方面呢?

  • Spring Boot的项目结构约定,Spring Boot默认采用Maven的目录结构,其中

    src.main.java 存放源代码文件

    src.main.resource 存放资源文件

    src.test.java 测试代码

    src.test.resource 测试资源文件

    target 编译后的class文件和jar文件

  • 内置了嵌入式的Web容器,在Spring 2.2.6版本的官方文档中3.9章节中,有说明Spring Boot支持四种嵌入式的Web容器

    Tomcat

    Jetty

    Undertow

    Reactor

  • Spring Boot默认提供了两种配置文件,一种是application.properties、另外一种是application.yml。Spring Boot默认会从该配置文件中去解析配置进行加载。
  • Spring Boot经过starter依赖,来减小第三方jar的依赖。

这些就是Spring Boot可以方便快捷的构建一个Web应用的秘密。固然Spring Boot的约定优于配置还不只体如今这些地方,在后续的分析中还会看到Spring Boot中约定优于配置的体现。

Spring Boot整合Mybatis

实际上Spring Boot的本质就是Spring,若是必定要从技术发展的过程当中找到一些类似的对比的话,大家能够对比一下Jsp/Servlet和Spring MVC, 二者均可以用来开发Web项目,可是在使用上,Spring MVC的使用会更加简单。

而Spring Boot和Spring 就至关于当年的JSP/Servlet和Spring MVC的关系。因此它自己并无所谓新的技术,接下来,我带着你们来经过Spring Boot整合Mybatis实现数据的基本操做的案例,来继续认识一下Spring Boot。

建立Spring Boot 应用

建立一个Web项目

引入项目中须要的starter依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

建立数据库表

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `address` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

配置数据库链接

spring:
  datasource:
    url: jdbc:mysql://192.168.13.106:3306/test_springboot
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

开发数据库访问层

1587536145803

建立实体对象

public class User {
    private int id;
    private String name;
    private String address;
}

建立Mapper

//@Repository能够支持在你的持久层做为一个标记,能够去自动处理数据库操做产生的异常
@Repository
@Mapper
public interface UserMapper {

    User findById(int id);
    List<User> list();
    int insert(User user);
    int delete(int id);
    int update(User user);
}

编写mapper文件

在resource文件目录下建立UserMapper.xml文件,内容以下

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC
        "-//mybatis.org//DTD com.example.Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <resultMap id="resultMap" type="com.example.demo.entity.User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="address" column="address"/>
    </resultMap>

    <select id="findById" resultMap="resultMap" parameterType="java.lang.Integer">
        select * from t_user where id=#{id}
    </select>
    <select id="list" resultMap="resultMap">
        select * from t_user
    </select>
    <insert id="insert" parameterType="com.example.demo.entity.User" keyProperty="id" useGeneratedKeys="true">
        insert into t_user(name,address) values(#{name,jdbcType=VARCHAR},#{address,jdbcType=VARCHAR})
    </insert>
    <delete id="delete" parameterType="java.lang.Integer">
        delete from t_user where id=#{id}
    </delete>
    <update id="update" parameterType="com.example.demo.entity.User">
        update t_user set name=#{name,jdbcType=VARCHAR},address=#{address,jdbcType=VARCHAR} where id=#{id,jdbcType=INTEGER}
    </update>
</mapper>

定义service及实现

public interface IUserService {

    User findById(int id);
    List<User> list();
    int insert(User user);
    int delete(int id);
    int update(User user);
}

@Service
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;
}

建立Controller

@RestController
public class Controller {

    @Autowired
    private IUserService userService;

    @GetMapping("/user/{id}")
    public User user(@PathVariable("id") int id){
        return userService.findById(id);
    }

    @GetMapping("/users")
    public List<User> users(){
        return userService.list();
    }

    @PostMapping("/user")
    public String insertUser(User user){
        int row=userService.insert(user);
        return row>0?"SUCCESS":"FAILED";
    }

    @PutMapping("/user")
    public String updateUser(User user){
        int row=userService.update(user);
        return row>0?"SUCCESS":"FAILED";
    }
    @DeleteMapping("/user/{id}")
    public String deleteUser(@PathVariable("id") int id){
        return userService.delete(id)>0?"SUCCESS":"FAILED";
    }

}

修改配置

  • 在Spring 的Main方法上增长如下注解,用来扫描Mybatis的Mapper文件

    @MapperScan("com.example.demo.mapper")
  • 配置Mapper配置文件的地址,在application.yml中

    mybatis:
      mapper-locations: classpath:*Mapper.xml

    id int,

    name varchar(20),

    address varchar(20)

)

项目打包

  • mvn -Dmaven.test.skip -U clean install
  • java -jar xxx.jar

简单总结

这个代码,我想,你们应该写过无数遍了,而在基于Spring Boot集成Mybatis这个案例中,核心的业务逻辑并无减小,它只减小了一些繁琐的配置,使得咱们更聚焦在业务开发层面。

简单来讲,基于Spring Boot的项目中,咱们只须要写Controlelr、Service、Dao便可。甚至不少状况下咱们dao都不须要管,好比使用mybatis-plus这个插件,就能够省去不少固定的dao层逻辑。

因此实际上,Spring Boot并无新鲜的东西,所以你看到市面上大部分讲spring boot的书,这些书我几乎都看过,基本上都是讲解Spring Boot的应用,以及Spring Boot的一些特性分析。由于一旦你想讲Spring Boot的原理,就必然会回归到Spring这块的内容上。好比小马哥的Spring Boot编程思想着本书,大篇幅的都是在讲Spring Framework。由于Spring Boot的内核仍是Spring Framework。

Spring Boot与微服务

接下来,给你们讲讲spring boot与微服务这块的内容。

什么是Spring Cloud

首先,咱们要简单了解一下什么是微服务,按照个人理解来讲,微服务就是微粒度的服务,它是面向服务架构(SOA)的进一步优化。若是你们不是很好理解,翻译成白话就是

一个业务系统,本来是在一个独立的war包中。如今为了更好的维护和提升性能,把这个war包按照业务纬度拆分红了一个个独立的业务子系统,每一个子系统提供该业务领域相关的功能,并暴露API接口。

这些服务彼此之间进行数据交换和通讯来实现整个产品的功能。

而这些业务子系统,实际上表明的就是一个服务,那么所谓的微服务,说的是这个服务的粒度。至于服务的粒度什么样才叫微,其实没有一个固定的衡量标准。更多的仍是在每一个公司具体的业务粒度的把控上。

微服务化遇到的问题

在为服务化以后,会面临不少的问题,好比服务注册、服务路由、负载均衡、服务监控等等。这些问题都须要有相应的技术来解决,这个时候,Spring Cloud就出现了。

简单来讲,Spring Cloud 提供了一些可让开发者快速构建微服务应用的工具,好比配置管理、服务发现、熔断、智能路由等,这些服务能够在任何分布式环境下很好地工做。Spring Cloud 主要
致力于解决以下问题:

  • Distributed/versioned configuration,分布式及版本化配置。
  • Service registration and discovery,服务注册与发现。
  • Routing,服务路由。
  • Service-to-service calls,服务调用。
  • Load balancing,负载均衡。
  • Circuit Breakers,断路器。
  • Global locks,全局锁。
  • Leadership election and cluster state,Leader 选举及集群状态。
  • Distributed messaging,分布式消息。

须要注意的是,Spring Cloud 并非 Spring 团队全新研发的框架,它只是把一些比较优秀的解决微服务架构中常见问题的开源框架基于 Spring Cloud 规范进行了整合,经过 Spring Boot 这个
框架进行再次封装后屏蔽掉了复杂的配置,给开发者提供良好的开箱即用的微服务开发体验。不难看出,Spring Cloud 其实就是一套规范,而 Spring Cloud Netflix、Spring Cloud Consul、Spring CloudAlibaba 才是 Spring Cloud 规范的实现。

为何Spring Cloud是基于Spring Boot

那为何Spring Cloud会采用Spring Boot来做为基础框架呢?缘由很简单

  1. Spring Cloud它是关注服务治理领域的解决方案,而服务治理是依托于服务架构之上,因此它仍然须要一个承载框架
  2. Spring Boot 能够简单认为它是一套快速配置Spring应用的脚手架,它能够快速开发单个微服务

在微服务架构下,微服务节点愈来愈多,须要一套成熟高效的脚手架,而Spring Boot正好能够知足这样的需求,以下图所示。

image-20211124135348046

Spring Boot的四大核心机制

若是必定要基于Spring Boot的特性去说,那么只能去说Spring Boot的四大核心机制,分别是@EnableAutoConfiguration 、 Starter开箱即用组件、Actuator应用监控、Spring Boot CLI 命令行工具。

EnableAutoConfiguration

Starter

告诉Spring Boot须要什么功能,它就能引入须要的库。

Actuator

让你可以深刻运行中的Spring Boot应用程序

Spring Boot CLI

Spring Boot CLI 为Spring Cloud 提供了Spring Boot 命令行功能。咱们能够经过编写groovy脚原本运行Spring Cloud 组件应用程序。步骤以下、

  • 下载spring-boot-cli

    Spring Boot CLI:https://repo.spring.io/releas...

  • 配置环境变量
  • 在控制台spring --version查看CLI版本
  • 使用CLI运行应用。咱们可使用run命令编译和运行Groovy源代码。Spring Boot CLI中包含全部运行Groovy所须要的依赖。
  • 建立一个hello.groovy文件

    @RestController
    class HelloController {
    
        @GetMapping("/hello")
        String hello(){
            return "Hello World";
        }
    }
  • 在控制台执行spring run hello.groovy,若是须要传递参数,好比端口,和JVM参数相似

    spring run hello.groovy -- --server.port=9000

Spring Boot的四大核心特性

  • EnableAutoConfiguration
  • Starter
  • Actuator
  • Spring Boot CLI

    Spring Boot CLI 为Spring Cloud 提供了Spring Boot 命令行功能。咱们能够经过编写groovy脚原本运行Spring Cloud 组件应用程序。步骤以下、

    • 下载spring-boot-cli

      Spring Boot CLI:https://repo.spring.io/releas...

    • 配置环境变量
    • 在控制台spring --version查看CLI版本
    • 使用CLI运行应用。咱们可使用run命令编译和运行Groovy源代码。Spring Boot CLI中包含全部运行Groovy所须要的依赖。
    • 建立一个hello.groovy文件

      @RestController
      class HelloController {
      
          @GetMapping("/hello")
          String hello(){
              return "Hello World";
          }
      }
    • 在控制台执行spring run hello.groovy,若是须要传递参数,好比端口,和JVM参数相似

      spring run hello.groovy -- --server.port=9000
版权声明:本博客全部文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Mic带你学架构
若是本篇文章对您有帮助,还请帮忙点个关注和赞,您的坚持是我不断创做的动力。欢迎关注同名微信公众号获取更多技术干货!