Przeglądaj źródła

fix:【framework 框架】确保在 Bean 创建前映射应用请求前缀

YunaiV 8 miesięcy temu
rodzic
commit
a9fdc6b42d

+ 43 - 18
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.framework.web.config;
 
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
 import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
@@ -7,6 +8,7 @@ import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
 import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
+import com.google.common.collect.Maps;
 import jakarta.annotation.Resource;
 import jakarta.servlet.Filter;
 import org.springframework.beans.factory.annotation.Value;
@@ -14,6 +16,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -26,35 +29,57 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 import org.springframework.web.filter.CorsFilter;
 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+import java.util.Map;
+import java.util.function.Predicate;
 
 @AutoConfiguration
 @EnableConfigurationProperties(WebProperties.class)
-public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
+public class YudaoWebAutoConfiguration {
 
-    @Resource
-    private WebProperties webProperties;
     /**
      * 应用名
      */
     @Value("${spring.application.name}")
     private String applicationName;
 
-    @Override
-    public void configurePathMatch(PathMatchConfigurer configurer) {
-        configurePathMatch(configurer, webProperties.getAdminApi());
-        configurePathMatch(configurer, webProperties.getAppApi());
-    }
+    @Bean
+    public WebMvcRegistrations webMvcRegistrations(WebProperties webProperties) {
+        return new WebMvcRegistrations() {
 
-    /**
-     * 设置 API 前缀,仅仅匹配 controller 包下的
-     *
-     * @param configurer 配置
-     * @param api        API 配置
-     */
-    private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) {
-        AntPathMatcher antPathMatcher = new AntPathMatcher(".");
-        configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class)
-                && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包
+            @Override
+            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
+                var mapping = new RequestMappingHandlerMapping();
+                // 实例化时就带上前缀
+                mapping.setPathPrefixes(buildPathPrefixes(webProperties));
+                return mapping;
+            }
+
+            /**
+             * 构建 prefix → 匹配条件的映射
+             */
+            private Map<String, Predicate<Class<?>>> buildPathPrefixes(WebProperties webProperties) {
+                AntPathMatcher antPathMatcher = new AntPathMatcher(".");
+                Map<String, Predicate<Class<?>>> pathPrefixes = Maps.newLinkedHashMapWithExpectedSize(2);
+                putPathPrefix(pathPrefixes, webProperties.getAdminApi(), antPathMatcher);
+                putPathPrefix(pathPrefixes, webProperties.getAppApi(), antPathMatcher);
+                return pathPrefixes;
+            }
+
+            /**
+             * 设置 API 前缀,仅仅匹配 controller 包下的
+             */
+            private void putPathPrefix(Map<String, Predicate<Class<?>>> pathPrefixes, WebProperties.Api api, AntPathMatcher matcher) {
+                if (api == null || StrUtil.isEmpty(api.getPrefix())) {
+                    return;
+                }
+                pathPrefixes.put(api.getPrefix(), // api 前缀
+                        clazz -> clazz.isAnnotationPresent(RestController.class)
+                                && matcher.match(api.getController(), clazz.getPackage().getName()));
+            }
+
+        };
     }
 
     @Bean