SpringCloud微服务

发布于:2025-08-03 ⋅ 阅读:(10) ⋅ 点赞:(0)

微服务是一种软件架构风格,它是以专注于单一职责的很多小型项目为基础,组合出复杂的大型应用

MyBatisPlus

1 引入MyBatisPlus依赖 代替MyBatis依赖

2 自定义的Mapper继承MyBatisPlus提供的BaseMapper接口

继承的泛型是实体类

常用注解

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息

MP自动实现增删改查的原理:

1 类名驼峰转下划线作为表名

2 名为id的字段作为主键

3 变量名驼峰转下划线作为表的字段名

@TableName:用来指定表名

@TableId:用来指定表中的主键字段信息

    如果id是自增长,需要在该注解的后面加上(type=IdType.AUTO)

    如果不加就默认是assign_id   id为雪花算法生成

@TableField:用来指定表中的普通字段信息

使用@TableField的常见场景:

   成员变量名与数据库字段名不一致

   成员变量名以is开头,且是boolean值

   成员变量名与数据库关键字冲突

   成员变量不是数据库字段

常见配置

 核心功能

条件构造器

QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分

UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊才使用

尽量使用LambdaQueryWrapper和LambdaUpdateWrapper,避免硬编码

自定义SQL

利用MyBatisPlus的wrapper来构建复杂的where条件,然后自己定义SQL语句中剩下的部分

1 基于Wrapper构建where条件

2 在mapper方法参数中Param注解声明Wrapper变量名称,必须是ew

   ew也可以用Constants.WRAPPER代替

3 自定义SQL,并使用Wrapper条件

   $后面拼接的就是where条件的查询语句

Service接口

 

1 自定义Service接口实现IService接口

2 自定义Service实现类,实现自定义接口并继承ServiceImpl类

lambda方法

逻辑删除

逻辑删除就是基于代码逻辑模拟删除效果,但不会真正删除数据

1 在表中添加一个字段标记数据是否删除

2 在删除数据时把标记置为1

3 查询时只查询标记为0的数据

删除操作:update user set deleted = 1 where id = 1 and deleted = 0 ;

查询操作:select * from user where deleted = 0 ;  保证查询到的都是标记的未删除的数据

MyBatisPlus提供了逻辑删除的功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD语句,我们只需在aplication.yaml文件中配置逻辑删除的字段名称和值即可

枚举处理器

 解决进行枚举后数据库中的字段类型与实体类的字段类型不一致情况

1 进行枚举

@EnumValue注解保证把这两个字段往数据库中写

2 在applicayion.yml中配置全局枚举处理器

3 修改实体类中的字段类型

4 修改业务

5 注意VO的数据类型也需要修改,否则拷贝过去就不行了

JSON处理器

 取出数据库表中JSON类型的字段中的内容必须实现JSON格式和java对象的转换

1 定义“info”中的实体

2 将private  String  info ;字段类型进行修改

将String改为UserInfo

3 加上注解

 4 开启自动结果映射

5 将VO里面的字段类型改为UserInfo

分页插件

在配置类中注册MyBatisPlus的核心插件,同时添加分页插件

使用分页查询的API


@Configuration
public class MyBatisConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //1 设置分页查询插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setMaxLimit(1000L);
        //2 添加分页插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }
}

进行分页查询

通用分页实体 

返回值

1 创建分页查询实体

2 如果其他业务也想进行分页查询,就继承分页查询实体类并加上@EqualsAndHashCode(callSuper = true) 注解

 3 定义通用的分页查询返回值结果

    注意此处把总条数和总页数的返回值改为Long

 4 编写Controller层代码

5  在service层生成方法并实现

    5.1 构建分页查询条件

    5.2进行分页查询

通用分页实体与MP转换

 1 PageQuary类中进行修改

2 将数据进行封装 将数据从PO转为VO

 3 修改实现类代码

 Docker

快速构建、运行、管理应用的工具

利用Docker安装应用时,Docker会自动搜索并下载应用镜像

镜像不仅包含应用本身,还包含应用运行所需要的环境、配置、系统数据库。

镜像仓库:存储和管理镜像的平台          Docker官方维护了一个公共仓库:Docker  Hub

Docker会在运行镜像时创建一个隔离环境,称为容器

命令解读

docker run:创建并运行一个容器,-d是让容器在后台运行

--name mysql:给容器起个名字,必须唯一

-p 3306:3306:将宿主机端口映射到容器内端口

