spring cloud3+jdk 17+ gateway +nacos 架构整体升级

【说明】

本次升级git分支为1.4
由于框架搭建在三年前,很多依赖已经比较老了,为了提高系统安全及新功能的使用,故将整体架构进行升级。
部分代码可能涉及方法过期和不可用,权衡后进行升级。
因为是最新版的依赖,依赖本身可能存在bug

【注意】
1、java版本最低17(我装的17,>17版本可以自己试试,环境变量要配好)
2、nacos可升级到最新版2.2.3
3、maven可升级3.9.3
4、升级后必须进行全面的测试

一、POM依赖升级

pom.xml
截至2023-07-20:14:16:00更新maven仓库最新版本如下:
在这里插入图片描述

部分版本暂未升级,根据需要自行升级
在这里插入图片描述

版本升级冲突问题暂未解决,有空再升级
image.png

二、JAR命令切换nacos

使用jar命令运行,可根据需要替换nacos配置信息,切换服务器时不再重新打包
bootstrap.yml
在这里插入图片描述

将bootstrap.yml文件和JAR包放在同一目录下,运行下列命令,覆盖jar内的bootsrap.yml

java -Dfile.encoding=utf-8 -jar mp-user.jar --spring.config.location=bootstrap.yml

image.png
相应文件放在resourse/jaruse下
在这里插入图片描述

三、网关换为gateway

网关不再使用zuul模块,更改为gateway模块
image.png
配置文件更改
在这里插入图片描述

application-url.yml

whitelist:
  urlset:
    /api-docs,
    /getTenantInfoVoListByPo,
    /checkToken,
    /getUserInfo,
    /byLoginName,
    /getTicket,
    /checkInfo,
    /checkTicket,
    /login,
    /doLogin,
    /logout,
    /error,
    /unauthorized,
    /getPermission,
    /addWeldTestData,
    /sso

  fileset:
    css,
    js,
    ico,
    jpg,
    png

gateway.yml

server:
  port: 8801

spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的服务
          #服务名小写
          lower-case-service-id: true
      # 配置跨域
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST


knife4j:
  gateway:
    enabled: true
    strategy: discover
    discover:
      version: openapi3
      enabled: true
      excluded-services:
        - gateway

gateway-router(未启用)

[{
  "id": "auth",
  "order": 0,
  "predicates": [{
    "args": {
      "pattern": "/apiauth/**"
    },
    "name": "Path"
  }],
  "uri": "lb://auth"
},{
  "id": "mp-user",
  "order": 2,
  "predicates": [{
    "args": {
      "pattern": "/mpuser/**"
    },
    "name": "Path"
  }],
  "uri": "lb://mp-user"
}]

【注意】
通过网关访问其他服务时,添加路由,名称为nacos服务名称
如:访问mp-user服务时,http://10.9.70.156:8801/mp-user/user/getUserVoPageListByDto

四、swagger2升级到knife4j-openapi3

注解进行全局替换,如下:

swagger2OpenAPI注解位置
@Api@Tag(name = “接口类名”,description = “接口类描述”)Controller 类上
@ApiOperation@Operation(summary =“接口方法描述”)Controller 方法上
@ApiImplicitParams@ParametersController 方法上
@ApiImplicitParam@Parameter(description=“参数描述”)Controller 方法上 @Parameters 里
@ApiParam@Parameter(description=“参数描述”)Controller 方法的参数上
@ApiIgnore@Parameter(hidden = true) 或 @Operation(hidden = true) 或 @Hidden
@ApiModel@SchemaDTO类上
@ApiModelProperty@SchemaDTO属性上

Entity类
在这里插入图片描述

Controller类
image.png
image.png
在nacos配置文件中添加配置swagger

springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'user'
      paths-to-match: '/**'
      packages-to-scan: com.cloud.mpuser.controller
  default-flat-param-object: true
knife4j:
  enable: true
  setting:
    language: zh_cn
    swagger-model-name: 实体类列表
  basic:
    enable: false
    username: knife4j
    password: 125487
  production: false

image.png
访问
通过gateway网关访问所有服务的swagger页面
http://10.9.70.156:8801/doc.html
在这里插入图片描述

单独访问的两种
http://10.9.70.156:8805/doc.html
image.png
http://10.9.70.156:8805/swagger-ui/index.html#/
在这里插入图片描述

