Spark和Spring整合处理离线数据
如果你比较熟悉JavaWeb应用开发,那么对Spring框架一定不陌生,并且JavaWeb通常是基于SSM搭起的架构,主要用Java语言开发。但是开发Spark程序,Scala语言往往必不可少。
众所周知,Scala如同Java一样,都是运行在JVM上的,所以它具有很多Java语言的特性,同时作为函数式编程语言,又具有自己独特的特性,实际应用中除了要结合业务场景,还要对Scala语言的特性有深入了解。
如果想像使用Java语言一样,使用Scala来利用Spring框架特性、并结合Spark来处理离线数据,应该怎么做呢?
本篇文章,通过详细的示例代码,介绍上述场景的具体实现,大家如果有类似需求,可以根据实际情况做调整。
1. 定义一个程序启动入口
object Bootstrap {
private val log = LoggerFactory.getLogger(Bootstrap.getClass)
//指定配置文件如log4j的路径
val ConfFileName = "conf"
val ConfigurePath = new File("").getAbsolutePath.substring(0, if (new File("").getAbsolutePath.lastIndexOf("lib") == -1) 0
else new File("").getAbsolutePath.lastIndexOf("lib")) + this.ConfFileName + File.separator
//存放实现了StatsTask的离线程序处理的类
private val TASK_MAP = Map("WordCount" -> classOf[WordCount])
def main(args: Array[String]): Unit = {
//传入一些参数,比如要运行的离线处理程序类名、处理哪些时间的数据
if (args.length < 1) {
log.warn("args 参数异常!!!" + args.toBuffer)
System.exit(1)
}
init(args)
}
def init(args: Array[String]) {
try {
SpringUtils.init(Array[String]("applicationContext.xml"))
initLog4j()
val className = args(0)
// 实例化离线处理类
val task = SpringUtils.getBean(TASK_MAP(className))
args.length match {
case 3 =>
// 处理一段时间的每天离线数据
val dtStart = DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(args(1))
val dtEnd = DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(args(2))
val days = Days.daysBetween(dtStart, dtEnd).getDays + 1
for (i <- 0 until days) {
val etime = dtStart.plusDays(i).toString("yyyy-MM-dd")
task.runTask(etime)
log.info(s"JOB --> $className 已成功处理: $etime 的数据")
}
case 2 =>
// 处理指定的某天离线数据
val etime = DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(args(1)).toString("yyyy-MM-dd")
task.runTask(etime)
log.info(s"JOB --> $className 已成功处理: $etime 的数据")
case 1 =>
// 处理前一天离线数据
val etime = DateTime.now().minusDays(1).toString("yyyy-MM-dd")
task.runTask(etime)
log.info(s"JOB --> $className 已成功处理: $etime 的数据")
case _ => println("执行失败 args参数:" + args.toBuffer)
}
} catch {
case e: Exception =>
println("执行失败 args参数:" + args.toBuffer)
e.printStackTrace()
}
// 初始化log4j
def initLog4j() {
val fileName = ConfigurePath + "log4j.properties"
if (new File(fileName).exists) {
PropertyConfigurator.configure(fileName)
log.info("日志log4j已经启动")
}
}
}
}
2. 加载Spring配置文件工具类
object SpringUtils {
private var context: ClassPathXmlApplicationContext = _
def getBean(name: String): Any = context.getBean(name)
def getBean[T](name: String, classObj: Class[T]): T = context.getBean(name, classObj)
def getBean[T](_class: Class[T]): T = context.getBean(_class)
def init(springXml: Array[String]): Unit = {
if (springXml == null || springXml.isEmpty) {
try
throw new Exception("springXml 不可为空")
catch {
case e: Exception => e.printStackTrace()
}
}
context = new ClassPathXmlApplicationContext(springXml(0))
context.start()
}
}
3. Spring配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置包扫描 -->
<context:component-scan base-package="com.bigdata.stats"/> </beans>
4. 定义一个trait,作为离线程序的公共"父类"
trait StatsTask extends Serializable {
//"子类"继承StatsTask重写该方法实现自己的业务处理逻辑
def runTask(etime: String)
}
5. 继承StatsTask的离线处理类
//不要忘记添加 @Component ,否则无法利用Spring对WordCount进行实例化
@Component
class WordCount extends StatsTask { override def runTask(etime: String): Unit = {
val sparkSession = SparkSession
.builder()
.appName("test")
.master("local[*]")
.getOrCreate() import sparkSession.implicits._ val words = sparkSession.read.textFile("/Users/BigData/Documents/data/wordcount.txt").flatMap(_.split(" "))
.toDF("word") words.createOrReplaceTempView("wordcount") val df = sparkSession.sql("select word, count(*) count from wordcount group by word") df.show()
}
}
推荐文章:
关注微信公众号:大数据学习与分享,获取更对技术干货
Spark和Spring整合处理离线数据的更多相关文章
- idea+springmvc+spring+mybatis+maven整合返回json数据webapi
首先看一张目录结构图: : 创建步骤: 1.创建maven webapp工程, 创建完后的目录结构为: 2.添加项目依赖(添加jar包) 需要的jar包: spring-webmvc, spring ...
- 项目一:第十四天 1.在realm中动态授权 2.Shiro整合ehcache 缓存realm中授权信息 3.动态展示菜单数据 4.Quartz定时任务调度框架—Spring整合javamail发送邮件 5.基于poi实现分区导出
1 Shiro整合ehCache缓存授权信息 当需要进行权限校验时候:四种方式url拦截.注解.页面标签.代码级别,当需要验证权限会调用realm中的授权方法 Shiro框架内部整合好缓存管理器, ...
- 使用Spring整合Hibernate,并实现对数据表的增、删、改、查的功能
1.1 问题 使用Spring整合Hibernate,并实现资费表的增.删.改.查. 1.2 方案 Spring整合Hibernate的步骤: 1.3 步骤 实现此案例需要按照如下步骤进行. 采用的环 ...
- spring整合flex
在常规的开发中只是用flex二不和后台交互是不可能的,为此flex也提供了和后台交互的2种解决方案一种是Data Services另一种是BlazeDs,本篇博客是用的是后一种,我的开发步骤如下: 1 ...
- java框架之Spring(4)-Spring整合Hibernate和Struts2
准备 导包 Struts2 导入 Struts2 zip 包解压目录下 'apps/struts-blank.war' 中所有 jar 包,如下: asm-3.3.jar asm-commons-3. ...
- Spark与Spring集成做web接口
需要实现的功能: 写访问spark的接口,也就是从web上输入网址就能把我们需要的信息通过提交一个job然后返回给我们json数据. 成果展示: 通过url请求,然后的到一个wordcount的jso ...
- hadoop离线数据存储和挖掘架构
前序: 当你把你知道的东西,写下来,让人看明白是一种境界:当你能把自己写下来的东西给人讲明白,又是另一种境界.在这个过程中,我们都需要历练. 基于hadoop集群下海量离线数据存储和挖掘分析架构: 架 ...
- Spring整合Ehcache管理缓存
前言 Ehcache 是一个成熟的缓存框架,你可以直接使用它来管理你的缓存. Spring 提供了对缓存功能的抽象:即允许绑定不同的缓存解决方案(如Ehcache),但本身不直接提供缓存功能的实现.它 ...
- spring整合hibernate
spring整合hibernate包括三部分:hibernate的配置.hibernate核心对象交给spring管理.事务由AOP控制 好处: 由java代码进行配置,摆脱硬编码,连接数据库等信息更 ...
随机推荐
- 在阿里云服务器上(centos 8) 安装自己的MQTT服务器 (mosquitto)
layout: post title: 在阿里云服务器上(centos 8) 安装自己的MQTT服务器 (mosquitto) subtitle: date: 2020-3-2 author: Dap ...
- canal-adapter1.1.14最新版本安装的过程中出现的NullPointerException异常
记录一下我在安装 canal-adapter1.1.14最新版本安装的过程中出现的NullPointerException异常 以下是我的canal-adapter/logs文件夹内adapter.l ...
- Wormholes (spfa)
一种路是双向的,路的长度是正值:另一种路是单向的,路的长度是负值: 如果有负环输出YES:否则输出NO:不同的路可能有相同的起点和终点:必须用邻接表 While exploring his many ...
- java的静态代码块和类变量的隐式覆盖
静态代码块特点:随着类的加载执行一次,且仅会执行一次 作用:初始化类中的static修饰的变量(static修饰的变量称为类变量.类变量和静态代码块差不多,类变量仅会被初始化一次) 一.静态代码块写法 ...
- python爬取QQVIP音乐
QQ音乐相比于网易云音乐加密部分基本上没有,但是就是QQ音乐的页面与页面之间的联系太强了,,导致下载一个音乐需要分析前面多个页面,找数据..太繁琐了 1.爬取链接:https://y.qq.com/ ...
- Codeforces Round #648 (Div. 2) F. Swaps Again
题目链接:F.Swaps Again 题意: 有两个长度为n的数组a和数组b,可以选择k(1<=k<=n/2)交换某一个数组的前缀k和后缀k,可以交换任意次数,看最后是否能使两个数组相等 ...
- MySql 执行 DELETE/UPDATE时,报 Error Code: 1175错误
MySql 执行 DELETE FROM Table 时,报 Error Code: 1175. You are using safe update mode and you tried to upd ...
- Win10 资源管理器经常卡死问题
什么问题? 我的Win10资源管理器开始出现卡死(假死.未响应)的情况,频率越来越高,触发方式越来越广,包括OpenDialog.打开拥有快捷方式的文件夹/桌面.右键空白处.右键文件/文件夹.拖动文件 ...
- Atlas 分表功能
目录 分表原因 分表方式 Atlas 分表 分表思路 配置 Atlas 创建原表 创建分表 数据测试 分表原因 1.数据过多,访问缓慢 2.创建索引时重新排序,创建缓慢,并且占用大量的磁盘空间 分表方 ...
- LINUX - pthread_mutex_lock
原文链接:https://www.cnblogs.com/fengbohello/p/7571722.html 互斥的概念 在多线程编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性. 每个对 ...