1, Spring cloud infrastructure and microservice architecture coding construction

Posted by emceej on Mon, 17 Jan 2022 17:01:09 +0100


Mind map: https://download.csdn.net/download/zhou_zhao_xu/20298704

1. Introduction to zero basic theory of microservice architecture

1.1 theoretical introduction

Microservice architecture and spring cloud

1. Overview of microservice architecture

Microservice architecture is a new technology for deploying applications and services in the cloud. Most of the debates about microservices focus on whether containers or other technologies can implement microservices well, and red hat said that API should be the focus.
Microservices can run in "their own programs" and communicate with HTTP APIs through "lightweight devices". The key is that the service can run in its own program. Through this, we can distinguish service disclosure from microservice architecture (distributing an API in the existing system). In service disclosure, many services can be limited by internal independent processes. If any of these services need to add some functionality, the scope of the process must be narrowed down. In the microservice architecture, only the required functions need to be added to a specific service without affecting the overall process architecture

2. Introduction to spring cloud

SpringCloud = one-stop solution of distributed microservice architecture, which is a collection of landing technologies of a variety of microservice architectures, commonly known as microservice architecture

2. From 2.2 Start with versions X and H

2.1 SpringBoot version selection

1. git source code address

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

2.2 spring cloud version selection

1. git source code address

https://github.com/spring-projects/spring-cloud

2. See the spring cloud version on the official website

SpringCloud official website: https://spring.io/projects/spring-cloud

  • In the old version naming method, the developed snapshot Version (BUILD-SNAPSHOT) to the milestone Version (M), the developed candidate release version (RELEASE) almost to be released, and finally to the official version (SR).

  • The new edition is named YYYY MINOR. MICRO [- MODIFIER], take 2020.0.1-SNAPSHOT for example, where YYYY is the full name of the year, minor is the auxiliary version number, and MICRO is the patch version number. MODIFIER is the same as the above modified key nodes, BUILD-SNAPSHOT, milestone M, etc.

2.3 dependencies between springcloud and SpringBoot

There is version mapping between SpringCloud and SpringBoot on the official website
SpringCloud official website: https://spring.io/projects/spring-cloud

More detailed version corresponding view
https://start.spring.io/actuator/info
View the returned json information

2.4 versions used in learning

SpringCloud Hoxton.SR1
SpringBoot 2.2.2.RELEASE
SpringCloud Alibaba 2.1.0.RELEASE
Java 8
Maven 3.5 and above
Mysql 5.7 and above

3. Suspension / upgrade / replacement of Cloud components

4. Microservice architecture coding construction

4.1 create parent project

1. Create a new parent project using maven site

4.2 modify pom file

<?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.zzx</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <!-- unified management  jar Package version -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <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.0</lombok.version>
        <mysql.version>8.0.25</mysql.version>
        <druid.version>1.1.17</druid.version>
        <mybatis.spring.boot.version>2.2.0</mybatis.spring.boot.version>
    </properties>

    <!-- After the sub module inherits, it provides functions:Locked version+son module Do not write groupId and 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>
            <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <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>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>
  • Dependency management is to declare that the jar package is managed uniformly. Dependencies is used as a reference to record the three-dimensional coordinates of the jar under dependency management
  • If the subclass is only wrapped by Dependencies, maven will download the jar and inherit the version number under dependency management
  • Dependency management only declares dependencies and does not introduce implementation. Therefore, the dependencies required for the declarations to be displayed in the subproject, and the subproject version and scope are read from the parent pom
  • If a dependency is not declared in a child project, it will not inherit from the parent project
  • If the version number is specified in the subproject, the version specified in the subproject takes precedence

4.2 create order payment module micro service

Create cloud provider payment8001 payment service module in the parent project
Modify pom file

<?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>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <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>
        <druid.spring.boot.starter.version>1.2.6</druid.spring.boot.starter.version>
    </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>${druid.spring.boot.starter.version}</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>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

yaml file preparation

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service # Set service name
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # Current data source operation type
    driver-class-name: com.mysql.cj.jdbc.Driver # mysql driver package
    url: jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&characterSetResults=UTF-8&autoReconnect=true&allowMultiQueries=true&useSSL=false
    username: root
    password: 123456

