MVC架构: module, view, controller
三层架构:Controller, Service, Dao
项目规范
- Application 应用类必须继承 APP
- 创建业务对应三层架构的代码 Controller, Service, Dao
- 关联代码之间的关系
- 相关框架目录
common, bean, utils, controller, service, dao, application
scala 拾遗
控制抽象
将一段逻辑作为参数传入到一个方法。 使用控制抽象
Breaks.breakable( )
// breakable 的原码
def breakable(op: => Unit) {
try {
op
} catch {
case ex: BreakControl =>
if (ex ne breakException) throw ex
}
}
// 将逻辑代码传给 start
start{
val filePath = ParameterTool.fromArgs(args).get("filePath")
worldCountController.execute()
}
// 定义 start()
def start( op: => Unit) = {
try {
// 初始化 Flink
FlinkStreamEnv.init()
// 传入处理逻辑
op
// 处理完成后执行 flink
FlinkStreamEnv.execute()
} catch {
case e:Exception => e.printStackTrace()
}
}
ThreadLocal 操控线程中的内存
private val localEnv = new ThreadLocal[StreamExecutionEnvironment]
def init() = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
localEnv.set(env)
env
}
def get() = {
val env = localEnv.get()
if (env == null) {
init()
}
env
}
scala 中变量的灵活定义
1.获取命令行参数 传参:
ParameterTool.fromArgs(args).get("XXX")
def main(args: Array[String]): Unit = {
val host = ParameterTool.fromArgs(args).get("host")
val port = ParameterTool.fromArgs(args).get("port")
println(s"host:${host}, port:${port}")
}
2. 通过 隐式参数,隐式值
// 隐式参数
def readFile(implicit path:String) {
env.readTextFile(path)
}
// 隐式值
1. 在当前调用环境中 设置隐值
implicit val path = "/tmp/file.txt"
worldCountDAO.readTextFile
2. (在当前调用的目录)创建一个 Package Object 文件 <-- implicit val path = "/tmp/file.txt"
用户行为
字段名 | 数据类型 | 说明 |
---|---|---|
userId | Long | 加密后的用户ID |
itemId | Long | 加密后的商品ID |
categoryId | Int | 加密后的商品所属类别ID |
behavior | String | 用户行为类型,包括(‘pv’, ‘’buy, ‘cart’, ‘fav’) |
timestamp | Long | 行为发生的时间戳,单位秒 |
需求1:实时热门商品统计
每隔5分钟输出最近1小时内点击量最多的商品Top10
为了方便使用,将 原始日志封装成脑样例类
需求2: 基于log的热门页面浏览统计
每隔5秒,输出最近10分钟内访问量最多的前 N个URL
字段名 | ** | ** |
---|---|---|
ip | String | 访问的 IP |
userId | Long | 访问的 user ID |
eventTime | Long | 访问时间 |
method | String | 访问方法 GET/POST/PUT/DELETE |
url | String | 访问的 url |
去重 val set = mutable.Set[Long] , set.add(datas)