Spring全家桶--SpringCloud(初级)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring全家桶--SpringCloud(初级)相关的知识,希望对你有一定的参考价值。
SpringCloud初级
- 前言
- 一、微服务介绍
- 1.1 分布式系统定义
- 1.2 应用架构的演变
- 1.2.1 单一应用架构
- 1.2.2 垂直应用架构
- 1.2.3 分布式应用架构
- 1.2.4 流动计算架构
- 1.3 RPC
- 1.3.1 什么是RPC?
- 1.3.2 实例
- 1.4 Spring Cloud简介
- 1.4.1 什么是微服务
- 1.4.2 微服务架构优势
- 1.4.3 Spring Cloud 都做了哪些事
- 1.4.4 Spring Cloud 工具框架
- 1.4.5 什么是 Spring Boot
- 1.4.6 三者之间的关系
- 二、环境说明
- 三、父工程Project空间新建
- 3.1 父工程pom文件
- 3.2 dependencyManagement
- 四、支付模块构建
- 4.1 创建微服务模块套路
- 4.2 业务类小套路
- 4.3 支付模块测试
- 4.3 热部署Devtools
- 五、消费者订单模块
- 六、工程重构
- 七、Eureka
- 7.1 初始Eureka
- 7.1.1 什么是服务治理
- 7.1.2 什么是服务注册与发现
- 7.2 EurekaServer服务端安装
- 7.2.1 支付微服务8001入驻进EurekaServer
- 7.2.2 订单微服务80入驻进EurekaServer
- 7.3 Eureka集群
- 7.3.1 Eureka集群原理说明
- 7.3.2 Eureka集群环境构建
- 7.3.3 订单支付微服务注册进Eureka集群
- 7.3.4 支付微服务集群配置
- 7.3.5 actuator微服务信息完善
- 7.3.6 服务发现Discovery
- 7.4 Eureka自我保护理论知识
- 7.4.1 怎么禁止自我保护
- 八、Zookeeper
- 8.1 安装
- 8.2 订单服务注册进zookeeper
- 8.3 临时还是持久节点
- 8.4 订单服务注册进zookeeper
- 九、Consul
- 9.1 Consul简介
- 9.2 安装并运行Consul
- 9.3 服务提供者注册进Consul
- 9.4 服务消费者注册进Consul
- 十、三个注册中心异同点
- 十一、Ribbon入门介绍
- 11.1 Ribbon的负载均衡和Rest调用
- 11.2 Ribbon默认自带的负载规则
- 11.3 Ribbon负载规则替换
- 11.4 测试
- 11.5 Ribbon默认负载轮询算法原理
- 十二、OpenFeign是什么
- 12.1 OpenFeign服务调用
- 12.2 OpenFeign超时控制
- 12.3 OpenFeign日志增强
- 十三、Hystrix
- 13.1 初始Hystrix
- 13.1.1 Hystrix停更
- 13.1.2 Hystrix的关键概念
- 13.2 Hystrix支付微服务构建
- 13.2.1 JMeter高并发压测后卡顿
- 13.2.2 订单微服务调用支付服务出现卡顿
- 13.2.3 降级容错解决的维度要求
- 13.3 Hystrix之服务降级
- 13.3.1 Hystrix之服务降级订单侧fallback
- 13.3.2 Hystrix之服务降级订单侧fallback
- 13.3.3 Hystrix之全局服务降级DefaultProperties
- 13.3.4 Hystrix之通配服务降级FeignFallback
- 13.4 Hystrix之服务熔断
- 13.4.1 Hystrix之服务熔断案例
- 13.5 服务降级与服务熔断区别
- 13.6 Hystrix图形化Dashboard搭建
- 13.6.1 Hystrix图形化Dashboard监控实战
- Bug记录
- zookeeper服务连接启动失败原因
- zookeeper解决Error contacting service. It is probably not running.
- 文章参考
前言
源码地址:
https://github.com/YuyanCai/SpringCloudDemo
https://gitee.com/cai-yuyan/SpringCloudDemo
软件包:
链接:https://pan.baidu.com/s/1ZqyOC4j_bTWPbp9cPZMZcA
提取码:kqvs
导航:
Spring全家桶–SpringCloud(初级)
Spring全家桶–SpringCloud(中级)
Spring全家桶–SpringCloud(高级)
一、微服务介绍
- 微服务是一种架构风格
- 一个应用拆分为一组小型服务
- 每个服务运行在自己的进程内,也就是可独立部署和升级
- 服务之间使用轻量级HTTP交互
- 服务围绕业务功能拆分
- 可以由全自动部署机制独立部署
- 去中心化,服务自治。服务可以使用不同的语言、不同的存储技术
SpringCloud=分布式微服务架构的站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶
1.1 分布式系统定义
随着业务量的增大,我们不可能把所有的功能都放在一台服务器上,所以我们用很多台服务器每个服务器上都放一点服务,把业务分散在多台主机上。分布在多个主机上也不行啊,怎么处理它们之间的关系呢?
没错,这个管理者就是我们今天的主角------》Dubbo
1.2 应用架构的演变
1.2.1 单一应用架构
1.2.2 垂直应用架构
1.2.3 分布式应用架构
RPC:分布式服务框架
主要解决不同服务器之间的远程调用问题
1.2.4 流动计算架构
分布式架构还存在问题就是资源调度问题,某个服务器请求突然多了,某个服务器很少请求。那么如何协调它们的资源呢,让闲着的帮忙的干点事
之后呢,出现了流动计算机架构。引入了调度中心能解决资源调度问题
1.3 RPC
1.3.1 什么是RPC?
将java对象转化为字节流的过程就叫序列化
将字节流转化为java对象的过程就叫反序列化
当java对象需要在网络上进行传输或者持久化存储到文件中,就需要对java对象进行序列化
对于一个RPC框架好坏的评判就是建立起网络连接的速度快不快,序列化与反序列化的速度快不快
简而言之RPC的核心模块就是:通讯,序列化
RPC(Remote Producedure Call)是指远程过程调用,是一种进程间的通信方式,它是一种技术思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
1.3.2 实例
客户端A想调用客户端b的方法,那么要经过如下过程
1.4 Spring Cloud简介
是什么?符合微服务技术维度
SpringCloud=分布式微服务架构的站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶
SpringCloud俨然已成为微服务开发的主流技术栈,在国内开发者社区非常火爆。
1.4.1 什么是微服务
微服务的概念源于 2014 年 3 月 Martin Fowler 所写的一篇文章“Microservices”。文中内容提到:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。
每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。
另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。
微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。
1.4.2 微服务架构优势
01复杂度可控
在将应用分解的同时,规避了原本复杂度无止境的积累。每一个微服务专注于单一功能,并通过定义良好的接口清晰表述服务边界。
由于体积小、复杂度低,每个微服务可由一个小规模开发团队完全掌控,易于保持高可维护性和开发效率。
02独立部署
由于微服务具备独立的运行进程,所以每个微服务也可以独立部署。当某个微服务发生变更时无需编译、部署整个应用。
由微服务组成的应用相当于具备一系列可并行的发布流程,使得发布更加高效,同时降低对生产环境所造成的风险,最终缩短应用交付周期。
03技术选型灵活
微服务架构下,技术选型是去中心化的。每个团队可以根据自身服务的需求和行业发展的现状,自由选择最适合的技术栈。
由于每个微服务相对简单,所以需要对技术栈进行升级时所面临的风险就较低,甚至完全重构一个微服务也是可行的。
04容错
当某一组件发生故障时,在单一进程的传统架构下,故障很有可能在进程内扩散,形成应用全局性的不可用。
在微服务架构下,故障会被隔离在单个服务中。若设计良好,其他服务可通过重试、平稳退化等机制实现应用层面的容错。
05扩展
单块架构应用也可以实现横向扩展,就是将整个应用完整的复制到不同的节点。当应用的不同组件在扩展需求上存在差异时,微服务架构便体现出其灵活性,因为每个服务可以根据实际需求独立进行扩展。
1.4.3 Spring Cloud 都做了哪些事
Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。
Spring 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 Spring Boot 风格进行再封装、屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
以下为 Spring Cloud 的核心功能:
- 分布式/版本化配置。
- 服务注册和发现。
- 路由。
- 服务和服务之间的调用。
- 负载均衡。
- 断路器。
- 分布式消息传递。
1.4.4 Spring Cloud 工具框架
Spring Cloud Config,配置中心,利用 git 集中管理程序的配置。
Spring Cloud Netflix,集成众多 Netflix 的开源软件。
Spring Cloud Bus,消息总线,利用分布式消息将服务和服务实例连接在一起,用于在一个集群中传播状态的变化 。
Spring Cloud for Cloud Foundry,利用 Pivotal Cloudfoundry 集成你的应用程序。
Spring Cloud Foundry Service Broker,为建立管理云托管服务的服务代理提供了一个起点。
Spring Cloud Cluster,基于 Zookeeper、Redis、Hazelcast、Consul 实现的领导选举和平民状态模式的抽象和实现。
Spring Cloud Consul,基于 Hashicorp Consul 实现的服务发现和配置管理。
Spring Cloud Security,在 Zuul 代理中为 OAuth2 rest 客户端和认证头转发提供负载均衡。
Spring Cloud Sleuth Spring Cloud,应用的分布式追踪系统和 Zipkin、HTrace、ELK 兼容。
Spring Cloud Data Flow,一个云本地程序和操作模型,组成数据微服务在一个结构化的平台上。
Spring Cloud Stream,基于 Redis、Rabbit、Kafka 实现的消息微服务,简单声明模型用以在 Spring Cloud 应用中收发消息。
Spring Cloud Stream App Starters,基于 Spring Boot 为外部系统提供 Spring 的集成。
Spring Cloud Task,短生命周期的微服务,为 Spring Boot 应用简单声明添加功能和非功能特性。
Spring Cloud Task App Starters。
Spring Cloud Zookeeper,服务发现和配置管理基于 Apache Zookeeper。
Spring Cloud for Amazon Web Services,快速和亚马逊网络服务集成。
Spring Cloud Connectors,便于 PaaS 应用在各种平台上连接到后端像数据库和消息经纪服务。
Spring Cloud Starters,项目已经终止并且在 Angel.SR2 后的版本和其他项目合并。
Spring Cloud CLI,插件用 Groovy 快速的创建 Spring Cloud 组件应用。
这个数量还在一直增加…
1.4.5 什么是 Spring Boot
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
用我的话来理解,就是 Spring Boot 不是什么新的框架,它默认配置了很多框架的使用方式,就像 maven 整合了所有的 jar 包,Spring Boot 整合了所有的框架(不知道这样比喻是否合适)。
Spring Boot 简化了基于 Spring 的应用开发,通过少量的代码就能创建一个独立的、产品级别的 Spring 应用。Spring Boot 为 Spring 平台及第三方库提供开箱即用的设置,这样你就可以有条不紊地开始。
Spring Boot 的核心思想就是约定大于配置,多数 Spring Boot 应用只需要很少的 Spring 配置。采用 Spring Boot 可以大大的简化你的开发模式,所有你想集成的常用框架,它都有对应的组件支持。
1.4.6 三者之间的关系
微服务是一种架构的理念,提出了微服务的设计原则,从理论为具体的技术落地提供了指导思想。
Spring Boot 是一套快速配置脚手架,可以基于 Spring Boot 快速开发单个微服务。
Spring Cloud 是一个基于 Spring Boot 实现的服务治理工具包;Spring Boot 专注于快速、方便集成的单个微服务个体;Spring Cloud 关注全局的服务治理框架。
Spring Boot / Cloud 是微服务实践的最佳落地方案。
二、环境说明
以下示例版本版本选型
Cloud - Hoxton.SR1
Boot - 2.2.2.RELEASE
Cloud Alibaba - 2.1.0.RELEASE
Java - Java 8
Maven - 3.5及以上
mysql - 5.7及以上
版本选择
三、父工程Project空间新建
archetype 英 [ˈɑːkitaɪp] 美 [ˈɑːrkitaɪp]
n. 典型site 英 [saɪt] 美 [saɪt]
n. (建筑物、城镇等的)地点,位置,建筑工地;现场;发生地;场所;网站;站点
v. 使坐落在;为…选址
约定 > 配置 > 编码
创建微服务cloud整体聚合父工程Project,有8个关键步骤:
- New Project - maven工程 - create from archetype: maven-archetype-site
- 聚合总父工程名字
- Maven选版本
- 工程名字
- 字符编码 - Settings - File encoding
- 注解生效激活 - Settings - Annotation Processors
- Java编译版本选8
- File Type过滤 - Settings - File Type
3.1 父工程pom文件
我们用父工程做maven的版本依赖,在父工程中声明版本,后序maven工程继承父工程就不用写v,只写ga即可
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.caq.cloud</groupId>
<artifactId>cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>cloud-provider-payment8001</module>
<module>cloud-api-commons</module>
<module>cloud-customer-order80</module>
</modules>
<packaging>pom</packaging>
<!-- 统一管理jar包版本 -->
<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>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<!-- 子模块继承之后,提供作用:
锁定版本+子modlue不用写groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>$mysql.version</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>$druid.version</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>$mybatis.spring.boot.version</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>$junit.version</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>$log4j.version</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>$lombok.version</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.2 dependencyManagement
Maven使用dependencyManagement元素来提供了一种管理依赖版本号的方式。
通常会在一个组织或者项目的最顶层的父POM中看到dependencyManagement元素。
使用pom.xml中的dependencyManagement元素能让所有在子项目中引用个依赖而不用显式的列出版本量。
Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用这个
dependencyManagement元素中指定的版本号。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysq1</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.2</version>
</dependency>
<dependencies>
</dependencyManagement>
然后在子项目里就可以添加mysql-connector
时可以不指定版本号,例如:
<dependencies>
<dependency>
<groupId>mysq1</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改;另外如果某个子项目需要另外的一个版本,只需要声明version就可。
- 如果不在子项目中声明依赖,是不会从父项目
- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version
- 如果子项目指定了版本号, 那么使用子项目中指定的jar版本
四、支付模块构建
4.1 创建微服务模块套路
- 建Module
- 改POM
- 写YML
- 主启动
- 业务类
创建cloud-provider-payment8001微服务提供者支付Module模块:
建立后的目录结构如下:
1.建名为cloud-provider-payment8001的Maven工程
2.改POM
<?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>cloud</artifactId>
<groupId>com.caq.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3.写YML
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/db2022?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.caq.cloud.entities # 所有Entity别名类所在包
4.主启动
package com.caq.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PaymentMain001
public static void main(String[] args)
SpringApplication.run(PaymentMain001.class, args);
4.2 业务类小套路
5.业务类
- 业务类也有对应的套路:
- 建表SQL
- entities(主实体类,JSON封装体)
- dao(接口,mybatis映射文件)
- service(service和impl)
- controller
SQL:
CREATE TABLE `payment`(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ID,
`serial` varchar(200) DEFAULT ,
PRIMARY KEY (id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4
Entities:
实体类Payment:
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;
JSON封装体CommonResult:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T>
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message)
this(code, message, null);
DAO:
接口PaymentDao:
package com.caq.cloud.dao;
import com.caq.cloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
*/
@Mapper
//@Repository不用Spring的
public interface PaymentDao
public int create(Payment payment);
public Payment getPaymentById(@Param("id") Long id);
MyBatis映射文件PaymentMapper.xml,路径:resources/mapper/PaymentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.caq.cloud.dao.PaymentDao">
<insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) values(#serial);
</insert>
<resultMap id="BaseResultMap" type="com.caq.cloud.entities.Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>
<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
select * from payment where id=#id;
</select>
</mapper>
Service:
接口PaymentService
package com.caq.cloud.service;
import com.caq.cloud.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.caq.cloud.service.impl;
import com.caq.cloud.dao.PaymentDao;
import com.caq.cloud.entities.Payment;
import com.caq.cloud.service.PaymentService;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
*/
@Service
public class PaymentServiceImpl implements PaymentService
@Resource
private PaymentDao paymentDao;
public int create(Payment payment)
return paymentDao.create(payment);
public Payment getPaymentById(Long id)
return paymentDao.getPaymentById(id);
Controller:
package com.caq.cloud.controller;
import com.caq.cloud.entities.CommonResult;
import com.caq.cloud.entities.Payment;
import com.caq.cloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
*
*/
@RestController
@Slf4j
public class PaymentController
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult<Payment> create(Payment payment)
int result = paymentService.create(payment);
log.info("*****插入结果:" + result);
if (result > 0)
return new CommonResult(200, "插入数据库成功",result);
else
return new CommonResult(444, "插入数据库失败", null);
@GetMapping(value = "/payment/get/id")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
Payment payment = paymentService.getPaymentById(id);
if (payment != null)
return new CommonResult<Payment>(200, "查询成功433", payment);
else
return new CommonResult<Payment>(444, "没有对应记录",null);
4.3 支付模块测试
我们用postman来模拟请求
4.3 热部署Devtools
开发时使用,生产环境关闭
1.Adding devtools to your project
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
2.Adding plugin to your pom.xml
下段配置复制到聚合父类总工程的pom.xml
<build>
<!--
<finalName>你的工程名</finalName>(单一工程时添加)
-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
3.Enabling automatic build
File -> Settings(New Project Settings->Settings for New Projects) ->Complier
下面项勾选
Automatically show first error in editor
Display notification on build completion
Build project automatically
Compile independent modules in parallel
4.Update the value of
键入Ctrl + Shift + Alt + / ,打开Registry,勾选:
compiler.automake.allow.when.app.running
actionSystem.assertFocusAccessFromEdt
5.重启IDEA
五、消费者订单模块
好的,让我们在一起来背一遍:
- 建模块
- 改pom
- 写yml
- 启动类
- 业务类
业务类编写流程如下:
- 建表写sql
- 实体类(数据库映射实体类,向前端传递实体类)
- 书写dao和mapper映射文件
- service(面向接口编程接口(接口写逻辑)和impl写实现)
- controller
1.建Module
创建名为cloud-consumer-order80的maven工程。
2.改POM
<?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>cloud</artifactId>
<groupId>com.caq.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-customer-order80</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3.写YML
server:
port: 80
4.主启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
Hello world!
*
*/
@SpringBootApplication
public class OrderMain80
public static void main( String[] args )
SpringApplication.run(OrderMain80.class, args);
5.业务类
实体类:
package com.caq.cloud.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.caq.cloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T>
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message)
this(code, message, null);
控制层:
package com.caq.cloud.controller;
import com.caq.cloud.entities.CommonResult;
import com.caq.cloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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 resetTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment)
return resetTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
@GetMapping("/consumer/payment/get/id")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id)
return resetTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
配置类:
package com.caq.cloud.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig
//通过注解的方式注入,这样我们的容器里就有这个resttemplate对象
@Bean
public RestTemplate getRestTemplate()
return new RestTemplate();
测试
六、工程重构
观察cloud-consumer-order80与cloud-provider-payment8001两工程有重复代码(entities包下的实体),重构。
1.新建 - cloud-api-commons
2.POM
<?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>cloud</artifactId>
<groupId>com.caq.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-api-commons</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>
3.entities
将cloud-consumer-order80与cloud-provider-payment8001两工程的公有entities包移至cloud-api-commons工程下。
4.maven clean、install cloud-api-commons工程,以供给cloud-consumer-order80与cloud-provider-payment8001两工程调用。
5.订单80和支付8001分别改造
将cloud-consumer-order80与cloud-provider-payment8001两工程的公有entities包移除
引入cloud-api-commons依赖
<dependency>
<groupId>com.caq.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>$project.version</version>
</dependency>
api-common目录结构如下:
测试
七、Eureka
7.1 初始Eureka
7.1.1 什么是服务治理
Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
7.1.2 什么是服务注册与发现
Eureka采用了CS的设计架构,Eureka Sever作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心存放服务地址相关信息(接口地址)
Eureka包含两个组件:Eureka Server和Eureka Client
Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClient通过注册中心进行访问
它是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
7.2 EurekaServer服务端安装
1.创建名为cloud-eureka-server7001的Maven工程
2.修改pom.xml
<?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>cloud</artifactId>
<groupId>com.caq.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.caq.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>$project.version</version>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--一般通用配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
区别:
<!-- eureka新旧版本 -->
<!-- 以前的老版本(2018)-->
<dependency>
<groupid>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 现在新版本(2020.2)--><!-- 我们使用最新的 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3.添加application.yml
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#单机就是7001自己
defaultZone: http://eureka7001.com:7001/eureka/
4.主启动
package com.caq以上是关于Spring全家桶--SpringCloud(初级)的主要内容,如果未能解决你的问题,请参考以下文章
Spring全家桶:Spring,SpringBoot,SpringCloud实战,Spring源码
开启springcloud全家桶8:配置中心的好搭档 Spring Cloud Bus 消息总线