改的地方实在太多了,所以过程记录不下去了,但是业务模块跟Boot是一毛一样的没有变化,直接发项目代码,包括了nacos中的配置文件在对应的模块,运行大概是没有问题。
成果:

链接已死,真的大无语。
等哪天把家里的k8s的minio整一下。先传到CSDN咯。
PS:其实过年前就已经改造结束了,但是因为带娃没空整理(借口)。前阵子看到了篇文章《Spring Boot 单体应用一键升级成 Spring Cloud Alibaba》,感觉再不发就没机会了!

引入模块:

  • 架构:Spring Cloud Alibaba-2020.0.5
  • 服务发现、治理中心:Nacos-2.0.1
  • 网关:Spring Cloud Gateway
  • 服务调用:Feign-3.0.6
  • 流量控制、服务降级:Sentinel

正文结束!下面都是一些杂乱的笔记,不保证正确。

记录

一、git提交记录

经历了三个阶段:pom整理 => cloud模块引入 => 业务模块调试

二、Pom整理记录

day1
原项目拆解出来的模块。

day2
迁移后引用报错解决,pom拆分。
引入spring cloud alibaba依赖

<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><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>

三、Nacos

pom引入nacos

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>

docker安装nacos

#拉取镜像docker pull nacos/nacos-server#创建映射文件mkdir -p /root/nacos/init.d /root/nacos/logstouch /root/nacos/init.d/custom.properties#在文件中写入management.endpoints.web.exposure.include=*#创建容器并启动提供a、b两种方案#a.创建容器:使用standalone模式并开放8848端口,并映射配置文件和日志目录,数据库默认使用 Derbydocker run -d -p 8848:8848 -e MODE=standalone -e PREFER_HOST_MODE=hostname -v /root/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties -v /root/nacos/logs:/home/nacos/logs --restart always --name nacos nacos/nacos-server

访问http://nacos.dinganwang.top/nacos可以打开nacos管理页面,默认账号密码nacos/nacos。
新建命名空间dev、pro区分一下开发环境还是正式环境。如果项目够大,项目粒度够多,可以根据模块创建命名空间。
Data ID需要与应用名称保持一致。

新建配置文件bootstrap.yml,增加配置。

spring:application:#应用名称name: dingx-webcloud:nacos:discovery:server-addr: nacos.dinganwang.top# 命名空间namespace: 命名空间ID

在启动类上使用**@EnableDiscoveryClient** 开启服务注册发现功能。

四、Gateway

引入gateway

<!-- SpringCloud Gateway --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>

报错:

***************************APPLICATION FAILED TO START***************************Description:Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.Action:Consider defining a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' in your configuration.

原因:gateWay 工程中同时引入了 Web依赖 和 webflux依赖,或者是父工程中有Web依赖,二当前微服务中有webflux依赖,这样会出现冲突。
查找了下是sa-token-spring-boot-starter中存在spring-boot-starter-web的依赖,排除掉即可。

<dependency><groupId>com.dingx</groupId><artifactId>common-redis</artifactId><version>1.0-SNAPSHOT</version><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></exclusion></exclusions></dependency>

根据nacos的配置方式加入配置后启动,服务列表出现一例服务实例,表示成功。

最后的目录结构:

从上到下依次介绍:

api:统一管理feign远程调用,对应modules中的业务模块,比如api-admin中存放的是对/modules/admin模块下接口的调用。
auth:统一权限管理,包括用户登录注销,生成token等。
common:所有可以拆解的工具模块。
┗━common-code:代码生成器模块。
┗━common-core:核心配置类,包括业务模块依赖包引入pom、工具类、全局变量、全局枚举、全局异常处理等等。业务模块必须引用。
┗━common-datasource:数据库连接模块,包括拦截器等。
┗━common-elasticsearch:es工具模块。
┗━common-log:日志切面处理。
┗━common-redis:redis工具模块。
┗━common-security:鉴权相关,主要给auth模块提供支持。
┗━common-swagger:swagger模块。
gateway:网关。
modules:业务模块统一管理。
┗━modules-admin:后台管理。
┗━modules-file:文件管理。
┗━modules-job:定时任务模块。
┗━modules-web:前台页面。
monitor:监控模块。

