微服务架构

一、微服务概述

1.1 微服务

微服务(MicroServices)最初是由 Martin Fowler 于 2014 年发表的论文 《MicroServices

微服务》,我们可以从字面上去理解,即“微小的服务”,下面我们从“服务”和“微小”两个方面进行介绍。

1) 所谓“服务”,其实指的是项目中的功能模块,它可以帮助用户解决某一个或一组问题,在开发过程中表现为 IDE(集成开发环境,例如 Eclipse 或 IntelliJ IDEA)中的一个工程或 Moudle。

2) “微小”则强调的是单个服务的大小,主要体现为以下两个方面:

  • 微服务体积小,复杂度低:一个微服务通常只提供单个业务功能的服务,即一个微服务只专注于做好一件事,因此微服务通常代码较少,体积较小,复杂度也较低。

  • 微服务团队所需成员少:一般情况下,一个微服务团队只需要 8 到 10 名人员(开发人员 2 到 5 名)即可完成从设计、开发、测试到运维的全部工作。

1.2 微服务架构

微服务架构是一种系统架构的设计风格。与传统的单体式架构(ALL IN ONE)不同,微服务架构提倡将一个单一的应用程序拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间使用轻量级通信机制(通常是 HTTP RESTFUL API)进行通讯。

通常情况下,这些小型服务都是围绕着某个特定的业务进行构建的,每一个服务只专注于完成一项任务并把它做好 ,即“专业的人做专业的事”。

每个服务都能够独立地部署到各种环境中,例如开发环境、测试环境和生产环境等,每个服务都能独立启动或销毁而不会对其他服务造成影响。

这些服务之间的交互是使用标准的通讯技术进行的,因此不同的服务可以使用不同数据存储技术,甚至使用不同的编程语言。

1.3 微服务架构&单体架构

在当今的软件开发领域中,主要有两种系统架构风格,那就是新兴的“微服务架构”和传统的“单体架构”。单体架构是微服务架构出现之前业界最经典的软件架构类型,许多早期的项目采用的也都是单体架构。单体架构将应用程序中所有业务逻辑都编写在同一个工程中,最终经过编译、打包,部署在一台服务器上运行。

  • 随着业务复杂度的提高,单体应用(采用单体架构的应用程序)的代码量也越来越大,导致代码的可读性、可维护性以及扩展性下降。

  • 随着用户越来越多,程序所承受的并发越来越高,而单体应用处理高并发的能力有限。

  • 单体应用将所有的业务都集中在同一个工程中,修改或增加业务都可能会对其他业务造成一定的影响,导致测试难度增加。

由于单体架构存在这些弊端,因此许多公司和组织都开始将将它们的项目从单体架构向微服务架构转型。

不同点微服务架构单体架构
团队规模微服务架构可以将传统模式下的单个应用拆分为多个独立的服务,每个微服务都可以单独开发、部署和维护。每个服务从设计、开发到维护所需的团队规模小,团队管理成本小。单体架构的应用程序通常需要一个大型团队,围绕一个庞大的应用程序工作,团队管理的成本大。
数据存储方式不同的微服务可以使用不同的数据存储方式,例如有的用 Redis,有的使用 MySQL。单一架构的所有模块共享同一个公共数据库,存储方式相对单一。
部署方式微服务架构中每个服务都可以独立部署,也可以独立于其他服务进行扩展。如果部署得当,基于微服务的架构可以帮助企业提高应用程序的部署效率。采用单体架构的应用程序的每一次功能更改或 bug 修复都必须对整个应用程序重新进行部署。
开发模式在采用微服务架构的应用程序中,不同模块可以使用不同的技术或语言进行开发,开发模式更加灵活。在采用单体架构的应用程序中,所有模块使用的技术和语言必须相同,开发模式受限。
故障隔离在微服务架构中,故障被隔离在单个服务中,避免系统的整体崩溃。在单体架构中,当一个组件出现故障时,故障很可能会在进程中蔓延,导致系统全局不可用。
项目结构微服务架构将单个应用程序拆分为多个独立的小型服务,每个服务都可以独立的开发、部署和维护,每个服务都能完成一项特定的业务需求。单体架构的应用程序,所有的业务逻辑都集中在同一个工程中。

