夜雨聆风学习资料网

ARTICLE · 1038902

一套SpringBoot后端支撑多APP,除了策略模式还有哪些方案?

一套SpringBoot后端支撑多APP,除了策略模式还有哪些方案?

在上一篇文章,我们讲解了最常用的3种方案:配置文件、策略模式、分包+条件注解。 很多同学留言问:除了这几种,还有没有别的架构方案?不同方案适合什么项目规模?

今天一次性盘点剩下主流方案,从简单到复杂,附带优缺点,方便选型。

方案1:AOP切面,拦截方法做差异化增强

核心思想:公共业务代码不动,通过AOP切面,根据当前app-code,对指定方法做前置/后置增强。 适合场景:不同APP只是在原有逻辑上追加额外动作,不改动主流程。 举个例子:APP-A下单后需要推送短信,APP-B下单不需要短信;或者APP-A需要额外记录操作日志。

代码示例:

@Aspect
@Component
public class AppOrderAspect {

    @AfterReturning("execution(* com.xxx.service.OrderService.createOrder(..))")
    public void afterCreateOrder(){
        String appCode = AppContext.getAppCode();
        if("app-a".equals(appCode)){
            // APPA专属:发送短信通知
            sendSms();
        }
    }

    private void sendSms(){
        System.out.println("发送短信");
    }
}

✅ 优点:原有业务代码完全不用改动,无侵入,只增强附加逻辑。 ❌ 缺点:不能修改主逻辑返回值;差异化逻辑复杂时切面会很臃肿,可读性差。

方案2:数据库动态配置 + 规则引擎

核心思想:把APP差异化规则全部放到数据库里,不用改代码、不用重启服务。 比如:不同APP的折扣比例、是否开启弹窗、按钮是否显示、限流阈值全部存在数据库。 如果规则比较复杂,可以引入轻量规则引擎:QLExpress、Drools。

适用场景:产品经常调整APP的差异化规则,不想频繁发版本上线。 ✅ 优点:规则动态配置,不用发布代码,运营可后台配置。 ❌ 缺点:学习成本高;复杂业务规则调试困难;不适合核心业务逻辑差异化,适合配置类规则。

方案3:插件化架构(SPI / Spring Plugin)

核心思想:公共基座工程不变,每个APP的定制逻辑打包成独立插件。运行时动态加载对应APP插件。 Java可以使用JDK SPI,或者Spring Plugin框架实现。 适用场景:APP数量多、定制逻辑很重,希望插件可以独立开发、独立测试。

✅ 优点:基座和插件完全解耦,插件可以单独开发;新增APP只新增插件,不改动基座代码。 ❌ 缺点:架构复杂度高,调试麻烦;中小型项目会过度设计。

方案4:接口路由转发(网关层做差异化)

核心思想:公共逻辑在主后端,差异化接口单独拆成微服务,在Spring Cloud Gateway网关根据app-code路由。 请求到达网关,读取请求头app-code:公共接口转发到主SpringBoot服务;APP专属接口转发到对应APP微服务。

适用场景:部分APP定制逻辑非常庞大,未来有可能单独拆分独立服务。 ✅ 优点:差异化代码彻底隔离;后期某个APP需要独立部署,直接拆分很方便。 ❌ 缺点:引入网关,架构变重;简单项目没必要。

方案5:基于注解 + 动态Bean选择

核心思想:自定义注解,标记不同APP对应的实现类,写一个通用Bean选择器,运行时根据app-code匹配对应的Bean。 和策略模式很像,但更加灵活,可以批量管理大量差异化组件。

示例注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AppSupport {
    String[] value(); // 支持哪些app-code
}
@Component
@AppSupport("app-a")
public class AppANotice implements NoticeService{
    @Override
    public void sendNotice(){
        System.out.println("APP A通知");
    }
}

✅ 优点:统一管理注解,方便查看每个类支持哪些APP;代码可读性高。 ❌ 缺点:需要自己维护Bean注册和选择逻辑,少量差异化场景没必要。

方案6:特性开关(Feature Toggle)

核心思想:使用特性开关框架(如OpenFeature),每个差异化功能作为一个开关,绑定对应的APP。 同一个接口,根据APP判断是否开启某个特性。 适合场景:同一个APP内部也需要灰度、版本控制,同时多APP共用一套开关体系。

✅ 优点:不仅区分APP,还支持灰度发布;可以线上一键关闭某个APP的功能。 ❌ 缺点:大量开关容易造成代码腐烂,形成“开关地狱”。

重要提醒:选型避坑

  1. 不要过度设计!
    很多同学一上来直接上插件化、规则引擎。如果只有2~3个APP,差异很小,策略模式就足够了。架构越复杂,维护成本越高。
  2. 所有方案通用底线:数据隔离!
    无论用哪套方案,数据库表必须带app_code,Redis缓存key拼接app-code,防止不同APP数据串掉,这是底线。
  3. 尽量避免硬编码if/else
    当APP数量超过3个,大量if else会让代码维护难度指数上升,尽量用上面的方案替代。

总结

方案没有好坏,只有适不适合项目:

  • 小项目,APP数量少:优先策略模式、AOP;
  • 规则经常变动:数据库配置+规则引擎;
  • 大型项目,APP持续增多:插件化、网关路由。

💬 互动:你们项目使用的是哪一种方案?踩过哪些坑?欢迎评论区交流。

相关学习资料