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

非Spring Boot环境下Spring MVC控制器触发Camel路由问题

解决方案:在Spring MVC控制器中触发Camel路由(非启动时自动执行)

针对你的问题,核心问题在于你直接启停整个CamelContext,不仅可能导致路由未完成文件处理就被终止,而且这种方式也不够灵活。下面提供两种更可靠的实现方案,帮你实现仅在访问JSP首页时触发文件移动路由的需求:


方案一:单独控制指定路由的启停(推荐)

这种方式不需要启停整个Camel上下文,只针对目标路由进行操作,更高效且可控。

步骤1:修改XML路由配置

给路由添加唯一ID,并配置文件组件参数,让它处理一次文件后就进入 idle 状态,避免持续轮询:

<camel:camelContext id="camelContext" trace="true" autoStartup="false">
    <!-- 给路由设置ID,方便后续单独控制 -->
    <camel:route id="fileMoveRoute" autoStartup="false">
        <!-- 配置file组件:立即轮询、仅处理一个文件、处理完停止轮询 -->
        <camel:from uri="file:data/inbox?noop=true&consumer.initialDelay=0&consumer.maxMessagesPerPoll=1&consumer.delay=-1" />
        <camel:to uri="file:data/outbox" />
    </camel:route>
</camel:camelContext>

步骤2:修改控制器代码

在控制器中获取指定路由,启动它并等待处理完成后再停止:

@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model) throws Exception {
    CamelContext camelContext = applicationContext.getBean("camelContext", CamelContext.class);
    String targetRouteId = "fileMoveRoute";

    try {
        // 仅当路由未启动时才启动
        if (!camelContext.isRouteStarted(targetRouteId)) {
            camelContext.startRoute(targetRouteId);
            System.out.println("文件移动路由已启动,开始处理文件...");
        }

        // 等待文件处理完成(生产环境建议用Camel事件监听替代sleep,这里为简化用sleep)
        Thread.sleep(1000);
        System.out.println("文件处理完成");
    } finally {
        // 确保路由最终被停止
        if (camelContext.isRouteStarted(targetRouteId)) {
            camelContext.stopRoute(targetRouteId);
            System.out.println("文件移动路由已停止");
        }
    }
    return "index";
}

方案二:使用ProducerTemplate直接触发路由逻辑

这种方式无需维护路由的启停状态,通过调用direct端点直接触发路由执行,更灵活。

步骤1:修改XML路由配置

将路由入口改为direct端点,并用pollEnrich获取文件:

<camel:camelContext id="camelContext" trace="true" autoStartup="true">
    <camel:route id="fileMoveRoute">
        <!-- 用direct作为触发入口 -->
        <camel:from uri="direct:triggerFileMove" />
        <!-- 从inbox获取文件,超时1秒 -->
        <camel:pollEnrich uri="file:data/inbox?noop=true" timeout="1000"/>
        <camel:to uri="file:data/outbox" />
    </camel:route>
    <!-- 配置ProducerTemplate,用于在控制器中调用路由 -->
    <camel:template id="producerTemplate" camelContextId="camelContext" />
</camel:camelContext>

步骤2:修改控制器代码

注入ProducerTemplate,通过它发送消息触发路由:

@Autowired
private ProducerTemplate producerTemplate;

@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model) throws Exception {
    System.out.println("开始触发文件移动操作...");
    // 发送消息到direct端点,触发路由执行
    producerTemplate.sendBody("direct:triggerFileMove", null);
    System.out.println("文件移动操作已触发");
    return "index";
}

额外说明

关于你之前@Autowired注入CamelContext无效的问题,建议检查:

  • 控制器类是否添加了@Controller注解,且Spring配置中扫描了该控制器所在的包
  • CamelContext的bean是否在Spring XML中正确定义(你用getBean能拿到,说明bean是存在的,可能是注入时的类型匹配问题,尝试用@Autowired CamelContext camelContext替代强转)

内容的提问来源于stack exchange,提问作者Eshan I.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:52:59