SpringCloudAlibaba微服务架构实战
#
# 前言
感慨一波
某个瞬间 感觉自己就像个土狗一样 什么iNode EasyConnet 也没听过 更不知道怎么用 之前学的SpringCloud也全还回去了 所以也算是给自己定个目标吧 重学下SpringCloud 顺便 备战软考
加油吧
这是朋友推荐的一个课程 感觉挺傻瓜教程的 顺便学的时候摘抄记录下吧 以后再忘了 也算整合资源了 因为比较细 很多内容其实也不是和Cloud很相关 选择性观看吧
# 学前引导
内容太偏于文字 还在整理中
# 1. 电商工程的第一行代码
首先创建
e-commerce-springcloud
项目作为电商工程父目录 为了方便后续pom
文件的引入 建议使用同项目名称设置 剩余其他模块全使用moudle
父目录不需要保留src目录
<modelVersion>4.0.0</modelVersion>
<groupId>com.imooc.ecommerce</groupId>
<artifactId>ecommerce-springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>e-commerce-common</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>
<properties>
<!-- Spring Cloud Hoxton.SR8 依赖 -->
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<!-- spring cloud alibaba 依赖 -->
<spring-cloud-alibaba.version>2.2.4.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!-- lombok 工具通过在代码编译时期动态的将注解替换为具体的代码,
IDEA 需要添加 lombok 插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.0</version>
</dependency>
<!-- 引入jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<!-- 项目依赖管理 父项目只是声明依赖,子项目需要写明需要的依赖(可以省略版本信息) -->
<dependencyManagement>
<dependencies>
<!-- spring cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 配置远程仓库 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 1.1 配置基础模块 e-commerce-common
通用模块 未引入 web
模块创建完成之后 查看在父目录的pom
中是否引入了当前module
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.imooc.ecommerce</groupId>
<artifactId>ecommerce-springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>e-commerce-common</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 模块名及描述信息 -->
<name>e-commerce-common</name>
<description>通用模块</description>
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.1.1 创建CommonResponse
封装通用响应对象
com.imooc.ecommerce.vo
package com.imooc.ecommerce.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 通用响应对象定义
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResponse<T> implements Serializable {
// 错误码
private Integer code;
// 错误消息
private String message;
// 泛型响应数据
private T data;
// 自定义无响应数据构造器
public CommonResponse(Integer code, String message) {
this.code = code;
this.message = message;
}
}
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
# 1.2 配置基础模块 e-commerce-mvc-config
通用配置模块 已引入 web
<parent>
<artifactId>ecommerce-springcloud</artifactId>
<groupId>com.imooc.ecommerce</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>e-commerce-mvc-config</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 模块名及描述信息 -->
<name>e-commerce-mvc-config</name>
<description>通用配置模块</description>
<dependencies>
<!-- 引入 Web 功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.imooc.ecommerce</groupId>
<artifactId>e-commerce-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
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
# 1.2.1 忽略统一响应注解定义
IgnoreResponseAdvice 注解类
com.imooc.ecommerce.annotation
当我们对某些响应想做些单独的处理 就可以通过自定义注解
package com.imooc.ecommerce.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略统一响应注解定义
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreResponseAdvice {
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.2.2 实现统一响应
CommonResponseDataAdvice
com.imooc.ecommerce.advice
package com.imooc.ecommerce.advice;
import com.imooc.ecommerce.annotation.IgnoreResponseAdvice;
import com.imooc.ecommerce.vo.CommonResponse;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
* 实现统一响应
*/
@RestControllerAdvice(value = "com.imooc.ecommerce")
public class CommonResponseDataAdvice implements ResponseBodyAdvice<Object> {
/**
* 判断是否需要对响应进行处理
*
* @param methodParameter
* @param aClass
* @return
*/
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseAdvice.class)) {
return false;
}
if (methodParameter.getMethod().isAnnotationPresent(IgnoreResponseAdvice.class)) {
return false;
}
return true;
}
@Override
// 屏蔽警告信息
@SuppressWarnings("all")
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
//定义最终的返回对象
CommonResponse<Object> response = new CommonResponse<>(0, "");
if (null == o) {
return response;
} else if (o instanceof CommonResponse) {
response = (CommonResponse<Object>) o;
} else {
response.setData(o);
}
return response;
}
}
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
# 1.2.3 全局异常捕获处理
GlobalExceptionAdvice
com.imooc.ecommerce.advice
package com.imooc.ecommerce.advice;
import com.imooc.ecommerce.vo.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
/**
* 全局异常捕获处理
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {
@ExceptionHandler(value = Exception.class)
public CommonResponse<String> handlerCommerceException(
HttpServletRequest request, Exception exception
) {
CommonResponse<String> response = new CommonResponse<>(
-1, "business error"
);
response.setData(exception.getMessage());
log.error("commerce service has error: [{}]",exception.getMessage(), exception);
return response;
}
}
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
# 2. AlibabaNacos
# 2.1 创建多个Nacos服务
集群模式 复制多个nacos 修改启动端口号 添加配置文件
cluster.conf
将集群内的nacos端口号 全部复制进去 格式 IP:端口号
分别启动nacos 在某一个nacos中查看集群管理 节点列表 可以查看到其他端口号下的nacos服务
# 2.2 服务注册与发现
# 2.2.1 新模块创建 e-commerce-alibaba-nacos-client
::: nacos client 创建对应的启动类 添加resource下的bootstrap.yml配置文件 :::
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ecommerce-springcloud</artifactId>
<groupId>com.imooc.ecommerce</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>e-commerce-alibaba-nacos-client</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!-- 模块名及描述信息 -->
<name>e-commerce-alibaba-nacos-client</name>
<description>Nacos Client</description>
<dependencies>
<!-- spring cloud alibaba nacos discovery 依赖 -->
<!-- 服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.imooc.ecommerce</groupId>
<artifactId>e-commerce-mvc-config</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 数据绑定 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- nacos config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- zipkin = spring-cloud-starter-sleuth + spring-cloud-sleuth-zipkin-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-zipkin</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
<!-- Ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<!-- open feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- feign 替换 JDK 默认的 URLConnection 为 okhttp -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<!-- 使用原生的 Feign Api 做的自定义配置, encoder 和 decoder -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>11.0</version>
</dependency>
<!-- 集成 hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
<!--
SpringBoot的Maven插件, 能够以Maven的方式为应用提供SpringBoot的支持,可以将
SpringBoot应用打包为可执行的jar或war文件, 然后以通常的方式运行SpringBoot应用
-->
<build>
<finalName>${artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- 配置远程仓库 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
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
98
99
100
101
102
103
104
105
106
107
108
109
server:
port: 8000
servlet:
context-path: /ecommerce-nacos-client
spring:
application:
name: e-commerce-nacos-client # 应用名称也是构成 Nacos 配置管理 dataId 字段的一部分 (当 config.prefix 为空时)
cloud:
nacos:
# 服务注册发现
discovery:
enabled: true # 如果不想使用 Nacos 进行服务注册和发现, 设置为 false 即可
server-addr: 127.0.0.1:8848
# server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850 # 集群下Nacos 服务器地址
namespace: 1bc13fd5-843b-4ac0-aa55-695c25bc0ac6
# 暴露端点
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
然后我们只需要启动服务 进入到nacos管理界面 在对应的命名空间下找到服务列表 查看服务是否成功进行注册
# 2.2.2 服务的发现
::: NacosClientService
创建NacosClientService
作为服务类 进行服务发现的接口
再通过NacosClientController
进行调用 实现服务的发现
:::
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class NacosClientService {
private final DiscoveryClient discoveryClient;
public NacosClientService(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
// 参数serviceId: 服务注册的名称
public List<ServiceInstance> getNacosClientInfo(String serviceId) {
log.info("request nacos client to get service instance info: [{}]", serviceId);
return discoveryClient.getInstances(serviceId);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24