一、SpringCloud(微服务、分布式)

SpringCloud

微服务理论

https://www.martinfowler.com/articles/microservices.html 微服务microservices

http://blog.cuicc.com/blog/2015/07/22/microservices/

In short(简言之), the microservice architectural style 【架构风格】[1] is an approach to developing a single application as a suite of small services【独立应用变成一套小服务】, each running in its own process and communicating with lightweight(轻量级沟通) mechanisms(每一个都运行在自己的进程内(容器)), often an HTTP resource API(用HTTP,将功能写成能接受请求). These services are built around business capabilities (独立业务能力)and independently deployable by fully automated deployment machinery(应该自动化独立部署). There is a bare minimum of centralized management of these services(应该有一个能管理这些服务的中心), which may be written in different programming languages (独立开发语言)and use different data storage technologies(独立的数据存储).

分布式概念

什么是分布式

《分布式系统原理与范型》定义:“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”。

分布式系统(distributed system)是建立在网络之上的软件系统。

分布式与集群的关系

集群指的是将几台服务器集中在一起,实现同一业务。

分布式中的每一个节点,都可以做集群。 而集群并不一定就是分布式的。

软件架构演变

单一应用架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键
垂直应用架构 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键
分布式服务架构 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键
流动计算架构 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键

RPC是什么

RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。

它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。

即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

解决分布式系统的各个服务之间互相交互问题

RPC思想原理

服务之间的交互可以用两种方式

  • RPC
    • Netty(Socket)+自定义序列化
  • RestAPI (严格来说,SpringCloud是使用Rest方式进行服务之间交互的,不属于RPC)
    • HTTP+JSON

分布式思想与基本概念

高并发

  1. 通过设计保证系统可以并行处理很多请求。应对大量流量与请求
  • Tomcat最多支持并发多少用户?

    Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当然了,也可以将其改大。

    当某个应用拥有 250 个以上并发的时候,应考虑应用服务器的集群。

    具体能承载多少并发,需要看硬件的配置,CPU 越多性能越高,分配给 JVM 的内存越多性能也就越高,但也会加重 GC 的负担。

  • 操作系统对于进程中的线程数有一定的限制:

    Windows 每个进程中的线程数不允许超过 2000

    Linux 每个进程中的线程数不允许超过 1000

    另外,在 Java 中每开启一个线程需要耗用 1MB 的 JVM 内存空间用于作为线程栈之用。

    Tomcat 默认的 HTTP 实现是采用阻塞式的 Socket 通信,每个请求都需要创建一个线程处理。这种模式下的并发量受到线程数的限制,但对于 Tomcat 来说几乎没有 BUG 存在了。

    Tomcat 还可以配置 NIO 方式的 Socket 通信,在性能上高于阻塞式的,每个请求也不需要创建一个线程进行处理,并发能力比前者高。但没有阻塞式的成熟。

    这个并发能力还与应用的逻辑密切相关,如果逻辑很复杂需要大量的计算,那并发能力势必会下降。如果每个请求都含有很多的数据库操作,那么对于数据库的性能也是非常高的。

    对于单台数据库服务器来说,允许客户端的连接数量是有限制的。

    并发能力问题涉及整个系统架构和业务逻辑。

    系统环境不同,Tomcat版本不同、JDK版本不同、以及修改的设定参数不同。并发量的差异还是满大的。

  • maxThreads=“1000” 最大并发数 ,默认值为200

  • minSpareThreads=“100”//初始化时创建的线程数,默认值为10

  • acceptCount=“700”// 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理,默认值为100

    https://tomcat.apache.org/tomcat-8.0-doc/config/http.html

高并发衡量指标

  • 响应时间(RT)
    • 请求做出响应的时间,即一个http请求返回所用的时间
  • 吞吐量
    • 系统在单位时间内处理请求的数量
  • QPS(Query/Request Per Second)、 TPS(Transaction Per Second)
  • 每秒查询(请求)数、每秒事务数
    • 专业的测试工具:Load Runner
    • Apache ab
    • Apache JMeter
  • 并发用户数
    • 承载的正常使用系统功能的用户的数量

高可用