mybatis:
  mapper-locations: classpath:mapper/*.xml

Write the SpringBoot startup class

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

Write entity classes and response result classes

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

    private static final long serialVersionUID = -1025999481836730517L;

    private Long id;
    private String serial;

}

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

    private int code;
    private String message;
    private T data;

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

Write mapper interface

@Mapper
public interface PaymentMapper {

    /**
     * Write data
     * @param payment
     * @return
     */
    int create(Payment payment);

    /**
     * Get data according to id
     * @param id
     * @return
     */
    Payment getPaymentById(@Param("id") Long id);
}

Configure mybatis master profile

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias type="com.zzx.springcloud.entities.Payment" alias="Payment"></typeAlias>
    </typeAliases>
</configuration>

Configure mapper profile

<?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.zzx.springcloud.mapper.PaymentMapper">

    <resultMap id="paymentResultMap" type="Payment">
        <id column="id" property="id"></id>
        <result column="serial" property="serial"></result>
    </resultMap>

    <sql id="PaymentColumn">
        id
        ,serial
    </sql>


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

    <select id="getPaymentById" resultMap="paymentResultMap">
        select
        <include refid="PaymentColumn"/>
        from payment
        where id=#{id}
    </select>

</mapper>

Write service interface and impl

public interface PaymentService {

    /**
     * Write data
     * @param payment
     * @return
     */
    Integer create(Payment payment);


    /**
     * Get data according to id
     * @param id
     * @return
     */
    Payment getPaymentById(Long id);
}

@Service
public class PaymentServiceImpl implements PaymentService {

    private final PaymentMapper paymentMapper;

    @Autowired
    public PaymentServiceImpl(PaymentMapper paymentMapper) {
        this.paymentMapper = paymentMapper;
    }

    @Override
    public Integer create(Payment payment) {
        int i = 0;
        try {
            i = paymentMapper.create(payment);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return i;
    }

    @Override
    public Payment getPaymentById(Long id) {
        Payment payment = null;
        try {
            payment = paymentMapper.getPaymentById(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return payment;
    }
}

Write controller

@RestController
@Slf4j
public class PaymentController {

    private final PaymentService paymentService;

    @Autowired
    public PaymentController(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    @PostMapping("/payment/create")
    public CommonResult create(@RequestBody Payment payment) {
        Integer result = paymentService.create(payment);
        log.info("Insert result:", result);
        if (result > 0) {
            return new CommonResult(200, "Insert successful", result);
        }
        return new CommonResult(444, "Insert failed");
    }

    @GetMapping("/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id) {

        Payment payment = paymentService.getPaymentById(id);

        if (!Objects.isNull(payment)) {
            return new CommonResult(200, "query was successful", payment);
        }
        return new CommonResult(444, "No corresponding data,Inquired id Is:" + id);
    }

}

Use postman to test, insert and query data

4.3 create order module micro service

Create the cloud-consumer-order80 module in the parent project
Modify pom file

<?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>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-comsumer-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>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

Write yaml

server:
  port: 80

Write entity classes and response result classes

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

    private static final long serialVersionUID = -1025999481836730517L;

    private Long id;
    private String serial;

}

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

    private int code;
    private String message;
    private T data;

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

Configure RestTemplate

@Configuration
public class ApplicationContextConfig {

    /**
     * Register RestTemplate with container
     * @return
     */
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

Write controller

@RestController
@Slf4j
public class OrderController {

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

    private final RestTemplate restTemplate;

    @Autowired
    public OrderController(RestTemplate restTemplate) {
        this.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);
    }

}

Test with postman

4.4 project reconstruction and optimization

Now there is common code in the two modules. Extract it and put it into a core module for reuse
Create a new cloud API commons module in the parent project

Modify 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>springcloud</artifactId>
        <groupId>com.zzx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-api-commons</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>

</project>

Extract common code

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Payment implements Serializable {

    private static final long serialVersionUID = -1025999481836730517L;

    private Long id;
    private String serial;

}

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

    private int code;
    private String message;
    private T data;

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

Delete the entities in cloud-comsumer-order80 and cloud-provider-payment8001 modules
Introduce in the respective pom

        <dependency>
            <groupId>com.zzx</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

Topics: Java Spring