本系列文章为【狂神说 Java 】视频的课堂笔记,若有需要可配套视频学习。
1. 简介
1.1 SpringCloud
SpringCloud 基于 SpringBoot 提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了 NetFlix 的开源组件做高度抽象封装之外,还有一些选型中立的开源组件。
SpringCloud 为开发人员提供了配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞争,分布式会话等快速构建分布式系统的工具。
SpringCloud 将各个成熟的服务框架组合起来,通过 SpringBoot 风格进行再封装,屏蔽了复杂的配置和实现原理,为开发者提供一个易部署易维护的分布式系统开发工具包。
1.2 SpringBoot 与 SpringCloud 的关系
- SpringBoot 专注于开发单个微服务。
- SpringCloud 是关注全局的微服务协调整理治理框架。
1.3 Dubbo 和 SpringCloud 技术选型
-
一个成熟、传统的互联网架构
-
Dubbo 和 SpringCloud 对比
Dubbo SpringCloud 服务注册中心 Zookeeper SpringCloud NetFilx Eureka 服务调度方式 RPC REST API 服务监控 Dubbo-Monitor SpringBoot Admin 断路器 不完善 SpringCloud NetFilx Hystrix 服务网关 无 SpringCloud NetFilx Zuul 分布式配置 无 SpringCloud Config 服务跟踪 无 SpringCloud Sleuth 消息总线 无 SpringCloud Bus 数据流 无 SpringCloud Stream 批量处理 无 SpringCloud Task SpringCloud 抛弃了 Dubbo 的 RPC 通信,采用 HTTP 的 REST 方式。
SpringCloud 能够与 Spring 项目完美融合。
1.4 下载地址
-
SpringCloud 官网:Spring Cloud
-
Spring Cloud NetFlix 中文文档:Spring Cloud Netflix 中文文档 参考手册 中文版
-
Spring Cloud 中文文档:Spring Cloud Dalston 中文文档 参考手册 中文版
-
Spring Cloud 中文网:Spring Cloud中文网-官方文档中文版
1.5 版本控制
版本说明
SpringBoot | SpringCloud | 关系 |
---|---|---|
1.2.x | Angel(天使) | 兼容 Spring Boot 1.2.x |
1.3.x | Brixton(布里克斯顿) | 兼容 Spring Boot 1.3.x,Spring Boot 1.4.x |
1.4.x | Camden(卡姆登) | 兼容 Spring Boot 1.4.x,Spring Boot 1.5.x |
1.5.x | Dalston(多尔斯顿) | 兼容 Spring Boot 1.5.x,不兼容 Spring Boot 2.0.x |
1.5.x | Edgware(埃奇韦尔) | 兼容 Spring Boot 1.5.x,不兼容 Spring Boot 2.0.x |
2.0.x | Finchley(芬奇利) | 兼容 Spring Boot 2.0.x,不兼容 Spring Boot 1.5.x |
2.1.x | Greenwich(格林威治) |
版本关系
spring-boot-starter-parent | spring-cloud-dependencies | ||
---|---|---|---|
版本号 | 发布日期 | 版本号 | 发布日期 |
1.5.2.RELEASE | 2017年3月 | Dalston.RC1 | 2017年未知月 |
1.5.9.RELEASE | Nov.2017 | Edgware.RELEASE | Nov.2017 |
1.5.16.RELEASE | Sep.2018 | Edgware.SR5 | Oct.2018 |
1.5.20.RELEASE | Apr.2019 | Edgware.SR5 | Oct.2018 |
2.0.2.RELEASE | May.2018 | Finchley.BUILD-SNAPSHOT | 2018年未知月 |
2.0.6.RELEASE | Oct.2018 | Finchley.SR2 | Oct.2018 |
2.1.4.RELEASE | Apr.2019 | Greenwich.SR1 | Mar.2019 |
2. 环境搭建
(1) 创建一个基础的 maven 项目
-
删除 src 目录,将此项目作为父项目 springcloud
-
管理依赖
<!--打包方式--> <packaging>pom</packaging> <!--版本控制--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <lombok.version>1.16.10</lombok.version> <log4j.version>1.2.17</log4j.version> </properties> <!--依赖管理(不显示在 Libraries 中)--> <dependencyManagement> <dependencies> <!--springcloud--> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <!--springboot--> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.4.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!--数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!--springboot 启动器--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <!--日志和测试--> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!--log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!--logback--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> </dependencies> </dependencyManagement>
(2) 创建一个 maven 模块作为 api 服务
springcloud-api
● 导入依赖
<!--pom.xml-->
<artifactId>springcloud-api</artifactId>
<!--若是 springcloud (父项目)管理的依赖,则使用父项目的依赖,无需添加版本-->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
● 创建数据库
● 编写实体类
@Data
@NoArgsConstructor
/**
* 链式写法
* Dept dept = new Dept();
* dept.setDeptNo(1).setDname("why").setDb_source("cloud01");
*/
@Accessors(chain = true)
public class Dept implements Serializable {
// 主键
private Long deptno;
private String dname;
// 数据所在数据库
private String db_source;
public Dept(String dname) {
this.dname = dname;
}
}
(3) 创建一个 maven 模块作为 provider 服务
springcloud-provider-dept-8001
● 导入依赖
<!--pom.xml-->
<artifactId>springcloud-provider-dept-8001</artifactId>
<dependencies>
<!--api moudle-->
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jetty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--热部署工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
● 编写 mybatis 配置文件(回顾)
<!--resources/mybatis/mybatis-config.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
● 编写应用配置文件
# resources/application.yml
server:
port: 8001
# mybatis
mybatis:
type-aliases-package: com.why.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
# spring配置
spring:
application:
name: springcloud-provider-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/cloud01?useUnicode=true&characterEncoding=utf-8
username: root
password: 981030
● 编写 dao 和 service
@Mapper
@Repository
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
public interface DeptService {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
DeptDao deptDao;
@Override
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept queryById(Long id) {
return deptDao.queryById(id);
}
@Override
public List<Dept> queryAll() {
return queryAll();
}
}
● 编写 controller 和 启动类
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
// 此方法为 Post 请求方式,浏览器直接输入 url 方式无法访问,但是 consumer 服务可以调用并访问
@PostMapping("/dept/add")
public boolean addDept(@RequestBody Dept dept) {
return deptService.addDept(dept);
}
@GetMapping("/dept/getDept/{id}")
public Dept getDept(@PathVariable("id") Long id) {
return deptService.queryById(id);
}
@GetMapping("/dept/list")
public List<Dept> queryAll() {
return deptService.queryAll();
}
}
@SpringBootApplication
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class, args);
}
}
● 错误解决
java.lang.IllegalStateException: Failed to load property source from location 'classpath:/application.yml'
Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1
Caused by: java.nio.charset.MalformedInputException: Input length = 1
file was loaded in the wrong encoding utf-8
文章来源:https://uudwc.com/A/9djWV
- 删除 application.yml 文件,重新创建编写
(4) 创建一个 maven 模块作为 consumer 服务
springcloud-consumer-dept-80文章来源地址https://uudwc.com/A/9djWV
● 导入依赖
<artifactId>springcloud-consumer-dept-80</artifactId>
<!--实体类 + web-->
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
● 设置服务端口
# resources/application.yml
server:
port: 80
● 将 RestTemplate 注册到 spring 中
// config
@Configuration // spring applicationContext.xml
public class ConfigBean {
// 注册 bean <bean></bean>
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
● 编写控制器和主类
@RestController
public class DeptConsumerController {
// 提供访问远程 http 服务的方法
@Autowired
private RestTemplate restTemplate;
private static final String REST_URL_PREFIX = "http://localhost:8001";
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class);
}
@RequestMapping("/consumer/dept/getDept/{id}")
public Dept getDept(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/getDept/"+id, Dept.class);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list() {
return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class);
}
}
@SpringBootApplication
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class, args);
}
}