对boot项目拆分成cloud项目的笔记

news2024/11/16 1:53:58

引言:这里我用的是新版本的技术栈

spring-boot-starter-parent                        ==>3.2.5

mybatis-spring-boot-starter                      ==>3.0.3

mybatis-plus-boot-starter                         ==>3.5.5

spring-cloud-dependencies                     ==>2023.0.1

spring-cloud-alibaba-dependencies        ==>2022.0.0.0

nacos                                                       ==>v2.3.2-slim

笔记也可以参考黑马的笔记:Docs

下面这些是我自己拆分自己项目的过程及其笔记。

一、引入项目中关键依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
    </parent>

    <properties>
        <spring-cloud.version>2023.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
        <mybatis.spring>3.0.3</mybatis.spring>
        <mybatisPlus>3.5.5</mybatisPlus>
    </properties>


    <dependencyManagement>
        <dependencies>
            <!--mybatis的起步依赖-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring}</version>
            </dependency>
            <!--mybatisPlus的起步依赖-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatisPlus}</version>
            </dependency>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

二 、在docker中安装mysql和nacos

1、创建通用网络

这里hm-net是之前跟着黑马学习学习创建的 ,这里就也用这个网络

docker network create hm-net
2、安装mysql

在虚拟机的root目录下建一个mysql目录用于存放信息,也可以在随便的目录创建

在mysql目录里面创建三个包,conf,data和init,到时候创建mysql容器的时候自动挂载。init包主要放初始化的sql,让创建mysql的时候自动加载你需要的数据库信息,如果你是之后再创建也可以不在init包里面放信息,在conf包里面加载默认配置,文件名为xx.cnf,该文件的配置信息如下:

[client]
default_character_set=utf8mb4
[mysql]
default_character_set=utf8mb4
[mysqld]
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'

运行下面指令创建mysql容器。下面所有-v :左边都是你自己创建的包,:右边是系统中创建的位置,用自己创建的包进行挂载。

docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD=123 \
  -v /root/mysql/data:/var/lib/mysql \
  -v /root/mysql/conf:/etc/mysql/conf.d \
  -v /root/mysql/init:/docker-entrypoint-initdb.d \
  --network hm-net\
  mysql
3、安装nacos

可以参考我其他博客,里面也有介绍:学习springcloud中Nacos笔记-CSDN博客

用database连上虚拟机里面的mysql,运行下面sql:

/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
/******************************************/
/*   表名称 = config_info                  */
/******************************************/
CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) DEFAULT NULL COMMENT 'group_id',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL COMMENT 'configuration description',
  `c_use` varchar(64) DEFAULT NULL COMMENT 'configuration usage',
  `effect` varchar(64) DEFAULT NULL COMMENT '配置生效的描述',
  `type` varchar(64) DEFAULT NULL COMMENT '配置的类型',
  `c_schema` text COMMENT '配置的模式',
  `encrypted_data_key` text NOT NULL COMMENT '密钥',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
 
/******************************************/
/*   表名称 = config_info_aggr             */
/******************************************/
CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '内容',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
 
 
/******************************************/
/*   表名称 = config_info_beta             */
/******************************************/
CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `encrypted_data_key` text NOT NULL COMMENT '密钥',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
 
/******************************************/
/*   表名称 = config_info_tag              */
/******************************************/
CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
 
/******************************************/
/*   表名称 = config_tags_relation         */
/******************************************/
CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增长标识',
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
 
/******************************************/
/*   表名称 = group_capacity               */
/******************************************/
CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
 
