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


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

    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

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

    一、引入项目中关键依赖

    1. <parent>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-parentartifactId>
    4. <version>3.2.5version>
    5. parent>
    6. <properties>
    7. <spring-cloud.version>2023.0.1spring-cloud.version>
    8. <spring-cloud-alibaba.version>2022.0.0.0spring-cloud-alibaba.version>
    9. <mybatis.spring>3.0.3mybatis.spring>
    10. <mybatisPlus>3.5.5mybatisPlus>
    11. properties>
    12. <dependencyManagement>
    13. <dependencies>
    14. <dependency>
    15. <groupId>org.mybatis.spring.bootgroupId>
    16. <artifactId>mybatis-spring-boot-starterartifactId>
    17. <version>${mybatis.spring}version>
    18. dependency>
    19. <dependency>
    20. <groupId>com.baomidougroupId>
    21. <artifactId>mybatis-plus-boot-starterartifactId>
    22. <version>${mybatisPlus}version>
    23. dependency>
    24. <dependency>
    25. <groupId>org.springframework.cloudgroupId>
    26. <artifactId>spring-cloud-dependenciesartifactId>
    27. <version>${spring-cloud.version}version>
    28. <type>pomtype>
    29. <scope>importscope>
    30. dependency>
    31. <dependency>
    32. <groupId>com.alibaba.cloudgroupId>
    33. <artifactId>spring-cloud-alibaba-dependenciesartifactId>
    34. <version>${spring-cloud-alibaba.version}version>
    35. <type>pomtype>
    36. <scope>importscope>
    37. dependency>
    38. dependencies>
    39. 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,该文件的配置信息如下:

    1. [client]
    2. default_character_set=utf8mb4
    3. [mysql]
    4. default_character_set=utf8mb4
    5. [mysqld]
    6. character_set_server=utf8mb4
    7. collation_server=utf8mb4_unicode_ci
    8. init_connect='SET NAMES utf8mb4'

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

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

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

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

    1. /*
    2. * Copyright 1999-2018 Alibaba Group Holding Ltd.
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * http://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16. /******************************************/
    17. /* 表名称 = config_info */
    18. /******************************************/
    19. CREATE TABLE `config_info` (
    20. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
    21. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
    22. `group_id` varchar(128) DEFAULT NULL COMMENT 'group_id',
    23. `content` longtext NOT NULL COMMENT 'content',
    24. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
    25. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    26. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    27. `src_user` text COMMENT 'source user',
    28. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
    29. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
    30. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
    31. `c_desc` varchar(256) DEFAULT NULL COMMENT 'configuration description',
    32. `c_use` varchar(64) DEFAULT NULL COMMENT 'configuration usage',
    33. `effect` varchar(64) DEFAULT NULL COMMENT '配置生效的描述',
    34. `type` varchar(64) DEFAULT NULL COMMENT '配置的类型',
    35. `c_schema` text COMMENT '配置的模式',
    36. `encrypted_data_key` text NOT NULL COMMENT '密钥',
    37. PRIMARY KEY (`id`),
    38. UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
    39. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
    40. /******************************************/
    41. /* 表名称 = config_info_aggr */
    42. /******************************************/
    43. CREATE TABLE `config_info_aggr` (
    44. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
    45. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
    46. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
    47. `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
    48. `content` longtext NOT NULL COMMENT '内容',
    49. `gmt_modified` datetime NOT NULL COMMENT '修改时间',
    50. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
    51. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
    52. PRIMARY KEY (`id`),
    53. UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
    54. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
    55. /******************************************/
    56. /* 表名称 = config_info_beta */
    57. /******************************************/
    58. CREATE TABLE `config_info_beta` (
    59. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
    60. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
    61. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
    62. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
    63. `content` longtext NOT NULL COMMENT 'content',
    64. `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
    65. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
    66. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    67. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    68. `src_user` text COMMENT 'source user',
    69. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
    70. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
    71. `encrypted_data_key` text NOT NULL COMMENT '密钥',
    72. PRIMARY KEY (`id`),
    73. UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
    74. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
    75. /******************************************/
    76. /* 表名称 = config_info_tag */
    77. /******************************************/
    78. CREATE TABLE `config_info_tag` (
    79. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
    80. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
    81. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
    82. `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
    83. `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
    84. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
    85. `content` longtext NOT NULL COMMENT 'content',
    86. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
    87. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    88. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    89. `src_user` text COMMENT 'source user',
    90. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
    91. PRIMARY KEY (`id`),
    92. UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
    93. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
    94. /******************************************/
    95. /* 表名称 = config_tags_relation */
    96. /******************************************/
    97. CREATE TABLE `config_tags_relation` (
    98. `id` bigint(20) NOT NULL COMMENT 'id',
    99. `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
    100. `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
    101. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
    102. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
    103. `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
    104. `nid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增长标识',
    105. PRIMARY KEY (`nid`),
    106. UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
    107. KEY `idx_tenant_id` (`tenant_id`)
    108. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
    109. /******************************************/
    110. /* 表名称 = group_capacity */
    111. /******************************************/
    112. CREATE TABLE `group_capacity` (
    113. `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    114. `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
    115. `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
    116. `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
    117. `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
    118. `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
    119. `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
    120. `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
    121. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    122. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    123. PRIMARY KEY (`id`),
    124. UNIQUE KEY `uk_group_id` (`group_id`)
    125. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
    126. /******************************************/
    127. /* 表名称 = his_config_info */
    128. /******************************************/
    129. CREATE TABLE `his_config_info` (
    130. `id` bigint(20) unsigned NOT NULL COMMENT 'id',
    131. `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'nid, 自增标识',
    132. `data_id` varchar(255) NOT NULL COMMENT 'data_id',
    133. `group_id` varchar(128) NOT NULL COMMENT 'group_id',
    134. `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
    135. `content` longtext NOT NULL COMMENT 'content',
    136. `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
    137. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    138. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    139. `src_user` text COMMENT 'source user',
    140. `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
    141. `op_type` char(10) DEFAULT NULL COMMENT 'operation type',
    142. `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
    143. `encrypted_data_key` text NOT NULL COMMENT '密钥',
    144. PRIMARY KEY (`nid`),
    145. KEY `idx_gmt_create` (`gmt_create`),
    146. KEY `idx_gmt_modified` (`gmt_modified`),
    147. KEY `idx_did` (`data_id`)
    148. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
    149. /******************************************/
    150. /* 表名称 = tenant_capacity */
    151. /******************************************/
    152. CREATE TABLE `tenant_capacity` (
    153. `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    154. `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
    155. `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
    156. `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
    157. `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
    158. `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
    159. `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
    160. `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
    161. `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    162. `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    163. PRIMARY KEY (`id`),
    164. UNIQUE KEY `uk_tenant_id` (`tenant_id`)
    165. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
    166. CREATE TABLE `tenant_info` (
    167. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
    168. `kp` varchar(128) NOT NULL COMMENT 'kp',
    169. `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
    170. `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
    171. `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
    172. `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
    173. `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
    174. `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
    175. PRIMARY KEY (`id`),
    176. UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
    177. KEY `idx_tenant_id` (`tenant_id`)
    178. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
    179. CREATE TABLE `users` (
    180. `username` varchar(50) NOT NULL PRIMARY KEY COMMENT 'username',
    181. `password` varchar(500) NOT NULL COMMENT 'password',
    182. `enabled` boolean NOT NULL COMMENT 'enabled'
    183. );
    184. CREATE TABLE `roles` (
    185. `username` varchar(50) NOT NULL COMMENT 'username',
    186. `role` varchar(50) NOT NULL COMMENT 'role',
    187. UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
    188. );
    189. CREATE TABLE `permissions` (
    190. `role` varchar(50) NOT NULL COMMENT 'role',
    191. `resource` varchar(255) NOT NULL COMMENT 'resource',
    192. `action` varchar(8) NOT NULL COMMENT 'action',
    193. UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
    194. );
    195. INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
    196. INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');

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

    1. PREFER_HOST_MODE=hostname
    2. MODE=standalone
    3. SPRING_DATASOURCE_PLATFORM=mysql
    4. MYSQL_SERVICE_HOST=192.168.147.130
    5. MYSQL_SERVICE_DB_NAME=nacos
    6. MYSQL_SERVICE_PORT=3306
    7. MYSQL_SERVICE_USER=root
    8. MYSQL_SERVICE_PASSWORD=123
    9. MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
    10. NACOS_AUTH_ENABLE=true
    11. NACOS_AUTH_IDENTITY_KEY=nacos
    12. NACOS_AUTH_IDENTITY_VALUE=nacos
    13. NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789

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

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

    1. docker run -d \
    2. --name nacos6 \
    3. --env-file ./nacos/quick-nacos.env \
    4. -p 8868:8848 \
    5. -p 9868:9848 \
    6. -p 9869:9849 \
    7. --restart=always \
    8. nacos/nacos-server:v2.3.2-slim

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

    docker logs -f nacos6

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

    1. spring:
    2. profiles:
    3. active: dev
    4. application:
    5. name: user-service #微服务名称
    6. cloud:
    7. nacos:
    8. server-addr: 192.168.147.130:8868
    9. username: nacos #用户名
    10. password: nacos #密码
    4、一些常用的dockers指令

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

    1. docker start mysql
    2. docker stop mysql
    3. docker start nacos6
    4. docker stop nacos6
    5. dis
    6. dps

    三、拆分项目

    1、原则

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

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

    • 纵向拆分

    • 横向拆分

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

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

    2、创建单一服务模块

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

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

    3、给模块引入依赖

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

     user-service:

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <parent>
    7. <groupId>com.quickgroupId>
    8. <artifactId>quick-pickupartifactId>
    9. <version>0.0.1-SNAPSHOTversion>
    10. parent>
    11. <artifactId>user-serviceartifactId>
    12. <properties>
    13. <maven.compiler.source>17maven.compiler.source>
    14. <maven.compiler.target>17maven.compiler.target>
    15. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    16. properties>
    17. <dependencies>
    18. <dependency>
    19. <groupId>com.quickgroupId>
    20. <artifactId>quick-commenartifactId>
    21. <version>0.0.1-SNAPSHOTversion>
    22. dependency>
    23. <dependency>
    24. <groupId>cn.hutoolgroupId>
    25. <artifactId>hutool-allartifactId>
    26. dependency>
    27. <dependency>
    28. <groupId>com.github.xiaoymingroupId>
    29. <artifactId>knife4j-openapi3-jakarta-spring-boot-starterartifactId>
    30. dependency>
    31. <dependency>
    32. <groupId>com.github.xiaoymingroupId>
    33. <artifactId>knife4j-openapi3-uiartifactId>
    34. dependency>
    35. <dependency>
    36. <groupId>org.springframework.bootgroupId>
    37. <artifactId>spring-boot-starter-webartifactId>
    38. dependency>
    39. <dependency>
    40. <groupId>com.mysqlgroupId>
    41. <artifactId>mysql-connector-jartifactId>
    42. dependency>
    43. <dependency>
    44. <groupId>org.mybatis.spring.bootgroupId>
    45. <artifactId>mybatis-spring-boot-starterartifactId>
    46. dependency>
    47. <dependency>
    48. <groupId>com.baomidougroupId>
    49. <artifactId>mybatis-plus-boot-starterartifactId>
    50. dependency>
    51. <dependency>
    52. <groupId>com.alibaba.cloudgroupId>
    53. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    54. dependency>
    55. <dependency>
    56. <groupId>org.springframework.cloudgroupId>
    57. <artifactId>spring-cloud-starter-openfeignartifactId>
    58. dependency>
    59. <dependency>
    60. <groupId>org.springframework.cloudgroupId>
    61. <artifactId>spring-cloud-starter-loadbalancerartifactId>
    62. dependency>
    63. <dependency>
    64. <groupId>io.github.openfeigngroupId>
    65. <artifactId>feign-okhttpartifactId>
    66. dependency>
    67. <dependency>
    68. <groupId>com.quickgroupId>
    69. <artifactId>quick-apiartifactId>
    70. <version>0.0.1-SNAPSHOTversion>
    71. dependency>
    72. dependencies>
    73. <build>
    74. <finalName>${project.artifactId}finalName>
    75. <plugins>
    76. <plugin>
    77. <groupId>org.springframework.bootgroupId>
    78. <artifactId>spring-boot-maven-pluginartifactId>
    79. plugin>
    80. plugins>
    81. build>
    82. project>

     quick-api:

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <parent>
    7. <groupId>com.quickgroupId>
    8. <artifactId>quick-pickupartifactId>
    9. <version>0.0.1-SNAPSHOTversion>
    10. parent>
    11. <artifactId>quick-apiartifactId>
    12. <properties>
    13. <maven.compiler.source>17maven.compiler.source>
    14. <maven.compiler.target>17maven.compiler.target>
    15. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    16. properties>
    17. <dependencies>
    18. <dependency>
    19. <groupId>com.quickgroupId>
    20. <artifactId>quick-commenartifactId>
    21. <version>0.0.1-SNAPSHOTversion>
    22. dependency>
    23. <dependency>
    24. <groupId>org.springframework.cloudgroupId>
    25. <artifactId>spring-cloud-starter-openfeignartifactId>
    26. dependency>
    27. <dependency>
    28. <groupId>org.springframework.cloudgroupId>
    29. <artifactId>spring-cloud-starter-loadbalancerartifactId>
    30. dependency>
    31. <dependency>
    32. <groupId>com.github.xiaoymingroupId>
    33. <artifactId>knife4j-openapi3-jakarta-spring-boot-starterartifactId>
    34. dependency>
    35. <dependency>
    36. <groupId>com.github.xiaoymingroupId>
    37. <artifactId>knife4j-openapi3-uiartifactId>
    38. dependency>
    39. dependencies>
    40. project>
    4、给每个服务做好配置文件

    这里我只展示user-service

    application.yml :

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

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

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

    1. server:
    2. port: 8082 # 服务端口
    3. spring:
    4. profiles:
    5. active: dev # 环境配置,dev开发环境,test测试环境,prod生产环境
    6. application:
    7. name: user-service #微服务名称
    8. cloud:
    9. nacos:
    10. server-addr: 192.168.147.130:8868 # nacos地址
    11. username: nacos #用户名
    12. password: nacos #密码
    13. discovery:
    14. group: QUICK_CLOUD # 配置服务注册分组
    15. openfeign:
    16. okhttp:
    17. enabled: true # 开启okhttp
    18. datasource:
    19. driver-class-name: ${quick.datasource.driver-class-name}
    20. 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
    21. username: ${quick.datasource.username}
    22. password: ${quick.datasource.password}
    23. # springdoc-openapi项目配置
    24. springdoc:
    25. swagger-ui:
    26. path: /swagger-ui.html
    27. tags-sorter: alpha
    28. operations-sorter: alpha
    29. api-docs:
    30. path: /v3/api-docs
    31. group-configs:
    32. - group: 'C端用户接口'
    33. paths-to-match: '/**'
    34. packages-to-scan: com.quick.user.controller # 配置需要扫描的controller包路径
    35. knife4j:
    36. enable: true
    37. setting:
    38. language: zh_cn
    39. mybatis-plus:
    40. type-aliases-package: com.quick.user.domain.po # 配置实体类存放的包路径
    41. global-config:
    42. db-config:
    43. update-strategy: not_null
    44. id-type: auto #配置实体类中id默认自增
    45. logic-delete-field: deleted # 配置逻辑删除字段
    46. configuration:
    47. default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
    48. map-underscore-to-camel-case: true
    49. logging:
    50. level:
    51. com:
    52. quick:
    53. user:
    54. mapper: debug
    55. service: info
    56. controller: info
    57. quick:
    58. jwt:
    59. user-secret-key: quick
    60. user-ttl: 72000000
    61. user-token-name: authentication
    62. wechat:
    63. appid: ${quick.wechat.appid}
    64. secret: ${quick.wechat.secret}

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

    application-dev.yml :

    1. quick:
    2. datasource:
    3. driver-class-name: com.mysql.cj.jdbc.Driver
    4. host: 192.168.147.130 #虚拟机端口
    5. port: 3306
    6. database: quick-user #自己给自己对应服务建立的对应数据库
    7. username: #自己数据库用户名
    8. password: #自己数据库用户名
    9. wechat:
    10. #小程序:
    11. appid: #自己小程序的appid
    12. secret: #自己小程序的secret

    application-local.yml :

    1. quick:
    2. datasource:
    3. driver-class-name: com.mysql.cj.jdbc.Driver
    4. host: 192.168.147.130 #虚拟机端口
    5. port: 3306
    6. database: quick-user #自己给自己对应服务建立的对应数据库
    7. username: #自己数据库用户名
    8. password: #自己数据库用户名
    9. wechat:
    10. #小程序:
    11. appid: #自己小程序的appid
    12. secret: #自己小程序的secret
    5、给每个服务创建对应的包

    6、启动项目观察nacos

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

    可以看到成功注册上去。

    四、用OpenFeign实现服务调用

    1、引入依赖

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

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

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-openfeignartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>org.springframework.cloudgroupId>
    7. <artifactId>spring-cloud-starter-loadbalancerartifactId>
    8. dependency>
    2、在服务启动类启用OpenFeign

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

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

    1. @SpringBootApplication
    2. @EnableTransactionManagement //开启注解方式的事务管理
    3. @EnableCaching//开启缓存注解功能
    4. @EnableScheduling//开启任务调度
    5. @MapperScan("com.quick.user.mapper")
    6. //basePackages标记FeignClients扫描的包,defaultConfiguration标记日志级别配置类使得对该模块全局生效
    7. @EnableFeignClients(basePackages = "com.quick.api.client",defaultConfiguration = DefaultFeignConfig.class)
    8. public class UserApplication {
    9. public static void main(String[] args) {
    10. SpringApplication.run(UserApplication.class, args);
    11. }
    12. }
    3、编写OpenFeign客户端

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

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

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

    1. //调用同一个服务下的不同接口,用contextId区分
    2. @FeignClient(contextId = "store", name = "store-service")
    3. public interface StoreClient {
    4. //通过店铺id查询店铺所有信息
    5. @GetMapping("/user/store/{storeId}")
    6. @Operation(summary = "通过店铺id查询店铺所有信息")
    7. Result getByStoreId (@PathVariable Long storeId);
    8. }
    1. //调用同一个服务下的不同接口,用contextId区分
    2. @FeignClient(contextId = "mark",name = "store-service")
    3. public interface MarkClient {
    4. @GetMapping("/user/mark/getMarkListByUserId")
    5. @Operation(summary = "通过用户id查看用户对所有店铺的评分")
    6. Result> getMarkListByUserId(@RequestParam("userId") Long userId);
    7. }

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

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

    MarkController:

    1. @RestController("userMarkController")
    2. @RequestMapping("/user/mark")
    3. @Tag(name = "C端-评分接口")
    4. @Slf4j
    5. @RequiredArgsConstructor
    6. public class MarkController {
    7. @Resource
    8. private IMarkService markService;
    9. //通过用户id查看用户对所有店铺的评分
    10. @GetMapping("/getMarkListByUserId")
    11. @Operation(summary = "通过用户id查看用户对所有店铺的评分")
    12. public Result> getMarkListByUserId(@RequestParam("userId") Long userId){
    13. QueryWrapperqueryWrapper=new QueryWrapper<>();
    14. queryWrapper.lambda()
    15. .eq(Mark::getUserId,userId);
    16. List markList = markService.list(queryWrapper);
    17. return Result.success(markList);
    18. }
    19. }

    MarkClient:

    1. //调用同一个服务下的不同接口,用contextId区分
    2. @FeignClient(contextId = "mark",name = "store-service")
    3. public interface MarkClient {
    4. @GetMapping("/user/mark/getMarkListByUserId")
    5. @Operation(summary = "通过用户id查看用户对所有店铺的评分")
    6. Result> getMarkListByUserId(@RequestParam("userId") Long userId);
    7. }

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

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

    就是下面的dto。

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

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

    1. public class DefaultFeignConfig {
    2. // NONE:不记录任何日志信息,这是默认值。
    3. // BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
    4. // HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
    5. // FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
    6. //声明日志级别配置
    7. @Bean
    8. public Logger.Level feignLogLevel() {
    9. return Logger.Level.FULL;
    10. }
    11. }

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

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

    6、使用FeignClient

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

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

    1. @Service
    2. @Slf4j
    3. @RequiredArgsConstructor
    4. public class UserServiceImpl extends ServiceImpl implements UserService {
    5. private final MarkClient markClient;
    6. private final StoreClient storeClient;
    7. }

    在接口实现里面调用

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

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

    接口测试:

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

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

  • 相关阅读:
    Pandas中at、iat函数详解
    阿里云有奖体验:用PolarDB-X搭建一个高可用系统
    mysql远程连接 Communications link failure失败问题
    vue3学习笔记(异步组件,包含defineAsyncComponent、Suspense的使用)
    2022 开源之夏|EMQ 三大开源项目开发圆满收官
    springboot- redis常见数据存取
    【卫朋】硬件创业:营销与开发同行
    Java创建Document对象有哪些方法呢?
    SpringMVC常用的三种获取请求参数的方式
    小型目标检测中的Transformer:一个基准和最先进技术的综述
  • 原文地址:https://blog.csdn.net/qq_73440769/article/details/139376179