SpringCloud 是微服务一站式服务解决方案,微服务全家桶。它是微服务开发的主流技术栈。它采用了名称,而非数字版本号。
SpringCloud 和 SpringCloud Alibaba 目前是最主流的微服务框架组合。本笔记根据B站尚硅谷教程整理而成!
教程:https://www.bilibili.com/video/BV18E411x7eT
比如搭建一个电商系统:客户下订单,商品展示,用户管理。这种将所有功能度部署在一个web容器中运行的系统就叫做单体架构,目前也有人称为单体地狱。
优点:
缺点:
优点:
缺点:
SOA,全称是Service-Oriented Architecture,即面向服务的架构。它可以根据需要通过网络对松散耦合的粗粒度应用组件(服务)进行分布式部署、组合和使用。一个服务通常以独立的形式存在于操作系统进程中。
站在功能的角度,把业务逻辑抽象成可复用、可组装的服务,通过服务的编排实现业务的快速再生,目的是把原先固有的业务功能转变为通用的业务服务,实现业务逻辑的快速复用。
通过上面的描述可以发现SOA有如下的特点:分布式、可重用、扩展灵活、松耦合。
优点:
缺点:
优点:
缺点:
SOA:面向服务的架构,是一种设计方法,其中包含多个服务,服务和服务之间通过相互依赖最终提供一系列的功能。一个服务通常以独立的形式存在于操作系统的进程之中。各个服务之间通过网络调用。
微服务架构:其实和SOA架构类似,微服务是SOA架构上的升华,微服务架构强调的一个重点是"业务需要彻底的组件化和服务化",原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
功能 | SOA | 微服务 |
---|---|---|
组件大小 | 大块业务逻辑 | 单独任务或小块业务逻辑 |
耦合 | 通常松耦合 | 总是松耦合 |
公司架构 | 任何类型 | 小型,专注于功能交叉团队 |
管理 | 着重中央管理 | 着重分散管理 |
目标 | 确保应用能够交互操作 | 执行新功能、快速拓展开发团队 |
RESTful。
RPC。
现如今,对于大多数大型互联网应用,分布式系统正变得越来越重要。分布式系统最大的难点,就是各个节点的状态如何同步。CAP定理是这方面的基本定理,也是理解分布式系统的起点。
CAP理论有Eirc Brewer在ACM研讨会上提出的,而后CAP被奉为分布式领域的重要理论。分布式系统的CAP理论,首先把分布式系统中的三个特性进行了如下的归纳。
C(Consistency,一致性):数据一致更新,所有数据的变化都是同步的。
A(Availability,可用性):在集群中一部分节点故障后,集群整体是否还能有影响客户端的读写请求。
P(Partition tolerance,分区容错性):某个节点的故障,并不影响整个系统的运行。
一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。
当你一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了。这时分区就是无法容忍的。
提高分区容忍性的办法就是一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了。
然而,要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。
总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。
作者:邬江
链接:https://www.zhihu.com/question/54105974/answer/139037688
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
选择 | 说明 |
---|---|
CA | 放弃分区容错性,加强一致性和可用性,其实就是传统的关系型数据库的选择 |
AP | 放弃一致性(强一致性),追求分区容错性和可用性,这时很多分布式系统设计时的选择,比如很多NoSQL数据库就是如此 |
CP | 放弃可用性,追求一致性和分区容错性,基本不会选择,网络问题会直接让整个系统不可用,比如zookeeper就是CP |
SpringCloud是一系列框架的有序集合
。它利用SpringBoot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册
、配置中心
、消息中线
、负载均衡
、熔断器
、数据监控
等,都可以用SpringBoot的开发风格做到一键启动和部署。SpringCloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考研的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机IP和提供服务的Port,以及暴露服务自身状态以及访问协议等信息。
服务发现:服务实例请求注册中心获取所依赖服务信息。服务实例通过注册中心,获取到注册到其中的服务实例的信息,通过这些信息去其你去它们提供的服务。
随着微服务的不断增多,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接和各个微服务通信可能出现:
客户端需要调用不同的URL地址,增加难度。
在一定的场景下,存在跨域请求的问题。
每个微服务都需要进行单独的身份认证。
针对上面的问题,API网关顺势而生。
API网关直面意思是将所有API调用统一接入到API网关层,由网关层统一接入和输出。一个网关的基本功能有:统一接入、安全防护、协议适配、流量监管、长短链接支持、容错能力。有了网关之后,各个API服务提供团队可以专注于自己的业务逻辑处理,而API网关更专注于安全、流量和路由等问题。
Spring Cloud是一系列框架的有序集合
。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基参考资料,尽量去官网
SpringCloud 官网:https://spring.io/projects/spring-cloud#learn
SpringCloud 官方文档:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
SpringBoot 官网:https://spring.io/projects/spring-boot#learn
SpringBoot 官方文档:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/
Spring Cloud中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md
Spring Cloud的本质是在 Spring Boot 的基础上,增加了一堆微服务相关的规范,并对应用上下文
(Application Context)进行了功能增强。既然 Spring Cloud 是规范,那么就需要去实现,目前
Spring Cloud 规范已有 Spring官方,Spring Cloud Netflix,Spring Cloud Alibaba等实现。通过组件
化的方式,Spring Cloud将这些实现整合到一起构成全家桶式的微服务技术栈。
Spring Cloud Netflix组件 :
组件名称 | 作用 |
---|---|
Eureka | 服务注册中心 |
Ribbon | 客户端负载均衡 |
Feign | 声明式服务调用 |
Hystrix | 客户端容错保护 |
Zuul | API服务网关 |
组件名称 | 作用 |
---|---|
Nacos | 服务注册中心 |
Sentinel | 客户端容错保护 |
组件 | 作用 |
---|---|
Consul | 服务注册中心 |
Config | 分布式配置中心 |
Gateway | API服务网关 |
Sleuth/Zipkin | 分布式链路追踪 |
从上图可以看出Spring Cloud各个组件相互配合,合作支持了一套完整的微服务架构。
注册中心
负责服务的注册与发现,很好将各服务连接起来。
断路器
负责监控服务之间的调用情况,连续多次失败进行熔断保护。
API网关
负责转发所有对外的请求和服务。
配置中心
提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息 。
版本选择:
查看官网:https://spring.io/projects/spring-cloud#overview,拖到下面查看官方给出的版本对应关系。
例如以如下版本对应为例:
工程步骤:
构建父工程 spring_cloud_atguigu_2020
,后面的项目模块都在此工程中:
设置编码:Settings -> Editor-> File Encodings
注解激活:
选择java编译版本:
文件过滤,可以不设置
(这样就显示不出来这些文件了,有的文件看着有点烦):
删掉 src 目录,只留 pom 文件
<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">
<modelVersion>4.0.0modelVersion>
<groupId>com.itjing.springcloudgroupId>
<artifactId>spring_cloud_atguigu_2020artifactId>
<version>1.0-SNAPSHOTversion>
<packaging>pompackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<junit.version>4.12junit.version>
<log4j.version>1.2.17log4j.version>
<lombok.version>1.16.18lombok.version>
<mysql.version>5.1.47mysql.version>
<druid.version>1.1.16druid.version>
<mybatis.spring.boot.version>1.3.0mybatis.spring.boot.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-project-info-reports-pluginartifactId>
<version>3.0.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.2.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Hoxton.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>${mybatis.spring.boot.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>${log4j.version}version>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
<addResources>trueaddResources>
configuration>
plugin>
plugins>
build>
project>
上面配置的解释:
首先要加
<packaging>pompackaging>
聚合版本依赖,dependencyManagement
只声明依赖
,并不实现引入
,所以子项目还需要写要引入的依赖。
步骤:
在父工程中新建子模块:cloud-provider-payment8001
查看父工程 pom 文件变化,多了 modules
标签
<modules>
<module>cloud-provider-payment8001module>
modules>
<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>spring_cloud_atguigu_2020artifactId>
<groupId>com.itjing.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-provider-payment8001artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
在 resources 目录下新建 application.yml
# 端口号
server:
port: 8001
spring:
application:
name: cloud-payment-service
# 数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
# mybatis 相关
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.itjing.springcloud.entities # 所有Entity 别名类所在包
package com.itjing.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
五步:
创建数据库:springcloud2020,建表:payment
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` varchar(200) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
package com.itjing.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
private Long id;
private String serial;
}
真正做开发的时候,可以自定义枚举类处理,具体去查询百度学习。
package com.itjing.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 如果前后端分离,这个是提供给前端信息和数据的类
*
* @param
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
private Integer code;
private String messgae;
private T data;
/**
* 查询为空的时候使用的构造器
*
* @param code
* @param messgae
*/
public CommonResult(Integer code, String messgae) {
this(code, messgae, null);
}
}
package com.itjing.springcloud.dao;
import com.itjing.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface PaymentDao {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itjing.springcloud.dao.PaymentDao">
<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) values (#{serial})
insert>
<resultMap id="BaseReslutMap" type="com.itjing.springcloud.entities.Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="serial" property="serial" jdbcType="VARCHAR"/>
resultMap>
<select id="getPaymentById" parameterType="Long" resultMap="BaseReslutMap">
select id,serial from payment where id = #{id}
select>
mapper>
package com.itjing.springcloud.service;
import com.itjing.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;
public interface PaymentService {
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
}
package com.itjing.springcloud.service.impl;
import com.itjing.springcloud.dao.PaymentDao;
import com.itjing.springcloud.entities.Payment;
import com.itjing.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
package com.itjing.springcloud.controller;
import com.itjing.springcloud.entities.CommonResult;
import com.itjing.springcloud.entities.Payment;
import com.itjing.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController //必须是这个注解,因为是模拟前后端分离的 restful风格的请求,要求每个方法返回 json
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/payments")
public CommonResult create(Payment payment) {
int result = paymentService.create(payment);
log.info("****插入结果:" + result);
if (result > 0) {
return new CommonResult(200, "插入数据库成功", result);
}
return new CommonResult(444, "插入数据库失败", null);
}
@GetMapping(value = "/payment/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment result = paymentService.getPaymentById(id);
log.info("****查询结果:" + result);
if(result != null){
return new CommonResult(200, "查询成功", result);
}
return new CommonResult(444, "没有对应id的记录", null);
}
}
使用 postman
工具进行测试,自测通过!
spring-boot-devtools
依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
<addResources>trueaddResources>
configuration>
plugin>
plugins>
build>
#配置项目热部署
spring.devtools.restart.enabled=true
1.打开Settings,设置当前项目自动编译,搜索Compiler,勾选Build project automatically
2.打开Other Settings ,设置新建的项目都自动编译,搜索Compliler,勾选Build project automatically
3.按住ctrl + shift + alt + /,出现如下图所示界面,点击Registry…
4.点击进入后,勾选compiler.automake.allow.when.app.running后关闭即可
重启IDEA!
通过以上步骤,就完成了SpringBoot项目的热部署功能!!!
步骤参考提供者。
创建子模块:cloud-consumer-order80
消费者现在只模拟调用提供者的Controller方法,没有持久层配置,只有Controller和实体类
当然也要配置主启动类和启动端口
<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>spring_cloud_atguigu_2020artifactId>
<groupId>com.itjing.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-consumer-order80artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
server:
port: 80
spring:
application:
name: cloud-order-service
package com.itjing.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
将 提供者 中的 CommonResult 和 Payment 拷贝过来,创建
RestTemplate
。Spring框架提供的RestTemplate类可用于在应用中调用RESTful服务,它简化了和HTTP服务的通信方式,统一了RESTful的标准,封装了HTTP的链接,我们只需要传入URL和返回值类型即可。相较于之前常用的HttpClient、OkHttp等,RestTemplate是一种更加优雅的调用RESTful服务的方式。
在Spring应用程序中访问第三方REST服务和Spring的RestTemplate类有关。RestTemplate类的设计原则和许多其他Spring模块类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
RestTemplate默认依赖JDK提供HTTP连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为如Apache HttpComponents、Netty或OkHttp等其他HTTP库。
考虑到RestTemplate类是为调用REST服务而设计的,因此他的主要方法和REST的基础紧密相连就不足为奇,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()等方法。
package com.itjing.springcloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
package com.itjing.springcloud.controller;
import com.itjing.springcloud.entities.CommonResult;
import com.itjing.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class OrderController {
//远程调用的 地址
public static final String PAYMENT_URL = "http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@PostMapping("consumer/payment/create")
public CommonResult<Payment> create(Payment payment) {
/**
param1 请求地址,param2 请求参数, param3 返回类型
*/
return restTemplate.postForObject(PAYMENT_URL + "/payment/payments", payment, CommonResult.class);
}
@GetMapping("consumer/payment/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
return restTemplate.getForObject(PAYMENT_URL + "/payment/" + id, CommonResult.class);
}
}
启动 服务提供者:cloud-provider-payment8001
启动服务消费者:cloud-consumer-order80
这时候右下角会弹出 Run Dashboard 提示,我们应该让它显示出来,以后微服务多了,我们需要它管理。
访问消费者的接口进行测试!
发现执行添加操作
的时候,数据库中的数据为 null
,是因为之前的 服务提供者中 没有加 @RequestBody
注解
// 注意这里的 @RequestBody 是必须要写的,虽然 MVC可以自动封装参数成为对象,
// 但是当消费者项目调用,它传参是 payment 整个实例对象传过来的, 即Json数据,因此需要写这个注解
public CommonResult create(@RequestBody Payment payment){
...}
上面的两个子模块,有多次重复的导入jar
,和重复的 Entity 实体类
。
可以把多余的部分,加入到一个独立的模块中,将这个模块打包,并提供给需要使用的 module 。
1、新建一个 cloud-api-commons 子模块
2、将 entities 包里面的实体类复制到这个子模块中,将所需依赖引入 pom 文件中。如下:
<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>spring_cloud_atguigu_2020artifactId>
<groupId>com.itjing.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-api-commonsartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.1.0version>
dependency>
dependencies>
project>
3、将此项目打包 install 到 maven仓库
先 clean,再 install
4、改造提供者和消费者,将 提供者 和 消费者 两个项目中的 entities 包删除。
5、将 打包到 maven 仓库的 cloud-api-commons 模块,引入到 提供者 和 消费者的 pom 文件中,如下所示
<dependency>
<groupId>com.itjing.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>${project.version}version>
dependency>
服务调用者将微服务的请求路径硬编码到Java代码中。
不能对微服务负载均衡的调用,因为请求路径的URL硬编码了。
服务多起来,对前端调用不友好,需要加入API网关。
微服务多起来的话,如果每次都需要重新修改配置文件,很麻烦,需要配置的统一管理。
链路追踪。
系统容错。
……