/******************************************/
/*   表名称 = his_config_info              */
/******************************************/
CREATE TABLE `his_config_info` (
  `id` bigint(20) unsigned NOT NULL COMMENT 'id',
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增标识',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
  `op_type` char(10) DEFAULT NULL COMMENT 'operation type',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `encrypted_data_key` text NOT NULL COMMENT '密钥',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
 
 
/******************************************/
/*   表名称 = tenant_capacity              */
/******************************************/
CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
 
 
CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
 
CREATE TABLE `users` (
	`username` varchar(50) NOT NULL PRIMARY KEY COMMENT 'username',
	`password` varchar(500) NOT NULL COMMENT 'password',
	`enabled` boolean NOT NULL COMMENT 'enabled'
);
 
CREATE TABLE `roles` (
	`username` varchar(50) NOT NULL COMMENT 'username',
	`role` varchar(50) NOT NULL COMMENT 'role',
	UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
);
 
CREATE TABLE `permissions` (
    `role` varchar(50) NOT NULL COMMENT 'role',
    `resource` varchar(255) NOT NULL COMMENT 'resource',
    `action` varchar(8) NOT NULL COMMENT 'action',
    UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
);
 
INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
 
INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

配置nacos/custom.env文件,再将这个文件放在指定目录(root)下

PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=192.168.147.130
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=123
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
NACOS_AUTH_ENABLE=true
NACOS_AUTH_IDENTITY_KEY=nacos
NACOS_AUTH_IDENTITY_VALUE=nacos
NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789

拉取并安装nacos的镜像和容器

在本项目中我用的是nacos6这个名字,用于区分其他容器,端口也不一样,还要加载的配置文件也不一样,上面的配置文件可以参考我之前的博客。

docker run -d \
--name nacos6 \
--env-file ./nacos/quick-nacos.env \
-p 8868:8848 \
-p 9868:9848 \
-p 9869:9849 \
--restart=always \
nacos/nacos-server:v2.3.2-slim

用下面指令查看日志,最后面那个是容器名

docker logs -f nacos6

注意:这里需要注意,在新版本的nacos中,在java代码的配置里面需要加入nacos的用户名和密码,否则会报错。

spring:
  profiles:
    active: dev
  application:
    name: user-service #微服务名称
  cloud:
    nacos:
      server-addr: 192.168.147.130:8868
      username: nacos #用户名
      password: nacos #密码
4、一些常用的dockers指令

其中dps和dis可以去看看黑马的docker课,里面有自定义配置dps和dis,一般开机你都去停止那几个容器再去开启,因为有时候如果默认也是开启的,可能会存在一些bug,有时候你运行项目没事,有时候会出bug。所以你开虚拟机的时候顺便两个都停止再开启一边准没事。

docker start mysql
docker stop mysql
docker start nacos6
docker stop nacos6
dis
dps

三、拆分项目

1、原则

这里直接套用黑马的笔记,我用的是纵向拆分

明确了拆分目标,接下来就是拆分方式了。我们在做服务拆分时一般有两种方式:

  • 纵向拆分

  • 横向拆分

所谓纵向拆分,就是按照项目的功能模块来拆分。例如黑马商城中,就有用户管理功能、订单管理功能、购物车功能、商品管理功能、支付功能等。那么按照功能模块将他们拆分为一个个服务,就属于纵向拆分。这种拆分模式可以尽可能提高服务的内聚性。

横向拆分,是看各个功能模块之间有没有公共的业务部分,如果有将其抽取出来作为通用服务。例如用户登录是需要发送消息通知,记录风控数据,下单时也要发送短信,记录风控数据。因此消息发送、风控数据记录就是通用的业务功能,因此可以将他们分别抽取为公共服务:消息中心服务、风控管理服务。这样可以提高业务的复用性,避免重复开发。同时通用业务一般接口稳定性较强,也不会使服务之间过分耦合。

2、创建单一服务模块

新建模块,按你业务来起名,下面有三个模块是我已经拆分好的了,就是新建模块选好maven和自己jdk版本,起好名,点击ok即可。

给对应服务模块也要创建对应的数据库:

3、给模块引入依赖

这里注意一般业务模块的依赖都差不多,但是上面我抽取出来api模块和之前的common模块都是工具包,依赖会有所不同,下面我展示user-service和quick-api模块的依赖

 user-service:

<?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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.quick</groupId>
        <artifactId>quick-pickup</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>user-service</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.quick</groupId>
            <artifactId>quick-commen</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!--hutool工具包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>

        <!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-ui -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-ui</artifactId>
        </dependency>

        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--数据库-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>

        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>

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

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

        <!--OK http 的依赖 是发http请求的连接池,用于不同服务之间发起调用接口请求的连接池 -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
        </dependency>

        <!--api 这里放openFeign用到的接口,在这个api里面自定义接口,给各个服务调用-->
        <dependency>
            <groupId>com.quick</groupId>
            <artifactId>quick-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>


    </dependencies>


    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 quick-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">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.quick</groupId>
        <artifactId>quick-pickup</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>quick-api</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.quick</groupId>
            <artifactId>quick-commen</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

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

        <!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-ui -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-ui</artifactId>
        </dependency>

    </dependencies>



</project>
4、给每个服务做好配置文件

这里我只展示user-service

application.yml :

下面的一些配置需要看具体配置,其中的swagger我用的是swagger3,不同swagger配置不一样,swagger3可以参考我的一篇博客:SpringBoot3+支持Knife4j 4.0以上_knife4j-openapi3-jakarta-spring-boot-starter-CSDN博客

还有服务端口,服务名称,扫描的包等等需要按自己项目修改。

这里注意,新版本由于鉴权问题所以一定要加上nacos的用户名和密码

server:
  port: 8082 # 服务端口
spring:
  profiles:
    active: dev # 环境配置,dev开发环境,test测试环境,prod生产环境
  application:
    name: user-service #微服务名称
  cloud:
    nacos:
      server-addr: 192.168.147.130:8868 # nacos地址
      username: nacos #用户名
      password: nacos #密码
      discovery:
        group: QUICK_CLOUD # 配置服务注册分组
    openfeign:
      okhttp:
        enabled: true # 开启okhttp
  datasource:
      driver-class-name: ${quick.datasource.driver-class-name}
      url: jdbc:mysql://${quick.datasource.host}:${quick.datasource.port}/${quick.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
      username: ${quick.datasource.username}
      password: ${quick.datasource.password}

# springdoc-openapi项目配置
springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'C端用户接口'
      paths-to-match: '/**'
      packages-to-scan: com.quick.user.controller # 配置需要扫描的controller包路径
knife4j:
  enable: true
  setting:
    language: zh_cn

mybatis-plus:
  type-aliases-package: com.quick.user.domain.po # 配置实体类存放的包路径
  global-config:
    db-config:
      update-strategy: not_null
      id-type: auto #配置实体类中id默认自增
      logic-delete-field: deleted # 配置逻辑删除字段
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
    map-underscore-to-camel-case: true

logging:
  level:
    com:
      quick:
        user:
          mapper: debug
          service: info
          controller: info
quick:
  jwt:
    user-secret-key: quick
    user-ttl: 72000000
    user-token-name: authentication
  wechat:
    appid: ${quick.wechat.appid}
    secret: ${quick.wechat.secret}

下面是不同环境下的yml,如果你用的是dev就会用到application-dev.yml ,如果是local就是application-local.yml

application-dev.yml :

quick:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    host: 192.168.147.130 #虚拟机端口
    port: 3306
    database: quick-user #自己给自己对应服务建立的对应数据库
    username: #自己数据库用户名
    password: #自己数据库用户名

  wechat:

    #小程序:
    appid: #自己小程序的appid
    secret: #自己小程序的secret

application-local.yml :

quick:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    host: 192.168.147.130 #虚拟机端口
    port: 3306
    database: quick-user #自己给自己对应服务建立的对应数据库
    username: #自己数据库用户名
    password: #自己数据库用户名

  wechat:

    #小程序:
    appid: #自己小程序的appid
    secret: #自己小程序的secret

5、给每个服务创建对应的包

6、启动项目观察nacos

输入访问nacos地址:http://192.168.147.130:8868/nacos/ (路径工具自己配置)

可以看到成功注册上去。

四、用OpenFeign实现服务调用

1、引入依赖

(操作对象:服务模块,user-service等等)

在之前拆分项目的时候里面也有该依赖

  <!--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、在服务启动类启用OpenFeign

(操作对象:服务模块,user-service等等)

添加注解@EnableFeignClients,这个注解后面那个属性在后面再解释

@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@EnableCaching//开启缓存注解功能
@EnableScheduling//开启任务调度
@MapperScan("com.quick.user.mapper")
//basePackages标记FeignClients扫描的包,defaultConfiguration标记日志级别配置类使得对该模块全局生效
@EnableFeignClients(basePackages = "com.quick.api.client",defaultConfiguration = DefaultFeignConfig.class)
public class UserApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }

}
3、编写OpenFeign客户端

