Unity应用架构设计(11)——一个网络层的构建
对于客户端应用程序,免不了和远程服务打交道。设计一个良好的『服务层』能帮我们规范和分离业务代码,提高生产效率。服务层最核心的模块一定是怎样发送请求,虽然Mono提供了很多C#网络请求类,诸如
WebClient,HttpWebRequest,但考虑到跨平台,这些类不一定适用。不过不用担心,Unity 5.x提供了新的与网络相关类UnityWebRequest用来替代原先的WWW,这是官方推荐的,也是最佳选择。
使用Token进行身份验证
首先我们必须要考虑的是,怎样和Web服务安全的通信。没错,肯定是身份验证(Authentication)。对于像WebClient这些类,它们会提供一个属性,比如Credentials,可以在此属性设置一些身份验证信息,比如用户名,密码,域。这是一个很『重』的解决方案,且不论是否能在Unity中实现,单从密码这个角度,很多游戏根本不需要密码。所以,我们需要一种『轻』量级的身份验证机制,这就是Token,中文翻译叫『令牌』。
Token有两个重要的特点:
- 代表了唯一的身份验证令牌
- 具有时效性
第一点我们肯定可以理解,唯一性是身份验证的的基础。那第二点怎么理解呢?其实,Token本质上是一串加密过后的字符串,如果没有时效性,万一被窃取之后,他人很容易进行伪造。所以,易变的Token一定比不变的安全,你需要一个算法来动态生成Token,我提供一个简单的算法:
md5(((day*10) + (month*100) + (last2DigitsofYear)*1000)+userId+deviceId)
同理,你需要在Web服务前加上一个过滤器,一样的算法来验证Token是否一致。
Request Pipeline
Pipeline是管道的意思,管道是相连的,代表了请求的流转。由于UnityWebRequest必须配合StartCoroutine,而StartCoroutine又属于View层的代码,这和分层(详见之前的文章)冲突,MVVM框架需要将业务逻辑从View解耦。一个比较好的解决方案是通过中介的HttpTool来解决,它是一个单例的MonoBehaviour,并且不会随着场景的加载被销毁。
public class HttpTool : Singleton<HttpTool>
{
// 无法在外界使用构造函数,确保Singleton
protected HttpTool() { }
}
不管是请求还是响应,本质上是一堆数据的集合,将这些数据封装成对象的形式会更加容易管理,我将请求相关的数据封装成HttpRequest对象:
public class HttpRequest
{
public string Url { get; set; }
public HttpMethod Method { get; set; }
public string Parameters { get; set; }
}
而将从Web服务返回的数据封装成HttpResponse对象:
public class HttpResponse
{
public bool IsSuccess { get; set; }
public string Error { get; set; }
public long StatusCode { get; set; }
public string Data { get; set; }
}
值得注意的是,对应Http请求,不论Get还是Post都会将参数组装成“field1=value1&field2=value2”格式,不同的是Get请求,参数会跟在Url后,而Post请求则在Request Body里。所以需要一个帮助类,反射要传递的对象属性,拼装返回字符串。
核心的请求交由UnityWebRequest实现,通过yield等待返回的结果:
using (var www = UnityWebRequest.Get(url + parameters))
{
yield return www.Send();
var response = new HttpResponse
{
IsSuccess = !www.isError, Error = www.error, StatusCode = www.responseCode, Data = www.downloadHandler.text
};
onComplete(response);
}
最后再对返回的Json字符串反序列化成对象,值得注意的是,在此我用了内置的JsonUtility类,它并不能直接反序列化一个Json数组 ,而是需要将它包装成一个对象 ,通过集合类型属性的形式间接被反序列化。
至此,一个完整的Request Pipeline 如下图所示:

使用策略模式增强RemoteRepository
由于JsonUtility的限制因素多,你可能使用其他第三方的库。又或者不反序列化Json,而是Xml。所以在RemoteRepository中不应该限制死反序列化的代码,更好的想法是通过『策略模式』,交由外部算法来实现。这样的好处是你根本不需要改动RemoteRepository里的代码,这也符合『开闭原则』。
所以,你需要在RemoteRepository定义一个序列化接口:
public ISerializer Serializer { get; set; }
然后,对返回的HttpResponse中的Json反序列化:
Serializer.Deserialize<R>(httpResponse.Data)
真正的对Json序列化器实现了ISerializer接口,以策略的形式存在:
public class SerializerJson:ISerializer
{
public static readonly SerializerJson Instance=new SerializerJson();
private SerializerJson()
{
}
public string Serialize<T>(T obj, bool readableOutput = false) where T : class, new()
{
throw new NotImplementedException();
}
public T Deserialize<T>(string json) where T : class, new()
{
return JsonUtility.FromJson<T>(json);
}
}
策略模式在编程领域运用非常广,比如Java或者.NET框架里的集合排序,大量用到策略模式。由程序员指定的算法来最终实现排序。
小结
本文的核心思想就是如何在合理分层结果下构建一个好用的服务层。谈到了如何动态生成Token来实现身份验证,以及分层情况下的请求流程。对于2D并且以数据绑定为基础的游戏,我认为这是一个好的实践方案。因为不管是三层架构还是N层架构,通过分层的好处是更加清晰去实现业务逻辑。
源代码托管在Github上,点击此了解
Unity应用架构设计(11)——一个网络层的构建的更多相关文章
- Unity应用架构设计(10)——绕不开的协程和多线程(Part 2)
在上一回合谈到,客户端应用程序的所有操作都在主线程上进行,所以一些比较耗时的操作可以在异步线程上去进行,充分利用CPU的性能来达到程序的最佳性能.对于Unity而言,又提供了另外一种『异步』的概念,就 ...
- Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 2)
MVVM回顾 经过上一篇文章的介绍,相信你对MVVM的设计思想有所了解.MVVM的核心思想就是解耦,View与ViewModel应该感受不到彼此的存在. View只关心怎样渲染,而ViewModel只 ...
- Unity应用架构设计(13)——日志组件的实施
对于应用程序而言,日志是非常重要的功能,通过日志,我们可以跟踪应用程序的数据状态,记录Crash的日志可以帮助我们分析应用程序崩溃的原因,我们甚至可以通过日志来进行性能的监控.总之,日志的好处很多,特 ...
- Unity应用架构设计(9)——构建统一的 Repository
谈到 『Repository』 仓储模式,第一映像就是封装了对数据的访问和持久化.Repository 模式的理念核心是定义了一个规范,即接口『Interface』,在这个规范里面定义了访问以及持久化 ...
- Unity应用架构设计(6)——设计动态数据集合ObservableList
什么是 『动态数据集合』 ?简而言之,就是当集合添加.删除项目或者重置时,能提供一种通知机制,告诉UI动态更新界面.有经验的程序员脑海里迸出的第一个词就是 ObservableCollection.没 ...
- Unity应用架构设计(4)——设计可复用的SubView和SubViewModel(Part 1)
『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率. 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则. 组件化 ...
- Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 1)
初识 MVVM 谈起 MVVM 设计模式,可能第一映像你会想到 WPF/Sliverlight,他们提供了的数据绑定(Data Binding),命令(Command)等功能,这让 MVVM 模式得到 ...
- Unity应用架构设计(10)————绕不开的协程和多线程(Part 1)
在进入本章主题之前,我们必须要了解客户端应用程序都是单线程模型,即只有一个主线程(Main Thread),或者叫做UI线程,即所有的UI控件的创建和操作都是在主线程上完成的.而服务器端应用程序,也就 ...
- Unity应用架构设计(12)——AOP思想的实践
想象一下,当程序所有的业务逻辑都完成的时候,你可能还来不及喘口气,紧张的测试即将来临.你的Boss告诉你,虽然程序没问题,但某些方法为什么执行这么慢,性能堪忧.领会了Boss的意图之后,漫长的排查问题 ...
随机推荐
- IP设置
由于家里的IP地址与公司的不一样,每次都要修改很麻烦,所以自己只做了一个IP修改bat. 打开记事本,把一下代码复制到记事本里,保存成bat就OK了.在23行设置自己的IP地址就可以了. @echo ...
- 关于String类和String[]数组的获取长度方法细节
一.在Java中,以下代码段有错误的是第( )行 public static void main(String[] args) { String name = "小新"; ...
- LRU Cache java实现
要求: get(key):如果key在cache中,则返回对应的value值,否则返回null set(key,value):如果key不在cache中,则将该(key,value)插入cache中( ...
- SQL注入详细介绍及如何防范SQL注入式攻击
一. SQL注入攻击的简单示例. statement := "SELECT * FROM Users WHERE Value= " + a_variable + " 上面 ...
- 接口加密《二》: API权限设计总结
来源:http://meiyitianabc.blog.163.com/blog/static/105022127201310562811897/ API权限设计总结: 最近在做API的权限设计这一块 ...
- 使用OpenOffice实现各种文档转pdf或者html文档
---恢复内容开始--- 最近在做项目时需要写一个功能,将doc,ppt,xsl等文档做在线预览.网上查了很多资料,开始适用poi将文档转成pdf没成功,后来使用了OpenOffice4 + jodc ...
- 在android中,如何去掉webview读取网页后点击网页上的按钮出现的方框
参考:http://blog.sina.com.cn/s/blog_64056edc0100xt3l.html <style type="text/css"> .bor ...
- Linux之定时任务
定时任务Crond介绍 Crond是linux系统中用来定期执行命令/脚本或指定程序任务的一种服务或软件,一般情况下,我们安装完Centos5/6 linux操作系统之后,默认便会启动Crond任务调 ...
- TreeSet源码分析
第1部分 TreeSet介绍 TreeSet 是一个有序的集合,它的作用是提供有序的Set集合.它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneab ...
- git编译安装与常见问题解决
1. 先去官网下载一个安装包 ,假设目录/APP/ido 2. cd /APP/ido 3. tar -zxvf git-2.7.2.tar.gz 4. 安装依赖 yum -y insta ...