1.4 微服务的特点

微服务具有以下特点:

  • 服务按照业务来划分,每个服务通常只专注于某一个特定的业务、所需代码量小,复杂度低、易于维护。

  • 每个微服都可以独立开发、部署和运行,且代码量较少,因此启动和运行速度较快。

  • 每个服务从设计、开发、测试到维护所需的团队规模小,一般 8 到 10 人,团队管理成本小。

  • 采用单体架构的应用程序只要有任何修改,就需要重新部署整个应用才能生效,而微服务则完美地解决了这一问题。在微服架构中,某个微服务修改后,只需要重新部署这个服务即可,而不需要重新部署整个应用程序。

  • 在微服务架构中,开发人员可以结合项目业务及团队的特点,合理地选择语言和工具进行开发和部署,不同的微服务可以使用不同的语言和工具。

  • 微服务具备良好的可扩展性。随着业务的不断增加,微服务的体积和代码量都会急剧膨胀,此时我们可以根据业务将微服务再次进行拆分;除此之外,当用户量和并发量的增加时,我们还可以将微服务集群化部署,从而增加系统的负载能力。

  • 微服务能够与容器(Docker)配合使用,实现快速迭代、快速构建、快速部署。

  • 微服务具有良好的故障隔离能力,当应用程序中的某个微服发生故障时,该故障会被隔离在当前服务中,而不会波及到其他微服务造成整个系统的瘫痪。

  • 微服务系统具有链路追踪的能力。

1.5 微服务框架

微服务架构是一种系统架构风格和思想,想要真正地搭建一套微服务系统,则需要微服务框架的支持。随着微服务的流行,很多编程语言都相继推出了它们的微服务框架,下面我们就来简单列举下。(1)Java 微服务框架

市面上的 Java 微服务框架主要有以下 5 种:

  • Spring Cloud:它能够基于 REST 服务来构建服务,帮助架构师构建出一套完整的微服务技术生态链。

  • Dropwizard:用于开发高性能和 Restful 的 Web 服务,对配置、应用程序指标、日志记录和操作工具都提供了开箱即用的支持。

  • Restlet: 该框架遵循 RST 架构风格,可以帮助 Java 开发人员构建微服务。

  • Spark:最好的 Java 微服务框架之一,该框架支持通过 Java 8 和 Kotlin 创建微服务架构的应用程序。

  • Dubbo:由阿里巴巴开源的分布式服务治理框架。

(2)Go 语言微服务框

Go 语言中的微服务框架较少,使用的较多的是 GoMicro,它是一个 RPC 框架,具有负载均衡、服务发现、同步通信、异步通讯和消息编码等功能。Phyton 中的微服务框架主要有

(3)NodeJS微服务框架

Molecular 是一种使用 NodeJS 构建的事件驱动架构,该框架内置了服务注册表、动态服务发现、负载均衡、容错功能和内置缓存等组件。

(4)Phyton 微服务框架

Phyton 中的微服务框架主要有 Flask、Falcon、Bottle、Nameko 和 CherryPy 等。

 二、Spring Cloud 环境搭建-父工程-支付模块构建及测试

2.1 Boot和Cloud版本选型

2.1.1 Boot和Cloud版本选型

Spring Boot 2.X 版

Spring Boot 2 的新特性

2.1.2 Spring Cloud H版

官网Spring Boot 与 Spring Cloud 兼容性查看

Spring CloudLevel up your Java code and explore what Spring can do for you.icon-default.png?t=N7T8https://spring.io/projects/spring-cloud#adding-spring-cloud-to-an-existing-spring-boot-application

2.1.3 开发中的组件版本

Cloud - Hoxton.SR5

Boot - 2.2.2.RELEASE

Cloud Alibaba - 2.1.0.RELEASE

