相关文章推荐
阳刚的牛排  ·  Detecting noop ...·  2 年前    · 
刀枪不入的生姜  ·  如何在Ubuntu ...·  2 年前    · 
冷冷的警车  ·  netty rtsp webrtc ...·  2 年前    · 

HttpManager,统一对外接口,目前封装了Get/Put/Post,尚未用的Delete(原理一样)

  • //GET请求会向服务器发送索取数据的请求,从而获取信息。只是用来查询数据,不会修改、增加数据,无论进行多少次操作结果一样。
  • //PUT请求是向服务器发送数据的,从而改变信息。用来修改数据的内容,但不会增加数据的种类,无论进行多少次操作结果一样。
  • //POST请求同PUT请求类似,向服务器发送数据。但是会改变数据的种类等资源,会创建新的内容。
  • //DELETE请求删除某一个资源,尚未使用。
  • using System.Collections.Generic;
    using System;
    using System.Text;
    public enum HttpType
        Post,
    public class HttpManager : MonoSingleton<HttpManager>
        private HttpClient httpClient;
        private void Awake()
            httpClient = new HttpClient();
            httpClient.Init();
        private void Update()
            httpClient.UpdateHttpRequest();
        private void OnDestroy()
            httpClient.Clear();
        /// <summary>
        /// Get接口
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="httpId"></param>
        /// <param name="getParameDic"></param>
        public void HttpGet<T>(int httpId,Dictionary<string,string> getParameDic) where T : class
            string getParameStr;
            if(getParameDic == null || getParameDic.Count == 0)
                getParameStr = null;
                StringBuilder stringBuilder = new StringBuilder();
                bool isFirst = true;
                foreach(var item in getParameDic)
                    if(isFirst)
                        isFirst = false;
                        stringBuilder.Append('&');
                    stringBuilder.Append(item.Key);
                    stringBuilder.Append('=');
                    stringBuilder.Append(item.Value);
                getParameStr = stringBuilder.ToString();
            httpClient.SendHttpRequest<T>(httpId,HttpType.Get,getParameStr);
        /// <summary>
        /// Get接口
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="httpId"></param>
        /// <param name="getParameStr"></param>
        public void HttpGet<T>(int httpId,string getParameStr) where T : class
            //Get请求通过URL传递数据的格式:URL中请求的文件名后跟着“ ?”;多组键值对,键值对之间用“&”进行分割;URL中包含汉字、特殊符号、需要对这些字符进行编码。
            //url?parame1Name=parame1Value&parame2Name=parame2Value
            httpClient.SendHttpRequest<T>(httpId,HttpType.Get,getParameStr);
        /// <summary>
        /// Get接口
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="httpId"></param>
        public void HttpGet<T>(int httpId) where T : class
            httpClient.SendHttpRequest<T>(httpId,HttpType.Get,null);
        /// <summary>
        /// Post接口
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="httpId"></param>
        /// <param name="postParameStr"></param>
        public void HttpPost<T>(int httpId,string postParameStr) where T : class
            httpClient.SendHttpRequest<T>(httpId,HttpType.Post,postParameStr);
        /// <summary>
        /// Post接口
        /// </summary>
        /// <typeparam name="T">返回的数据类型</typeparam>
        /// <param name="httpId"></param>
        /// <param name="postParame"></param>
        public void HttpPost<T>(int httpId,object postParame) where T : class
            //在传参中定义json
            string postParameStr = FileUtility.DataToJson(postParame);
            //UnityEngine.Debug.Log(postParameStr);
            httpClient.SendHttpRequest<T>(httpId,HttpType.Post,postParameStr);
        /// <summary>
        /// Put接口
        /// </summary>
        /// <param name="httpId"></param>
        /// <param name="putParameStr"></param>
        public void HttpPut(int httpId,string putParameStr)
            httpClient.SendHttpRequest<string>(httpId,HttpType.Put,putParameStr);
        /// <summary>
        /// Put接口
        /// </summary>
        /// <param name="httpId"></param>
        /// <param name="putParame"></param>
        public void HttpPut(int httpId,object putParame)
            string putParameStr = FileUtility.DataToJson(putParame);
            httpClient.SendHttpRequest<string>(httpId,HttpType.Put,putParameStr);
    

    HttpClient,实际Http请求处理,没有使用协程等待UnityWebRequest响应,避免了频繁的创建启动协程,

    在sendList中记录需要发送的请求,在receiveList中记录已发送,需要等待返回的请求,通过webRequest.isDone判断是否已得到服务器响应

    using System.Collections.Generic;
    using System;
    using UnityEngine.Networking;
    using UnityEngine;
    using System.Text;
    public class HttpClient
        private const int webReqTimeout = 15;
        private const int webReqTryCount = 3;
        //发送/接受队列
        private List<HttpPack> sendList = new List<HttpPack>(10);
        private List<HttpPack> receiveList = new List<HttpPack>(10);
        #region --- 外部接口 ---
        public void Init()
        public void Clear()
        public void UpdateHttpRequest()
            HandleSend();
            HandleRecive();
        /// <summary>
        /// 发送服务器请求
        /// </summary>
        /// <typeparam name="T">返回值类型</typeparam>
        /// <param name="httpId"></param>
        /// <param name="httpType"></param>
        /// <param name="parame"></param>
        public void SendHttpRequest<T>(int httpId,HttpType httpType,string parame) where T : class
            AddHttpRequest<T>(httpId,httpType,parame,typeof(T));
        #endregion
        //注册一个请求到发送队列中
        private void AddHttpRequest<T>(int httpId,HttpType httpType,string parame,Type dataType) where T : class
            //将参数设置到HttpPack中然后插入到发送队列里
            //HttpPack pack = GetHttpPack();
            HttpPack<T> pack = new HttpPack<T>();
            pack.id = httpId;
            string apiKey = HttpId.GetHttpApi(httpId);
            if(string.IsNullOrEmpty(apiKey))
                Debug.LogError("为获取到对应的Api : " + httpId);
                return;
            string serviceHost = "******";
            pack.url =  serviceHost + apiKey;
            pack.httpType = httpType;
            pack.dataType = dataType;
            pack.parame = parame;
            pack.tryCount = webReqTryCount;
            sendList.Add(pack);
        //从发送队列中取得一个HttpPack分类型调用请求
        private void HandleSend()
            if(sendList.Count == 0)
                return;
            for(int i = 0; i < sendList.Count; i++)
                HttpPack pack = sendList[i];
                switch(pack.httpType)
                    case HttpType.Get:
                            //Get请求
                            if(!string.IsNullOrEmpty(pack.parame))
                                //在Url后拼接参数字符串
                                pack.url = string.Format("{0}?{1}",pack.url,pack.parame);
                            pack.webRequest = new UnityWebRequest(pack.url,UnityWebRequest.kHttpVerbGET);
                            pack.webRequest.downloadHandler = new DownloadHandlerBuffer();
                            pack.webRequest.timeout = webReqTimeout;
                            pack.webRequest.SetRequestHeader("Content-Type","text/json;charset=utf-8");
                            pack.webRequest.SendWebRequest();
                        break;
                    case HttpType.Post:
                            //Post请求
                            pack.webRequest = new UnityWebRequest(pack.url,UnityWebRequest.kHttpVerbPOST);
                            if(!string.IsNullOrEmpty(pack.parame))
                                byte[] databyte = Encoding.UTF8.GetBytes(pack.parame);
                                pack.webRequest.uploadHandler = new UploadHandlerRaw(databyte);
                            pack.webRequest.downloadHandler = new DownloadHandlerBuffer();
                            pack.webRequest.timeout = webReqTimeout;
                            pack.webRequest.SetRequestHeader("Content-Type","text/json;charset=utf-8");
                            pack.webRequest.SendWebRequest();
                        break;
                    case HttpType.Put:
                            //Put
                            pack.webRequest = new UnityWebRequest(pack.url,UnityWebRequest.kHttpVerbPUT);
                            if(!string.IsNullOrEmpty(pack.parame))
                                byte[] databyte = Encoding.UTF8.GetBytes(pack.parame);
                                pack.webRequest.uploadHandler = new UploadHandlerRaw(databyte);
                            pack.webRequest.downloadHandler = new DownloadHandlerBuffer();
                            pack.webRequest.timeout = webReqTimeout;
                            pack.webRequest.SetRequestHeader("Content-Type","text/json;charset=utf-8");
                            pack.webRequest.SendWebRequest();
                        break;
                receiveList.Add(pack);
            sendList.Clear();
        //处理接收
        private void HandleRecive()
            if(receiveList.Count == 0)
                return;
            for(int i = receiveList.Count - 1; i >= 0; i--)
                HttpPack pack = receiveList[i];
                if(pack.webRequest == null)
                    receiveList.Remove(pack);
                    continue;
                if(pack.webRequest.isDone)
                else if(pack.webRequest.isHttpError || pack.webRequest.isNetworkError)
                    Debug.LogError(pack.webRequest.error);
                    continue;
                int responseCode = (int)pack.webRequest.responseCode;
                string responseJson = pack.webRequest.downloadHandler.text;
                pack.webRequest.Abort();
                pack.webRequest.Dispose();
                pack.webRequest = null;
                receiveList.Remove(pack);
                if(responseCode != 200 && --pack.tryCount > 0)
                    Debug.Log("try " + pack.tryCount);
                    sendList.Add(pack);
                    continue;
                CheckResponseCode(pack.id,responseCode,responseJson);
                pack.OnData(responseJson,responseCode,pack.id);
        private void CheckResponseCode(int httpId,int responseCode,string responseJson)
            if(responseCode == 200)
                return;
            int codeType = responseCode / 100;
            string apiKey = HttpId.GetHttpApi(httpId);
            switch(codeType)
                case 4:
                    Debug.Log(string.Format("{0} : {1} : 客户端错误,请尝试重试操作~",responseCode,apiKey));
                    break;
                case 5:
                case 6:
                    Debug.Log(string.Format("{0} : {1} : 服务器错误,请尝试重新登陆~",responseCode,apiKey));
                    break;
                default:
                    Debug.Log(string.Format("{0} : {1} : 未知错误,请尝试重试操作~",responseCode,apiKey));
                    break;
    

     HttpPack,记录每次请求数据,在收到服务器返回数据后,通过泛型将json解析后的数据通过广播系统转发给功能模块

    using System;
    using UnityEngine;
    using UnityEngine.Networking;
    public abstract class HttpPack
        // 事件id
        public int id;
        // 请求地址
        public string url;
        // 协议类型(Get/Post)
        public HttpType httpType;
        // 返回数据类型
        public Type dataType;
        // 请求参数
        public string parame;
        // 重试次数
        public int tryCount;
        public UnityWebRequest webRequest;
        public abstract void OnData(string dataStr,int code,int messageId);
    public class HttpPack<T> : HttpPack where T : class
        public override void OnData(string dataStr,int code,int messageId)
            T data;
            //返回数据只有两种格式:字符串或类
            if(typeof(T).Name == "String")
                data = dataStr as T;
                data = FileUtility.JsonToData<T>(dataStr);
            //广播系统发出消息,功能模块开始处理服务器返回数据
            //MessageBroker.Instance.Publish<T>(data,messageId);
    

    HttpId,使用id作为key,既用于Http发送请求(通过自定义特性,可以将id与api绑定,每次发送请求只需要传入id,自动拼接url),又用于广播系统广播消息

    public class HttpId
        //示例,给id标记api
        [HttpApiKey("Register")]
        public const int registerId = 10001;
        [HttpApiKey("Login")]
        public const int loginId = 10002;
        public static void GetHttpApi()
            //反射获取字段
            System.Reflection.FieldInfo[] fields = typeof(HttpId).GetFields();
            System.Type attType = typeof(HttpApiKey);
            for(int i = 0; i < fields.Length; i++)
                if(fields[i].IsDefined(attType,false))
                    //获取id
                    int httpId = (int)fields[i].GetValue(null);
                    //获取api,读取字段的自定义Attribute
                    object attribute = fields[i].GetCustomAttributes(typeof(HttpApiKey),false)[0];
                    string httpApi = (attribute as HttpApiKey).httpApi;
    public class HttpApiKey : Attribute
        public HttpApiKey(string _httpApi)
            httpApi = _httpApi;
        public string httpApi;
            21.6k