五、fastjson完全替换为fastjson2

序列化统一处理
image.png
据网上资料表明,fastjson2比fastjon更安全,更高速,建议替换
jackson除部分依赖包中依赖,不再使用jackson,注意版本升级问题

六、mp核心包升级

两个版本同时存在
image.png
老版本不影响使用
新版本

  • @ServerFieldBinder暂不支持,后续升级
  • 部分方法有变更,选择合适的方法
  • 支持mybatis plus 批量插入功能

根据最新版core包进行扩展,支持的新功能查看文档
起步简介
Mybatis plus问题在这里插入图片描述

暂时解决方案:

<!-- mybatis plus -->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <exclusions>
    <exclusion>
      <groupId>com.github.jsqlparser</groupId>
      <artifactId>jsqlparser</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>com.github.jsqlparser</groupId>
  <artifactId>jsqlparser</artifactId>
</dependency>

七、开启异步传递request

由于新的mp核心包字段绑定注解采用异步的方式,在多租户的情况下,request未传递到子线程中,异步获取偶尔发生错误如下:
java.lang.IllegalStateException: The request object has been
recycled and is no longer associated with this facade

o.a.c.c.C.[Tomcat].[localhost].[/].[dispatcherServlet].log:175: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.util.concurrent.CompletionException: org.mybatis.spring.MyBatisSystemException] with root cause
java.lang.IllegalStateException: The request object has been recycled and is no longer associated with this facade
	at org.apache.catalina.connector.RequestFacade.checkFacade(RequestFacade.java:856)
	at org.apache.catalina.connector.RequestFacade.getHeader(RequestFacade.java:505)
	at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:82)
	at com.stwc.messagecenter.config.MyTenantHandler.getTenantId(MyTenantHandler.java:51)
	at com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor.buildTableExpression(TenantLineInnerInterceptor.java:240)
	at com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor.lambda$builderExpression$3(BaseMultiTableInnerInterceptor.java:387)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor.builderExpression(BaseMultiTableInnerInterceptor.java:389)
	at com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor.processPlainSelect(BaseMultiTableInnerInterceptor.java:113)
	at com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor.processSelectBody(BaseMultiTableInnerInterceptor.java:54)
	at com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor.processSelect(TenantLineInnerInterceptor.java:88)
	at com.baomidou.mybatisplus.extension.parser.JsqlParserSupport.processParser(JsqlParserSupport.java:91)
	at com.baomidou.mybatisplus.extension.parser.JsqlParserSupport.parserSingle(JsqlParserSupport.java:50)
	at com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor.beforeQuery(TenantLineInnerInterceptor.java:68)
	at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:78)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:62)
	at jdk.proxy3/jdk.proxy3.$Proxy235.query(Unknown Source)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at jdk.internal.reflect.GeneratedMethodAccessor238.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427)
	at jdk.proxy3/jdk.proxy3.$Proxy194.selectList(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224)
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForMany(MybatisMapperMethod.java:166)
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:77)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
	at jdk.proxy3/jdk.proxy3.$Proxy199.selectList(Unknown Source)
	at com.baomidou.mybatisplus.extension.service.IService.list(IService.java:370)
	at com.cloud.mpstarter2.service.impl.BaseServiceImpl.getEntityList(BaseServiceImpl.java:668)
	at com.cloud.mpstarter2.service.impl.BaseServiceImpl.getEntityList(BaseServiceImpl.java:632)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
	at com.stwc.messagecenter.service.impl.MessageSysTypeServiceImpl$$SpringCGLIB$$0.getEntityList(<generated>)
	at com.cloud.mpstarter2.binding.binder.BaseBinder.getEntityList(BaseBinder.java:349)
	at com.cloud.mpstarter2.binding.binder.FieldBinder.bind(FieldBinder.java:117)
	at com.cloud.mpstarter2.binding.binder.parallel.ParallelBindingManager.doBinding(ParallelBindingManager.java:185)
	at com.cloud.mpstarter2.binding.binder.parallel.ParallelBindingManager.doBindingField(ParallelBindingManager.java:89)
	at jdk.internal.reflect.GeneratedMethodAccessor298.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:756)
	at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
	at org.apache.skywalking.apm.plugin.spring.async.SWCallable.call(SWCallable.java:47)
	at org.springframework.util.concurrent.FutureUtils.lambda$toSupplier$0(FutureUtils.java:74)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)

