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

Spring Boot应用重构咨询:新增Journey无需修改代码方案

重构Spring Boot应用实现Journey的动态扩展

1. 结构化配置文件,实现Journey配置的动态加载

把原来分散的单个Journey配置改成列表形式,借助Spring的@ConfigurationProperties实现配置与代码的解耦,新增Journey仅需添加配置项,无需修改代码。

定义配置绑定类

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

import java.util.List;

@Data
@Validated
@ConfigurationProperties(prefix = "journeys")
public class JourneyProperties {
    private List<JourneyConfig> items;

    @Data
    public static class JourneyConfig {
        @NotNull
        private Integer id; // 每个Journey的唯一标识
        @NotBlank
        private String name;
        // 按需添加Journey所需的常量配置,比如计算因子、阈值等
        private String calculationFactor;
        private Integer threshold;
    }
}

配置文件示例(application.properties)

# 已有Journey配置
journeys.items[0].id=1
journeys.items[0].name=Journey1
journeys.items[0].calculationFactor=0.8
journeys.items[0].threshold=100

journeys.items[1].id=2
journeys.items[1].name=Journey2
journeys.items[1].calculationFactor=0.9
journeys.items[1].threshold=150

# 新增Journey仅需追加以下配置,无需改动代码
journeys.items[2].id=3
journeys.items[2].name=Journey3
journeys.items[2].calculationFactor=0.75
journeys.items[2].threshold=120

最后在启动类或配置类上添加@EnableConfigurationProperties(JourneyProperties.class),启用配置绑定功能。

2. 重构SQL查询,支持动态获取所有Journey数据

摒弃硬编码的单Journey查询,改成通用查询逻辑,避免新增Journey时修改SQL:

场景A:每个Journey对应数据库单条记录

直接查询所有Journey的原始数据,无需区分个体:

SELECT journey_id, metric1, metric2, metric3 FROM journey_metrics

场景B:多Journey字段存储在同一行(列存形式)

如果数据是按列存储不同Journey的指标(如journey1_metric1、journey2_metric1),建议用SQL列转行功能(如MySQL的UNION ALL)统一数据格式;若无法修改表结构,可使用MyBatis动态SQL根据配置生成查询字段:

<!-- MyBatis Mapper示例 -->
<select id="getAllJourneyMetrics" resultType="com.example.dto.JourneyRawData">
    SELECT
    <foreach collection="journeyIds" item="id" separator=",">
        journey${id}_metric1 as metric1_${id},
        journey${id}_metric2 as metric2_${id}
    </foreach>
    FROM journey_data
</select>

代码中传入从配置中获取的所有journeyId,即可动态生成适配所有Journey的SQL。

3. 实现通用的Journey映射与计算逻辑

删除getJourney1()、getJourney2()等硬编码方法,编写通用方法根据配置和原始数据生成Journey对象:

定义原始数据DTO

@Data
public class JourneyRawData {
    private Integer journeyId;
    private Double metric1;
    private Integer metric2;
    // 对应SQL查询的字段,按需扩展
}

通用服务逻辑

@Service
public class JourneyService {
    private final JourneyProperties journeyProperties;
    private final JourneyMapper journeyMapper;

    // 构造注入依赖
    public JourneyService(JourneyProperties journeyProperties, JourneyMapper journeyMapper) {
        this.journeyProperties = journeyProperties;
        this.journeyMapper = journeyMapper;
    }

    public List<Journey> getAllJourneys() {
        // 1. 获取所有Journey的原始数据
        List<JourneyRawData> rawDataList = journeyMapper.getAllJourneyMetrics();

        // 2. 遍历配置,匹配数据并生成Journey对象
        return journeyProperties.getItems().stream()
                .map(config -> buildJourney(config, rawDataList))
                .collect(Collectors.toList());
    }

    private Journey buildJourney(JourneyConfig config, List<JourneyRawData> rawDataList) {
        // 根据配置ID匹配对应原始数据
        JourneyRawData rawData = rawDataList.stream()
                .filter(data -> data.getJourneyId().equals(config.getId()))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Journey " + config.getId() + " 数据不存在"));

        // 执行原有的计算与映射逻辑,复用配置中的常量
        Journey journey = new Journey();
        journey.setId(config.getId());
        journey.setName(config.getName());
        journey.setCalculatedValue(rawData.getMetric1() * Double.parseDouble(config.getCalculationFactor()));
        journey.setThreshold(config.getThreshold());
        // 其他属性映射逻辑

        return journey;
    }
}

4. 最终API接口实现

接口层直接调用通用方法,无需修改即可支持新增Journey:

@RestController
@RequestMapping("/journeys")
public class JourneyController {
    private final JourneyService journeyService;

    public JourneyController(JourneyService journeyService) {
        this.journeyService = journeyService;
    }

    @GetMapping
    public List<Journey> getAllJourneys() {
        return journeyService.getAllJourneys();
    }
}

扩展说明

  • 配置验证:通过@Validated和JSR-380注解确保配置完整性,避免无效配置导致的异常。
  • 异常处理:可扩展buildJourney方法的异常逻辑,比如返回空Journey实例或记录告警日志,而非直接抛出异常。
  • 性能优化:数据量较大时,可添加缓存机制或优化SQL查询效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:32:51