-e KEY=VALUE:设置环境变量

mysql:指定运行的镜像的名字

镜像命名规范:

镜像名称一般由两部分组成:[repository镜像名]:[tag镜像的版本]

在没有指定tag时,默认是latest,代表最新版本的镜像

常见命令

Docker最常见的命令就是操作镜像、容器的命令

数据卷(volume)挂载

数据卷是一个虚拟目录,是容器内目录宿主机目录之间映射的桥梁

数据卷可以实现容器内目录与宿主机目录的双向映射,可以不进入容器内目录就实现数据的修改

使用docker  volume  --help查看所用数据卷命令的操作

执行docker run命令时,使用 -v  数据卷:容器内目录  可以完成数据卷挂载

在创建容器时,如果挂载了数据卷且数据卷不存在,会自动创建数据卷

 本地目录挂载

需求:查看mysql容器,判断是否有数据卷挂载

           基于宿主机目录实现MySQL数据目录、配置文件、初始化脚本的挂载

自定义镜像

镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包

构建镜像的过程其实就是把上述文件打包的过程

镜像结构:

入口:镜像运行的入口,一般是程序启动的脚本和参数

层:添加安装包、依赖、配置等,每次操作都形成新的一层

基础镜像:应用依赖的系统函数、环境、配置、文件等

Dockerfile语法

Dockerfile就是一个文本文件,其中包含一个个的指令,用指令来说明要执行什么操作来构建镜像。将来Docker可以根据Doukerfile帮我们构建镜像。

常见指令:

当编写好了Dockerfile可以用下面命令来构建镜像

docker  build  -t  myImage:1.0   .

-t是给镜像起名,格式依然是repository:tag   不指定tag时,默认为latest

. :是指定Dockerfile所在目录,如果就在当前目录,则指定为“ .”   .前面是有一个空格的

网络

默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上:

 加入自定义网络的容器才可以通过容器名互相访问,Docker的网络操作命令如下:

项目部署步骤

后端:

1  把项目打包

2  把打包好的Jar包和Dockerfile放入MobaXterm

3  构建镜像 docker  build   -t  镜像名称

4  dis查看一下

5  启动容器  docker run -d --name 名称 -p 8080:8080 --network 网络名称 镜像名

6  docker  logs  -f  名称  查看启动日志

7  打开浏览器进行访问

前端+配置文件:

1  将html、配置文件挂载到容器内的html 

2  启动容器

3  浏览器进行访问

DockerCompose

通过一个单独的docker-compose.yml模板文件(YAML格式)来定义一组相关联的应用容器,帮我们实现多个相互关联的Docker容器的快速部署

相关命令

 微服务

 单体架构和微服务架构

单体架构:业务的所有功能集中在一个项目中开发,打包成一个包部署

 优点:架构简单  部署成本低

缺点:耦合度高

微服务架构:根据业务功能对系统进行拆分,每个业务模块作为独立项目开发

优点:降低服务耦合  有利于服务升级拓展

架构特征:

单一职责:微服务拆分力度小,每个服务对应唯一的业务能力,避免重复业务开发

面向服务:微服务对外暴露业务接口

自治:团队独立、技术独立、数据独立、部署独立

隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

微服务技术对比:

SpringCloud

 是目前国内使用最广泛的微服务架构

集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验

 微服务拆分

拆分原则

创业型项目:先采用单体架构,快速开发,快速试错。随着规模扩大,逐渐拆分

确定的大型项目:资金充足,目标明确,可以直接选择微服务架构,避免后续拆分的麻烦

要做到:

高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高

低耦合:每个微服务的功能要相对独立,尽量减少对其他微服务的依赖

拆分方式:

纵向拆分:按照业务模块来拆分

横向拆分:抽取公共服务,提高复用性

远程调用

RestTemplate工具可以方便的实现Http请求的发送

1  注入RestTemplate到Spring容器

2  发起远程调用

服务治理

注册中心原理

提供者与消费者

服务提供者:一次业务中,被其他微服务调用的服务(提供接口给其它微服务)

服务消费者:一次业务中,调用其他微服务的服务(调用其他微服务提供的接口)

注册中心:记录并监控微服务各实例状态,推送服务变更信息

每一个服务启动时都会向注册中心注册自己的服务信息,当消费者需要调用提供者的接口时,就会向注册中心发起请求,注册中心会将相应的信息发送给消费者。

