Summary of SpringCloud (service provider and consumer)

1. Concept

The architecture of the movie sales system is used to position service providers and consumers:
insert image description here
it can be seen that when a user accesses the movie ticket purchase system, the first thing they visit is the front-end system "movie microservice", and the movie microservice is selling In the process of ticketing, it is necessary to obtain the user information registered by the user before. At this time, it is necessary to call the service of the user microservice to obtain the user information. Here, the movie microservice is the "service consumer", and the user microservice is the "service provider". The movie microservice needs to consume user query services, and the user microservice provides user query services.
Definitions of "Service Consumer" and "Service Provider":
insert image description here

2. Write a service provider

First, let's write a simple service provider sample project. Here we create a SpringBoot project directly through the construction tools provided by Spring's official website. Open https://start.spring.io/:
insert image description here
Fill in the information we need here, where the system builds using Maven, the programming language uses Java, SpringBoot uses the latest 2.2.0 (SNAPSHOT snapshot) version, Group and Artifact are defined as microservice Demo Related information for: "com.microserver.cloud", "microserver-simple-provider-user".
Finally, some dependencies are needed, web, jpa and H2:
insert image description here
where web is the Spring-web we need to support Web development; jpa is Spring-jpa is the persistence layer framework for operating the database; H2 is the H2 database, built-in database, Used to display some data.
Click the "Generate Project" button to build a Project based on Spring boot. At this point, a Zip compressed package will pop up for us to download. After the download is complete, we will get a file:
insert image description here
insert image description here
insert image description here
insert image description here
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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.BUILD-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.microserver.cloud</groupId>
    <artifactId>microserver-simple-provider-user</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>microserver-simple-provider-user</name>
    <description>Demo project for Spring Boot</description>
 
    <properties>
        <java.version>1.8</java.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </pluginRepository>
    </pluginRepositories>
 
</project>

It can be seen that the version of SpringBoot is the 2.2.0-SNAPSHOT version we chose before, and then the related dependencies of web, jpa and H2 are also introduced. Under the top src, a default MicroserverSimpleProviderUserApplication.java class is generated:

package com.microserver.cloud.microserversimpleprovideruser;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class MicroserverSimpleProviderUserApplication {
    
    
 
    public static void main(String[] args) {
    
    
        SpringApplication.run(MicroserverSimpleProviderUserApplication.class, args);
    }
 
}

This class is used to load the default startup items and start the SpringBoot project.
insert image description here
Write the table creation statement in schema.sql:

DROP TABLE USER IF EXISTS;
CREATE TABLE USER(
    id BIGINT generated BY DEFAULT AS identity,  -- h2数据库自增主键语法
    username VARCHAR(40) COMMENT '账号',
    NAME VARCHAR(20) COMMENT '姓名',
    age INT(3) COMMENT '年龄',
    balance DECIMAL(10,2) COMMENT '余额',
    PRIMARY KEY(id)
);

Then create a data.sql to insert test data into the user table:

Write the inserted data in data.sql:

INSERT INTO USER(id,username,NAME,age,balance) VALUES(1,'user1','张三',20,100.00);
INSERT INTO USER(id,username,NAME,age,balance) VALUES(2,'user2','李四',21,200.00);
INSERT INTO USER(id,username,NAME,age,balance) VALUES(3,'user3','王五',22,300.00);
INSERT INTO USER(id,username,NAME,age,balance) VALUES(4,'user4','赵六',23,400.00);

After the data is ready, we create a User entity class under the com.microserver.cloud.entity package under src/main/java:

package com.microserver.cloud.entity;
 
import java.math.BigDecimal;
 
public class User implements Serializable{
    
    
    private Long id;
    private String username;
    private String name;
    private Short age;
    private BigDecimal balance;
    public Long getId() {
    
    
        return id;
    }
    public void setId(Long id) {
    
    
        this.id = id;
    }
    public String getUsername() {
    
    
        return username;
    }
    public void setUsername(String username) {
    
    
        this.username = username;
    }
    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name;
    }
    public Short getAge() {
    
    
        return age;
    }
    public void setAge(Short age) {
    
    
        this.age = age;
    }
    public BigDecimal getBalance() {
    
    
        return balance;
    }
    public void setBalance(BigDecimal balance) {
    
    
        this.balance = balance;
    }
}

