You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot中如何基于配置库规范分组请求字段并解析子规则

问题描述

在SpringBoot微服务中,接口会接收一个List<String>类型的Solr字段名列表,需要按照配置库中的规则将这些字段分组(例如gender_s、age_f、job_s需要归到demography分组),但不想用冗余的if-else代码实现分组逻辑;同时需要解析包含subrules的字段,展示对应的view-name。目前用@Value注解读取配置库内容,但因配置数据量较大,希望有更简洁高效的实现方案。

配置库内容如下:

project.search.categories:
  sms:
    view-name: Sms
    rules:
      sms:
        view-name: operator tarafindan atilan aylik atilan sms sayisi
        solr-name: sms_count_f
        view-type: NUMERIC
        solr-type: BIGINT
        min-value: 0
        max-value: 150
        max-range: 50  
  demography:
    view-name: Demografi
    rules:
      gender:
        view-name: Cinsiyet
        solr-name: gender_s
        view-type: SINGLE_SELECT
        solr-type: STRING
      age:
        view-name: Yas
        solr-name: age_f
        view-type: NUMERIC
        solr-type: BIGINT
        min-value: 0
        max-value: 150
        max-range: 50
      job:
        view-name: Meslek
        solr-name: job_s
        view-type: MULTI_SELECT
        solr-type: STRING
        values: JOBS
      citizenship:
        view-name: Uyruk
        solr-name: citizenship_s
        view-type: MULTI_SELECT
        solr-type: STRING
        values: ROAMING_COUNTRY 
  interest:
    view-name: Ilgi Alanlari
    rules:
      betting:
        view-name: Spor Bahisleri ile ilgilenen
        solr-name: betting__sports_interest_f
        view-type: SINGLE_SELECT
        solr-type: TINYINT
        values: 1@Evet, 0@Hayır
      career:
        view-name: Kariyer
        solr-name: career_interest_f
        view-type: SINGLE_SELECT
        solr-type: TINYINT
        values: 1@Evet, 0@Hayır
      coupons:
        view-name: İndirimler ile ilgilenen
        solr-name: coupons__discount_interest_f
        view-type: SINGLE_SELECT
        solr-type: TINYINT
        values: 1@Evet, 0@Hayır
      device_site:
        view-name: Teknoloji ile ilgilenen
        solr-name: device_site__technology_interest_f
        view-type: SINGLE_SELECT
        solr-type: TINYINT
        values: 1@Evet, 0@Hayır
      e-commerce:
        view-name: E-ticaret ile ilgilenen
        solr-name: ecommerce_interest_f
        view-type: MULTISELECT_TINYINT
        solr-type: TINYINT
        values: 1@Evet, 0@Hayır
        subrules:
          home_furniture:
            view-name: Ev dekorasyonu ile ilgilenen
            solr-name: ecommerce__home_furniture_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          clothing:
            view-name: Tekstil ile ilgilenen
            solr-name: ecommerce__clothing_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          automobiles:
            view-name: Otomobil ile ilgilenen
            solr-name: ecommerce__automobiles_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          market_place:
            view-name: Online Market Place Alısveris ile ilgilenen
            solr-name: ecommerce__market_place_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          sports:
            view-name: Spor Alışverişi ile ilgilenen
            solr-name: ecommerce__sports_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          technology:
            view-name: Teknoloji Alışverişi ile ilgilenen
            solr-name: ecommerce__technology_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          books:
            view-name: Kitap Alışverisi ile ilgilenen
            solr-name: ecommerce__books_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          kids:
            view-name: Çocuk için Alışveriş yapan
            solr-name: ecommerce__kids_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
          comparison:
            view-name: Fiyat Karşılaştırma # convert
            solr-name: ecommerce__comparison_interest_f
            view-type: SINGLE_SELECT
            solr-type: TINYINT
            values: 1@Evet, 0@Hayır
解决方案

1. 用@ConfigurationProperties绑定配置,替代@Value

