zoukankan      html  css  js  c++  java
  • 【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:IdeaWorkspacespringcloud_sellcloud2020.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>

    目前工程样图

    后海有树的院子,夏代有工的玉,此时此刻的云,二十来岁的你。——《可遇不可求的事》

    笔者将不定期更新【考研或就业】的专业相关知识以及自身理解,希望大家能【关注】我。
    如果觉得对您有用,请点击左下角的【点赞】按钮,给我一些鼓励,谢谢!
    如果有更好的理解或建议,请在【评论】中写出,我会及时修改,谢谢啦!
    关注
    评论
    收藏
    Top
  • 相关阅读:
    swift 中 Self 与self
    Swift 中的泛型
    mac 报文件已损坏 怎么办
    winxp秘钥
    字符串拷贝函数strcpy, strcat, sprintf, strncpy, strncat和snprintf的区别
    【原创】Linux应用程序完整调用自己写的字符设备驱动过程
    idea中新建git分支,并提交到远程github
    (JS-PHP)使用RSA算法进行加密通讯
    Linux日志相关的命令
    hibernate中关于is null的查询
  • 原文地址:https://www.cnblogs.com/blknemo/p/13526451.html
Copyright © 2011-2022 走看看