升级过程中遇到一堆的坑,不过都一一解决了,主要是版本冲突,启动失败
以下是正确配置:
springboot依赖
org.springframework.boot
spring-boot-starter-parent
2.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-client
2.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;
/**
* Swagger2配置
*/
@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.net}")
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;
}
/**
* Spring Boot 2.6.x版本引入依赖 springfox-boot-starter (Swagger 3.0) 后,启动容器会报错:
*
* Failed to start bean ‘ documentationPluginsBootstrapper ‘ ; nested exception…
*
* 原因
* Springfox 假设 Spring MVC 的路径匹配策略是 ant-path-matcher,而 Spring Boot 2.6.x版本的默认匹配策略是 path-pattern-matcher,这就造成了上面的报错。
* @return
*/
@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}