(操作对象:api模块,sky-api)

也可以在服务模块里面写,但是这样子多个服务都写有点臃肿,抽取出来更加方便各个服务调用,需要调用就引入api模块依赖即可

客户端针对性的写,比如user-service模块的服务需要调用到store-service服务,就写对应操作store-service服务的客户端。下面给出user-service服务用到的客户端

//调用同一个服务下的不同接口,用contextId区分
@FeignClient(contextId = "store", name = "store-service")
public interface StoreClient {

    //通过店铺id查询店铺所有信息
    @GetMapping("/user/store/{storeId}")
    @Operation(summary = "通过店铺id查询店铺所有信息")
    Result<Store> getByStoreId (@PathVariable Long storeId);

}
//调用同一个服务下的不同接口,用contextId区分
@FeignClient(contextId = "mark",name = "store-service")
public interface MarkClient {

    @GetMapping("/user/mark/getMarkListByUserId")
    @Operation(summary = "通过用户id查看用户对所有店铺的评分")
    Result<List<Mark>> getMarkListByUserId(@RequestParam("userId") Long userId);

}

由上面可见调用了两个客户端,在写客户端的时候需要在注解配置name,指定客户端调用的是哪个模块的接口,指定name为服务模块的服务名称,但是上面两个客户端都是store-service针对服务的客户端,如果写两个就会报错,所以需要区分两个客户端,所以得用contextId来区分。

 客户端里面的接口和对应模块的接口一致,下面给出对应一个的模块里面的controller接口和客户端比较