同时,服务提供者会每隔30秒向注册中心发送心跳请求,报告健康状态,注册中心会更新记录信息,心跳不正常会被剔除,消费者就可以拉取到最新信息

Nacos注册中心

基于Docker来部署Nacos的注册中心,首先我们要准备MySQL数据库表,用来存储Nacos的数据。由于是Docker部署,所以大家需要将资料中的SQL文件导入到你Docker中的MySQL容器

其中的nacos/custom.env文件中,有一个MYSQL_SERVICE_HOST也就是mysql地址,需要修改为你自己的虚拟机IP地址:

然后,将课前资料中的nacos目录上传至虚拟机的/root目录。

进入root目录,然后执行下面的docker命令:

docker run -d \
 --name nacos \ 
--env-file ./nacos/custom.env \ 
-p 8848:8848 \
 -p 9848:9848 \ 
-p 9849:9849 \ 
--restart=always \ 
nacos/nacos-server:v2.1.0-slim

启动完成后,访问下面地址:http://192.168.150.101:8848/nacos/,注意将192.168.150.101替换为你自己的虚拟机IP地址。

首次访问会跳转到登录页,账号密码都是nacos

服务注册

步骤:

1  引入nacos discovery依赖

<!--nacos 服务注册发现--> 
<dependency> 
    <groupId>com.alibaba.cloud</groupId> 
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2  配置Nacos地址

 服务发现

消费者需要连接nacos以拉去和订购服务,因此服务发现的前两步与服务注册是一样的,后面再加上服务调用即可:

1  引入nacos discovery依赖

2  配置nacos地址

3  服务发现

OpenFeign

OpenFeign是一个声明式的http客户端,其作用就是基于SpringMVC的常见注解,优雅的实现http请求的发送

基本用法

OpenFeign已经被SpringCloud自动装配,实现方式:

1  引入依赖,包括OpenFeign和负载均衡组件SpringCloudBalance

<!--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>

2  通过@EnableFeignClients注解,启用OpenFile功能

3  编写FeignClient接口   不用实现

4  使用FeignClient,实现远程调用

连接池

 OpenFeign整合OKHttp的步骤:

1  引入依赖

<!--OK http 的依赖 -->
 <dependency>
     <groupId>io.github.openfeign</groupId> 
     <artifactId>feign-okhttp</artifactId>
 </dependency>

2  开启连接池功能

feign: 
   okhttp: 
     enabled: true # 开启OKHttp功能

最佳实践

避免重复定义xxxClient接口,避免重复编码

解决方案:

1  抽取到微服务之外的公共module

2  每个微服务自己抽取一个module

方案1抽取更加简单,工程结构也比较清晰,但缺点是整个项目耦合度偏高。

方案2抽取相对麻烦,工程结构相对更复杂,但服务之间耦合度降低。

由于item-service已经创建好,无法继续拆分,因此这里我们采用方案1.

hmall下定义一个新的module,命名为hm-api

其依赖如下:

<?xml version="1.0" encoding="UTF-8"?>

<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>hmall</artifactId>

     <groupId>com.heima</groupId>

     <version>1.0.0</version>

   </parent>

   <modelVersion>4.0.0</modelVersion>

   <artifactId>hm-api</artifactId>

   <properties>

      <maven.compiler.source>11</maven.compiler.source>                      <maven.compiler.target>11</maven.compiler.target>

   </properties>

   <dependencies>

      <!--open feign-->

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-openfeign</artifactId>

      </dependency>

      <!-- load balancer-->

      <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-loadbalancer</artifactId>

      </dependency>

      <!-- swagger 注解依赖 -->

      <dependency>

        <groupId>io.swagger</groupId>

        <artifactId>swagger-annotations</artifactId>

        <version>1.6.6</version>

        <scope>compile</scope>

      </dependency>

   </dependencies>

</project>

日志

OpenFeign只会在FeignClient所在包的日志级别为debug时才会输出日志

四个日志级别:

NONE:不记录任何日志信息,这是默认值

BASIC:仅记录请求的方法,URL以及响应状态码和执行时间

HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息

FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据

自定义日志级别:

1  声明一个类型为Logger.Level的Bean,在其中定义日志级别

2  此时Bean并未生效,要想配置某个FeignClient的日志,可以在@FeignClient注解中声明

3  如果要全局配置,让所有FeignClient都按照这个日志配置,则需要在@EnableFeignClients注解中声明

网关

 就是网络的关口,负责请求的路由、转发、身份校验

