一、环境搭建 + 项目初始化
1、docker的安装和使用
docker run -p 3306:3306 --name mysql8.0 \
-v /mysqldata/mysql/log:/var/log/mysql \
-v /mysqldata/mysql/data:/var/lib/mysql \
-v /mysqldata/mysql/mysql-files:/var/lib/mysql-files \
-v /mysqldata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:8.0
参数说明:
-p 3306:3306 端口映射
-v 文件挂载到主机
-e -e MYSQL_ROOT_PASSWORD=root 初始化root 密码
-d 以后台方式运行
--------------------------
查看运行的
docker docker ps
docker ps -a
--------------------------
查看容器服务运行日志
docker logs -f id
docker container ls 正在运行的容器
-v /mysqldata/mysql/mysql-files(机器):
/var/lib/mysql-files \(容器内部安装mysql地址)docker exec -it id /bin/bash
update user set host='%' where user='root';
flush privileges;
Grant all privileges on *.* to 'root'@'%';
flush privileges;
ALTER USER 'root'@'%' IDENTIFIED BY '123456';
flush privileges;
----------------------------
whereis mysql
---------------redis----------------------
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf
docker run -p 6379:6379 --name redis7.0
-v /mydata/redis/data:/mydata/redis/data
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf
-d redis:7.0 redis-server /etc/redis/redis.conf
持久化 appendonly yes
docker exec -it redis7.0 redis-cli
2、开启启动
sudo systemctl enable docker
3、逆向生成项目
1、application、
扫描包、
2、创建微服务项目
1、逆向生成
2、创建微服务项目
3、项目依赖
4、解决包、类、依赖问题
3、服务架构
1、服务注册中心nacos
1、下载并安装nacos
修改解压文件中的配置文件指定数据库
配置集群模式
项目中增加配置中心、增加注解开启配置中心
开启注册于发现:@EnableDiscoveryClient
2、配置中心
1、bootstrap.properties
2、增加注解:
@RefreshScope:动态获取并刷新配置
@Value("${配置项的名}"):获取到配置。
3、创建各自的命名空间、配置集、配置分组,并写入配置文件【重要、重要】
配置好、开发、测试、生产、等【重要、重要】
2、网关:springcloud-gateway(api网管 webflux 模式)
1、开启注册与发现: @EnableDiscoveryClient
2、负载均衡:springclod-rabbon
3、声明式http: openFeign
4、服务容错: springcloud alibaba-sentinel(降级、限流、熔断)
5、
6、调用链监控: springcloud-sleuth
7、springcloud alibaba-seata: 分步式事务解决方案
------------------------
4、nacos
1、命名空间==> 配置集==> 配置群组==> 配置
2、修改bootstrap+ 增加动态注解
2-1、 **bootstrap.yml**
2-2、配置注入到项目中
@ConfigurationProperties 注入,自动刷新
@RefreshScope ==>刷新@Value
3、介绍:
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
5、配置路由gateway
1、页面
1、全局路由路径
index.js 中修改路径为网管路径
2、后台
1、pom + 开启nacos +
2、路由增加服务地址配置id
3、跨域: nginx 、 配置
Access-Control-Allow-Origin 那些来源的请求跨域
Access-Control-Allow-Methods
Access-Control-Allow-Credentials 跨域请求默认不包含cookies 设置为true 可以办函cookies
Access-Control-Expose-Headers 跨域请求暴露手段
CORS请求时:
XMLHttpRequest对象的getTesponseHeader()方法只能拿到6个基本字段:
Cache-Control 、Content-Language、Content-type、Expires、Last-Modified、Pragma
如果想获取其他字段、必须在Access-Control-Expose-Headers 里面指定
Access-Control-Max-Age:该响应的有效时间多少秒,有效时间内,浏览器无需为同一请求再次发送,
注意:浏览器本身维护了一个最大有效时间,如果超过了这个最大时间,则配置无效
4、取消2次请求:取消人人服务的跨域
yml
spring:
datasource:
username: root
password:
url: jdbc:mysql://192.168.56.10:3306/gulimall_pms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-product
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
# logic-delete-field: showStatus # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
# logic-delete-value: 1 # 逻辑已删除值(默认为 1)
# logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
server:
port: 12000
# 日志打印
logging:
level:
com.atguigu.gulimall: debug
bootstrap.properties
spring.application.name=gulimall-product
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=800ccb4c-ae4d-46c6-83b5-58930dc1ab3f
二 服务开发
1、配置
1、nocas
application.yml
bootstrap.properties
2、开启注解
@RefreshScope
@MapperScan("com.atguigu.gulimall.product.dao")
@SpringBootApplication
@EnableDiscoveryClient
3、gataway
spring:
cloud:
gateway:
routes:
- id: test_route
uri: https://www.baidu.com
predicates:
- Query=url,baidu
- id: qq_route
uri: https://www.qq.com
predicates:
- Query=url,qq
- id: product_rotue
uri: lb://gulimall-product
predicates:
- Path=/api/product/**
filters:
- RewritePath=/api/product/(?<segment>/?.*), /product/$\{segment}
- id: third_party_rotue
uri: lb://gulimall-third-party
predicates:
- Path=/api/thirdparty/**
filters:
- RewritePath=/api/thirdparty/(?<segment>/?.*), /$\{segment}
## 规则: 前端项目调用路由 都带 /api
## http://localhost:88/api/captcha.jpg ==》 http://renren-fast:8080/api/captcha.jpg 真正地址: http://renren-fast:8080/项目名/captcha.jpg
## 不精确 路由放后面
- id: admin_route
uri: lb://renren-fast
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>/?.*), /renren-fast/$\{segment}
4、异常统一管理
@Slf4j
@RestControllerAdvice("com.atguigu.gulimall.product.controller")
public class ControllerExceprionAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error("数据校验出现问题: {} , 异常类型 = {}", e.getMessage(), e.getClass());
BindingResult bindingResult = e.getBindingResult();
Map<String,Object> errorMap = new HashMap<>();
bindingResult.getFieldErrors().forEach(restlt ->{
errorMap.put(restlt.getField(),restlt.getDefaultMessage());
});
return R.error(BizCodeEnume.VAILD_EXCEPTION.getCode(),BizCodeEnume.VAILD_EXCEPTION.getMsg()).put("data",errorMap);
}
@ExceptionHandler(value = Throwable.class)
public R handleVaildException(Throwable e) {
log.error("系统异常",e);
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(),BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}
5、js303
1、注解配置
@NotNull(message = "品牌id不能为空",groups = {UpdateGroup.class})
@Null(message = "品牌新增不能指定id",groups = {AddGroup.class})
@RequestMapping("/update")
public R update(@Validated({UpdateGroup.class})@RequestBody BrandEntity brand) {
brandService.updateById(brand);
return R.ok();
}
2、自定义校验器
@Documented
@Constraint(
// 建立指定关系 validatedBy
validatedBy = {ListValueConstraintValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
String message() default "{com.atguigu.common.validator.ListValue.message}";// 全类名
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int[] vals() default {};
}