cloud Alibaba项目
架构演进
单体架构
- 统一在一个程序中 共享数据库和缓存,部署上线简单
- 缺点明显,代码耦合严重 牵一发而动全身
垂直架构
- 优点:服务,部署独立,水平扩展容易
- 缺点:搭建复杂,服务之间关系错综复杂,维护困难
SOA架构
- 开始有了分块的功能划分,但是还是通过一个总线,去调用各个服务节点
- 优点:提供了底层服务的统一路由,方便调用
- 缺点 : 实现难度较高,不同架构之间也有耦合
微服务架构
- 相比SOA,微服务的入口开始有了变化,不再是直接访问程序,而是通过网关来分派转发
- 通过过滤的请求会被转发到对应的微服务,每一个服务独立部,运行在不同的机器上,用rest或者http通信
认识领域驱动设计
优点,有入口鉴权,功能分布细化,性能卓越 缺点, 项目复杂难度,信息暴露,复杂链路等各种问题
对于领域驱动设计的理解
理解领域概念,学习领域知识,对领域建模
- 分析领域模型,推演实体,值对象,领域服务
- 找出聚合边界,降低服务耦合
- 为耦合配备储存仓库,数据持久化
- 实践DDD,并且不断的推到重构
经典分层架构
解读
- User Interface 用户接口层 接收用户指令,展示信息
- Appllcation 应用程序层
Controller
对外提供服务接口,对内调用领域层 - Domain 领域层,相当于是实体对象,领域模型 对应 数据库中的表
- infrastructure 基础设施层,为其他层提供基础通用的基础能力,通信能力和持久化机制
传统开发: 会在开始之前就设计好数据库的表,去实现需求,后面想要修改就会影响到功能甚至是整体结构 领域驱动设计: 初期关心的是业务,持久化只是为了业务设计后期的考虑
电商工程业务解读,微服务模块拆分
Tips 学习领域知识最好的方法就是参考和借鉴
简单理解图
微服务模块拆分
工程入口以及用户鉴权微服务
网关是微服务架构的唯一入口
这里是电商的门面
涉及到
- 权限鉴定
- 服务调用
- 限流等
主要功能服务模块
账户,商品,订单,物流
- 合理的微服务划分
- 尽可能让每一个服务减少依赖和与其他服务的交集,最好是没有交集
E-commerce开发
实现公共模块
步骤
创建项目 -->导入依赖–>编写配置
父工程创建e-commerce-springcloud
导入需要的对应依赖
<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.0modelVersion>
<groupId>com.hyc.ecommercegroupId>
<artifactId>e-commerce-springcloudartifactId>
<version>1.0-SNAPSHOTversion>
<modules>
<module>e-commerce-commonmodule>
<module>e-commerce-mvc-configmodule>
modules>
<packaging>pompackaging>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.1.RELEASEversion>
parent>
<properties>
<spring-cloud.version>Hoxton.SR8spring-cloud.version>
<spring-cloud-alibaba.version>2.2.4.RELEASEspring-cloud-alibaba.version>
properties>
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.18version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.11version>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-collections4artifactId>
<version>4.4version>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.6.0version>
dependency>
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwt-apiartifactId>
<version>0.10.5version>
dependency>
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwt-implartifactId>
<version>0.10.5version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwt-jacksonartifactId>
<version>0.10.5version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.47version>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring-cloud-alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<repositories>
<repository>
<id>spring-milestonesid>
<name>Spring Milestonesname>
<url>https://repo.spring.io/milestoneurl>
<snapshots>
<enabled>falseenabled>
snapshots>
repository>
repositories>
project>
公共子模块 公共库 commons
e-commerce-common
模块
依赖如下
代码语言:javascript复制<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>e-commerce-springcloudartifactId>
<groupId>com.hyc.ecommercegroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>e-commerce-commonartifactId>
<name>e-commerce-commonname>
<description>通用模块description>
project>
这么模块之后会放入很多的数据模型,来给功能服务模块使用,这里先创建并且统一响应,之后会有对应的数据模型加入其中
代码语言:javascript复制创建响应格式
/**
* @author : 冷环渊
* @date : 2021/12/2
* @context: 通用响应定义
* {
* "code":1
* "message":hyc
* "data":{}
* }
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResponse<T> implements Serializable {
//相应码
private Integer code;
//返回消息 信息描述
private String message;
public CommonResponse(Integer code, String message) {
this.code = code;
this.message = message;
}
//泛型内容数据
private T Data;
}
公共子模块 web统一返回与全局异常处理 e-commerce-mvc-config
e-commerce-mvc-config
这个模块主要是为了隔离功能,有的服务模块比如网关,不能有web依赖的启动,这样他导入commons就可以了,起到很好的服务对应功能隔离
依赖如下
代码语言:javascript复制<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>e-commerce-springcloudartifactId>
<groupId>com.hyc.ecommercegroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>e-commerce-mvc-configartifactId>
<name>e-commerce-mvc-configname>
<description>通用配置模块description>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.hyc.ecommercegroupId>
<artifactId>e-commerce-commonartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
project>
编写注解 IgnoreResponseAdvice
IgnoreResponseAdvice
忽略统一响应注解定义,就是不需要用我们定义的CommonsResponese的类使用这个注解就可以不使用
/**
* @author : 冷环渊
* @date : 2021/12/2
* @context:忽略统一响应注解定义
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreResponseAdvice {
}
实现统一响应和统一忽略响应注解
代码语言:javascript复制/**
* @author : 冷环渊
* @date : 2021/12/2
* @context: 实现统一响应和统一忽略响应注解
* @params : null
* @return : * @return : null
*/
@RestControllerAdvice(value = "com.hyc.ecommerce")
//实现响应体建议接口
public class CommonResponseDataAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter,
Class<? extends HttpMessageConverter<?>> aClass) {
//判断类上面有没有这个注解 IgnoreResponseAdvice
if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseAdvice.class)) {
return false;
}
//判断方法上有没有这个注解 IgnoreResponseAdvice
if (methodParameter.getMethod().isAnnotationPresent(IgnoreResponseAdvice.class)) {
return false;
}
//都没有的话 就代表要使用公共返回格式
return true;
}
//处理 如果是需要使用的话怎么用
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter,
MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest,
ServerHttpResponse serverHttpResponse) {
//定义最终的返回对象
CommonResponse<Object> response = new CommonResponse<>(0, "");
//如果等于null就代表没有 直接返回
if (o == null) {
return response;
//等于公共返回类型的 就把o转换成 公共返回 CommonResponse<>
} else if (o instanceof CommonResponse) {
response = (CommonResponse<Object>) o;
//如果都不是的话 那就是响应内容 设置响应data 为这个object
} else {
response.setData(o);
}
return response;
}
}
全局异常处理
GlobalExceptionAdvice
处理全局异常,只要出现了请求出现了异常给一个统一的返回结果
/**
* @author : 冷环渊
* @date : 2021/12/2
* @context:全局异常处理
* @params : null
* @return : * @return : null
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {
//这个注解的意思就是异常处理起,参数是你想要捕捉的异常
@ExceptionHandler(value = Exception.class)
public CommonResponse<String> handlerCommerceException(HttpServerRequest req, Exception ex) {
//初始化一个公共响应对象
CommonResponse<String> response = new CommonResponse<>(
-1, "business error"
);
//加入报错信息 到信息头
response.setData(ex.getMessage());
//控制后台打印报错日志 返回公共响应体 给调用方一个提示
log.error("commerce service has error:[{}]", ex.getMessage(), ex);
return response;
}
}