在SpringCloud中网关的实现包括两种:Spring Cloud Gateway和Netfilx  Zuul

1  创建新模块

2  引入网关依赖

<?xml version="1.0" encoding="UTF-8"?>
<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>hmall</artifactId>
        <groupId>com.heima</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hm-gateway</artifactId>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <!--common-->
        <dependency>
            <groupId>com.heima</groupId>
            <artifactId>hm-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!--网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--nacos discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3  编写启动类

4  配置路由规则

server:
  port: 8080
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: 192.168.150.101:8848
    gateway:
      routes:
        - id: item # 路由规则id,自定义,唯一
          uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表
          predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务
            - Path=/items/**,/search/** # 这里是以请求路径作为判断规则
        - id: cart
          uri: lb://cart-service
          predicates:
            - Path=/carts/**
        - id: user
          uri: lb://user-service
          predicates:
            - Path=/users/**,/addresses/**
        - id: trade
          uri: lb://trade-service
          predicates:
            - Path=/orders/**
        - id: pay
          uri: lb://pay-service
          predicates:
            - Path=/pay-orders/**

 路由属性

路由断言

路由过滤器

网关登录校验

自定义过滤器

网关过滤器有两种:

GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效

GlobalFilter:全局过滤器,作用范围是所有路由,声明后自动失效

自定义GlobalFilter直接实现GlobalFilter接口即可:

实现登录校验

package com.hmall.gateway.filters;

import cn.hutool.core.text.AntPathMatcher;
import com.hmall.common.exception.UnauthorizedException;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.utils.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter , Ordered {

    private final AuthProperties authProperties;
    private final JwtTool jwtTool;
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1 获取request
        ServerHttpRequest request = exchange.getRequest();
        //2 判断是否需要做登录拦截
        if (isExclude(request.getPath().toString())){
            //放行
            return chain.filter(exchange);
        }
        //3 获取token
        String token = null;
        List<String> headers = request.getHeaders().get("authorization");
        if (headers!=null&!headers.isEmpty()){
            token = headers.get(0);
        }
        //校验并解析token
        Long userId = null;
        try{
             userId = jwtTool.parseToken(token);
        }catch (UnauthorizedException e ){
            //拦截,设置响应状态吗为401
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //TODO 5 传递用户信息

        //6 放行
        return chain.filter(exchange);
    }

    private boolean isExclude(String path) {
        for (String pathPattern : authProperties.getExcludePaths()) {
           if ( antPathMatcher.match(pathPattern,path)){
               return true;
           }
        }
        return false;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

网关传递用户

1  基于实现登录校验 

2   

package com.hmall.common.config;

import com.hmall.common.interceptors.UserInfoInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@ConditionalOnClass(DispatcherServlet.class)
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new UserInfoInterceptor());
    }
}

3  让2能被扫描到 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.hmall.common.config.MyBatisConfig,\
  com.hmall.common.config.MvcConfig,\
  com.hmall.common.config.JsonConfig

OpenFeign传递用户

下单的过程中,需要调用商品服务扣减库存,调用购物车服务清理用户购物车。而清理购物车时必须知道当前登录的用户身份。但是,订单服务调用购物车时并没有传递用户信息,购物车服务无法知道当前用户是谁!

由于微服务获取用户信息是通过拦截器在请求头中读取,因此要想实现微服务之间的用户信息传递,就必须在微服务发起调用时把用户信息存入请求头

微服务之间调用是基于OpenFeign来实现的,并不是我们自己发送的请求。我们如何才能让每一个由OpenFeign发起的请求自动携带登录用户信息呢?

这里要借助Feign中提供的一个拦截器接口:feign.RequestInterceptor

public interface RequestInterceptor { 
/** * Called for every request. 
    * Add data using methods on the supplied {@link RequestTemplate}. 
    */ 
    void apply(RequestTemplate template);
 } 

我们只需要实现这个接口,然后实现apply方法,利用RequestTemplate类来添加请求头,将用户信息保存到请求头中。这样以来,每次OpenFeign发起请求的时候都会调用该方法,传递用户信息。

由于FeignClient全部都是在hm-api模块,因此我们在hm-api模块的com.hmall.api.config.DefaultFeignConfig中编写这个拦截器:

 在com.hmall.api.config.DefaultFeignConfig中添加一个Bean:

