SpringCloud
简介 Spring Cloud为开发人员提供了快速构建分布式系统中的一些常见模式的工具(例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导人选举、分布式会话、集群状态)。分布式系统的协调导致了锅炉板模式,而使用Spring Cloud开发人员可以快速建立实现这些模式的服务和应用程序。它们在任何分布式环境中都能很好地工作,包括开发人员自己的笔记本电脑、裸金属数据中心和云计算等托管平台。 优点
- 产出于Spring大家族,Spring在企业级开发框架中无人能敌,来头很大,可以保证后续的更新、完善
- 组件丰富,功能齐全。Spring Cloud 为微服务架构提供了非常完整的支持。例如、配置管理、服务发现、断路器、微服务网关等;
- Spring Cloud 社区活跃度很高,教程很丰富,遇到问题很容易找到解决方案
- 服务拆分粒度更细,耦合度比较低,有利于资源重复利用,有利于提高开发效率
- 可以更精准的制定优化服务方案,提高系统的可维护性
- 减轻团队的成本,可以并行开发,不用关注其他人怎么开发,先关注自己的开发
- 微服务可以是跨平台的,可以用任何一种语言开发
- 适于互联网时代,产品迭代周期更短
缺点
- 微服务过多,治理成本高,不利于维护系统
- 分布式系统开发的成本高(容错,分布式事务等)对团队挑战大
SpringCloud和SpringBoot对应版本
SpringBoot vs SpringCloud
- SpringBoot专注于快速方便的开发单个个体微服务。
- SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,
- 为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务
- SpringBoot可以离开SpringCloud独立使用开发项目, 但是SpringCloud离不开SpringBoot ,属于依赖的关系
- SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
SpringCloud入门初体验-Rest
- 创建一个空的Maven项目
springcloud-study
作为父项目 - 在这个父项目的
pom.xml
导入依赖:这里的依赖只是被管理,如果在子项目中要使用,就需要在子项目中把依赖引进来,父项目如果已经管理了,子项目就不需要写版本
<!-- 打包方式 pom -->
<packaging>pom</packaging>
<!--版本控制,易于后期的维护-->
<properties>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.18.10</lombok.version>
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<!-- spring-cloud的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springboot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.5</version>
</dependency>
<!--springboot启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.3.0-alpha5</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>
</dependencies>
</dependencyManagement>
-
创建一个数据库,IDEA连接数据库。
-
创建一个子模块
springcloyd-api
,在子模块导入需要用到的依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
- 在该模块下写对应数据库的实体类,实现ORM映射
package pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
//implements Serializable 序列化
@Data
@NoArgsConstructor
@Accessors(chain = true)//链式写法
public class Dept implements Serializable {
private Long deptId;
private String deptName;
//判断数据是从哪个数据库中取出来的
private String dbResource;
public Dept(String deptName) {
this.deptName = deptName;
}
}
服务提供者
- 新建一个子模块
springcloud-provider-8001
,作为服务提供者,该模块的结构
- 为该子模块添加需要用到的依赖
<dependencies>
<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>
</dependencies>
- 在该模块编写mapper层
DeptMapper.java
package springcloud.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import pojo.Dept;
import java.util.List;
@Mapper
@Repository
public interface DeptMapper {
public Boolean addDept(Dept dept);
public Dept getDeptById(Long deptId);
public List<Dept> queryAll();
}
- 在该模块编写mapper层的配置文件
DeptMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="springcloud.mapper.DeptMapper">
<insert id="addDept" parameterType="dept">
insert into db01.dept (deptName, dbResource) VALUES (#{deptName},DATABASE());
</insert>
<select id="getDeptById" resultType="dept" parameterType="Long">
select * from db01.dept where deptId=#{id};
</select>
<select id="queryAll" resultType="dept">
select * from db01.dept;
</select>
</mapper>
- 在该模块编写service层接口
DeptService.java
package springcloud.service;
import pojo.Dept;
import java.util.List;
public interface DeptService {
public Boolean addDept(Dept dept);
public Dept getDeptById(Long deptId);
public List<Dept> queryAll();
}
- 在该模块编写service层接口实现类
DeptServiceImpl.java
package springcloud.service;
import springcloud.mapper.DeptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pojo.Dept;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService{
@Autowired
private DeptMapper deptMapper;
public Boolean addDept(Dept dept) {
return deptMapper.addDept(dept);
}
public Dept getDeptById(Long deptId) {
return deptMapper.getDeptById(deptId);
}
public List<Dept> queryAll() {
return deptMapper.queryAll();
}
}
- 在该模块编写controller层
DeptController.java
package springcloud.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import pojo.Dept;
import springcloud.service.DeptService;
import java.util.List;
//提供Restful服务
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/provider/add")
public Boolean add(@RequestBody Dept dept){
return deptService.addDept(dept);
}
@GetMapping("/provider/get/{id}")
public Dept get(@PathVariable("id") Long id){
return deptService.getDeptById(id);
}
@PostMapping("/provider/query")
public List<Dept> query(){
return deptService.queryAll();
}
}
- 编写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>
- 编写
application.yml
配置
server:
port: 8001
mybatis:
type-aliases-package: pojo
mapper-locations: classpath:mybatis/mapper/*.xml
config-location: classpath:mybatis/mybatis-config.xml
spring:
application:
name: springcloud-provider
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: 123456
- 编写主启动类
DeptProvider.java
package springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//主启动类
@SpringBootApplication
public class DeptProvider {
public static void main(String[] args) {
SpringApplication.run(DeptProvider.class,args);
}
}
- 启动测试,保证服务提供者能够顺利提供服务
服务消费者
- 同样的,先创建一个子模块
springcloud-consumer-80
来实现服务消费者
- 导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-study</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-80</artifactId>
<dependencies>
<!--实体类-->
<dependency>
<groupId>org.example</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
- 编写
application.yml
配置
server:
port: 80
- 在config包下编写
RestfulBean.java
实现REST请求方案模版的配置
package springcloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/*
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例
如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。
*/
@Configuration
public class RestfulBean {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 在controller包下编写
DeptController.java
让消费者拿到服务
package springcloud.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import pojo.Dept;
import java.util.List;
@RestController
public class DeptController {
@Autowired
private RestTemplate restTemplate;
private static final String REST_URL_PREFIX="http://localhost:8001";
@RequestMapping("/consumer/add")
public boolean add(Dept dept){
//请求的路径:REST_URL_PREFIX+"add"
//传递的参数:dept
//返回的对象:boolean.class
return restTemplate.postForObject(REST_URL_PREFIX+"/provider/add",dept,boolean.class);
}
@RequestMapping("/consumer/get/{id}")
public Dept get(@PathVariable("id") Long id){
//请求的路径:REST_URL_PREFIX+"get/"+id
//请求返回的对象:Dept.class
return restTemplate.getForObject(REST_URL_PREFIX+"/provider/get/"+id,Dept.class);
}
@RequestMapping("/consumer/query")
public List<Dept> query(){
//请求的路径:REST_URL_PREFIX+"query"
//传递的参数:void.class
//返回的对象:List.class
return restTemplate.postForObject(REST_URL_PREFIX+"/provider/query",void.class,List.class);
}
}
- 编写主启动类
DeptConsumer,java
package springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DeptConsumer {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer.class,args);
}
}
这样子,我们就简单的实现了Rest学习环境的搭建,我们先启动服务提供者,再启动服务消费者,就可以进行测试了。
SpringCloud-Rest 初体验小结
-
@Mapper和@Repository
@Mapper:
1. 作用在dao层接口,使得其生成代理对象bean,交给spring容器管理 2. 相当于原来mybatis-config.xml中的 <mappers> <mapper resource="com/wu/dao/UserMapper.xml"/> </mappers> 3. 也就是将mapper注册到spring容器中 4. 不需要配置扫描地址,可以单独使用,有多个mapper的话, 可以在项目启动类中加入@MapperScan(“mapper文件所在包”), 这样就不需要每个mapper文件都加@Mapper注解了
@Repository:
1. 也作用在dao层,但是不能单独使用 2. 需要配置扫描地址
-
@RestController=@Controller+@ResponseBody跟@RequestBody不一样
-
@RequestBody接收请求,一篇对这个注解详细解释的Blog
-
@ResponseBody返回响应
-
主启动类不能放在java包下,要在java包下再建一个包,主启动类放在这个新建的包下
-
主启动类只会扫描和主启动类同级的包
-
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。
-
服务提供者提供访问的方式和服务消费者的访问方式要一致
- 使用post和get方式,返回时所需要的参数是不同的