关于java:Spring-Boot的前世今生以及它和Spring-Cloud的关系详解

39次阅读

共计 12990 个字符,预计需要花费 33 分钟才能阅读完成。

要理解 Spring Boot 的倒退背景,还得从 2004 年 Spring Framework1.0 版本公布开始说起,不过大家都是从开始学习 Java 就应用 Spring Framework 了,所以就不做过多开展。

随着应用 Spring Framework 进行开发的企业和集体越来越多,Spring 也缓缓从一个繁多简洁的小框架编程了一个大而全的开源软件,Spring Framework 的边界一直进行扩张,到了当初 Spring 简直能够做任何事件。目前市面上绝大部分的开源组件和中间件,都有 Spring 对应组件的反对,

你们如果去关注 Spring 目前的官网,你会发现他的 slogan 是:Spring makes Java Simple。它让 Java 的开发变得更加简略。

尽管 Spring 的组件代码是轻量级的,然而它的配置却是重量级的,Spring 每集成一个开源软件,就须要减少一些根底配置,缓缓的随着咱们开发的我的项目越来越宏大,往往须要集成很多开源软件,因而前期应用 Spirng 开发大型项目须要引入很多配置文件,太多的配置十分难以了解,并容易配置出错,这个给开发人员带来了不少的累赘。

大家设想一个场景,就是如果你须要用 spring 开发一个简略的 Hello World Web 应用程序,应该要做哪些动作呢?

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

在整个过程中,咱们发现只有一个货色和 Hello Word 性能相干,那就是控制器(controller),剩下的都是 Spring 开发的 Web 应用程序必须要的通用模版,既然所有 Spring Web 应用程序都要用到他们,那为什么还要你来提供这些货色呢?

所以,直到 2012 年 10 月份,一个叫 Mike Youngstrom(扬斯特罗姆)在 Spring Jira 中创立了一个性能申请,要求在 Spring Framework 中反对无容器 Web 应用程序体系结构,他谈到了在主容器疏导 spring 容器内配置 Web 容器服务。

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 开发团队也意识到了这些问题,急须要一套软件来解决这个问题,而这个时候微服务的概念也缓缓的起来,疾速开发渺小独立的利用也变得很急切。

而 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

开发数据库拜访层

创立实体对象

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 正好能够满足这样的需要,如下图所示。

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

      互联网大厂考点(阿里 + 百度 + 腾讯 + 字节跳动 + 美团 + 京东)

正文完
 0