一个APP的迭代(3) - 网络篇
2018-01-27 22:54
295 查看
添加登录、注册、忘记密码、备份日记功能
上一篇博文:一个APP的迭代(2) - 基础篇,已经把日记列表,查看日记,删除日记,修改日记的功能做出来了,并且已经上线到应用市场,有用户在使用。但也仅限本地使用,无法备份日记,这篇博文介绍如何把备份功能做上去的思路及相关技术。
上个版本的版本号为2.0.0,这个版本迭代新增了一个备份日记的功能,就把版本号算级为2.1.0,最后一个0表示的是修复BUG的版本,例如:你修复了一个备份日记的BUG,那么版本号就升级为2.1.1
需求拆分
注册功能
登录功能
忘记密码功能
备份日记功能
还原日记功能
后端搭建
一开始是计划用 Node + TypeScript + MongoDB 搭建后端,毕竟它是跨平台的方案。但是,技术只是手段,产品才是目的。 由于我是做C#出身的,那么我就用 ASP.NET Core + C# + MySQL ,这套也是开源的跨平台方案,性能要比NODE强。
搭数据库
用户表日记表
缓存表(用来处理注册时验证码等临时数据)
这三个表已经够用了,迭代开发,不做过度设计。
ASP.NET Core 控制器设计(RESTful)
UserController (用户控制器)请求短信验证码接口(注册用户与忘记密码)
注册用户接口
用户登录接口
忘记密码接口
DiaryController (日记控制器)
获取指定时间以后的日记接口
备份单篇日记接口
备份日记这个功能相当复杂,这就像SVN的版本记录一样,会存在日记内容冲突的矛盾,因为日记表的记录是必须存在的,若是不存在,就无法对比和解决冲突。日记表的记录不能删,而是用一个valid的字段表示该篇日记是否有效,另外还需要有一个modified_time的字段设为ON UPDATE CURRENT_TIMESTAMP来表示该日记被修改的时间。
关于 备份/还原 日记逻辑就不细说了,估计几万个字都说不完,总之有点复杂,当逻辑理清之后还是比较简单的
后端业务逻辑基础类的编写
上面的控制器只是用于输出http请求结果的json数据,业务逻辑还是与控制器分离的。MVC模式嘛,控制器表示C层,业务逻辑就写在M层那里,然而这里并没有V层,以后做日记网站了就可以用到V层咯。备份/恢复 日记的业务代码如下:
public class DiaryBusiness : IDiary { public CompareResult CompareServerDiary(DiaryDetail diaryDetail) { var connection = ToolFactory.BuildConnectionInstance(); var serverDiaryDetails = connection.QueryFirstOrDefault<DiaryDetail>($"select * from note_details where id=@id;", new { id = diaryDetail.id }); if (serverDiaryDetails == null) { return new CompareResult { Code = CompareCode.ServerNotData, Remark = "服务端无此日记。" }; } if (diaryDetail.modified_time > serverDiaryDetails.modified_time) { return new CompareResult { Code = CompareCode.ServerHasOldData, Remark = "服务端的日记较旧。" }; } else if (diaryDetail.modified_time < serverDiaryDetails.modified_time) { return new CompareResult { Code = CompareCode.ServerHasNewData, Remark = "服务端的日记较新。" }; } else if (diaryDetail.modified_time == serverDiaryDetails.modified_time) { return new CompareResult { Code = CompareCode.ServerHasSameData, Remark = "客户端与服务端的日记一致。" }; } return null; } public bool CreateDiary(DiaryDetail diaryDetails) { if (diaryDetails.modified_time == null) { diaryDetails.modified_time = DateTime.Now; } using (var connection = ToolFactory.BuildConnectionInstance()) { try { if (diaryDetails.id == null || diaryDetails.id == Guid.Empty) return false; var exeResult = connection.Execute($"insert into note_details (id,title,content,user_id,create_time,modified_time) value " + $"(@id,@title,@content,@user_id,@create_time,@modified_time);", diaryDetails); return exeResult > 0; } catch { return false; } } } public bool DeleteDiary(Guid diaryId) { using (var connection = ToolFactory.BuildConnectionInstance()) { var result = connection.Execute($"update note_details set valid=0 where id=@id;", new { id = diaryId }); return result > 0; } } public DiaryDetail PullServerDiary(Guid diaryId) { using (var connection = ToolFactory.BuildConnectionInstance()) { var DiaryDetails = connection.QueryFirstOrDefault<DiaryDetail>($"select * from note_details where id=@id;", new { id = diaryId }); return DiaryDetails; } } public List<DiaryDetail> PullServerDiarys(DateTime versionTime, Guid userId) { using (var connection = ToolFactory.BuildConnectionInstance()) { var diaryDetails = connection.Query<DiaryDetail>($"select * from note_details where modified_time>@modified_time and user_id=@user_id;", new { modified_time = versionTime, user_id = userId }); if (diaryDetails.Any()) { foreach (var item in diaryDetails) { item.content = ""; item.title = ""; } } return diaryDetails.AsList(); } } public bool UpdateDiary(DiaryDetail diaryDetails) { if (diaryDetails.modified_time == null) { diaryDetails.modified_time = DateTime.Now; } using (var connection = ToolFactory.BuildConnectionInstance()) { var exeResult = connection.Execute( $"update note_details set " + $"title=@title," + $"content=@content," + $"user_id=@user_id," + $"modified_time=@modified_time," + $"valid=@valid where id=@id;", diaryDetails); return exeResult > 0; } } }
目前 小励日记APP 只有10万的用户(包括已注册的和未注册的),日访客量500左右。
这里要注意的时,备份日记与恢复日记接口要做鉴权近控制,这里的做法是日记控制器继承鉴权控制器,一旦鉴权失败直接报错,而不进入日记控制器。
日记APP一定要严格保护好用户的隐私。
鉴权的逻辑
日记用户的注册、登录、忘记密码的功能代码我就不贴出来了。这里说一下鉴权的业务逻辑。登录成功后,接口会输一个TOKEN
APP端要保存好这个TOKEN,每次请求时,用这个TOKEN + 时间戳 + 密钥 计算MD5,后端接收到这个MD5后也要重新计算一次,然后对比MD5,如果一样,则鉴权通过
如果请求被拦截,那么黑客用这个MD5就可以获得用户的所有操作了,其实这个MD5只会有一次,并且时间在60分钟内有效,如果后端的历史记录表有该MD5,则表示该操作非法。
那如果是跨时区的,那这60分钟明显不够啊?所以呢,APP端就要转换为标准的北京时间了。
备份/恢复 日记、登录、注册 就这几个简单的需求,其实做起来也不容易啊,也是有很多代码量的。
这让我想起了前些天,有个网友找到我,让我帮它做个APP,就只有几个简单的界面而已,然而我报出来的天数是90天。他吓了一跳,说后端接口用PHP他们只用12天就做好了。
我问他:后端有做过测试验收没?他答:接口人员跟我说已经好了。
在我看来,后端未经过严格测试的,完成度只能算20%。前端APP人员要跟后端沟通、联调的时间成本就要占了一半,仅剩下的一半时间来完成APP需求。[/b]
前端界面
前端开发完成后的界面如下这个版本已经把备份/恢复日记 、注册、登录、忘记密码的功能做进去了,也发布到应用市场了,下一篇博文 要把扩展的功能 本地密码锁、日记照片、日记语音 迭代出来。
迭代开发就是这么回事,一个版本一个版本来,先做让用户可以用的版本,新功能在后面的版本迭代。这里说的只适合资源不足的情况下,如果开发人力充足,也可以一次做出一个大版本。
相关文章推荐
- 获取手机APP对网络访问数据的一个思路
- 一个APP的迭代(1) - 开始篇
- 一个App带你学会Retrofit2.0,麻麻再也不用担心我的网络请求了!
- 一个独立开发者总结的App 迭代设计思路
- 一个App带你学会Retrofit2.0,麻麻再也不用担心我的网络请求了!
- 一个App带你学会Retrofit2.0,麻麻再也不用担心我的网络请求了!
- 进入一个APP时对手机网络判断(使用广播和不使用广播)
- 一个App带你学会Retrofit2.0,麻麻再也不用担心我的网络请求了!
- Android Reader -- 一个简单的网络通信APP
- 一个APP的迭代(2) - 基础篇
- Android上实现一个简单的天气预报APP(三) 获取网络数据
- 一个App完成入门篇(二)-搭建主框架
- 万普广告遭金山毒霸封杀,祸及APP开发者,2家的恶斗成为“金山恶霸门”的一个重要起因
- Maven指令生存一个web-app项目
- 专家称GSM网络不安全 一个电话便泄露身份
- 多个app连接同一个service
- AppWidget应用(一)---创建一个appWidget
- 【如何快速的开发一个完整的iOS直播app】(采集篇)
- 记一个微信支付-1错误JSAPI缺少参数app|get_brand_request:Fail
- iOS 同一个工程下 使用多target来构建大量相似App