Spring Cloud【Finchley】-01服务提供者与服务消费者
Spring Cloud总览
概述
服务提供者: 服务的被调用发,为其他服务提供服务的服务
服务消费者: 服务的调用方,即依赖其他服务的服务
示例
场景描述
围绕该场景,需要两个微服务
- 用户微服务,作为服务提供者为电影微服务提供服务
- 电影微服务,作为消费者调用用户微服务提供的服务
用户微服务
Spring Boot 2.1.1
Spring Data JPA
H2
lombok简化编码
新建Spring Boot服务
项目结构
pom.xml
<?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.artisan</groupId>
<artifactId>micorservice-simple-provider-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>micorservice-simple-provider-user</name>
<description>Demo project for Spring Cloud</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
用户库表
简单起见,我们使用H2数据库
schema.sql
drop table user if exists;
create table user(
id bigint generated by default as identity,
username varchar(40),
name varchar(20),
age int(3),
balance decimal(10,2),
primary key(id)
);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
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', '李四', 20, 100.00);
insert into user(id,username, name, age, balance) values(3,'user3', '王五', 20, 100.00);
insert into user(id,username, name, age, balance) values(4,'user4', '马六', 20, 100.00);
- 1
- 2
- 3
- 4
Model
为了简化代码,使用了lombok的@Data注解
package com.artisan.microservice.model;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;
@Entity
@Data
public class User implements Serializable {
private static final long serialVersionUID = 226695758444267342L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id ;
@Column
private String username;
@Column
private String name;
@Column
private Integer age;
@Column
private BigDecimal balance;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
Dao层
使用Spring Data JPA操作数据库
package com.artisan.microservice.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.artisan.microservice.model.User;
@Repository
public interface UserRepository extends JpaRepository<User,Long>{
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Service
按道理都应该有Service层,这里demo比较简单,省略也可以,直接在Controller层调用Dao层
Controller 暴露Rest API
package com.artisan.microservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.artisan.microservice.model.User;
import com.artisan.microservice.repository.UserRepository;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
User user = new User();
user.setId(id);
User user2 = new User();
user2.setName("no this user");
// 我们使用的spring boot2.1.1版本中关联使用的spring data jpa不再支持findone(id)方法,改成如下写法
return userRepository.findOne(Example.of(user)).orElse(user2);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
配置文件application.yml
server:
port: 7900
spring:
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
datasource:
platform: h2
schema: classpath:schema.sql
data: classpath:data.sql
logging:
level:
root: INFO
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
com.artisan: DEBUG
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
测试
package com.artisan.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MicorserviceSimpleProviderUserApplication {
public static void main(String[] args) {
SpringApplication.run(MicorserviceSimpleProviderUserApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
右键–Run As --Spring Boot App,启动成功后
访问数据库中存在的用户
http://localhost:7900/user/1
{"id":1,"username":"user1","name":"张三","age":20,"balance":100.00}
- 1
http://localhost:7900/user/2
{"id":2,"username":"user2","name":"李四","age":20,"balance":100.00}
- 1
http://localhost:7900/user/3
{"id":3,"username":"user3","name":"王五","age":20,"balance":100.00}
- 1
http://localhost:7900/user/4
{"id":4,"username":"user4","name":"马六","age":20,"balance":100.00}
- 1
访问数据库中不存在的一个用户
http://localhost:7900/user/66
{"id":null,"username":null,"name":"no this user","age":null,"balance":null}
- 1
电影微服务
新建Spring Boot服务
如用户微服务,只不过我们这里仅仅作为消费者,仅使用web即可。
项目结构
pom.xml
<?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.artisan</groupId>
<artifactId>micorservice-simple-consumer-movie</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>micorservice-simple-consumer-movie</name>
<description>Demo project for Spring Cloud</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.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-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
Controller通过 RestTemplate 调用用户微服务提供的服务
因为仅仅作为服务消费者,所有只要在Controller层调用对应的rest接口即可
package com.artisan.microservice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.artisan.microservice.model.User;
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Value("${user.userServicePath}")
private String userServicePath;
@GetMapping("/movie/{id}")
public User findById(@PathVariable Long id) {
return this.restTemplate.getForObject(this.userServicePath + id, User.class);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
用到了User类,新建个User.java
package com.artisan.microservice.model;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
@Data
public class User implements Serializable {
private static final long serialVersionUID = 8912111288470833198L;
private Long id;
private String username;
private String name;
private Integer age;
private BigDecimal balance;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
启动类入口处,通过@Bean实例化RestTemplate
通过@Bean实例化RestTemplate
package com.artisan.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class MicorserviceSimpleConsumerMovieApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MicorserviceSimpleConsumerMovieApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
配置文件 application.yml
配置端口及用户微服务的地址
server:
port: 7901
user:
userServicePath: http://localhost:7900/user/
- 1
- 2
- 3
- 4
测试
启动用户微服务,访问7901
访问数据库中存在的用户
http://localhost:7901/movie/1
{"id":1,"username":"user1","name":"张三","age":20,"balance":100.00}
- 1
http://localhost:7901/movie/2
{"id":2,"username":"user2","name":"李四","age":20,"balance":100.00}
- 1
http://localhost:7901/movie/3
{"id":3,"username":"user3","name":"王五","age":20,"balance":100.00}
- 1
http://localhost:7901/movie/4
{"id":4,"username":"user4","name":"马六","age":20,"balance":100.00}
- 1
访问数据库中不存在的一个用户
http://localhost:7901/movie/66
{"id":null,"username":null,"name":"no this user","age":null,"balance":null}
- 1
成功调用到了用户微服务对外提供的服务。
示例的缺点
不难发现,虽然我们把用户微服务对外提供的接口地址配置在了配置文件中,然后通过@Value的方式去加载该属性,但是一旦用户微服务修改了地址,电影微服务作为消费者也要修改对应的地址,多了的话,也是很难管理
第二个原因,如果存在多个用户微服务,如何进行负载? nginx固然可以,如果这种服务比较多,依赖nginx, 增加节点还是需要修改nginx配置文件,比较头疼
所以 接下来我们来看下服务发现与服务注册,这里主要说的是Spring Cloud支持比较好的Eureka
文章来源: artisan.blog.csdn.net,作者:小小工匠,版权归原作者所有,如需转载,请联系作者。
原文链接:artisan.blog.csdn.net/article/details/84679248
- 点赞
- 收藏
- 关注作者
评论(0)