创建对应的实体类,让Spring自动将配置映射为Java对象,避免手动用@Value逐个读取:

实体类定义

// 根配置类
@ConfigurationProperties(prefix = "project.search")
@Data
public class SearchConfig {
    private Map<String, Category> categories;

    @Data
    public static class Category {
        private String viewName; // 对应配置里的view-name
        private Map<String, Rule> rules;
    }

    @Data
    public static class Rule {
        private String viewName;
        private String solrName;
        private String viewType;
        private String solrType;
        private Integer minValue;
        private Integer maxValue;
        private Integer maxRange;
        private String values;
        private Map<String, Rule> subrules; // 处理子规则
    }
}

启用配置绑定

在启动类或配置类上添加@EnableConfigurationProperties(SearchConfig.class):

@SpringBootApplication
@EnableConfigurationProperties(SearchConfig.class)
public class SearchServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(SearchServiceApplication.class, args);
    }
}

2. 预构建缓存映射,避免重复遍历配置

在服务启动时,将Solr字段名与所属分组、规则信息构建成全局缓存,这样请求到来时直接查询缓存,无需遍历整个配置结构:

@Component
public class SolrFieldMappingCache {
    private final Map<String, String> solrFieldToCategory = new HashMap<>();
    private final Map<String, Rule> solrFieldToRule = new HashMap<>();

    public SolrFieldMappingCache(SearchConfig searchConfig) {
        // 遍历所有分组和规则,构建缓存
        searchConfig.getCategories().forEach((categoryKey, category) -> {
            // 处理主规则
            category.getRules().forEach((ruleKey, rule) -> {
                solrFieldToCategory.put(rule.getSolrName(), categoryKey);
                solrFieldToRule.put(rule.getSolrName(), rule);
                // 处理子规则
                if (rule.getSubrules() != null) {
                    rule.getSubrules().forEach((subRuleKey, subRule) -> {
                        solrFieldToCategory.put(subRule.getSolrName(), categoryKey);
                        solrFieldToRule.put(subRule.getSolrName(), subRule);
                    });
                }
            });
        });
    }

    // 获取字段所属分组
    public String getCategoryBySolrField(String solrField) {
        return solrFieldToCategory.get(solrField);
    }

    // 获取字段对应的规则(含view-name)
    public Rule getRuleBySolrField(String solrField) {
        return solrFieldToRule.get(solrField);
    }
}

3. 业务逻辑实现

在业务类中直接注入缓存,处理字段分组和view-name解析,完全不需要if-else:

@Service
public class SearchFieldService {
    private final SolrFieldMappingCache mappingCache;

    @Autowired
    public SearchFieldService(SolrFieldMappingCache mappingCache) {
        this.mappingCache = mappingCache;
    }

    // 对输入的Solr字段列表进行分组
    public Map<String, List<String>> groupSolrFields(List<String> solrFields) {
        Map<String, List<String>> result = new HashMap<>();
        solrFields.forEach(field -> {
            String category = mappingCache.getCategoryBySolrField(field);
            if (category != null) {
                result.computeIfAbsent(category, k -> new ArrayList<>()).add(field);
            }
            // 可添加字段不存在时的默认处理逻辑
        });
        return result;
    }

    // 获取字段对应的view-name,包括子规则
    public Map<String, String> getViewNames(List<String> solrFields) {
        Map<String, String> result = new HashMap<>();
        solrFields.forEach(field -> {
            Rule rule = mappingCache.getRuleBySolrField(field);
            if (rule != null) {
                result.put(field, rule.getViewName());
            }
        });
        return result;
    }
}

优势说明

  • 完全消除if-else冗余代码,配置变更时无需修改业务逻辑,只需调整配置文件
  • 缓存预构建在启动阶段,请求处理时直接查Map,性能高效
  • 配置与代码解耦,符合Spring Boot最佳实践
  • 天然支持子规则的解析,无需额外递归处理

内容的提问来源于stack exchange,提问作者pasaklikukuli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 15:05:33