服务集群部署

数据库主从+双机热备

  • 主-备方式(Active-Standby方式)

主-备方式即指的是一台服务器处于某种业务的激活状态(即Active状态),另一台服务器处于该业务的备用状态(即Standby状态)。

  • 双主机方式(Active-Active方式)

双主机方式即指两种不同业务分别在两台服务器上互为主备状态(即Active-Standby和Standby-Active状态)

注册中心

保存某个服务所在地址等信息,方便调用者实时获取其他服务信息

  • 服务注册
    • 服务提供者
  • 服务发现
    • 服务消费者

负载均衡

  • 动态将请求派发给比较闲的服务器

策略:

  • 轮询(Round Robin)
  • 加权轮询(Weighted Round Robin)
  • 随机Random
  • 哈希Hash
  • 最小连接数LC
  • 最短响应时间LRT

服务雪崩

服务之间复杂调用,一个服务不可用,导致整个系统受影响不可用

熔断

某个服务频繁超时,直接将其短路,快速返回mock(模拟/虚拟)值

限流

限制某个服务每秒的调用本服务的频率

API网关

API网关要做很多工作,它作为一个系统的后端总入口,承载着所有服务的组合路由转换等工作,除此之外,我们一般也会把安全,限流,缓存,日志,监控,重试,熔断等放到 API 网关来做

服务跟踪

追踪服务的调用链,记录整个系统执行请求过程。如:请求响应时间,判断链中的哪些服务属于慢服务(可能存在问题,需要改善)。

弹性云

Elastic Compute Service(ECS)弹性计算服务

动态扩容,压榨服务器闲时能力

例如:双11,618,高峰时多配置些服务器,平时减少多余的服务器配置(用于其他服务应用),避免资源浪费

SpringCloud背景

背景介绍

微服务架构

物联网( IoT ,Internet of things )即“万物相连的互联网”,是互联网基础上的延伸和扩展的网络,将各种信息传感设备与互联网结合起来而形成的一个巨大网络,实现在任何时间、任何地点,人、机、物的互联互通。

Breaker dashboard 断路器仪表盘

Distributed Tracing分布式跟踪 (分布式处理程序链跟踪用于监视网络等待时间,并可视化通过微服务的请求流)

微服务框架之SpringBoot

https://docs.spring.io/spring-boot/docs/2.3.6.RELEASE/reference/htmlsingle/

分布式系统微服务架构之SpringCloud

https://docs.spring.io/spring-cloud/docs/Hoxton.SR9/reference/html/

英文困难的同学,也不耽误学习的

https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md

组件概述

关于SpringBoot和SpringCloud版本

SpringCloud版本选择

SpringBoot2.3.6版和SpringCloud Hoxton.SR9版

SpringCloud Alibaba 2.2.6

Springboot版本选择

git源码地址:

https://github.com/spring-projects/spring-boot/releases/

SpringBoot2.0新特性:

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes

通过上面官网发现,Boot官方强烈建议你升级到2.X以上版本

官网看Boot版本

springboot(截至2021.9.28)

SpringCloud版本选择

官网看Cloud版本

  • Cloud命名规则

    Spring Cloud采用了英国伦敦地铁站的名称来命名,并由地铁站名称字母A-Z依次类推的形式来发布迭代版本。

    Spring Cloud 是一个由许多子项目组成的综合项目,各子项目有不同的发布节奏。为了管理SpringCloud与各子项目的版本依赖关系,发布了一个清单,其中包括了某个SpringCloud版本对应的子项目版本。为了避免SpringCloud版本号与子项目版本号混淆,SpringCloud版本采用了名称而非版本号的命名,这些版本的名字采用了伦敦地铁站的名字,根据字母表的顺序来应对版本时间顺序。例如Angel是第一个版本,Brixton是第二个版本。当SpringCloud的发布内容积累到临界点或者一个重大BUG被解决后,会发布一个"service releases"版本,简称SRX版本,比如Greenwich.SR2就是SpringCloud发布的Greenwich版本的第二个SRX版本。

  • SpringCloud(截至2021.9.28)

SpringCloud和Springboot之间的依赖关系

