Commit a9fdc6b42d4a2df297a39e4d9485f286d5591321

Authored by YunaiV
1 parent 56821608

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

yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
1 1 package cn.iocoder.yudao.framework.web.config;
2 2  
  3 +import cn.hutool.core.util.StrUtil;
3 4 import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
4 5 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
5 6 import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
... ... @@ -7,6 +8,7 @@ import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
7 8 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
8 9 import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
9 10 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
  11 +import com.google.common.collect.Maps;
10 12 import jakarta.annotation.Resource;
11 13 import jakarta.servlet.Filter;
12 14 import org.springframework.beans.factory.annotation.Value;
... ... @@ -14,6 +16,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
14 16 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
15 17 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
16 18 import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
  19 +import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
17 20 import org.springframework.boot.context.properties.EnableConfigurationProperties;
18 21 import org.springframework.boot.web.client.RestTemplateBuilder;
19 22 import org.springframework.boot.web.servlet.FilterRegistrationBean;
... ... @@ -26,35 +29,57 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
26 29 import org.springframework.web.filter.CorsFilter;
27 30 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
28 31 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  32 +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
  33 +
  34 +import java.util.Map;
  35 +import java.util.function.Predicate;
29 36  
30 37 @AutoConfiguration
31 38 @EnableConfigurationProperties(WebProperties.class)
32   -public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
  39 +public class YudaoWebAutoConfiguration {
33 40  
34   - @Resource
35   - private WebProperties webProperties;
36 41 /**
37 42 * 应用名
38 43 */
39 44 @Value("${spring.application.name}")
40 45 private String applicationName;
41 46  
42   - @Override
43   - public void configurePathMatch(PathMatchConfigurer configurer) {
44   - configurePathMatch(configurer, webProperties.getAdminApi());
45   - configurePathMatch(configurer, webProperties.getAppApi());
46   - }
  47 + @Bean
  48 + public WebMvcRegistrations webMvcRegistrations(WebProperties webProperties) {
  49 + return new WebMvcRegistrations() {
47 50  
48   - /**
49   - * 设置 API 前缀,仅仅匹配 controller 包下的
50   - *
51   - * @param configurer 配置
52   - * @param api API 配置
53   - */
54   - private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) {
55   - AntPathMatcher antPathMatcher = new AntPathMatcher(".");
56   - configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class)
57   - && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包
  51 + @Override
  52 + public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
  53 + var mapping = new RequestMappingHandlerMapping();
  54 + // 实例化时就带上前缀
  55 + mapping.setPathPrefixes(buildPathPrefixes(webProperties));
  56 + return mapping;
  57 + }
  58 +
  59 + /**
  60 + * 构建 prefix → 匹配条件的映射
  61 + */
  62 + private Map<String, Predicate<Class<?>>> buildPathPrefixes(WebProperties webProperties) {
  63 + AntPathMatcher antPathMatcher = new AntPathMatcher(".");
  64 + Map<String, Predicate<Class<?>>> pathPrefixes = Maps.newLinkedHashMapWithExpectedSize(2);
  65 + putPathPrefix(pathPrefixes, webProperties.getAdminApi(), antPathMatcher);
  66 + putPathPrefix(pathPrefixes, webProperties.getAppApi(), antPathMatcher);
  67 + return pathPrefixes;
  68 + }
  69 +
  70 + /**
  71 + * 设置 API 前缀,仅仅匹配 controller 包下的
  72 + */
  73 + private void putPathPrefix(Map<String, Predicate<Class<?>>> pathPrefixes, WebProperties.Api api, AntPathMatcher matcher) {
  74 + if (api == null || StrUtil.isEmpty(api.getPrefix())) {
  75 + return;
  76 + }
  77 + pathPrefixes.put(api.getPrefix(), // api 前缀
  78 + clazz -> clazz.isAnnotationPresent(RestController.class)
  79 + && matcher.match(api.getController(), clazz.getPackage().getName()));
  80 + }
  81 +
  82 + };
58 83 }
59 84  
60 85 @Bean
... ...