升级过程中遇到一堆的坑,不过都一一解决了,主要是版本冲突,启动失败
以下是正确配置:
springboot依赖
org.springframework.boot spring-boot-starter-parent2.6.6
dubbo依赖
org.apache.dubbo
dubbo-spring-boot-starter
${dubbo.version}
org.apache.dubbo
dubbo
${dubbo.version}
nacos依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
2021.0.1.0
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
2021.0.1.0
nacos-client依赖
com.alibaba.nacos nacos-client2.0.4
升级到springboot2.6.6后,swagger2会出问题,所以需要在SwaggerConfig类中添加以下代码
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private void customizeSpringfoxHandlerMappings(List mappings) {
List copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
SwaggerConfig完整代码
package com.dengfeng.framework.common.config;
import com.google.common.collect.Sets;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Configuration
@EnableSwagger2
@Profile({"local", "dev", "test"})
public class SwaggerConfig {
@Value("${spring.application.name:校园在线}")
private String applicationName;
@Value("${dadaodata.app.description:用于开发环境的 RestFul Api 文档}")
private String dadaodata_app_description;
@Value("${dadaodata.app.termsOfServiceUrl:https://www.zgxyzx.ne}")
private String dadaodata_app_termsOfServiceUrl;
@Value("${dadaodata.app.version:v1}")
private String dadaodata_app_version;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.protocols(Sets.newHashSet("http"))
.select()
.paths(PathSelectors.any())
.build()
.globalOperationParameters(commonParameters())
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(applicationName)
.version(dadaodata_app_version)
.description(dadaodata_app_description)
.build();
}
private List commonParameters() {
List parameters = new ArrayList<>();
parameters.add(new ParameterBuilder()
.name("version")
.description("全局默认版本号")
.modelRef(new ModelRef("String"))
.parameterType("path")
.defaultValue(dadaodata_app_version)
.required(true)
.build());
return parameters;
}
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private void customizeSpringfoxHandlerMappings(List mappings) {
List copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}
swagger依赖
com.github.xiaoymin
knife4j-spring
com.github.xiaoymin
knife4j-spring-ui
io.springfox
springfox-swagger2
io.springfox
springfox-swagger-ui
上面加上了knife4j依赖,API界面更漂亮
Dobbo3服务启动后注册到nacos中,效果
Nacos Docker
还有一点非常重要,nacos启动的时候要暴露几个端口,nacos新版本用到grpc,当nacos客户端升级为2.x版本后,新增了gRPC的通信方式,新增了两个端口。这两个端口在nacos原先的端口上(默认8848),进行一定偏移量自动生成.。
比如我用docker安装暴露了4个端口,如果只暴露了8848端口,启动会报以下错误:
Nacos Server check fail, please check server 101.200.84.241 ,port 9848 is available
参考文档地址:https://nacos.io/zh-cn/docs/quick-start-docker.html
用docker镜像启动nacos2,镜像下载:Docker Hub
docker run --name nacos2 -e MODE=standalone -p 8848:8848 -p 8849:8849 -p 9848:9848 -p 9849:9849-d nacos/nacos-server
最近spring重大漏洞CVE-2022-22968会在springboot2.6.7版本中解决,下次记得升级
漏洞说明:Spring Framework RCE, Early Announcement
异常处理
java.lang.NoSuchMethodError: com.alibaba.nacos.api.config.ConfigService.publishConfigCas(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z *************************** APPLICATION FAILED TO START *************************** Description: An attempt was made to call a method that does not exist. The attempt was made from the following location: org.apache.dubbo.metadata.store.nacos.NacosConfigServiceWrapper.publishConfigCas(NacosConfigServiceWrapper.java:65) The following method did not exist: com.alibaba.nacos.api.config.ConfigService.publishConfigCas(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z The calling method's class, org.apache.dubbo.metadata.store.nacos.NacosConfigServiceWrapper, was loaded from the following location: jar:file:/Users/liujunguang1/.m2/repository/org/apache/dubbo/dubbo/3.0.6/dubbo-3.0.6.jar!/org/apache/dubbo/metadata/store/nacos/NacosConfigServiceWrapper.class The called method's class, com.alibaba.nacos.api.config.ConfigService, is available from the following locations: jar:file:/Users/liujunguang1/.m2/repository/com/alibaba/nacos/nacos-api/1.4.2/nacos-api-1.4.2.jar!/com/alibaba/nacos/api/config/ConfigService.class The called method's class hierarchy was loaded from the following locations: com.alibaba.nacos.api.config.ConfigService: file:/Users/liujunguang1/.m2/repository/com/alibaba/nacos/nacos-api/1.4.2/nacos-api-1.4.2.jar Action: Correct the classpath of your application so that it contains compatible versions of the classes org.apache.dubbo.metadata.store.nacos.NacosConfigServiceWrapper and com.alibaba.nacos.api.config.ConfigService
上面的异常需要升级nacos-client
2.0.4 com.alibaba.nacos nacos-client${nacos-client.version}