解决方案:
1、参考
在这里插入图片描述

2、

其他情况:

  • 本次升级有多处细节,不一一说明,根据代码提示进行替换
  • 如有问题,联系作者,不一定能解决,慎重升级
  • 升级后必须进行全面的测试
  • 持续更新

【参考】

Swagger2和openAPI3注解对比_openapi注解_banyejiu的博客-CSDN博客
SpringBoot 整合 knfe4j ,使用 OpenAPI3 规范_knife4j openapi_N_007的博客-CSDN博客
千万不要把Request传递到异步线程里面!有坑!

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Spring Cloud Alibaba 技术栈搭建项目手脚架可以提高开发效率和项目可维护性,以下是基于 Spring Cloud Alibaba 技术栈的项目手脚架搭建步骤: 1. 环境准备 确保已安装 JDK,Maven,Nacos,RocketMQ,Seata 和 Sentinel 等必需的软件。 2. 创建 Spring Boot 项目 使用 Spring Initializr 创建一个 Spring Boot 项目,添加必需的依赖项: ```xml <!-- Spring Boot 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Cloud Alibaba 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-dubbo</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency> <!-- RocketMQ 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-stream-rocketmq</artifactId> </dependency> ``` 3. 配置 Nacos 在 application.properties 文件中添加 Nacos 相关配置: ```properties spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.namespace=dev ``` 4. 配置 Dubbo 在 application.properties 文件中添加 Dubbo 相关配置: ```properties spring.application.name=service-provider spring.cloud.dubbo.application.name=service-provider spring.cloud.dubbo.registry.address=nacos://127.0.0.1:8848 spring.cloud.dubbo.protocol.name=dubbo spring.cloud.dubbo.protocol.port=20880 ``` 5. 配置 RocketMQ 在 application.properties 文件中添加 RocketMQ 相关配置: ```properties spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876 spring.cloud.stream.rocketmq.binder.group=group1 ``` 6. 配置 Seata 在 application.properties 文件中添加 Seata 相关配置: ```properties spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group ``` 7. 配置 Sentinel 在 application.properties 文件中添加 Sentinel 相关配置: ```properties spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080 ``` 8. 创建 Dubbo 服务接口 ```java public interface HelloService { String sayHello(String name); } ``` 9. 实现 Dubbo 服务接口 ```java @Service(version = "1.0.0") public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "Hello, " + name; } } ``` 10. 配置 Dubbo 服务提供者 ```java @Configuration public class DubboProviderConfig { @Bean public ApplicationConfig applicationConfig() { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("service-provider"); return applicationConfig; } @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress("nacos://127.0.0.1:8848"); return registryConfig; } @Bean public ProtocolConfig protocolConfig() { ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.setName("dubbo"); protocolConfig.setPort(20880); return protocolConfig; } @Bean public ProviderConfig providerConfig() { ProviderConfig providerConfig = new ProviderConfig(); providerConfig.setTimeout(3000); return providerConfig; } @Bean public ServiceConfig<HelloService> helloServiceServiceConfig() { ServiceConfig<HelloService> serviceConfig = new ServiceConfig<>(); serviceConfig.setInterface(HelloService.class); serviceConfig.setRef(new HelloServiceImpl()); serviceConfig.setVersion("1.0.0"); return serviceConfig; } } ``` 11. 创建测试类 ```java @RunWith(SpringRunner.class) @SpringBootTest public class HelloServiceTest { @Reference(version = "1.0.0") private HelloService helloService; @Test public void sayHelloTest() { String result = helloService.sayHello("World"); Assert.assertEquals("Hello, World", result); } } ``` 12. 启动项目 正常启动项目,并在浏览器中访问 http://localhost:8848/nacos,可以看到 Nacos 控制台。 在 Dubbo 服务提供者启动后,在 Dubbo 服务消费者中调用 Dubbo 服务,验证服务调用成功。 在 Sentinel 控制台中配置相关规则,验证 Sentinel 报警和限流功能。 在 RocketMQ 控制台中创建一个主题,发送消息,验证消息发送和接收功能。 在 Seata 控制台中创建一个事务分组,验证分布式事务功能。 以上就是使用 Spring Cloud Alibaba 技术栈搭建项目手脚架的步骤,可以根据实际需求进行扩展和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值