记录一下项目更新版本依赖踩坑

这个是项目最早的版本依赖
在这里插入图片描述

这里最初是最初是升级到 2.5.7 偷了个懒 这个版本的兼容性比较强 就选了这版本 也不用去修改就手动的去换了一下RabbitMQ的依赖 因为这边项目有AMQP 风险预警
1.spring-amqp版本低于2.4.17的用户应升级到2.4.17
2.spring-amqp是3.0.0至3.0.9版本的用户应升级至3.0.10

之前用的是starter 依赖

    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-amqp</artifactId>
         <version>3.0.10</version>
    </dependency>        

然后打包后发现并没有什么用 版本依旧是跟着springboot走的 就手动换成了单个依赖

单个依赖

    <properties>
        <spring-amqp.version>2.4.17</spring-amqp.version>
        <spring-rabbit.version>2.4.17</spring-rabbit.version>
    </properties>
    
    <dependencyManagement>
          <dependencies>
            <!-- rabbit mq 配置 -->
            <dependency>
                <groupId>org.springframework.amqp</groupId>
                <artifactId>spring-amqp</artifactId>
                <version>${spring-amqp.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.amqp</groupId>
                <artifactId>spring-rabbit</artifactId>
                <version>${spring-rabbit.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

就在我也觉得没啥问题的时候 发现 swagger 在线下运行是正常的 到线上就显示不出来 一开始是以为升级版本后跨域的影响 毕竟后台管理明显提示是有跨域 好嘛 那就改跨域
这里 着重就是改了一个 addAllowedOriginPattern

修改前

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
   @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        /* 是否允许请求带有验证信息 */
        corsConfiguration.setAllowCredentials(true);
        /* 允许访问的客户端域名 */
        corsConfiguration.addAllowedOrigin("*");
        /* 允许服务端访问的客户端请求头 */
        corsConfiguration.addAllowedHeader("*");
        /* 允许访问的方法名,GET POST等 */
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

修改后

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
   @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        /* 是否允许请求带有验证信息 */
        corsConfiguration.setAllowCredentials(true);
        /* 允许访问的客户端域名 */
        corsConfiguration.addAllowedOriginPattern("*");
        /* 允许服务端访问的客户端请求头 */
        corsConfiguration.addAllowedHeader("*");
        /* 允许访问的方法名,GET POST等 */
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

心想这下总该好了吧 结果一上线又是swagger访问不到 甚至连响应返回的数据都不是json的了 我想着难道 Filter 也要跟着改 这块要改的话变动有点大 心一横 不行就把swagger升级到3.0 说不定就是版本问题

引了最新版本的Knife4j

      <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
       </dependency>

修改config

@EnableOpenApi
@Configuration
public class SwaggerConfig {

    private static final String SPLITOR = ";";

    public static Predicate<RequestHandler> basePackage(final String basePackage) {
        return input -> declaringClass(input).map(handlerPackage(basePackage)).orElse(true);
    }

    private static Optional<Class<?>> declaringClass(RequestHandler input) {
        return Optional.ofNullable(input.declaringClass());
    }

    private static Function<Class<?>, @Nullable Boolean> handlerPackage(final String basePackage) {
        return input -> {
            // 循环判断匹配
            for (String strPackage : basePackage.split(SPLITOR)) {
                boolean isMatch = input.getPackage().getName().startsWith(strPackage);
                if (isMatch) {
                    return true;
                }
            }
            return false;
        };
    }

    /**
     * 配置基本信息
     * @return
     */
    @Bean
    public ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("xxxx sss端API接口文档")
                .description("swagger app restful api")
                .termsOfServiceUrl("https://xxx.xxx.xxx")
                .contact(new Contact("Dotclv","",""))
                .version("1.0")
                .build();
    }

    /**
     * 配置文档生成最佳实践
     * @param apiInfo
     * @return
     */
    @Bean
    public Docket createRestApi(ApiInfo apiInfo) {
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo)
                .groupName("SwaggerGroupOneAPI")
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(Collections.singletonList(securityScheme()))
                .globalOperationParameters(setHeaderToken());
    }

    @Bean
    public Docket groupCommon() {
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(this.apiInfo())
                .ignoredParameterTypes(ModelAttribute.class)
                .groupName("通用模块")
                .select()
                //此包路径下的类,才生成接口文档
                .apis(basePackage("xxx.xxx.xxxx.common"))
                //加了ApiOperation注解的类,才生成接口文档
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(Collections.singletonList(securityScheme()))
                .securityContexts(securityContexts());

    }

    /**
     * 新增 securityContexts 保持登录状态
     */
    private List<SecurityContext> securityContexts() {
        return new ArrayList(
                Collections.singleton(SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .forPaths(PathSelectors.regex("^(?!auth).*$"))
                        .build())
        );
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return new ArrayList(
                Collections.singleton(new SecurityReference(DefContants.X_ACCESS_TOKEN, authorizationScopes)));
    }

    /***
     * oauth2配置
     * 需要增加swagger授权回调地址
     * http://localhost:8888/webjars/springfox-swagger-ui/o2c.html
     * @return
     */
    @Bean
    SecurityScheme securityScheme() {
        return new ApiKey(DefContants.X_ACCESS_TOKEN, DefContants.X_ACCESS_TOKEN, "header");
    }

    /**
     * JWT token
     *
     * @return
     */
    private List<Parameter> setHeaderToken() {
        ParameterBuilder tokenPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<>();
        tokenPar.name(DefContants.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
        pars.add(tokenPar.build());
        return pars;
    }


    /**
    * 增加如下配置可解决Spring Boot 6.x 与Swagger 3.0.0 不兼容问题
    **/
    @Bean
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        String basePath = webEndpointProperties.getBasePath();
        EndpointMapping endpointMapping = new EndpointMapping(basePath);
        boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
        return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
    }
    private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
        return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
    }
}

你以为完了 不不 它又出问题了 升级到3.0 本地运行没有一点问题 但是一打包到线上运行就报错mapstruct 转换异常 什么swagger-2.0的错误 我就纳闷了我用的是3.0啊 咋报2.0的错误 千搜万搜 找了一堆没有用的解释文章 后面在一个github的评论区看到一老哥说 运行时和编译时依赖不一样
心想这还玩个花 加个依赖试试

       <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>mapstruct</artifactId>
                    <groupId>org.mapstruct</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
        </dependency>

后面编译运行果然没有问题 swagger也正常了 接口也返回数据也正常了 真难
改都改到这了算了 直接升springboot 版本到2.x最后一个版本算了 就又改了 parent 的版本到2.7.16 后面在运行就没有其他问题了 但是它又报循环依赖 好嘛 这个还要手动配置

spring:
  main:
    allow-circular-references: true
    lazy-initialization: true
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

这边循环依赖 懒加载 包括2.6后整合swagger的依赖启动报错 一起配置了 然后这会是真的没有问题了 真是一波好几折

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