MarkController:

@RestController("userMarkController")
@RequestMapping("/user/mark")
@Tag(name = "C端-评分接口")
@Slf4j
@RequiredArgsConstructor
public class MarkController {

    @Resource
    private IMarkService markService;

    //通过用户id查看用户对所有店铺的评分
    @GetMapping("/getMarkListByUserId")
    @Operation(summary = "通过用户id查看用户对所有店铺的评分")
    public Result<List<Mark>> getMarkListByUserId(@RequestParam("userId") Long userId){

        QueryWrapper<Mark>queryWrapper=new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Mark::getUserId,userId);
        List<Mark> markList = markService.list(queryWrapper);
        return Result.success(markList);
    }

}

MarkClient:

//调用同一个服务下的不同接口,用contextId区分
@FeignClient(contextId = "mark",name = "store-service")
public interface MarkClient {

    @GetMapping("/user/mark/getMarkListByUserId")
    @Operation(summary = "通过用户id查看用户对所有店铺的评分")
    Result<List<Mark>> getMarkListByUserId(@RequestParam("userId") Long userId);

}

 上面可以看出,接口基本一致,但是在Client客户端里面要注意里面的路径信息必须完整,不能只复制异步的controller的一部分地址,要完整。

4、编写客户端用到的实体类

就是下面的dto。

5、给api模块加上日志配置

可能这个功能不算在OpenFeign里面,但是在api模块里面也顺便讲了

public class DefaultFeignConfig {

//    NONE:不记录任何日志信息,这是默认值。
//    BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
//    HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
//    FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

    //声明日志级别配置
    @Bean
    public Logger.Level feignLogLevel() {
        return Logger.Level.FULL;
    }

}

加上这个配置类后,在之前谈过的在启动类加上@EnableFeignClients注解里面有个属性就是是这个配置在那个服务里面生效。就是里面的defaultConfiguration属性,加上这个配置类的信息。

//basePackages标记FeignClients扫描的包,defaultConfiguration标记日志级别配置类使得对该模块全局生效
@EnableFeignClients(basePackages = "com.quick.api.client",defaultConfiguration = DefaultFeignConfig.class)

6、使用FeignClient

在需要用到别的服务的时候,用FeignClient里面自定义写好的接口。

用@RequiredArgsConstructor这个注解就能通过构造函数的方式对客户端接口的注入,导入也可以用@Resource或者@Autowired讲工厂里面的bean对象注入来使用

@Service
@Slf4j
@RequiredArgsConstructor 
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {

    private final MarkClient markClient;
    private final StoreClient storeClient;

}

在接口实现里面调用

        // 调用mark-service获取当前用户的所有评分
        List<Mark> markList = markClient.getMarkListByUserId(currentId).getData();
        log.info("当前用户的所有评分:{}",markList);
        // 同时查询相关的Store信息并设置到UserMarkVO中
        Store store =storeClient.getByStoreId(mark.getStoreId()).getData();
        log.info("store:{}",store);

