为了账号安全,请及时绑定邮箱和手机立即绑定

Storm框架:Storm整合springboot

标签:
SpringBoot

我们知道Storm本身是一个独立运行的分布式流式数据处理框架,Springboot也是一个独立运行的web框架。那么如何在Strom框架中集成Springboot使得我们能够在Storm开发中运用Spring的Ioc容器及其他如Spring Jpa等功能呢?我们先来了解以下概念:

  • Storm主要的三个Component:Topology、Spout、Bolt。Topology作为主进程控制着spout、bolt线程的运行,他们相当于独立运行的容器分布于storm集群中的各个机器节点。

  • SpringApplication:是配置Spring应用上下文的起点。通过调用SpringApplication.run()方法它将创建ApplicationContext实例,这是我们能够使用Ioc容器的主要BeanFactory。之后Spring将会加载所有单例模式的beans,并启动后台运行的CommandLineRunner beans等。

  • ApplicationContextAware:这是我们能够在普通Java类中调用Spring容器里的beans的关键接口。

5be4578d0001910704000260.jpg

实现原理

Storm框架中的每个Spout和Bolt都相当于独立的应用,Strom在启动spout和bolt时提供了一个open方法(spout)和prepare方法(bolt)。我们可以把初始化Spring应用的操作放在这里,这样可以保证每个spout/bolt应用在后续执行过程中都能获取到Spring的ApplicationContext,有了ApplicationContext实例对象,Spring的所有功能就都能用上了。

  • Spout.open方法实现

@Overridepublic void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {    //启动Springboot应用
    SpringStormApplication.run();    this.map = map;    this.topologyContext = topologyContext;    this.spoutOutputCollector = spoutOutputCollector;
}
  • Bolt.prepare方法实现

@Overridepublic void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {    //启动Springboot应用
    SpringStormApplication.run();    this.map = map;    this.topologyContext = topologyContext;    this.outputCollector = outputCollector;
}
  • SpringStormApplication启动类

@SpringBootApplication@ComponentScan(value = "com.xxx.storm")public class SpringStormApplication {
    /**
     * 非工程启动入口,所以不用main方法
     * @param args
     */
    public static void run(String ...args) {
        SpringApplication app = new SpringApplication(SpringStormApplication.class);        //我们并不需要web servlet功能,所以设置为WebApplicationType.NONE
        app.setWebApplicationType(WebApplicationType.NONE);        //忽略掉banner输出
        app.setBannerMode(Banner.Mode.OFF);        //忽略Spring启动信息日志
        app.setLogStartupInfo(false);
        app.run(args);
    }
}

与我们传统的Springboot应用启动入口稍微有点区别,主要禁用了web功能,看下正常的启动方式:

@SpringBootApplication@ComponentScan(value = "com.xxx.web")
public class PlatformApplication {    public static void main(String[] args) {        SpringApplication.run(PlatformApplication.class, args);
    }
}
  • 在spout/bolt中调用了SpringStormApplication.run方法后,我们还需要能够拿到ApplicationContext容器对象,这时候我们还需要实现ApplicationContextAware接口,写个工具类BeanUtils:

@Componentpublic class BeanUtils implements ApplicationContextAware {    private static ApplicationContext applicationContext = null;    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        if (BeanUtils.applicationContext == null) {
            BeanUtils.applicationContext = applicationContext;
        }
    }    
    public static ApplicationContext getApplicationContext() {        return applicationContext;
    }    
    public static Object getBean(String name) {        return getApplicationContext().getBean(name);
    }    
    public static <T> T getBean(Class<T> clazz) {        return getApplicationContext().getBean(clazz);
    }    
    public static <T> T getBean(String name, Class<T> clazz) {        return getApplicationContext().getBean(name, clazz);
    }
}

通过@Component注解使得Spring在启动时能够扫描到该bean,因为BeanUtils实现了ApplicationContextAware接口,Spring会在启动成功时自动调用BeanUtils.setApplicationContext方法,将ApplicationContext对象保存到工具类的静态变量中,之后我们就可以使用BeanUtils.getBean()去获取Spring容器中的bean了。

写个简单例子

  • 在FilterBolt的execute方法中获取Spring bean

@Overridepublic void execute(Tuple tuple) {
    FilterService filterService = (FilterService) BeanUtils.getBean("filterService");
    filterService.deleteAll();
}
  • 定义FilterService类,这时候我们就可以使用Spring的相关注解,自动注入,Spring Jpa等功能了。

@Service("filterService")public class FilterService {    @Autowired
    UserRepository userRepository;    
    public void deleteAll() {
        userRepository.deleteAll();
    }
}

将storm应用作为Springboot工程的一个子模块

工程主目录的pom文件还是springboot相关的依赖,在storm子模块中引入storm依赖,这时候启动Strom的topology应用会有一个日志包依赖冲突。

SLF4J: Class path contains multiple SLF4J bindings.SLF4J: Found binding in [jar:file:/Applications/IntelliJ%20IDEA.app/Contents/bin/~/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.11.1/log4j-slf4j-impl-2.11.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: Found binding in [jar:file:/Applications/IntelliJ%20IDEA.app/Contents/bin/~/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]

我们需要在storm子模块的pom文件中重写org.springframework.boot:spring-boot-starter包依赖,将Springboot的相关日志包排除掉,如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j2</artifactId>
        </exclusion>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic2</artifactId>
        </exclusion>
    </exclusions></dependency>

OK,完美整合!

原文出处:https://www.cnblogs.com/gouyg/p/storm-springboot.html  

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 3
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消