@Bean
public RequestInterceptor userInfoRequestInterceptor(){
    return new RequestInterceptor() {
        @Override
        public void apply(RequestTemplate template) {
            // 获取登录用户
            Long userId = UserContext.getUser();
            if(userId == null) {
                // 如果为空则直接跳过
                return;
            }
            // 如果不为空则放入请求头中,传递给下游微服务
            template.header("user-info", userId.toString());
        }
    };
}

配置管理

微服务重复配置过多,维护成本高

业务配置经常变动,每次修改都要重启服务

网关路由写死,如果变更需要重启网关

配置共享

我们可以把微服务共享的配置抽取到Nacos中统一管理,这样就不需要每个微服务都重复配置了。分为两步:

1  在Nacos中添加共享配置

以cart-service为例,我们看看有哪些配置是重复的,可以抽取的:

首先是jdbc相关配置:

然后是日志配置:

 然后是swagger以及OpenFeign的配置:

我们在nacos控制台分别添加这些配置。

首先是jdbc相关配置,在配置管理->配置列表中点击+新建一个配置:

在弹出的表单中填写信息:

其中详细的配置如下:

spring:
  datasource:
    url: jdbc:mysql://${hm.db.host:192.168.150.101}:${hm.db.port:3306}/${hm.db.database}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: ${hm.db.un:root}
    password: ${hm.db.pw:123}
mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
  global-config:
    db-config:
      update-strategy: not_null
      id-type: auto

注意这里的jdbc的相关参数并没有写死,例如:

  • 数据库ip:通过${hm.db.host:192.168.150.101}配置了默认值为192.168.150.101,同时允许通过${hm.db.host}来覆盖默认值

  • 数据库端口:通过${hm.db.port:3306}配置了默认值为3306,同时允许通过${hm.db.port}来覆盖默认值

  • 数据库database:可以通过${hm.db.database}来设定,无默认值

然后是统一的日志配置,命名为shared-log.yaml,配置内容如下:

logging:
  level:
    com.hmall: debug
  pattern:
    dateformat: HH:mm:ss:SSS
  file:
    path: "logs/${spring.application.name}"

然后是统一的swagger配置,命名为shared-swagger.yaml,配置内容如下:

knife4j:
  enable: true
  openapi:
    title: ${hm.swagger.title:黑马商城接口文档}
    description: ${hm.swagger.description:黑马商城接口文档}
    email: ${hm.swagger.email:zhanghuyi@itcast.cn}
    concat: ${hm.swagger.concat:虎哥}
    url: https://www.itcast.cn
    version: v1.0.0
    group:
      default:
        group-name: default
        api-rule: package
        api-rule-resources:
          - ${hm.swagger.package}

注意,这里的swagger相关配置我们没有写死,例如:

  • title:接口文档标题,我们用了${hm.swagger.title}来代替,将来可以有用户手动指定

  • email:联系人邮箱,我们用了${hm.swagger.email:zhanghuyi@itcast.cn},默认值是zhanghuyi@itcast.cn,同时允许用户利用${hm.swagger.email}来覆盖。

2  微服务拉取配置

接下来,我们要在微服务拉取共享配置。将拉取到的共享配置与本地的application.yaml配置合并,完成项目上下文的初始化。

SpringCloud在初始化上下文的时候会先读取一个名为bootstrap.yaml(或者bootstrap.properties)的文件,如果我们将nacos地址配置到bootstrap.yaml中,那么在项目引导阶段就可以读取nacos中的配置了。

微服务整合Nacos配置管理的步骤如下:

1)引入依赖:

在cart-service模块引入依赖:

  <!--nacos配置管理-->
  <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  </dependency>
  <!--读取bootstrap文件-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
  </dependency>

2)新建bootstrap.yaml

在cart-service中的resources目录新建一个bootstrap.yaml文件:

内容如下:

spring:
  application:
    name: cart-service # 服务名称
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: 192.168.150.101 # nacos地址
      config:
        file-extension: yaml # 文件后缀名
        shared-configs: # 共享配置
          - dataId: shared-jdbc.yaml # 共享mybatis配置
          - dataId: shared-log.yaml # 共享日志配置
          - dataId: shared-swagger.yaml # 共享日志配置

3)修改application.yaml

由于一些配置挪到了bootstrap.yaml,因此application.yaml需要修改为:

server:
  port: 8082
feign:
  okhttp:
    enabled: true # 开启OKHttp连接池支持
hm:
  swagger:
    title: 购物车服务接口文档
    package: com.hmall.cart.controller
  db:
    database: hm-cart

配置热更新

动态路由