Since our project uses SpringData-JPA, we need to add JPA annotations:

package com.microserver.cloud.entity;
 
import java.math.BigDecimal;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
 
@Entity
public class User implements Serializable{
    
    
    @Id  //标记为主键
    @GeneratedValue(strategy=GenerationType.AUTO) //主键自增
    private Long id;
    @Column //标记为数据库字段,下同
    private String username;
    @Column
    private String name;
    @Column
    private Short age;
    @Column
    private BigDecimal balance;
        //Get与Set方法省略
}

Then write the DAO layer and create a UserRepository interface under the com.microserver.cloud.dao package under src/main/java:

package com.microserver.cloud.dao;
 
import org.springframework.data.jpa.repository.JpaRepository;
import com.microserver.cloud.entity.User;
 
@Repository
public interface UserRepository extends JpaRepository<User, Long>{
    
    
 
}

Here, the method body does not need to implement other method definitions. The parent interface of JpaRepository has already defined common operation methods for adding, deleting, modifying and checking:

package org.springframework.data.jpa.repository;
 
import java.util.List;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
 
@NoRepositoryBean
public abstract interface JpaRepository<T, ID>
  extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
{
    
    
  public abstract List<T> findAll();
  
  public abstract List<T> findAll(Sort paramSort);
  
  public abstract List<T> findAllById(Iterable<ID> paramIterable);
  
  public abstract <S extends T> List<S> saveAll(Iterable<S> paramIterable);
  
  public abstract void flush();
  
  public abstract <S extends T> S saveAndFlush(S paramS);
  
  public abstract void deleteInBatch(Iterable<T> paramIterable);
  
  public abstract void deleteAllInBatch();
  
  public abstract T getOne(ID paramID);
  
  public abstract <S extends T> List<S> findAll(Example<S> paramExample);
  
  public abstract <S extends T> List<S> findAll(Example<S> paramExample, Sort paramSort);
}

This example is very simple, we will no longer write the Service layer here, and directly call the DAO layer from the Controller layer. We create a UserController class under the com.microserver.cloud.controller package under src/main/java:

package com.microserver.cloud.controller;
 
import java.util.Optional;
 
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 com.microserver.cloud.dao.UserRepository;
import com.microserver.cloud.entity.User;
 
@RestController
public class UserController {
    
    
    @Autowired
    private UserRepository userDao;
    
    @GetMapping("/findById/{id}")
    public User findById(@PathVariable Long id){
    
    
        Optional<User> userOptional = this.userDao.findById(id);
        return userOptional.get();
    }
}

Among them, @RestController specifies that the Controller exposes REST-style services to the outside world. @RestController is the combined annotation of @Controller and @ResponseBody, aiming to provide REST services in json format.
Add the following configuration to the application.yml file:

server:
  port: 7900//在application.yml文件中加入以下配置:
spring:
  jpa:
    generate-ddl: false//为启动时是否生成DDL语句,这里我们已经自己编写好了,所以false不生成;
    show-sql: true//为是否打印SQL语句,这里设置为true
    hibernate:
      ddl-auto: none//为hibernate每次启动时是否自动创建表单(jpa依赖hibernate),这里要求启动时不做DDL的处理,所以设置为none;
  datasource:
    platform: h2//用于设置数据源使用的数据库类型,这里为H2;
    schema: classpath:schema.sql//用于设置数据库启动时的建表语句文件位置
    data: classpath:data.sql//用于设置数据库启动时的数据库信息插入语句文件位置
logging:
  level:
    root: info//用于设置根目录的日志级别
    org.hibernate: INFO//用于设置hibernate的日志级别
    org.hibernate.type.descripter.sql.BasicBinder: TRACE
    org.hibernate.type.descripter.sql.BasicExtractor: TRACE//用于设置hibernate输出SQL语句到日志,与上面的“spring.jpa.show-sql”配合
    com.microserver: DEBUG//设置我们自己业务代码的日志级别为DEBUG,用于体现细粒度的日志,方便查找Bug。

