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代码进行配置,摆脱硬编码,连接数据库等信息更 ...
随机推荐
- Linux系统磁盘管理(lvm逻辑卷管理)
linux系统用户常遇到的一个问题就是如何精准的评估分区的大小,已分配合适的磁盘空间:普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某个文件时,这个文件因为受上层文 ...
- Thank in Java
Think in Java 2.一切都是对象 2.1 引用操作对象 Java 中一切都是对象,因此可以采用单一固定得语法. 操作对象得标识符实际上是对对象得一个 "引用"refer ...
- Spring MVC 处理一个请求的流程分析
Spring MVC是Spring系列框架中使用频率最高的部分.不管是Spring Boot还是传统的Spring项目,只要是Web项目都会使用到Spring MVC部分.因此程序员一定要熟练掌握MV ...
- 2019牛客暑期多校训练营(第四场)D-triples I
>传送门< 题意:求最少需要多少个3的倍数按位或后可以得到数字a 思路:利用3的倍数对应的二进制数的性质来先选出一个x,然后根据数字a再配一个y出来 首先,我们都知道十进制中,任意一个数只 ...
- Codeforces Round #641 (Div. 2)
只写了A~D A - Orac and Factors 题意:f(n)就是n的第二小因数,问执行k次 n=f(n)+n 后的结果. 题解:如果一直找第二小的因子的话,1e9肯定得t.看下边样例解释就会 ...
- HDU - 2328 Corporate Identity(kmp+暴力)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2328 题意:多组输入,n==0结束.给出n个字符串,求最长公共子串,长度相等则求字典序最小. 题解:(居 ...
- Python中“*”和“**”的用法 || yield的用法 || ‘$in’和'$nin' || python @property的含义
一.单星号 * 采用 * 可将列表或元祖中的元素直接取出,作为随机数的上下限: import random a = [1,4] print(random.randrange(*a)) 或者for循环输 ...
- C#Assembly、程序集、装配件、命名空间以及类型的关系
Assembly = 程序集 = 装配件 命名空间是类的逻辑组织形式,程序集是类的物理组织形式. 程序集其实和命名空间没有什么必然的联系. 程序集1: namespace1{ public class ...
- PowerShell启用多跳远程控制
有些场景下,我们使用远程连接了某个Server,在远程Server中再想进行远程操作,就会提示错误.因为默认的认证信息只会传递一跳. 对此,微软官方文档给出的解决方案是:https://docs.mi ...
- Python——requests模块
一.安装模块 pip install requests 二.引用 import requests 三.get方法 #GET访问页面 r = requests.get(url) print(r.text ...