非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.
相关产品推荐
相关产品推荐

