改的地方实在太多了,所以过程记录不下去了,但是业务模块跟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-starter与sa-token-reactor-spring-boot-starter存在冲突,不可同时引用。
直接访问需要鉴权