这里面的实体对象都是api包下的实体,实现不耦合。

接口测试:

之前用的log日志打印也出现了,成功用Feign实现跨服务调用。

目前还没实现用网关去拦截等等操作,这些天在忙ddl,可能得过些天才继续更新,这也算自己做的笔记吧......

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1788942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JMeter Plugins Manager---插件安装

参考文章&#xff1a;https://blog.51cto.com/u_14126/6291032 需求&#xff1a; 安装【jpgc - Standard Set】插件 常用插件&#xff1a; 点击下载–报错如下&#xff1a; Failed to apply changes:Cannotapplychanges:Haveno write accessforJMeterdirectories,notpossib…

iTerm2 携手 OpenAI,带来命令行的自然语言革新

在技术不断进步的今天&#xff0c;命令行工具的智能化已成为提升效率的关键。iTerm2&#xff0c;macOS 系统上广受欢迎的开源终端工具&#xff0c;通过最新版本 v3.5 的发布&#xff0c;实现了与 OpenAI 的集成&#xff0c;引领了这一变革。 iTerm2 简介 iTerm2 是一款功能强…

宝塔部署vue+springboot过程(图文)

宝塔是傻瓜式操作部署&#xff0c;xshell是用linux命令部署 &#xffe5;过程&#xffe5; 整个流程具体服务器开端口在阿里云服务器打开3306端口&#xff08;有用到的端口都要打开&#xff09;宝塔&#xff1a;添加数据库获取数据库名、用户名、密码&#xff1b;点击“工具”…

容器化部署Pig微服务快速开发框架

系统说明 基于 Spring Cloud 、Spring Boot、 OAuth2 的 RBAC 企业快速开发平台&#xff0c; 同时支持微服务架构和单体架构 提供对 Spring Authorization Server 生产级实践&#xff0c;支持多种安全授权模式 提供对常见容器化方案支持 Kubernetes、Rancher2 、Kubesphere、E…

iotdb时序库在火电设备锅炉场景下的实践【原创文字,IoTDB社区可进行使用与传播】

一.概述 1.1 说明 本文章主要介绍iotdb数据库在电站锅炉工业场景下&#xff0c;对辅助智能分析与预警的使用介绍。 【原创文字&#xff0c;IoTDB社区可进行使用与传播】 1.2 项目背景 随着人工智能算法在电力领域的发展&#xff0c;以及燃煤锅炉设备精细化调整需求的增加&…

君方船舶智能设计平台技术架构

1.整体架构 2.基础能力 2.1 测试工具 2.1.1 测试框架 2.1.2 调试工具 2.2 UI交互 2.2.1 通用属性面板 2.2.2 对象通用拷贝框架 2.2.3 命令交互操作框架 2.2.4 夹点编辑框架 2.2.5 对象捕捉 2.3 模型管理 2.3.1 对象数据管理 2.3.2 对象空间关系管理 2.3.3 对象依赖关系管理…

发现情绪背后的真实心理需求,选择适合你的情绪调节方式

一、教程描述 心态对人的生活质量以及身体健康等多方面&#xff0c;都会产生非常重要的影响&#xff0c;受到不良情绪的影响&#xff0c;人的心态也会发生一定的变化。对于处于不良情绪状态的人来讲&#xff0c;应该重视学会调整自己的情绪。在心理学上&#xff0c;人的每种情…

AR和AP重分类(Regroup)[FAGLF101/OBBU/OBBV]

一、为什么AR和AP科目需要重分类 1.1 执行操作的前提(重要) 存在AR的当月总余额在贷方&#xff08;客户贷项凭证、预收账款等&#xff09;或AP的当月总余额在借方&#xff08;供应商贷项凭证、预收账款等&#xff09;&#xff0c;这种情况下无法真实的反映出资产和负债情况&…

Window10磁盘的分盘和合并

注意&#xff1a; 当我们c盘不够大需要扩大磁盘空间时&#xff0c;当c盘后面没有未划分的磁盘时候&#xff0c;我们是无法进行扩充c盘的&#xff0c;此时&#xff0c;我们可以先删除后面一个磁盘&#xff0c;再进行扩大。 如下&#xff1a;c盘后没有未分配的空间&#xff0c;…

