𝓝𝓮𝓶𝓸&博客

【SpringCloud】微服务架构编码构建

微服务架构编码构建

约定>配置>编码

Mysql的主从

slave会从master读取binlog来进行数据同步

三步骤+原理图


MySQL复制过程分成三步:

  1. master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;
  2. slave将master的binary log events拷贝到它的中继日志(relay log);
  3. slave重做中继日志中的事件,将改变应用到自己的数据库中。 MySQL复制是异步的且串行化的

IDEA新建project工作空间

微服务cloud整体聚合工程

父工程步骤

父工程的打包方式为 pom,父工程只需要保留 pom.xml 文件即可

1.New Project

2.聚合总父工程名字

3. Maven选版本

4. 工程名字

5. 字符编码

6. 注解生效激活

7. java编译版本选8

8.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.springcloud</groupId>
    <artifactId>cloud2020</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.19</mysql.version>
        <druid.version>1.1.16</druid.version>
        <spring.boot.version>2.2.2.RELEASE</spring.boot.version>
        <spring.cloud.version>Hoxton.SR1</spring.cloud.version>
        <spring.cloud.alibaba.version>2.1.0.RELEASE</spring.cloud.alibaba.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>

    <!--子模块继承后,提供作用:锁定版本+子module不用groupId和version-->
    <dependencyManagement>
        <dependencies>
            <!--springboot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--Spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</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>${spring.cloud.alibaba.version}</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.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </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>

    <!--第三方maven私服-->
    <repositories>
        <repository>
            <id>nexus-aliyun</id>
            <name>Nexus aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

Maven工程落地细节复习

Maven中的DependencyManagement和Dependencies

dependencyManagement

Maven使用dependencyManagement元素来提供了-种管理依赖版本号的方式。
通常会在一个 组织或者项目的最顶层的父POM中看到dependencyManagement元素。
使用pom.xml中的dependencyManagement元索能让所有在子项目中引用一个依赖而不用显式的列出版本号。
Maven会沿着父子层次向上走,直到找到-个拥有dependencyManagement元索的项目,然后它就会使用这个dependencyManagement元素中指定的版本号。

例如在父项目里:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.2</version>
    </dependency>
  </dependencies>
</dependencyManagement>

然后在子项目里就可以添加mysql-connector时可以不指定版本号,例如:

<dependencies>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
</dependencies>

这样做的好处就是: 如果有多个子项目都引用同一样的依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样想升级或切换到另一个版本时,只需在顶层父容器里更新,而不需要一个一个子项目的修改l;另外如果某个子项目需要另外的一个版本,只需声明version版本。

dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。

maven中跳过单元测试

父工程创建完成执行mvn:insall将父工程发布到仓库方便子工程继承

Rest微服务工程搭建

构建步骤

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

1.Cloud-provider-payment8001 微服务提供者Module模块

1 建module

建cloud-provider-payment8001

创建完成后回到父工程查看pom文件变化

2 改POM

3 写YML

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    # 当前数据源操作类型
    type: com.alibaba.druid.pool.DruidDataSource
    # mysql驱动类
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root

mybatis:
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities

4 主启动

5 业务类

1.建表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=utf8
2.entities
主实体Payment
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {

    private Long id;
    private String serial;
}
Json封装体CommonResult
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    // 404 not found
    private Integer code;
    private String message;
    private T       data;

    public CommonResult(Integer code,String message){
        this(code,message,null);
    }
}
3.dao
接口PaymentDao
@Mapper
public interface PaymentDao {

    public int create(Payment payment);

    public Payment getPaymentById(@Param("id") Long id);
}
mybatis的映射文件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.atguigu.springcloud.dao.PaymentDao">
    <insert id="create" parameterType="com.atguigu.springcloud.entities.Payment" useGeneratedKeys="true"
            keyProperty="id">
        insert into payment (serial) values (#{serial});
    </insert>
 
    <resultMap id="BaseResultMap" type="com.atguigu.springcloud.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>
4.service
接口PaymentService
public interface PaymentService {

    public int create(Payment payment);

    public Payment getPaymentById(@Param("id") Long id);
}
实现类
@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);
    }
}
5.controller
@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    @PostMapping(value="/payment/create")
    public CommonResult 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 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);
        }
    }
}

测试

http://localhost:8001/payment/get/31

postman模拟post

运行
通过修改idea的workspace.xml的方式快速打开Run Dashboard窗口
你自己路径 E:\IdeaWorkspace\springcloud_sell\cloud2020.idea

<option name="configurationTypes">
  <set>
      <option value="SpringBootApplicationConfigurationType" />
   </set>
</option>

添加代码块

开启Run DashBoard

部分同学可能由于idea版本不同,需要关闭重启

小总结

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

2.热部署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下
<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>

3.Enabling automatic build

4. Update the value of


CTRL+SHIFT + ALT + /
打开上面的这个界面,选择 registry
主要是打开 compiler.aotomake.allow.when.app.running

5.重启idea

3.cloud-consumer-order80 微服务消费者订单Module模块

建cloud-consumer-order80

改POM

<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>
    <!--eureka client-->
    <!--<dependency>-->
    <!--<groupId>org.springframework.cloud</groupId>-->
    <!--<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>-->
    <!--</dependency>-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <!--如果没写版本,从父层面找,找到了就直接用,全局统一-->
    </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>

注意你前期跟着做项目,如果没有用到dao层和相关配置,记得把POM.xml中 mybatis和 mysql的注释掉

写YML

主启动

@SpringBootApplication
public class OrderMain80 {

    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

业务类

entites

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接口非常的简单粗暴无脑。
(urI, requestMap, ResponseBean.class)这三个参数分别代表
REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。

config配置类

ApplicationContextConfig

@Configuration
public class ApplicationContextConfig {

    @Bean
    public RestTemplate getRestTemplate() {
        return  new RestTemplate();
    }
}
controller
@RestController
@Slf4j
public class OrderController {

    public static final String PAYMENT_URL = "http://localhost:8001";

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

测试

http://localhost/consumer/payment/get/1
不要忘记@RequestBody注解

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);

4. 工程重构

观察问题


系统中有重复部分,重构

新建

cloud-api-common 存放公共依赖,父工程的打包方式为 pom,父工程只需要保留 pom.xml 文件即可。

POM

<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>

entities

Payment实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {

    private Long id;
    private String serial;
}
CommonResult通用封装类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    // 404 not found
    private Integer code;
    private String message;
    private T       data;

    public CommonResult(Integer code,String message){
        this(code,message,null);
    }
}

maven命令clean install

订单80和支付8001分别改造

删除各自的原先的entities文件夹
各自粘贴POM内容
<dependency>
     <groupId>com.eiletxie.springcloud</groupId>
     <artifactId>cloud-api-commons/artifactId>
     <version>${project.version}</version>
</dependency>

目前工程样图

posted @ 2020-08-23 14:15  Nemo&  阅读(395)  评论(0编辑  收藏  举报