Here you need to move the MicroserverSimpleProviderUserApplication to the com.microserver.cloud package, that is, there is a customary rule in SpringBoot, because the Application needs to scan the annotations of the sub-packages, so the Application startup class is required to be at the top of the business package: all
insert image description here
preparations Finished, let's start the project. Execute the main method of the MicroserverSimpleProviderUserApplication startup class:
insert image description here
the last time the words MicroserverSimpleProviderUserApplication: Started appear on the console, the startup is successful.
We access the service we just wrote in the browser to get the user information with id 1:
insert image description here

2. Write a service consumer

Let's write a service consumer to call the service provider's service. Build a new project named "microserver-simple-consumer-movie" (artifact with the same name), which is the same as the previous construction method (only web is required for external dependencies, jpa and h2 are not required), so I won't go into details here.
The User class is the same as in microserver-simple-provider-user, which is to remove all annotations related to JPA:

package com.microserver.cloud.entity;
 
import java.io.Serializable;
import java.math.BigDecimal;
 
 
public class User implements Serializable{
    
    
	private Long id;
	private String username;
	private String name;
	private Short age;
	private BigDecimal balance;
	public Long getId() {
    
    
		return id;
	}
	public void setId(Long id) {
    
    
		this.id = id;
	}
	public String getUsername() {
    
    
		return username;
	}
	public void setUsername(String username) {
    
    
		this.username = username;
	}
	public String getName() {
    
    
		return name;
	}
	public void setName(String name) {
    
    
		this.name = name;
	}
	public Short getAge() {
    
    
		return age;
	}
	public void setAge(Short age) {
    
    
		this.age = age;
	}
	public BigDecimal getBalance() {
    
    
		return balance;
	}
	public void setBalance(BigDecimal balance) {
    
    
		this.balance = balance;
	}
}

We write a MovieController to call the service provider's service:

package com.microserver.cloud.controller;
 
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;
 
import com.microserver.cloud.entity.User;
 
@RestController
public class MovieController {
    
    
    
    @Autowired
    private RestTemplate restRemplate;
    
    @GetMapping("/movie/{id}")
    public User findUserById(@PathVariable Long id){
    
    
        return this.restRemplate.getForObject("http://localhost:7900/findById/"+id, User.class);
    }
}

Here, the RestTemplate class is used to call the Http service, and getForObject is used to pass in the URL of the requested HTTP service and the returned entity class type.

Since RestTemplate requires developers to configure the parameter SimpleClientHttpRequestFactory object of its constructor, so here only write @Autowired without configuration, it cannot be automatically injected. Create a new RestTemplateConfig class, add @Configuration as a configuration class, similar to writing the injection configuration of the RestTemplate class in XML:

package com.microserver.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
 
/**
 * RestTemplate配置
 * 这是一种JavaConfig的容器配置,用于spring容器的bean收集与注册,并通过参数传递的方式实现依赖注入。
 * "@Configuration"注解标注的配置类,都是spring容器配置类,springboot通过"@EnableAutoConfiguration"
 * 注解将所有标注了"@Configuration"注解的配置类,"一股脑儿"全部注入spring容器中。
 *
 */
@Configuration
public class RestTemplateConfig {
    
    
    
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
    
    
        return new RestTemplate(factory);//在Spring容器中注入RestTemplate对象
    }
 
    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
    
    
        //初始化RestTemplate对象需要的Factory工厂类,biang注入到Spring容器中
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);//读取反馈超时时间5000ms
        factory.setConnectTimeout(15000);//连接超时时间15000ms
        return factory;
    }
}

Then create an application.yml under src/main/resource, which only needs to configure the port number:

server:
  port: 7901

Finally, don't forget to move the MicroserverSimpleConsumerMovieApplication class to the top level of the package.

Start the service provider and service consumer successively, and then access the movie request of the service consumer:
insert image description here
get the user information with userId 1. So far our consumer has successfully created and successfully consumed the service information provided by the service provider.

Summarize

Spring Cloud focuses on providing a good out-of-the-box experience for typical use cases and provides extension mechanisms to cover other use cases.

  • Distributed/versioned configuration
  • Service Registration and Discovery
  • routing
  • service to service call
  • load balancing
  • breaker
  • global lock
  • Leader election and cluster state
  • distributed messaging

Guess you like

Origin blog.csdn.net/lj20020302/article/details/129377260