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}}
// 将逻辑代码传给 startstart{val filePath = ParameterTool.fromArgs(args).get("filePath")worldCountController.execute()}// 定义 start()def start( op: => Unit) = {try {// 初始化 FlinkFlinkStreamEnv.init()// 传入处理逻辑op// 处理完成后执行 flinkFlinkStreamEnv.execute()} catch {case e:Exception => e.printStackTrace()}}
ThreadLocal 操控线程中的内存

private val localEnv = new ThreadLocal[StreamExecutionEnvironment]def init() = {val env = StreamExecutionEnvironment.getExecutionEnvironmentenv.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.readTextFile2. (在当前调用的目录)创建一个 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)
