【从单体架构到分布式架构】(一)万丈高楼平地起:环境准备
【从单体架构到分布式架构】
本系列文章希望用浅显直白的语言介绍架构发展过程中遇到的各种问题,以及对应的解决方案和优缺点。
在正式学习之前,开发环境需要做好哪些准备呢?
我们为什么要选择使用 Spring Boot 呢?
Spring Boot 和 Spring 是两个截然不同的框架么?
1. 环境准备
本课程在学习过程中,会有大量的代码配合讲解,所以在正式学习之前,你需要做好以下准备。
1.1 JDK
必备;本课程所有代码基于 JDK 1.8 编写。
C:\>java -version
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
1.2 Maven
C:\>mvn -v
C:\
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:4
7+08:00)
Maven home: D:\Program Files\apache-maven-3.3.9\bin\..
Java version: 1.8.0_171, vendor: Oracle Corporation
Java home: D:\Program Files\Java\jdk1.8.0_171\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "dos"
1.3 IDE
必备;选择一个你熟悉的 IDE,我使用的是 Eclipse,这里要注意,有些 IDE 需要进行一些 Maven 环境变量的配置。
1.4 数据库
必备;建议在本机上安装一个 MySQL 数据库;为了方便操作,最好安装一个自己熟悉的数据库可视化工具,也可以使用 MySQL 自带的 MySQL Workbench。
1.5 Git
非必备;本课程所有代码都上传到了 github ,可以通过 git clone 下载所有代码,如果你未安装相关软件,也可以直接下载压缩包。
1.6 SoapUI 或 PostMan 或其他
非必备;在讲解的过程中,会经常进行接口测试,包括接口压力测试,建议安装 SoapUI 或 PostMan 或其他类似的软件。
2. Spring Boot的历史
在有 Spring Boot 之前,Spring 框架是当时很火的一个框架(现在也很火),不过随着使用 Spring 框架的人越来越多,Spring 从一个简洁的框架,慢慢地变成大而全;Spring 能够支持的组件越来越多,需要引入的配置文件也越来越多,这也就是我们经常听到的"配置文件爆炸"、"配置炼狱";
Spring 也意识到这个问题,而且随着微服务概念的兴起,也需要有一个可以支持快速开发微小独立应用的框架;在 2012年10月,Spring JIRA 中创建了一个功能请求,要求在 Spring 框架中支持无容器 Web 应用程序体系结构;这个功能要求促使了 2013年 Spring Boot 项目的研发。继而在 2014年4月,Spring Boot 1.0.0 发布。
3. 基于 Spring Boot 的应用搭建
3.1 在线生成 Spring Boot 项目
本章节项目的代码:
https://github.com/CodeDaShu/ArchitectureEvolution/tree/master/chapter1
Step 1. start.spring.io
如果你能连接互联网,可以打卡 start.spring 这个网址,Spring 提供了一个在线生成 Spring Boot 项目的功能。
图中的 GroupID 和 ArtifactID 组合起来被称作“坐标”,是为了保证项目的唯一性所提出来的,如果你的项目要被上传到 Mavan 仓库中,可以根据 GroupID + ArtifactID 找到你的项目。
GroupID: 可以分成两组字段,第一组是域,我们可以看做是“分类”,第二组是域名,可以是公司名、组织名或者你给自己起的任何名字;比如 Apache 的项目的 GroupID 都是 [org.apache],org 表示非盈利组织,另外一个常见的 com 表示商业组织;apache 是公司名称。
ArtifactID: 项目名称或者模块名称。
Step 2. 新建一个项目
这里我们这样填写,点击 Genarate 按钮生成项目 :
GroupID = com.archevolution
ArtifactID = chapter1 //表示是第一章节的项目,后面的章节如果有代码,都会建立单独的项目,GroupID 保持不变,ArtifactID 对应相应的章节
Search dependencies to add = Web
Step 3. 导入项目
将下载好的项目解压,然后通过 [Import Existing ] 导入到 Eclipse 中,到了这一步,我们就有了第一个基于 Spring Boot 的项目了。
Step 4. 修改项目端口
如果跳过这一步也是可以的,这样项目默认的端口是 8080。
修改 application.properties 文件为 application.yml 文件,配置项目访问端口:
server:
port: 8082
Step 5. 创建第一个接口
在 src/main/java/com/archevolution/chapter1 下新建 package Controller 作为项目的控制层,并新建 UserController 类,代码如下:
package com.archevolution.chapter1.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@RequestMapping(value = "/queryAdmin")
public String queryUser(){
return "User : Admin";
}
}
Step 6. 启动项目并测试接口
在 Chapter1Application 类中的空白处,选择 [Run As - Java Application] 运行项目;
待项目启动后,通过接口测试软件或直接打开浏览器输入:
http://127.0.0.1:8088/queryAdmin
输出结果:
User : Admin
4. Spring Boot 的优势
我们为什么要学习,这就要看看 Spring Boot 可以给软件开发带来什么样的好处。
让开发变快: 构建项目很快;支持主流的关系数据库和非关系数据库;内嵌容器;自带监控;简洁的安全策略集成...;总结来说,Spring Boot支持大部分主流框架的集成,并且只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。
支持多种测试框架: 比如 JUnit、Spring Test、Mockito 等等,开发人员只需要引入 spring-boot-start-test,就可以对数据库、Mock 等进行测试;
配置变的简单: 【约定优于配置】,这个意思是,已经制定好一套规则了,如果你遵守的话,就不用再写配置了,如果你不打算遵守的话,再写配置告诉程序你想怎么样;
部署变的简单: 首先Spring Boot是内置容器的,这让我们不需要关心容器环境的问题;另外Spring Boot和主流的持续集成软件比如Jenkins,集成的很好,只需要做简单的配置,就可以完成代码的拉取、打包、自动化测试、部署等工作,简化了运维的工作;
5. Spring Boot 常见知识点
5.1 Spring Boot 核心功能
内嵌容器:内嵌了 Tomcat、Jetty、Undertow,我们选择其中一个直接运行我们的项目;
独立运行:因为内嵌了容器,所以 Spring Boot 可以以 jar 包的方式独立运行;
提供了大量的 starter:通过在 pom.xml 中添加依赖,简化了和其他框架的集成;
用注解替代配置文件:Spring Boot 使用了大量的注解,避免过多使用 XML 配置文件;
约定优于配置:制定好一套规则,如果完全按照这个规则的话,可以简化我们的代码;
5.2 什么是 Spring Boot Starter?
Spring Boot 已经完成了与很多框架的集成,当我们想在自己的项目中集成某一种框架的时候,只需要配置 Starter ,Spring Boot 会自动帮我们完成相关的配置和相关的依赖(引入什么 jar 包、jar 包的版本、是否需要引入其他的 jar 包等等),开发人员不需要关心框架整合的问题。
5.3 什么叫做约定优于配置?
已经制定好一套规则了,如果你遵守的话,就不用再写配置了,如果你不打算遵守的话,再写配置告诉程序你想怎么样;
比如你的项目要使用内置的 Tomcat,端口默认是 8080,你可以不做任何配置,但是当你想修改端口为 8088(不遵守规则),那么你就需要增加配置,设置 server.port = 8088 。
5.4 Spring Boot 配置的加载顺序
Spring Boot 可以通过很多方式进行配置,而配置是有优先级的,优先级高的会覆盖优先级低的配置。
最常用的配置中:
命令行参数 > 系统环境变量 > YAML 配置文件 > 默认参数
比如我们在启动的时候设置: java-jar springboot.jar--server.port=9090
在配置文件中设置: server.port=8888
那么启动后的应用端口将是 9090
。
5.5 如何在不同的环境中使用不同的配置?
在很多实际项目中,都会分成开发环境、测试环境、(准生产环境)、生产环境等等,不同的测试环境配置文件多多少少会有一些不同,传统的项目中,我们都是有多个代码基线,不同的代码极限中,配置文件的内容是不相同的。
那么 Spring Boot 项目中会通过什么方式实现在不同的环境中使用不同的配置呢?
通常我们会在一个程序包中设置多个配置文件,然后通过配置文件、启动命令、设置服务器环境变量等方式,指定生效的配置文件。
有些同学看到这里可能会有疑问,感觉没有什么差别啊,两个环境中,总会有一个配置文件是不相同的;但实际上 Spring Boot 可以有好多中配置的方式;
比如我们可以在启动命令中设置哪个配置文件生效:
当然,如果你害怕启动命令敲错了,可以直接将启动命令写成 sh 脚本,通过脚本启动;或者直接将其作为环境变量,配置到服务器上。
5.6 Spring Boot 只能通过内置的容器运行么?
因为 Spring Boot 内置了 web 容器,所以可以让应用像本地程序一样启动运行,但并不是说 Spring Boot 只能通过内置的 Tomcat 或 Jetty 运行。
Spring 应用的运行方式有两种:
以 jar 包方式运行;
打包成 war 包,部署到 web 容器,比如 Tomcat、Weblogic 等等;
使用 jar 的方式无序在部署 web 容器,似的调试和部署更加的简单,适合大规模的快速部署;但同时也会导致应用包体积过大,而且内置 web 容器的相关配置修改起来比较困难。
使用 war 包部署,一般 web 容器都有功能比较强大的可视化界面,管理起来更为简单,数据源也可以交给 web 容器进行管理,应用体积比较小;但同时需要开发或运维人员搭建和维护 web 容器,应用和容器也可能会存在兼容性的问题。
5.6 Spring Boot 常用注解
有些注解不一定是 Spring Boot 才有或者独有的,可能是 Spring 、Spring MVC 或其他框架的,但根据常见程度我也列出来了。
5.6.1 SpringBootApplication
用在 Spring Boot 的主类上,标识着这个应用是一个 Spring Boot 应用, @SpringBootApplication
又是三个注解的组合,包含了:
@SpringBootConfiguration
:源于@Configuration
,作用就是将当前类标注为配置类;@EnableAutoConfiguration
:自动配置,让 Spring Boot 应用将所有@Configuration
配置都加载到 IoC 容器中;@ComponentScan
:将一些标注了特定注解的 bean 注册到 IoC 容器中,比如:@Controller
、@Component
、@Entity
等等。
5.6.2 @ImportResource
用于将加载 xxxx.xml
文件中的配置;比如老的 Spring 项目迁移到 Spring Boot 上,可以使用这个标签加载制定的配置文件。
"classpath:beans.xml") (
public class Chapter1Application {
public static void main(String[] args) {
SpringApplication.run(Chapter1Application.class, args);
}
}
5.6.3 @Autowired
自动装配,会在 IoC 容器中查询对应类型的 Bean,如果查询到了,就装配上,如果查询不到,那么会抛出异常; @Autowired
可以消除 set、get 方法,对应着 XML 配置文件中的:
"classpath:beans.xml") (
public class Chapter1Application {
public static void main(String[] args) {
SpringApplication.run(Chapter1Application.class, args);
}
}
5.6.4 Controller 相关
@Controller
:标记在一个类上,表示这是一个 Controller 对象,是一个控制器类;@RestController
:等于@Controller
和@ResponseBody
的组合,方法返回的对象可以直接转化成 JSON 格式;@RequestParam
:接收请求头 Request Head 中的内容,比如Content-Type
标识了具体请求中的资源类型,常用的application/xml
、application/json
等等。@PathVariable
:获取 url 中的参数;@RequestBody
:读取请求体 Request Body ,并将其反序列化成 Java 对象;@RequestMapping
:将 http 请求映射到控制器上,也就是将请求路径和其处理类和方法进行绑定。
5.6.5 Bean相关
@Service
:用于标注服务层组件,表示这是一个 Bean,Bean 的名称默认为当前类的名字,也可以传递参数,指定 Bean 的名称;@Repository
:数据库访问组件,也就是 DAO 层;@Scope
:用于配置作用域,比如设置 singleton 表示单例,prototype 每次都会创建一个新的对象等等;@Entity
:实体类,可以使用@Table
注解和数据库中的表绑定,主键使用@Id
标注,其余字段使用@Column
进行标注(如果保持属性名和字段名一致,可以省略 @Column);@Component
:当组件不好归类的时候,可以使用@Component
进行标注;@Autowired
:当我们需要使用组件的时候,可以使用@Autowired
实现的 Bean 的自动注入。
6. 总结
在本节课中,我们学习了 Spring Boot 的概念、历史、优点、常见知识点,以及搭建了一个最简单的 Spring Boot 应用;现在我们项目的架构是这样的,不要笑,就是这么“简陋”。
单体架构就是把所有的功能都放在一个工程项目中,但是当访问量不断增加,我们只部署一套环境就有些吃不消了,这时候有什么解决方案么?有兴趣的伙伴可以关注我,下期文章介绍。
会点代码的大叔 | 原创
【从单体架构到分布式架构】本系列文章希望用浅显直白的语言介绍架构发展过程中遇到的各种问题,以及对应的解决方案和优缺点。
适合人群:想从事 JavaWeb 开发的学生,建议要有一定的 Java 语言基础;新手程序员,想要了解现在 JavaWeb 开发比较流行的中间件和框架;技术栈长期为 SSH、SSM ,但是想寻求改变的程序员。