https://docs.spring.io/spring-cloud/docs/Hoxton.SR9/reference/html/

更详细的版本对应查看方法: https://start.spring.io/actuator/info

SpringCloud(版本)

  • cloud
    • Hoxton.SR9
    • boot
      • 2.3.6.RELEASE
    • cloud Alibaba
      • 2.2.6.RELEASE
    • java
      • JAVA8
    • maven
      • 3.5及以上
    • mysql
      • 5.7及以上

微服务架构编码构建-IDEA新建project工作空间

微服务cloud整体聚合父工程Project

New Project

聚合总工程名字

Maven选版本

工程名字

字符编码

注解生效激活

java编译版本

File Type过滤【可选】

父工程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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.aqrlmy</groupId>
  <artifactId>cloud2021</artifactId>
  <version>1.0-SNAPSHOT</version>
  <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>8.0.18</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>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.3.6.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR9</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.6.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>

Maven工程落地细节复习

Maven中的dependencyManagementdependencies区别

maven中跳过单元测试【可选】

父工程创建完成执行mvn:install

微服务架构编码构建-Rest微服务-【服务提供者】

建cloud-provider-payment8001

创建完成后请回到父工程查看pom文件变化,增加了聚合模块

  <modules>
    <module>cloud-provider-payment8001</module>
  </modules>

改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>cloud2021</artifactId>
        <groupId>com.aqrlmy.springcloud</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>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <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>

写YML

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud2021?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root

