Springcloud from entry to mastery (full)

Keywords: Java Spring Boot Spring Cloud

preface

This video learns through this connection and summarizes your notes
Silicon Valley spring cloud framework development tutorial (spring cloud Alibaba microservice distributed architecture Spring Cloud)

What is microservice?

  • Microservice architecture is an architecture pattern, which divides a single application into a group of small services, and services coordinate with each other
  • Each service runs its own independent process, and the services cooperate with each other by using lightweight communication mechanism
  • In order to avoid a unified and centralized service management mechanism, for a specific service, appropriate language tools should be selected according to its context

Technology needed?
Service registration and discovery, service invocation, service fusing, load balancing, service degradation, service message queue, configuration center management, service gateway, service monitoring, full link tracking, automatic construction and deployment, service timing, task scheduling


cloud upgrade technology usage

Version configuration of Spring Boot and Spring Cloud
See this document
Official website document

1. Introduction project

1.1 parent project

  • Select maven architecture for new project

  • Select the correct character code after configuration


Aside: if your project involves database garbled code
But look at my previous article
Solution of adding data to display garbled code in database

  • Activation on annotation

  • Compiler version number

  • Create parent project
<?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.lun</groupId>
    <artifactId>LearnCloud</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging><!-- Add here. Note that it is not jar or war -->
    
    <!-- unified management  jar Package version -->
    <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>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>
    
    <!-- After the sub module inherits, it provides the following functions:
		Locked version+son modlue 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>
            <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>

One module in the parent project is dependency management, which is mainly used to manage dependent version numbers
Let all reference dependencies in subprojects without explicitly listing version quantities

The main working principle of Maven is: Maven will go up the parent-child hierarchy until it finds a project with a dependency management element and uses the specified version number

  • Dependency management only declares dependencies and does not implement the introduction. Therefore, the dependencies required for the declarations to be displayed in the subproject
  • Without declaring dependencies, subclasses will not be used. The declaration depends on the undeclared version, and the subclass uses the parent class. The declaration depends on the version used, and the subclass uses the subclass version number

For more information about maven, please refer to my previous articles

  1. Maven detailed configuration (full)
  2. Maven actual combat from introduction to mastery (all)

Similar as follows

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

Subclass works are

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

1.2 module

  • Build Module
  • Change POM
  • Write YML
  • Main start
  • Business class

1.2.1 provider payment module

  • Its xml module is
<?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>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

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

    <dependencies>
        <!--Contains sleuth+zipkin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--Introduce self defined api General package, you can use Payment payment Entity-->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <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>
        <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>

The difference from normal modules without a parent class is
A < parent > label representing the father is added in front
The version tag may not be applicable when referencing dependent files later

  • Database file information
    It is mainly matched with a port number, server name, server database package user name, password and other information
    And the mapping package of mybatis
server:
  port: 8001

spring:
  application:
    name: cloud-provider-service

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource      #Current data source operation type
    driver-class-name: org.gjt.mm.mysql.Driver        #mysql driver package
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root

mybatis:
    mapper-locations: classpath:mapper/*.xml
    type-aliases-package: com.atguigu.springcloud.entities       #Package of all Entity alias classes
  • Configure boot class (boot class of springboot)
@SpringBootApplication
public class PaymentMain8001 {

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

}

Next is the business logic class, mainly dao service and business logic layer
When establishing business logic, it is necessary to interact with the database, so first create tables in the database

  • Build table
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

Then configure the entity class

  • Configure entity classes

The set get classes generated by the entity classes here are annotated with @ Data, which can be explained in my previous articles
Detailed analysis of @ Data annotation in spring

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

The front and back ends of microservices are separated

  • Entity class of front-end and back-end interaction

Directly pass in the front-end commponResult (mainly the display of coding and information) to judge whether the coding is successful
Return the common json code module of the front end, and data is the specific module

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

  • dao class is mainly used to interact with the database

The interface uses @ Mapper annotation instead of @ Repository

import com.atguigu.springcloud.entities.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);
}

And the mapper mapping file involved in mybatis
The knowledge of mybatis can be found in my previous articles

  1. Mybatis from introduction to mastery (all)
  2. Detailed configuration explanation of mybatis Reverse Engineering (full)
  3. Mybatis plus from entry to mastery (all)

In the following knowledge points, resultMap is mainly used to distinguish the mapping of database column names
column is the name of the database, and property is the name of the java entity class

<?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.lun.springcloud.dao.PaymentDao">

    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial)  values(#{serial});
    </insert>
    
    <resultMap id="BaseResultMap" type="com.manong.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>

  • service class

Writing interfaces and implementation classes
The interfaces of interface class and dao class are consistent

import org.apache.ibatis.annotations.Param;


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

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

Interface implementation class
The annotation of the interface implementation class uses @ Service

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

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

  • Business logic class

It is mainly transmitted through CommonResult
@Slf4j this annotation is mainly used to output logs

Be sure to add this @ RequestBody
@The RequestBody annotation is mainly used to insert the http body into the method

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

    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment)
    {
        int result = paymentService.create(payment);
        log.info("*****Insert result:"+result);

        if(result > 0)
        {
            return new CommonResult(200,"Insert database succeeded,serverPort: "+serverPort,result);
        }else{
            return new CommonResult(444,"Insert database failed",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,"query was successful,serverPort:  "+serverPort,payment);
        }else{
            return new CommonResult(444,"No corresponding record,query ID: "+id,null);
        }
    }
}

Test the get and post used in the web page
It's best not to test in the browser
Testing in postman

1.2.2 consumer order module

This module is the same as the previous module
Configure dependency files, add port numbers, and startup classes
Add business logic classes and front-end interaction entity classes (not shown here)

The most important is the code of the control layer interface

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;

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

RestTemplate provides a variety of convenient methods to access remote Http services. It is a simple and convenient restful service template class. It is the client template tool set provided by Spring to access Rest services

The main parameters of the code function are (url, requestMap, ResponseBean.class)
These three parameters represent the REST request address, request parameters and the object type converted by HTTP response conversion

Also set up a configuration class

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

}

If the startup is not successful
You can appropriately delete some irrelevant dependent packages and change some configurations of port numbers

After successful startup
If there are multiple projects to run together
You can right-click other files such as pom.xml to find this configuration

Then find the directory of the project
Click in. idea
(or you can find the workspace.xml file under. idea from the location of your project)

Modify the in this xml file
Find this code and add the following code below

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

You can have it after restarting
The higher version of idea may be different. You need to click here

1.3 hot deployment plug-ins

  • Add dependent packages for hot deployment
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

  • Add a plug-in to the parent project
<build>
    <!--
	<finalName>Add project name when a single project</finalName>
    -->
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
                <addResources>true</addResources>
            </configuration>
        </plugin>
    </plugins>
</build>

  • Add settings to the idea and update it


Ctrl + Shift + Alt + /, open Registry
If it doesn't work, open Registry by Ctrl + Shift +a search
Or hot deployment through crtl+f9

Then check and restart to succeed

  • compiler.automake.allow.when.app.running
  • actionSystem.assertFocusAccessFromEdt

1.4 project reconstruction

Place the same parts of the project in a public area
The main pom.xml file is

<?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>LearnCloud</artifactId>
        <groupId>com.springcloud</groupId>
        <version>1.0.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>

If each engineering module calls this common part
Then configure in the dependency file
Represents the version number of the module that uses the common version and the dependent package that finds its common part

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

2. Eureka

Posted by wilburforce on Thu, 02 Dec 2021 19:12:39 -0800