总体学习步骤:先构建一个简单的订单-支付模块微服务,然后一步一步融合springcloud各种技术组件
微服务cloud整体聚合父工程Project
- New Project
- Maven版本
- 字符编码
- 注解生效激活
- 如果想不显示
.idea,.iml
,可以在File Types设置项里 ignore files and folders 添加 *.idea;*.iml
,让眼睛看地清爽一些
- 删除src文件夹
pom.xml
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
<?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>org.eh</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>
<lombok.version>1.16.18</lombok.version>
<mysql.connector.java.version>8.0.21</mysql.connector.java.version>
<druid.verison>1.1.16</druid.verison>
<mybatis.spring.boot.verison>2.1.3</mybatis.spring.boot.verison>
</properties>
<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为jar,pom表示依赖的是一个父工程,父工程里引入了很多jar-->
<type>pom</type>
<!--
在Spring boot 项目的POM文件中,我们可以通过在POM文件中继承 Spring-boot-starter-parent来引用Spring boot默认依赖的jar包
但是,通过上面的parent继承的方法,只能继承一个 spring-boot-start-parent。
实际开发中,用户很可能需要继承自己公司的标准parent配置,这个时候可以使用 scope=import 来实现多继承。
-->
<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.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.java.version}</version>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.verison}</version>
</dependency>
<!-- mybatis-springboot整合 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.verison}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</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>
|
设置跳过测试

- 建moudle
- 改pom
- 写yml
- 主启动
- 业务类
订单模块(consumer) - > 支付模块(provider)
支付模块
改pom
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
|
<?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>org.eh</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8001</artifactId>
<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>1.1.10</version>
</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>
</project>
|
写yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/eden?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 333
mybatis:
mapperLocations: classpath:mapper/*.xml
|
主启动
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package com.eh.springcloud.payment8001;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.eh.springcloud.payment8001.dao")
@SpringBootApplication
public class SpringbootPayment8001Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootPayment8001Application.class, args);
}
}
|
业务类
-
建表sql
1
2
3
4
5
6
7
|
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Data for the table `payment` */
insert into `payment`(`serial`) values ('aaabbb01');
|
-
entities
主实体Payment, 这里使用mbg自动生成
Json封装体CommonResult
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
|
package com.eh.springcloud.payment8001.entity;
import lombok.Data;
@Data
public class CommonResult<T> {
private Integer code;
private String desc;
private T data;
public static <T> CommonResult<T> success(T data) {
CommonResult<T> commonResult = new CommonResult<>();
commonResult.setCode(200);
commonResult.setDesc("处理成功");
commonResult.setData(data);
return commonResult;
}
public static <T> CommonResult<T> error(Integer code, String desc) {
CommonResult<T> commonResult = new CommonResult<>();
commonResult.setCode(code);
commonResult.setDesc(desc);
return commonResult;
}
}
|
-
dao
-
service
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
|
package com.eh.springcloud.payment8001.service.impl;
import com.eh.springcloud.payment8001.dao.PaymentMapper;
import com.eh.springcloud.payment8001.entity.Payment;
import com.eh.springcloud.payment8001.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @auther zzyy
* @create 2020-02-18 10:40
*/
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentMapper paymentDao;
public int create(Payment payment) {
return paymentDao.insertSelective(payment);
}
public Payment getPaymentById(Long id) {
return paymentDao.selectByPrimaryKey(id);
}
}
|
-
controller
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
|
package com.eh.springcloud.payment8001.controller;
import com.eh.springcloud.payment8001.entity.CommonResult;
import com.eh.springcloud.payment8001.entity.Payment;
import com.eh.springcloud.payment8001.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class PaymentController {
private final PaymentService paymentService;
public PaymentController(PaymentService paymentService) {
this.paymentService = paymentService;
}
@PostMapping("/create")
public CommonResult<Payment> create(Payment payment) {
log.info("开始创建订单:{}", payment);
try {
Assert.notNull(payment.getSerial(), "参数serial不能为空");
paymentService.create(payment);
return CommonResult.success(payment);
} catch (Exception e) {
log.error("创建订单出现异常", e);
return CommonResult.error(444, "创建订单失败");
}
}
@GetMapping("/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentService.getPaymentById(id);
if (payment != null) {
log.info("hello");
return CommonResult.success(payment);
} else {
return CommonResult.error(444, "没有对应记录, 查询ID: " + id);
}
}
}
|
-
测试:
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
|
GET http://localhost:8001/payment/1
输出
{
"code": 200,
"desc": "处理成功",
"data": {
"id": 1,
"serial": "aaabbb01"
}
}
###
POST http://localhost:8001/payment/create
Content-Type: application/x-www-form-urlencoded
serial=david001
输出
{
"code": 200,
"desc": "处理成功",
"data": {
"id": 2,
"serial": "david001"
}
}
|
订单模块
pom.xml
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
|
<?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>org.eh</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-order80</artifactId>
<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.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>
|
订单模块调支付模块,由于这里还没有微服务的远程调用,那么如果要调用另外一个模块,则需要使用基本的api调用,这里使用RestTemplate
RestTemplate
RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务的模板类,是spring提供的用于访问Rest服务的客户端模板工具集。
RestTemplate
使用RestTemplate访问restful接口非常简单,url,requestMap,ResponseBean.class这个三个参数分别代表REST请求地址,请求参数,HTTP响应转换被转换成的对象类型。
Controller
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
|
package com.eh.springcloud.order80.controller;
import com.eh.springcloud.order80.entity.CommonResult;
import com.eh.springcloud.order80.entity.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController {
private final static String PAYMENT_URL = "http://localhost:8001";
private RestTemplate restTemplate;
public OrderController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/order/payment/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
return restTemplate.getForObject(PAYMENT_URL + "/payment/" + id, CommonResult.class, id);
}
@PostMapping("/order/payment/create")
public CommonResult<Payment> create(Payment payment) {
return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
}
}
|
注意
order调payment,由于是json调用(postForObject),payment对应方法参数需要加@RequestBody注解
1
2
|
@PostMapping("/payment/create")
public CommonResult<Payment> create(@RequestBody Payment payment) {
|
测试:
1
2
3
4
5
6
7
8
9
|
GET http://localhost/order/payment/1
###
### Send POST request with body as parameters
POST http://localhost/order/payment/create
Content-Type: application/x-www-form-urlencoded
serial=david002
|
工程重构
新建一个common模块,将重复代码抽取到一个公共模块中
-
创建common模块
-
抽取公共pom
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
|
<?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>org.eh</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-common</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.7</version>
</dependency>
</dependencies>
</project>
|
-
将Payment和CommonResult两个实体类放到common模块中
-
maven clean install
-
其他模块引入common模块
1
2
3
4
5
|
<dependency>
<groupId>org.eh</groupId>
<artifactId>cloud-common</artifactId>
<version>${project.version}</version>
</dependency>
|
-
再次测试
至此,springcloud微服务架构学习的准备工作完毕
完整示例地址