MySQL—多表查询—多表关系介绍

一、引言 提到查询&#xff0c;我们想到之前学习的单表查询&#xff08;DQL语句&#xff09;。而这一章节部分的博客我们将要去学习和了解多表查询。 对于多表查询&#xff0c;主要从以下7个方面进行学习。 &#xff08;1&#xff09;第一部分&#xff1a;介绍 1、多表关系 2、…

SpringBoot之静态资源

默认静态资源路径 classpath:/META-INF/resources/classpath:/resources/classpath:/static/classpath:/public/ 静态资源路径下的文件&#xff0c;可以通过根目录访问 resources 文件夹的文件如下图所示&#xff1a; 启动项目&#xff0c;分别访问以下路径&#xff1a; ht…

关于URL获取的参数,无法执行二选一查询

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

0X JavaSE-- 集合框架【Collection(List、Set、Queue)、Map】

每一个集合类底层采用的数据结构不同&#xff0c;例如ArrayList集合底层采用了数组&#xff0c;LinkedList集合底层采用了双向链表&#xff0c;HashMap集合底层采用了哈希表&#xff0c;TreeMap集合底层采用了红黑树。**集合中存储的是引用。**即。集合中存放的是对象的地址&am…

【学习】DCMM认证提升企业竞争优势的表现

DCMM认证是企业提升数据管理能力的重要途径。它不仅可以帮助企业评估自身的数据管理水平&#xff0c;还可以为企业提供改进的方向和目标。在数字化时代&#xff0c;拥有强大的数据管理能力是企业成功的关键。因此&#xff0c;通过DCMM认证&#xff0c;企业可以更好地适应数字化…

【iOS】UI——关于UIAlertController类

目录 前言关于UIAlertController具体操作及代码实现总结 前言 在UI学习中&#xff0c;我们发现UIAlertView在iOS 9中已经被废弃&#xff0c;我们找到UIAlertController来代替UIAlertView实现弹出框的功能&#xff0c;从而有了这篇关于UIAlertController的学习笔记。 关于UIAle…

基于websocket与node搭建简易聊天室

一、前言 上一篇文章介绍了websocket的详细用法与工具类的封装&#xff0c;本篇就基于websocket搭建一个简易实时的聊天室。 在本篇开始之前也可以去回顾一下websocket详细用法&#xff1a;WebSocket详解与封装工具类 二、基于node搭建后台websocket服务 首先确认本机电脑中…

手机录屏怎么没有声音?一键排查,轻松解决!

“手机录屏怎么没有声音&#xff1f;今天录制了一个线上的音乐会&#xff0c;结束的时候发现完全没有声音&#xff0c;我检查了手机的设置&#xff0c;录屏功能看起来是正常的&#xff0c;但为什么就是录不到声音呢&#xff1f;希望大家能帮我解答这个疑惑。” 随着智能手机的…

linux上VirtualBox使用

前言 最近想把唯一的windows系统装成linux&#xff0c; 但是确实存在一些特殊软件无法舍弃&#xff0c;所有装完linux需要用虚拟机装个windows 上来使用特定的一些软件&#xff08;不想用wine了&#xff09;。 还有对一些特定usb设备的透传&#xff0c;这样才能保证在虚拟机中…

数据库开发-Mysql03

目录 1. 多表查询 1.1 概述 1.1.1 数据准备 1.1.2 介绍 1.1.3 分类 1.2 内连接 1.3 外连接 1.4 子查询 1.4.1 介绍 1.4.2 标量子查询 1.4.3 列子查询 1.4.4 行子查询 1.4.5 表子查询 1.5 案例 2. 事务 2.1 介绍 2.2 操作 2.3 四大特性 3. 索引 3.1 介绍 3…

雷士大路灯有必要买吗?雷士、书客、孩视宝护眼落地灯实测PK!

面对市面上众多的护眼大路灯品牌&#xff0c;其中雷士、书客和孩视宝这几款大路灯受到了广泛的青睐&#xff0c;也是热度比较高的几款产品&#xff0c;正是因为这么多款大路灯&#xff0c;很多伙伴在看到文章推荐后很纠结&#xff0c;不知道如何选择&#xff0c;也有一部分伙伴…