Java - Java 1.8

Maven - 3.6及以上

MySQL - 5.7及以上

2.2 Cloud组件停更说明

停更引发的“升级惨案”

停更不停用

被动修复bugs

不再接受合并请求

不再发布新版本

Cloud升级

2.2.1 服务注册中心

× Eureka

√ Zookeeper

√ Consul

√ Nacos

2.2.2 服务调用

√ Ribbon

√ LoadBalancer

2.2.3 服务调用2

× Feign

√ OpenFeign

2.2.4 服务降级

× Hystrix

√ resilience4j

√ sentinel

2.2.5 服务网关

× Zuu

l! Zuul2

√ gateway

2.2.6 服务配置

× Config

√ Nacos

服务总线

× Bus

√ Nacos

Eureka停用,可以使用zk作为服务注册中心

服务调用,Ribbon准备停更,代替为LoadBalance

Feign改为OpenFeign

Hystrix停更,改为resilence4j,或者阿里巴巴的sentienl

Zuul改为gateway

服务配置Config改为 Nacos

服务总线Bus改为Nacos

2.3 创建父工程

重要:约定 > 配置 > 编码

(1)配置自己的Maven,不要使用IDEA自带的,在settings.xml文件中配置本地maven库的路径和阿里云的镜像:

(2)lombok 的版本问题,如果是jdk1.8 建议 lombok的版本选择1.16.18 即可。

(3)强调所有的命名必须规范 ,请务必严格遵守。

2.3.1 父工程创建

创建微服务cloud整体聚合父工程,有8个关键步骤:

(1)New Project - Maven Archetype - create from archetype: maven-archetype-site

 (2)聚合总父工程名字

 (3)Maven选版本

 (4)工程名字

 (5)字符编码 - Settings - File encoding

(6)注解生效激活 - Settings - Annotation Processors  

 (7)Java编译版本选1.8

(8)File Type过滤 - Settings - File Type,可根据个人习惯设置 (可忽略)

2.3.2 父工程pom配置

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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.rys.springcloud</groupId>
    <artifactId>cloud2024</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>cloud-provider-payment8001</module>
    </modules>

    <!-- 统一管理jar包版本 -->
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.18.24</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>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </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.SR5-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR5</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>
                <!--给这个插件加上version标签fork标签不在变红-->
                <version>2.3.12.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
2.3.3 回顾maven中dependencyManagement 与dependencies

1、父项目中 不使用dependencyManagement,直接使用 dependencies,则子项目会继承引入父项目中的依赖。

2、父项目中使用dependencyManagement,则子项目不会引入依赖,需要显式的自行添加依赖。但可以不用添加版本号,直接继承父项目的版本号

说明:dependencyManagement一般用在maven构建的聚合项目的父项目中,只是用来声明和锁定版本(通常用于有多个子项目,但是不是每个子项目都需要引入同一种依赖的场景),所以使用dependencyManagement元素提供了一种管理依赖版本号的方式,通常会在一个组织或者项目的最顶层父POM中看到dependencyManagement元素

2.3.4 支付模块

cloud-provider-payment8001

总体步骤:

(1)建module

选中cloud2024项目,右键 new -> module

输入项目的ArtifactId:cloud-provider-payment8001  

(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>
        <groupId>cn.rys.springcloud</groupId>
        <artifactId>cloud2024</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </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.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

在resources目录下,创建application.yml文件,添加如下内容:

注意:需要在mysql中创建数据库 db2024

鼠标右键工程项目的resource文件夹,选择new->File,然后再弹出的对话框中输入文件名:application.yml即可。IDE会自动识别该文件。 

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/db2024?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: cn.jqy.springcloud.entity    # 所有Entity别名类所在包

(4)主启动类

package cn.rys.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);
    }
}

(5)业务类

步骤:1. 建表 2. 实体类entity 3. dao 4. service 5. controller

1. 建表:

db2024数据库中:

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

2. 实体类

Payment:

package cn.rys.springcloud.entity;

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

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id; // 和mysql的bigint数据类型对应
    private String serial;

}