五、Feign

引入feign

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>${feign.version}</version></dependency>

新建模块统一管理。
模块下创建service。

@FeignClient(contextId = "remoteAdminLogService" ,value = ServiceNameConstants.ADMIN_SERVICE)public interface RemoteAdminLogService {@PostMapping(value = "/system/adminLog/insert")ResponseResult insert(@RequestBody AdminLog log);}

具体使用的地方与其他service一样引入即可

六、Auth

鉴权中心模块,由业务登录校验抽离。
报错
Caused by: java.lang.IllegalStateException: No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer” /><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

七、Modules

报错:Parameter 0 of constructor in com.dingx.modules.admin.service.article.impl.ArticleServiceImpl required a bean of type ‘*.mapper’ that could not be found.
原因:Mapper未扫描到。
解决方案:在MybatisPlusConfig上加@MapperScan("com.dingx.modules.**.mapper.**")注解

报错:Parameter 2 of constructor in com.dingx.modules.admin.service.article.impl.ArticleServiceImpl required a bean of type ‘org.springframework.web.client.RestTemplate’ that could not be found.
原因:错误提示说RestTemplate没找到,这是因为在 Spring Boot 1.3版本中,会默认提供一个RestTemplate的实例Bean,而在 Spring Boot 1.4以及以后的版本中,这个默认的bean不再提供了,我们需要在Application启动时,手动创建一个RestTemplate的配置。
解决方案:写个通用BeanConfig,再遇到同类问题统一管理

@Configurationpublic class BeanConfig {@BeanRestTemplate restTemplate(){return new RestTemplate();}}

报错:Caused by: com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException: dynamic-datasource can not find primary datasource
原因:引入了多数据源配置。
解决方案:暂时没用,先注释。

报错:[RemoteUserService#updateLoginInfo(LoginInfoVO)]: [{“timestamp”:“2022-12-07T10:28:10.782+00:00”,“status”:405,“error”:“Method Not Allowed”,“message”:“”,“path”:“/system/user/updateLoginInfo”}]
解决方案:加入依赖

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId></dependency>

异常:feign调用参数未传递

解决方案:指定调用方式consumes

@PostMapping(value = "/system/user/selectNameAndPassword", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)

八、sa-token

1、Gateway网关引入依赖

<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-reactor-spring-boot-starter</artifactId><version>1.33.0</version></dependency><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-dao-redis-jackson</artifactId><version>1.33.0</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>

2、Auth实现鉴权接口

/*** 自定义权限验证接口扩展 */@Component public class StpInterfaceImpl implements StpInterface {@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {// 返回此 loginId 拥有的权限列表 return ...;}@Overridepublic List<String> getRoleList(Object loginId, String loginType) {// 返回此 loginId 拥有的角色列表return ...;}}

3、Gateway注册全局过滤器

/** * [Sa-Token 权限认证] 配置类* @author kong */@Configurationpublic class SaTokenConfigure {// 注册 Sa-Token全局过滤器 @Beanpublic SaReactorFilter getSaReactorFilter() {return new SaReactorFilter()// 拦截地址 .addInclude("/**")/* 拦截全部path */// 开放地址 .addExclude("/favicon.ico")// 鉴权方法:每次访问进入 .setAuth(obj -> {// 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录 SaRouter.match("/**", "/user/doLogin", r -> StpUtil.checkLogin());// 权限认证 -- 不同模块, 校验不同权限 SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));// 更多匹配 ...*/})// 异常处理方法:每次setAuth函数出现异常时进入 .setError(e -> {return SaResult.error(e.getMessage());});}}

4、子模块引用sa-token-spring-boot-starter

注意:sa-token-spring-boot-startersa-token-reactor-spring-boot-starter存在冲突,不可同时引用。
直接访问需要鉴权