# okgomall
**Repository Path**: enjoycode10/okgomall
## Basic Information
- **Project Name**: okgomall
- **Description**: init okgomall
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-12
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# okgomall
### Nacos
如何使用Nacos作为配置中心统一管理配置
1)、引入依赖,
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
2)、创建一个bootstrap.properties。
spring.application.name=okgomall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
3)、需要给配置中心默认添加一个叫 数据集(Data Id)okgomall-coupon.properties。默认规则,应用名.properties
4)、给 应用名.properties 添加任何配置
5)、动态获取配置。
@RefreshScope:动态获取并刷新配置
@Value("${配置项的名}"):获取到配置。
如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的配置。
细节
1)、命名空间:配置隔离;
默认:public(保留空间);默认新增的所有配置都在public空间。
1、开发,测试,生产:利用命名空间来做环境隔离。
注意:在bootstrap.properties;配置上,需要使用哪个命名空间下的配置,
spring.cloud.nacos.config.namespace=9de62e44-cd2a-4a82-bf5c-95878bd5e871
2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
2)、配置集:所有的配置的集合
3)、配置集ID:类似文件名。
Data ID:类似文件名
4)、配置分组:
默认所有的配置集都属于:DEFAULT_GROUP;
1111,618,1212
项目中的使用:每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod
同时加载多个配置集
1)、微服务任何配置信息,任何配置文件都可以放在配置中心中
2)、只需要在bootstrap.properties说明加载配置中心中哪些配置文件即可
3)、@Value,@ConfigurationProperties。。。
以前SpringBoot任何方法从配置文件中获取值,都能使用。
配置中心有的优先使用配置中心中的,
### feign
想要远程调用别的服务
1)、引入open-feign
2)、编写一个接口,告诉SpringCloud这个接口需要调用远程服务
3) 、声明接口的每一个方法都是调用哪个远程服务的那个请求
4)、开启远程调用功能
### gateway
版本
spring-cloud.version=Hoxton.SR6, spring-boot.version=2.3.1.RELEASE
or
spring-cloud.versio n=Hoxton.SR6, spring-boot.version=2.2.1.RELEASE
+
io.projectreactor.netty
reactor-netty
0.9.4.RELEASE
### Validate
1、整合MyBatis-Plus
1)、导入依赖
com.baomidou
mybatis-plus-boot-starter
3.2.0
2)、配置
1、配置数据源;
1)、导入数据库的驱动。https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-versions.html
2)、在application.yml配置数据源相关信息
2、配置MyBatis-Plus;
1)、使用@MapperScan
2)、告诉MyBatis-Plus,sql映射文件位置
2、逻辑删除
1)、配置全局的逻辑删除规则(省略)
2)、配置逻辑删除的组件Bean(省略)
3)、给Bean加上逻辑删除注解@TableLogic
3、JSR303
1)、给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示
2)、开启校验功能@Valid
效果:校验错误以后会有默认的响应;
3)、给校验的bean后紧跟一个BindingResult,就可以获取到校验的结果
4)、分组校验(多场景的复杂校验)
1)、 @NotBlank(message = "品牌名必须提交",groups = {AddGroup.class,UpdateGroup.class})
给校验注解标注什么情况需要进行校验
2)、@Validated({AddGroup.class})
3)、默认没有指定分组的校验注解@NotBlank,在分组校验情况@Validated({AddGroup.class})下不生效,只会在@Validated生效;
5)、自定义校验
1)、编写一个自定义的校验注解
2)、编写一个自定义的校验器 ConstraintValidator
3)、关联自定义的校验器和自定义的校验注解
* @Documented
* @Constraint(validatedBy = { ListValueConstraintValidator.class【可以指定多个不同的校验器,适配不同类型的校验】 })
* @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
* @Retention(RUNTIME)
* public @interface ListValue {
4、统一的异常处理
@ControllerAdvice
1)、编写异常处理类,使用@ControllerAdvice。
2)、使用@ExceptionHandler标注方法可以处理的异常。
### SpringCache简化缓存开发
1). 引入依赖 spring-boot-starter-cache, spring-boot-starter-data-redis
2). 写配置
1. 自动配置了CacheAutoConfiguration会导入RedisCacheConfiguration
// 获取缓存类型
CacheConfigurations.getConfigurationClass(types[i]);
static {
Map> mappings = new EnumMap<>(CacheType.class);
mappings.put(CacheType.GENERIC, GenericCacheConfiguration.class);
mappings.put(CacheType.EHCACHE, EhCacheCacheConfiguration.class);
mappings.put(CacheType.HAZELCAST, HazelcastCacheConfiguration.class);
mappings.put(CacheType.INFINISPAN, InfinispanCacheConfiguration.class);
mappings.put(CacheType.JCACHE, JCacheCacheConfiguration.class);
mappings.put(CacheType.COUCHBASE, CouchbaseCacheConfiguration.class);
mappings.put(CacheType.REDIS, RedisCacheConfiguration.class);
mappings.put(CacheType.CAFFEINE, CaffeineCacheConfiguration.class);
mappings.put(CacheType.SIMPLE, SimpleCacheConfiguration.class);
mappings.put(CacheType.NONE, NoOpCacheConfiguration.class);
MAPPINGS = Collections.unmodifiableMap(mappings);
}
2. RedisCacheConfiguration 自动配好了缓存管理器 RedisCacheManager cacheManager():返回RedisCacheManager bean
3. cacheManager() 初始化缓存配置
4. 缓存配置:
spring.cache.type=redis
5. 测试使用缓存
@Cacheable: Triggers cache population.触发将数据保存到缓存的操作
代表当前的方法需要缓存,如果缓存中有,方法不调用执行;如果缓存中没有,会调用方法,并将结果放入缓存
每一个需要缓存的数据我们要指定缓存cacheNames或value, 即缓存的分区(按照业务类型分)
* 默认行为
* 如果缓存中有,方法不再调用
* key是默认生成的:缓存的名字::SimpleKey::[](自动生成key值)
* 缓存的value值,默认使用jdk序列化机制,将序列化的数据存到redis中
* TTL默认时间是 -1:
*
* 自定义操作:key的生成
* 指定生成缓存的key:key属性指定,接收一个SpEL,如果是一个字符串,用单引号
* 指定缓存的数据的存活时间:配置文档中修改存活时间,spring.cache.redis.time-to-live=3600000
* 将数据保存为json格式
@CacheEvict: Triggers cache eviction.触发将数据从缓存移除的操作
@CachePut: Updates the cache without interfering with the method execution.不影响方法执行更新缓存
@Caching: Regroups multiple cache operations to be applied on a method.组合以上多个操作
@CacheConfig: Shares some common cache-related settings at class-level.在类级别共享缓存的相同配置
1). 启动类开启缓存功能:@EnableCaching
2).
6. 原理
CacheAutoConfiguration -> RedisCacheConfiguration -> 自动配置了RedisCacheManager -> 初始化所有的缓存 -> 每个缓存决定使用什么配置 ->
如果 redisCacheConfiguration 有就用已有的,没有就用默认配置 -> 想修改缓存的配置,只需要给容器中存放一个 RedisCacheConfiguration 即可 ->
就会应用到当前RedisCacheManager管理的所有缓存分区中
7. Spring-Cache的不足
1)、读模式
缓存穿透:查询一个null数据。解决方案:缓存空数据。spring.cache.redis.cache-null-values=true
缓存击穿:大量并发进来同时查询一个正好过期的数据。解决方案:加锁 ? 默认是无加锁的;使用sync = true来解决击穿问题
缓存雪崩:大量的key同时过期。解决:加随机时间。加上过期时间。spring.cache.redis.time-to-live=3600000
2)、写模式:(缓存与数据库一致)
1)、读写加锁,适合读多写少的系统。
2)、引入Canal,感知到MySQL的更新去更新Redis
3)、读多写多,直接去数据库查询就行
总结:
常规数据(读多写少,即时性、一致性要求不高的数据,完全可以使用Spring-Cache):写模式(只要缓存的数据有过期时间就足够了)
特殊数据:特殊设计
原理:
CacheManager(RedisCacheManager)->Cache(RedisCache)->Cache负责缓存的读写
### ThreadLocal
同一个线程内共享数据:每一个http请求过来,Tomcat会开一个线程处理请求(从拦截器的执行,到调用controller,service,dao)直到请求结束给浏览器进行响应,从始至终都是同一个线程。
在同一个线程期间,ThreadLocal内的数据共享。
### RabbitMQ
1. 引入AMQP场景启动器,RabbitAutoConfiguration就会自动生效
org.springframework.boot
spring-boot-starter-amqp
2. 给容器中自动配置
CachingConnectionFactory
RabbitConnectionFactoryBean
RabbitTemplate
AmqpAdmin
RabbitMessagingTemplate
3. 所以属性都是配置在
@EnableConfigurationProperties(RabbitProperties.class)
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitProperties {}
4. 开启注解 @EnableRabbit
5. 监听消息:使用@RabbitListener(前提必须开启@EnableRabbit)
@RabbitListener 可以加在类和方法上:表明当前类种的方法可以接收多个队列中的多种消息
@RabbitHandler 只能加在方法上:根据消息体的类型来判断要执行哪个方法
### Seata控制分布式事务
1)、每一个微服务对应的数据库必须创建undo_Log
2)、安装事务协调器:seate-server https://github.com/seata/seata/releases
3)、整合
1、导入依赖 spring-cloud-starter-alibaba-seata seata-all:1.1.0
2、解压并启动seata-server:
registry.conf:注册中心配置
修改 registry : nacos
file.conf:配置文件
3、所有想要用到分布式事务的微服务使用seata DataSourceProxy 代理自己的数据源
4、每个微服务,都必须导入 registry.conf file.conf
vgroup_mapping.{application.name}-fescar-server-group = "default"
5、启动测试分布式事务
6、给分布式大事务的入口标注@GlobalTransactional
7、每一个远程的小事务用@Trabsactional
#### Sentinel
1. 整合
1)、导入依赖 spring-cloud-starter-alibaba-sentinel
2)、下载sentinel控制台
3)、配置 sentinel 控制台地址信息
4)、在控制台调整参数、【默认所有的流控规则保存在内存中,重启失效】
2、每一个微服务都导入 actuator :并配合 management.endpoints.web.exposure.include=*
3、自定义 sentinel 流控返回的数据
4、使用Sentinel来保护feign远程调用,熔断;
1)、调用方的熔断保护:feign.sentinel.enable=true
2)、调用方手动指定远程服务的降级策略。远程服务被降级处理。触发我们的熔断回调方法
3)、超大浏览的时候,必须牺牲一些远程服务。在服务的提供方(远程服务)指定降级策略;
提供方是在运行,但是不允许自己的业务逻辑,返回的是默认的降级数据(限流的数据)
5、自定义受保护的资源
1)、代码
try (Entry entry = SphU.entry("seckillSkus")) {
//业务逻辑
} catch(Exception e) {}
2)、基于注解
Windows 查看所有端口:netstat -ano
Windows 查看指定端口:netstat -ano|findstr 端口号
Windows 查看指定端口的进程:tasklist|findstr 进程号
#### 介绍
OKGO商城
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 码云特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)