CommonResult:json封装体

package cn.rys.springcloud.entity;

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);
    }
}

 3. Dao层

package cn.rys.springcloud.Dao;

import cn.rys.springcloud.entity.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface PaymentDao
{
    int create(Payment payment);

    Payment getPaymentById(@Param("id") Long id);
}

在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="cn.rys.springcloud.dao.PaymentDao">

    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial)  values(#{serial});
    </insert>

    <resultMap id="BaseResultMap" type="cn.jqy.springcloud.entity.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>

4. service层  

接口:

package cn.rys.springcloud.service;

import cn.rys.springcloud.entity.Payment;
import org.apache.ibatis.annotations.Param;

public interface PaymentService {
    public int create(Payment payment);

    public Payment getPaymentById(@Param("id") Long id);
}

实现类:

package cn.rys.springcloud.service.Impl;

import cn.rys.springcloud.Dao.PaymentDao;
import cn.rys.springcloud.entity.Payment;
import cn.rys.springcloud.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PaymentServiceImpl implements PaymentService {
    @Autowired
    private PaymentDao paymentDao;

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

    public Payment getPaymentById(Long id)
    {
        return paymentDao.getPaymentById(id);
    }
}

 5.controller

package cn.rys.springcloud.controller;

import cn.rys.springcloud.entity.CommonResult;
import cn.rys.springcloud.entity.Payment;
import cn.rys.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
public class PaymentController
{
    @Autowired
    private PaymentService paymentService;

    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody 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(200,"查询成功:  ",payment);
        }else{
            return new CommonResult(444,"没有对应记录,查询ID: "+id,null);
        }
    }

}

6.启动项目测试

在db2024数据库表payment中手动插入测试数据。

启动项目,使用postman工具进行测试,分别发起get请求和post请求。

如果出现lombok不能使用的情况,可以添加lombok插件,开启注解支持。注意lombok和jdk版本的兼容问题。修改lombok版本如下:

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
</dependency>

 测试截图如下:

7.补充maven中的scope

scope的值有以下几种可能,进行分情况讲解:

compile 默认就是compile,什么都不配置也就是意味着compile。compile表示被依赖项目需要参与当前项目的编译,当然后续的测试,运行周期也参与其中,是一个比较强的依赖。打包的时候通常需要包含进去。默认的scope,在部署的时候将会打包到lib目录下,项目在编译,测试,运行阶段都需要

testscope为test表示依赖项目仅仅参与测试相关的工作,在编译和运行环境下都不会被使用,更别说打包了。

runntimerunntime这个scope,仅仅适用于运行环境,在编译和测试环境下都不会被使用

providedprovided适合在编译和测试的环境,他和compile很接近,但是provide仅仅需要在编译和测试阶段,同样provide将不会被打包到lib目录下。

system从参与度来说,也provided相同,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用。

scope的依赖传递A–>B–>C。当前项目为A,A依赖于B,B依赖于C。知道B在A项目中的scope,那么怎么知道C在A中的scope呢?答案是: 当C是test或者provided时,C直接被丢弃,A不依赖C; 否则A依赖C,C的scope继承于B的scope。

为什么需要区分这些scope可以用来限制dependency的范围可以在不同的环境下打包不同的jar包,比如junit测试类的jar包不需要在编译运行的时候,就可以设置scope为test。

最后还有一个<optional>true</optional>是什么意思,怎么用的呢?

在SpringBoot官网文件中你可以得到解释就是,<optional>true</optional>的话,其他项目依赖此项目也不会进行传递,只能本项目使用。

8.热部署Devtools

可以参考学习Springboot时的热部署配置。

搭建步骤:(1)在pom文件中添加spring-boot-devtools热部署依赖

<dependency>                
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-devtools</artifactId>
   <optional>true</optional>
</dependency>

(2)IDEA中热部署设置

选择【File】→【Settings】选项,打开Compiler面板设置页。

