HTTP接口访问类

using UnityEngine;
using System.Collections;
using System;
using System.Text;
using LitJson;
using System.Collections.Generic;
using NetworkMessages;
using System.Reflection;

/// <summary>
/// HTTP接口访问类
/// </summary>
public class WebAccess : MonoBehaviour
{
/// <summary>
/// 接口分类与后台服务基地址映射关系
/// </summary>
private static Dictionary<string, string> apiTypeToServerBaseUrlMap;

private static void InitializeApiTypeToServerUrlMap()
{
apiTypeToServerBaseUrlMap = new Dictionary<string, string>
{
{ "account", "http://192.168.0.75:8990/" },
{ "logic", "http://192.168.0.75:9601/" },
{ "PENDING", "http://192.168.0.75:11001/" },
};
}
private const float timeout = 3f;
static WebAccess instance;

public static WebAccess Instance
{
get
{
if (instance == null)
{
InitializeApiMaps();
InitializeApiTypeToServerUrlMap();
GameObject go = new GameObject("WebAccess");
instance = go.AddComponent<WebAccess>();
DontDestroyOnLoad(go);
return instance;
}
else
{
return instance;
}
}
}

private string token;
private Dictionary<string, string> headersToSend = new Dictionary<string, string>();

public string Token
{
get
{
return token;
}
set
{
token = value;
Debug.Log("set token to " + value);
headersToSend["Authorization"] = token;
}
}

/// <summary>
/// HTTP接口的返回结果类型与该接口对应的名称的字典
/// </summary>
static Dictionary<Type, string> apiNameMaps = null;
static Dictionary<Type, string> apiTypeMaps = null;

static void InitializeApiMaps()
{
apiNameMaps = new Dictionary<Type, string>();
apiTypeMaps = new Dictionary<Type, string>();
// 添加所有用到的HTTP接口的返回结果类型
Assembly current = Assembly.GetExecutingAssembly();
Type[] allTypes = current.GetTypes();
for (int i = 0; i < allTypes.Length; i++)
{
Type type = allTypes[i];
if (type.IsDefined(typeof(WebApiResultAttribute), false))
{
WebApiResultAttribute attr = type.GetCustomAttributes(typeof(WebApiResultAttribute), false)[0] as WebApiResultAttribute;
apiNameMaps.Add(type, attr.ApiName);
apiTypeMaps.Add(type, attr.ApiType);
}
}
Debug.Log("registered Web-API count: " + apiNameMaps.Count);
}

void OnDestroy()
{
instance = null;
if (apiNameMaps != null)
{
apiNameMaps.Clear();
apiNameMaps = null;
}
if (apiTypeMaps != null)
{
apiTypeMaps.Clear();
apiTypeMaps = null;
}
}

string GetApiUrlByType(Type type)
{
string apiType = apiTypeMaps[type];
string apiName = apiNameMaps[type];
return apiTypeToServerBaseUrlMap[apiType] + apiName;
}

/// <summary>
/// 执行HTTP接口
/// </summary>
/// <param name="parameters">接口所需的参数</param>
/// <param name="onSuccess">接口调用成功时回调</param>
/// <param name="onFail">接口调用失败时的回调</param>
/// <typeparam name="TResult">该HTTP接口的返回结果类型</typeparam>
public void RunAPI<TResult>(WebApiParameter parameters, Action<WebApiResult> onSuccess, Action<WebApiError> onFail) where TResult : WebApiResult
{
DialogTipsCtrl.Instance.BeginWait();
StartCoroutine(GetData(parameters, typeof(TResult), onSuccess, onFail));
}

/// <summary>
/// 以协程方式访问HTTP接口
/// </summary>
/// <param name="parameters">接口所需的参数</param>
/// <param name="resultType">返回结果类型</param>
/// <param name="onSuccess">接口调用成功时回调</param>
/// <param name="onFail">接口调用失败时的回调</param>
IEnumerator GetData(WebApiParameter parameters, Type resultType, Action<WebApiResult> onSuccess, Action<WebApiError> onFail)
{
string json = JsonMapper.ToJson(parameters);
string encrypted = Web.Networking.AesBase64Encrypt.Encrypt(json);
byte[] rawData = Encoding.UTF8.GetBytes(encrypted);
string fullUrl = GetApiUrlByType(resultType);
Debug.Log("accessing " + fullUrl + " with parameters: " + json + " with rawdata: " + encrypted);
WWW www = new WWW(fullUrl, rawData, headersToSend);
float time = 0f;
float progress = 0f;
while (string.IsNullOrEmpty(www.error) && !www.isDone)
{
// 如果进度长时间不动,就累积这个时间,做超时处理。
if (www.progress != progress)
{
// 如果进度变化,重置超时计时为0
time = 0f;
progress = www.progress;
}
time += Time.deltaTime;
if (time > timeout)
{
break;
}
yield return null;
}
try
{
if (time > timeout)
{
Debug.LogError("HTTP接口访问超时");
SafelyInvokeOnFailCallback(onFail, new WebApiError("HTTP接口访问超时"));
}
else if (string.IsNullOrEmpty(www.error))
{
string webResult = www.text;
Debug.Log("server reply: " + www.text);
string decrypted = Web.Networking.AesBase64Encrypt.Decrypt(webResult);
Debug.Log("decrypted server reply: " + decrypted);
object obj = JsonMapper.ToObject(decrypted, resultType);
WebApiResult result = (WebApiResult)obj;
if (result.result == 0)
{
SafelyInvokeOnSuccessCallback(onSuccess, result);
}
else
{
SafelyInvokeOnFailCallback(onFail, new WebApiError(result.result));
}
}
else
{
SafelyInvokeOnFailCallback(onFail, new WebApiError(www.error));
}
}
catch (Exception e)
{
Debug.LogException(e);
SafelyInvokeOnFailCallback(onFail, new WebApiError(e));
}
finally
{
DialogTipsCtrl.Instance.EndWait();
}
}

/// <summary>
/// 安全地调用成功回调方法
/// </summary>
void SafelyInvokeOnSuccessCallback(Action<WebApiResult> onSuccess, WebApiResult result)
{
if (onSuccess != null)
{
// 包裹回调调用,可以避免因为回调本身的异常被判定为 RunAPI 的错误。
try
{
onSuccess(result);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
}

/// <summary>
/// 安全地调用失败回调方法
/// </summary>
void SafelyInvokeOnFailCallback(Action<WebApiError> onFail, WebApiError error)
{
if (onFail != null)
{
// 包裹回调调用,可以避免因为回调本身的异常被判定为 RunAPI 的错误。
try
{
onFail(error);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
}

}

时间: 2024-08-07 22:51:38

HTTP接口访问类的相关文章

Java知多少(111)几个重要的java数据库访问类和接口

修改数据表记录也有3种方案. 一.使用Statement对象 实现修改数据表记录的SQL语句的语法是:    update表名 set 字段名1 = 字段值1,字段名2 = 字段值2,……where特定条件例如: update ksInfo set 姓名 = ‘张小卫’where 姓名 = ‘张大卫’ 先创建一个SQL语句,然砶调用Statement对象的executeUpdate()方法.例如, 1 sql = “update ksInfo set 姓名 = ‘”+txtName.getTex

C#连接层的数据访问类(简单版)

目前只写了与SqlServer的数据处理. 首先是静态工厂类. using System; using System.Configuration; namespace XPSoft.BaseLibrary.DataAccess { /// <summary> /// 数据访问对象的静态工厂类,用于创建不同类型的数据访问对象. /// </summary> public static class DataAccessFactory { /// <summary> ///

asp.net mvc,基于aop实现的接口访问统计、接口缓存等

其实asp.net 上aop现有的框架应该蛮多的,比如静态注入式的PostSharp(新版本好像已经商业化了,旧版本又不支持.net4.0+),或者通过反射的(性能会降低). 本文则是通过mvc其中一种方法拦截器ActionFilter(参考网上已经有很多类似例子). 首先新建一个日志控制类,命名为ApiLogAttribute,继承于ActionFilterAttribute /// <summary> /// 记录访问日志以及站点安全检查 /// </summary> publ

学习实践:使用模式,原则实现一个C++数据库访问类

一.概述 在我参与的多个项目中,大家使用libMySQL操作MySQL数据库,而且是源码即复用,在多个项目中有多套相同或相似的源码,这样的复用方式给开发带来了不变,而且libMySQL的使用比较麻烦,要应对很多的细节,很容易出错. 我要写一个动态链接库,将对libMySQL的操作封装起来,以二进制复用代替源码级复用:要提供线程安全的接口,用户无需关系是否加锁这样细节性的问题,减少出错及死锁的机会,当然也要允许用户自己选择是否线程安全的访问数据库:要简化访问数据库的流程,接口越简单越好. 我从20

Servlet基础之一:Servlet基本接口与类

1.概述 Servlet API中共有5个包,约113个接口和类: javax.servlet javax.servlet.http javax.servlet.jsp javax.servlet.annotation javax.servlet.descriptor 2.Servlet接口 (1)所有Servlet/JSP应用必须直接或者间接实现Servlet接口, Servlet/JSP容器会将实现了Servlet接口的类加载至容器,以供访问. (2)Servlet中共定义了5个方法: vo

PHP 面向对对象基础(接口,类)

介绍PHP面向对象的基础知识 1. 接口的定义interface ,类定义class,类支持abstract和final修饰符,abstract修饰为抽象类,抽象类 不支持直接实例化,final修饰的类/方法不能被继承/方法重写.2. 接口的实现通过implements,类继承extends interface IShape{ function draw_core(); }; class PathShape implements IShape{ public function draw_core

List接口实现类-ArrayList、Vector、LinkedList集合深入学习以及源码解析

学习List接口实现类 ArrayList  Vector  LinkedList List接口的实现类中最常用最重要的就是这三个:ArrayList.Vector.LinkedList. JDK中这三个类的定义: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { <span st

我的C++数据库访问类

一.概述 在我参与的多个项目中,大家使用libMySQL操作MySQL数据库,而且是源码即复用,在多个项目中有多套相同或相似的源码,这样的复用方式给开发带来了不变,而且libMySQL的使用比较麻烦,要应对很多的细节,很容易出错. 我要写一个动态链接库,将对libMySQL的操作封装起来,以二进制复用代替源码级复用:要提供线程安全的接口,用户无需关系是否加锁这样细节性的问题,减少出错及死锁的机会,当然也要允许用户自己选择是否线程安全的访问数据库:要简化访问数据库的流程,接口越简单越好. 我从20

MyBatis核心接口和类

MyBatis核心接口和类 SqlSessionFactoryBuilder: SqlSessionFactoryBuilder负责构建SqlSessionFactory.它的最大特点是:用过即丢.一旦创建了SqlSessionFactory对象之后,这个类就不需要存在了,因此SqlSessionFactoryBuilder的最佳范围就是存在于方法体内,也就是局部变量而已. SqlSessionFactory: SqlSessionFactory简单的理解就是创建SqlSession实例的工厂.