mybatis:
  mapperLocations: classpath:/mapper/*.xml
  type-aliases-package: com.aqrlmy.springcloud.entities

主启动

package com.aqrlmy.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);
    }
}

业务类

建表SQL
CREATE DATABASE  IF NOT EXISTS cloud2021 DEFAULT CHARACTER SET utf8 ;

USE cloud2022 ;

DROP TABLE IF EXISTS payment ;

CREATE TABLE payment (
  id BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  SERIAL VARCHAR (300) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE = INNODB AUTO_INCREMENT = 33 DEFAULT CHARSET = utf8 ;

INSERT INTO payment (id, SERIAL) VALUES(31, 'aqr001'),(32, 'aqrlmy002') ;
Entitles
主实体Payment
package com.aqrlmy.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;
}
Json封装体CommonResult
package com.aqrlmy.springcloud.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult <T> implements Serializable{

    private Integer code;
    private String message;
    private T data;

    public CommonResult(Integer code,String message){
        this(code,message,null);//如果这行报错,请安装lombok插件
    }
}
安装lombok插件

https://www.projectlombok.org/

@Data:提供getter/setter

@NoArgsConstructor, 无参构造器 @RequiredArgsConstructor @AllArgsConstructor 全参数构造器

@EqualsAndHashCode:提供equals和hashCode方法

@Getter/@Setter

@Slf4j 内置log对象,直接调用日志方法输出日志

Dao
接口PaymentDao
package com.aqrlmy.springcloud.dao;

import com.aqrlmy.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Component       //代替@Repository声明bean
@Mapper               //mybatis提供的,等价:@MapperScan("com.aqrlmy.springcloud.dao")
//@Repository     //spring提供的。在此,只是为了声明bean对象
public interface PaymentDao {
    public int create(Payment payment);    
    public Payment getPaymentById(@Param("id") Long id);
}
mybatis的映射文件

src\main\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.aqrlmy.springcloud.dao.PaymentDao">
    <insert id="create"  useGeneratedKeys="true" keyProperty="id">
            insert into payment(serial) values(#{serial});
    </insert>

    <resultMap id="BaseResultMap" type="com.aqrlmy.springcloud.entities.Payment">
        <id column="id" property="id" jdbcType="BIGINT"></id>
        <result column="serial" property="serial" jdbcType="VARCHAR"></result>
    </resultMap>

    <select id="getPaymentById"  parameterType="Long" resultMap="BaseResultMap">
            select * from payment where id=#{id}
    </select>

</mapper>
Service
接口PaymentService
package com.aqrlmy.springcloud.service;

import com.aqrlmy.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;

public interface PaymentService {
    public int create(Payment payment); //写
    public Payment getPaymentById(Long id);  //读取
}
实现类PaymentServiceImpl
package com.aqrlmy.springcloud.service.impl;

import com.aqrlmy.springcloud.dao.PaymentDao;
import com.aqrlmy.springcloud.entities.Payment;
import com.aqrlmy.springcloud.service.PaymentService;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Resource
    //@Autowired
    private PaymentDao paymentDao;

    public int create(Payment payment){
        return paymentDao.create(payment);
    }

    public Payment getPaymentById( Long id){
        return paymentDao.getPaymentById(id);
    }
}
Controller
package com.aqrlmy.springcloud.controller;

import com.aqrlmy.springcloud.entities.CommonResult;
import com.aqrlmy.springcloud.entities.Payment;
import com.aqrlmy.springcloud.service.PaymentService;
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 javax.annotation.Resource;

@RestController
@Slf4j
public class PaymentController {

    @Resource
private PaymentService paymentService;


    @Value("${server.port}")
    private String serverPort;

    @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);
        log.info("*****查询结果:"+payment);
        if (payment!=null){  //说明有数据,能查询成功
            return new CommonResult(200,"查询成功",payment);
        }else {
            return new CommonResult(444,"没有对应记录,查询ID:"+id,null);
        }
    }
}

测试

postman测试get请求

postman测试post请求

快速运行设置

开发步骤-小总结

  1. 建module
  2. 改POM
  3. 写YML
  4. 主启动
  5. 业务类

热部署Devtools

Adding devtools to your project
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
   <scope>runtime</scope>
    <optional>true</optional>
</dependency>
Adding plugin to your pom.xml
下一段配置黏贴到父工程当中的pom里
<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>
Enabling automatic build

Update the value of

Ctrl+Shift+Alt+/选择Registry…

compiler.automake.allow.when.app.running -> 自动编译

compiler.document.save.trigger.delay -> 自动更新文件;它主要是针对静态文件如JS CSS的更新,将延迟时间减少后,直接按F5刷新页面就能看到效果!

重启IDEA

微服务架构编码构建-Rest微服务-【服务消费者】

建cloud-consumer-order80

改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>cloud2021</artifactId>
        <groupId>com.aqrlmy.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-consumer-order80</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.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>

写YML

server:
  port: 80
spring:
  application:
    name: cloud-consumer-order80

主启动

package com.aqrlmy.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);
    }
}

业务类

创建entities

(将cloud-provider-payment8001工程下的entities包下的两个实体类复制过来)

RestTemplate
  • 是什么

RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问Restful服务模板类,是Spring 提供的用于访问Rest服务的客户端模板工具集

  • 官网及使用

官网地址: https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

使用RestTemplate访问Restful接口非常的简单粗暴无脑。(url,requestMap,ResponseBean.class)这三个参数分别代表REST请求地址、请求参数、Http响应转换被转换成的对象类型。

config配置类

ApplicationContextConfig

package com.aqrlmy.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

//@Configuration
@SpringBootConfiguration
public class ApplicationContextConfig {

    @Bean
    //@LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}
创建controller
package com.aqrlmy.springcloud.controller;

import com.aqrlmy.springcloud.entities.CommonResult;
import com.aqrlmy.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.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){
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);  //写操作
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

测试

  1. 先启动cloud-provider-payment8001
  2. 再启动cloud-consumer-order80
  3. http://localhost/consumer/payment/get/32
  4. 不要忘记@RequestBody注解
  5. 服务提供者接口方法需要增加@RequestBody注解(踩雷or破雷);否则,接收不到数据。

工程重构

观察问题

新建:cloud-api-commons

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>cloud2021</artifactId>
        <groupId>com.aqrlmy.springcloud</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>

entities

Payment实体

CommonResult通用封装类

maven命令clean install

订单80和支付8001分别改造

删除各自的原先有过的entities

各自黏贴POM内容,依赖于cloud-api-commons公共项目

<dependency>
    <groupId>com.aqrlmy</groupId>
    <artifactId>cloud-api-commons</artifactId>
    <version>${project.version}</version>
</dependency>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值