勾选 Build project automatically

 使用快捷键“Ctrl+Shift+Alt+/”打开Maintenance选项框,选中并打开Registry页面。指定IDEA工具在程序运行过程中自动编译  

 

(3)热部署测试

启动项目,通过浏览器访问http://localhost:8081/payment/get/1

修改类PaymentController中的请求处理方法getPaymentById中的代码,观察后台的输出。(可能反应慢,多点几次)

开发阶段必须开启热部署。

参考步骤:

Adding devtools to your project

Adding plugin to your pom.xml

Enabling automatic build

Update the value of

重启IDEA

部署热配置后出现:Unable to start LiveReload server&testWhileIdle is true, validationQuery not set问题

解决方法:修改application.yml文件

server:
  port: 8001
spring:
  devtools:
    livereload:
      port: 35731
  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/db2024?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    druid:
      test-while-idle: false
mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: cn.rys.springcloud.entity    # 所有Entity别名类所在包

即可成功运行

参考链接:http://t.csdnimg.cn/CPTC1

http://t.csdnimg.cn/pQObn

2.3.5. 消费模块构建

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>cloud2024</artifactId>
        <groupId>cn.rys.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.rys.springcloud</groupId>
    <artifactId>cloud-consumer-order80</artifactId>
    <version>1.0-SNAPSHOT</version>
	
     <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>
            <version>1.18.24</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

</project>

创建yml文件

src main resources下添加application.yml 文件,内容如下:

server:
  port: 80

主启动类:

package cn.rys.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);
    }
}

业务类:

创建包cn.rys.springcloud.entity,添加如下两个类:

Payment.java

package cn.rys.springcloud.entity;

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

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id; // 和mysql的bigint数据类型对应
    private String serial;

}

CommonResult.java

package cn.rys.springcloud.entity;

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);
    }
}

创建OrderController类:

补充RestTemplate:

· 首说RestTemplate· 是什么

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

官网地址

RestTemplate (Spring Framework 5.2.2.RELEASE API)

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

config配置类:使用需要将此类放到spring容器中。也就是说要有这个类的实例对象。

ApplicationContextConfig

package cn.rys.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 getRestTemplate()
    {
        return new RestTemplate();
    }
}

OrderController代码如下:  

package cn.rys.springcloud.controller;

import cn.rys.springcloud.entity.CommonResult;
import cn.rys.springcloud.entity.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.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Slf4j
public class OrderController {
    public static final String PAYMENT_URL = "http://localhost:8001";
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/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);
    }
}

启动测试 :

分别启动支付模块和消费模块

postman中测试截图如下:

为了方便测试:

通过修改idea的workspace.xml的方式来快速打开Run Dashboard窗口 开启Run DashBoard

D:\JavaCode\cloud2024\.idea\workspace.xml 中<component name="RunDashboard">标签下添加

<option name="configurationTypes">
      <set>
          <option value="SpringBootApplicationConfigurationType" />
      </set>
   </option>
2.3.6 工程重构

观察问题:

系统中有重复部分,entity包中的两个类。重构

(1)建Module

新建 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>cloud2024</artifactId>
        <groupId>cn.rys.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.rys.springcloud</groupId>
    <artifactId>cloud-api-commons</artifactId>
    <version>1.0-SNAPSHOT</version>

    <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>
            <version>1.18.24</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>
    </dependencies>

</project>

(3)实体类

创建包cn.rys.springcloud.entity,添加如下两个类:

Payment实体类:

package cn.rys.springcloud.entity;

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

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id; // 和mysql的bigint数据类型对应
    private String serial;

}

(4)通用封装类

CommonResult通用封装类:

package cn.rys.springcloud.entity;

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);
    }
}

(5)生成jar包

maven命令clean install

(6)修改80和8001的pom

· 订单80和支付8001分别改造· 删除各自的原先有过的entity文件夹· 各自粘贴POM内容

80和8001的pom文件中分别添加如下依赖:

		<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>cn.jqy.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

(7)测试

重启启动两个项目,并测试通过。

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值