springcloud
springcloud
MyBatis-Plus
增强了mybatis,类似与C++对c
依赖引入
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.10.1</version> </dependency>
增强点
自带一些常见的方法,如一些查询操作
只需要继承plus提供的BaseMapper就行,因为人家写好了常见的操作
@Mapper public interface UserMapper extends BaseMapper<User> { }
常用的注解:
TableName
,TableId
,TableField
@TableName("user") public class User { @TableId(value = "id", type = IdType.ASSIGN_ID) private Long id; @TableField("user_name") private String name; }
- TableName:标注表名,当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,您需要使用这个注解来明确指定表名
- TableId:标注主键, value:字段名, type:主键的填充方式,自己填,还是自增啥的
- TableField:可以指定表中普通字段名,对于不一致的时候可以这样指定,省去了人工映射步骤
常见的yaml配置
mybatis-plus: configuration: # 配置日志输出在控制台,这个就可以显示出sql语句 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath*:mapper/*.xml # 扫描的mapper文件
核心功能
我感觉可以看作生成条件sql语句的类
自定义sql语句
<update id="update"> update user set name = #{name} where id = #{id} where id in <foreach collection="list" item="item" separator="," open="(" close=")"> #{item} </foreach> </update>
上面的就可以简化为下面的
List<Long> ids = List.of(1L, 2L, 3L); LambdaQueryWrapper <User> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(User::getId,ids);// 这样就相当于上面的那个forecah的sql语句 ---------------------------------------------- public interface UserMapper extends BaseMapper<User> { @Update("update user set name = .... where id in ${ew.customSqlSegment}") // 这样相当于把复杂的sql语句复制过来一样 void update(@Param("ew") Wrapper<User> wrapper); }
注意事项
- 版本要求:确保你的项目中使用的
mybatis-plus
版本至少为3.0.7
,以支持自定义 SQL 功能。 - 参数命名:在自定义 SQL 时,传递 Wrapper 对象作为参数时,参数名必须为
ew
,或者使用注解@Param(Constants.WRAPPER)
明确指定参数为 Wrapper 对象。 - 使用
${ew.customSqlSegment}
:在 SQL 语句中,使用${ew.customSqlSegment}
来引用 Wrapper 对象生成的 SQL 片段。 - 不支持基于 entity 的 where 语句:自定义 SQL 时,Wrapper 对象不会基于实体类自动生成 where 子句,你需要手动编写完整的 SQL 语句。
- 版本要求:确保你的项目中使用的
这跟mapper类似的,集成了常见的CRUD
public class UserService extends ServiceImpl<UserMapper, User>{ // 这样继承这个类就行了,实现了IService }
代码生成器
docker
docker run -d \ # 创建容器并运行
-v /home/html:/nginx/html
--name mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123 \
mysql
- -d:在后台运行
- --name:容器的名称
- -p:端口映射,宿主机端口:容器端口,宿主机同一个端口只能有一个映射,也就是可以3306:3306,3307:3306,宿主机不能出现多个3306:
- -e:环境设置
- -v: 数据卷:容器内数据卷 ,映射数据卷到容器内,访问该目录相当于访问容器对应的目录
- mysq:镜像的名称,在镜像仓库的名称
常见命令
- docker pull 从仓库拉取镜像
- docker images 查看存在的镜像
- docker ps 查看运行容器的进程
- docker exec -it nginx bash 进入nginx容器的bash终端
- docker rm 容器名 删除容器
- docker volume -option 数据卷之类的操作
- docker inspect 容器名 查看容器的详细信息
Dockerfile
创建镜像的文件,也就是可以根据需要去构建自定义的镜像
docker build -t nginx1
这样就能构建名为镜像nginx1的自定义镜像
容器网络互联
就是可以让容器之间进行数据连接
加入自定义网络后,两个容器可以直接通过容器名互联,相当于容器名代替了ip地址
- docker network create 创建网络
- ~ ls 查看网络
- ~ rm 删除网络
- ~ connect 将容器加入网络
DockerCompose
用于快速的定义一组相关联的容器,可用于多个容器的快速部署
微服务
服务治理
采用nacos作为中间件
三个角色
- 服务提供者:暴露服务接口,供其它业务调用
- 服务消费者:调用其他服务提供的接口
- 注册中心:(中间件)记录并监控各实例状态,推送服务变更信息
nacos:注册中心
服务注册
引入nacos的服务注册发现maven坐标
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
配置nacos服务注册发现
spring: cloud: nacos: server-addr: localhost:8848 # nacos服务地址
- 在启动nacos的时候,遇到了JAVA_HOME找不到,原因是路径不是设在bin,而是更外一层的目录 服务发现
还是需要上面的依赖以及配置
使用cloud的DiscoveryCilent去获取服务列表
使用RestTemplate作为请求类,去请求对应的uri
// 2.1 获取服务列表 List<ServiceInstance> instances = discoveryClient.getInstances("item-server"); // 如果无服务列表,直接返回 if (CollUtils.isEmpty(instances)){ return; } // 2.2 挑一个服务 ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size())); ResponseEntity<List<ItemDTO>> response = restTemplate.exchange( instance.getUri() + "/items?ids={ids}", HttpMethod.GET, new HttpEntity<>(null), new ParameterizedTypeReference<List<ItemDTO>>() { }, Map.of("ids", CollUtils.join(itemIds, ",")) ); // 2.3 解析响应 List<ItemDTO> items = response.getBody();
改用OpenFegin(使发送http请求更加简单,采用了mvc的风格)
- 引用依赖
<!-- OpenFeign依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- 负载均衡--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
通过@EnableFeignCilents注解启用OpenFeign功能
@SpringBootApplication @EnableFeignClients(basePackages = "com.hmall.api.client")// 启用OpenFeign功能 public class CartServiceApplication {//...}
- 当client不在扫描路径中时,需要这样配置扫描路径,或者指定对应的class,尤其是client定义在其他模块时,其包名是不同的
编写client类
@FeignClient("item-service") // 对应的服务名称 public interface ItemClient { @GetMapping("/items") // 对应的路径 List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids); }
实际调用
就像springmvc那样使用,直接替代了上面的复杂步骤,使用注解帮助你快速开发,实际的步骤和上面的差不多
List<ItemDTO> items = itemClient.queryItemByIds(itemIds);
优化,使用连接池,减少创建连接开销
feign: okhttp: # 启用okhttp连接池 enabled: true
启用日志
// 先定义这样的配置类 public class DefaultFeignConfig { @Bean public Logger.Level defaultLevel() { return Logger.Level.FULL; } }
局部设置日志等级
@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
全局设置日志等级
@EnableFeignClients(basePackages = "com.hmall.api.client", defaultConfiguration = DefaultFeignConfig.class)
网关
就是网络的关口,负责请求的路由、转发、身份校验
导入依赖
配置文件
spring: cloud: nacos: server-addr: localhost:8848 gateway: routes: - id: item-service # 这个是唯一标识,可以自定义 uri: lb://item-service # 服务的名称,就是每个服务的项目名 predicates: # 这是断言,判断请求路径是否匹配 - Path=/items/** # 下面就是匹配的路径 - id: cart-service uri: lb://cart-service predicates: - Path=/carts/**
路由断言
路由过滤器
示例用法:
网关登录校验
自定义过滤器
GatewayFilter:路由过滤器,默认不生效,需要配置到路由后生效
GlobalFilter:全局过滤器,作用于所有路由器,配置后自动生效
@Component public class MyGlobaFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); // 执行一些逻辑 // 放行 chain.filter(exchange); } @Override public int getOrder() { return 0; // 值越小,越先执行 } }
- 实现Order,是为了把当前的过滤器放到更前面,更先执行
传递用户信息,即通过添加请求头
- 使用openfeign的配置类
配置管理
添加配置到nacos中,直接在web-ui中进行操作
拉取配置
引入依赖
<!-- nacos配置管理--> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>spring-cloud-starter-nacos-config</artifactId> </dependency> <!-- 读取bootstrap文件--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency>
新建bootstrap.yaml
spring: application: name: user-service profiles: dev clound: nacos: server-addr: localhost:8848 config: # 这部分就是去拉取配置,将其先读入上下文 file-extension: yaml # 文件名后缀 shared-configs: # 共享配置 - data-id: shared-jdbc.yaml - data-id: shared-log.yaml
- 默认为去拉取user-service-dev.yaml,也就是上面的name,profiles,file-extension
动态路由
服务保护
使用工具:sentinel
安装教程
引入依赖:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
配置文件
spring: cloud: sentinel: transport: port: 8719 dashboard: localhost:8080
如需客户端,需要下载对应的jar包,运行下面的命令
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar # 对应的参数需要修改
解决雪崩问题
- 方案:
- 请求限流:通过sentinel去限制QPS
- 线程隔离:也是可以通过sentinel去限制线程数
- 服务熔断:统计请求异常比例或慢调用比例,如果超过阈值则熔断该业务,也就是拦截接口的请求走写好的fallback逻辑
- 方案: