如何在 8 小时内开发上线一个在线表单系统
欢迎使用 moform,一个无需注册、基于 Serverless 的开源表单系统。
在使用开发了一个精简版的 Serverless 日志存储系统 molog 之后。我便想开发一个更实用的 Serverless 应用,在一个微信群里,看到了使用金数据已经填满(每月 50 条的限额)的问题,便想表单这是一个非常合适的场景。毕竟表单作为一个数据分析的工具,本身也是事件驱动的。
任何能够用 Serverless 架构实现的应用系统,最终都必将用 Serverless 实现。
Showcase
基于 Serverless 架构的 moform 的最大特色是自动扩展、无需注册即可使用。从理论上来说,你不用担心系统的并发问题,FaaS 服务本身就是高可用、自动扩展。
打开 https://www.pho.im/,我们就可以直接创建表单了:
moform 创建示例
如上,拖拉一些相应的字段,就可以生成表单了。提交完,会生成一个相应的表单 URL,如下:
moform 表单地址
如在这里,我们的地址是:https://www.pho.im/f/HyvMI79ZG。
接着,打开对应的结果页:https://www.pho.im/f/HyvMI79ZG/results。
moform 表单结果
除了查看相应的结果,我们还可以搜索内容、下载 CSV、Excel 格式的数据,也可以直接打印数据。
忘说了,无需注册的原因是——到目前为止,比较成熟的在线授权服务只有 Auth0,然而它只支持微博和人人。如果你想接入这个授权,可以看我之前写的文章 Serverless 架构应用开发:基于 Auth0 授权的 Serverless 应用登录
业务
好了,接下来,让我们简单的过一下 moform 的基本业务逻辑:
我相信有了这张表就足够了。
技术及架构
所用到的前端技术栈有:
- formBuilder,用于创建表单和生成表单
- Bootstrap,你懂的 UI 框架
- jQuery,对,我还在用 jQuery
- dataTables,用于展示数据,打印、导出数据(csv,excel)
每次在大限将至的时候,我都会选择 jQuery——它不需要复杂的构建,三秒钟就能开箱了,引入网页即可使用。不过最主要的原因是,formBuilder 和 Bootstrap 都依赖于 jQuery。
所使用的 AWS 服务有
- AWS CloudFront,用于作为静态资源的 CDN
- AWS S3,用于存储静态资源文件
- AWS API Gateway,顾名思义 API 网关
- AWS Lambda,无服务器的函数计算服务
- AWS Route 53,用于为服务分配域名
底层依然是 Serverless Framework,同时还用到了几个相关的插件:
- serverless-domain-manager,用于管理、分配域名
- serverless-finch,用于部署静态资源文件到 S3
- serverless-plugin-simulate,用于调试,在本地模拟 Serverless 环境。
代码实现
理清了这些关系之后,剩下的就简单多了。对应的 serverless.yml 中的函数配置如下所示:
functions: index: handler: backend/index.handler events: - http: path: '' method: get formCreate: handler: backend/form/create.handler events: - http: path: f/ method: post formGet: handler: backend/form/get.handler events: - http: path: f/{formId} method: get formSubmit: handler: backend/form/submit.handler events: - http: path: f/{formId} method: post formResults: handler: backend/form/results.handler events: - http: path: f/{formId}/results method: get
为此,我们需要至少两个 DynamoDB 数据库表资源:
provider: name: aws runtime: nodejs6.10 timeout: 5 FORM_DYNAMODB_TABLE: ${self:service}-form-${opt:stage, self:provider.stage} FORM_DATA_DYNAMODB_TABLE: ${self:service}-form-data-${opt:stage, self:provider.stage} SLS_STAGE: ${self:custom.stage} iamRoleStatements: - Action: - dynamodb:GetItem - dynamodb:PutItem - dynamodb:Query - dynamodb:Scan Resource: - "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.FORM_DYNAMODB_TABLE}" - "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.FORM_DATA_DYNAMODB_TABLE}" Effect: Allow
未来,我们还需要用户的登录信息。
总体的代码与我们之前看到的 molog 的代码差不多。考虑到代码比较简单,我们就看一个获取表单的例子就好了:
...module.exports.handler = (event, context, callback) => { const params = { TableName: process.env.FORM_DYNAMODB_TABLE, Key: { id: event.pathParameters.formId, }, }; dynamoDb.get(params, (error, result) => { // handle potential errors if (error) { ... } // create a response const response = { statusCode: 200, headers: {'Content-Type': 'text/html'}, body: generateHtml(result.Item) }; callback(null, response); });};
我们从 URL 中获得表单的 ID,然后返回对应的 HTML,就这么简单。获取所有的数据,实际上也和这个差不多。
结论
任何能够用 Serverless 架构实现的应用系统,最终都必将用 Serverless 实现。
欢迎试用并提出建议,地址是:https://www.pho.im/ 。移动端界面如下所示:
moform-mobile.png
- 如何成为一名10x的数据分析师?
- 肥料生产商全套三拼在手:拟融资1.47亿元
- 《外媒Cointelegraph专访Qtum量子链Jordan Earls》—浅谈目前Dapps的主要问题
- ASP .Net Core 2.0 修改默认端口
- 不满一岁的潜力股:2017年3D打印机器人盘点
- Reporting Service报表开发
- 不要信任云:这不只是安全的问题
- C#温故而知新—闲话.Net
- c# IO&&线程 打造 定时打开指定程序
- 前FDIC主席:比特币政策不应打击加密货币发展
- 任何人都不应该控制区块链供应链
- c# IO操作(带进度的文件复制器,读取文本文件的指定行)
- 高科技来了!玩游戏一样开船的时代来了……
- C++库大全
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解Android Service 使用时的注意事项
- Android自定义View实现QQ运动积分转盘抽奖功能
- 请简述Spring JDBC是如何进行配置的
- Java高频面试题 -- 静态
- 2020Java核心面试题--基础题
- 一日一技:在网页上如何获取鼠标当前指向的元素
- B树和B+树
- 根据CCDS数据库信息拿到全部外显子坐标
- 查找算法其实不简单
- 一日一技:如何防止 Homebrew 自动升级和自动清理过期程序
- 吐血整理--史上最全排序算法Python实现
- 2020数据库最新面试题常考汇总
- [剑指Offer]面试题25: 合并两个排序的链表
- 环形链表
- 二十年前做科研你只需要检测一些基因在一些癌症细胞系表达量情况即可