钉钉的客户端开发和服务端有一个重要的区别,服务端只需要得到access_token就可以了,而客户端还需要进一步换取jsticket。所以我们要进行客户端的开发,第一步就是得到jsticket。又由于jsticket有7200秒的限制,而且每请求一次前面的就会失效,为此我们需要做一个缓存层来保存。
首先我们来看缓存层的代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DDSDK { /// <summary> /// 简易缓存 /// </summary> public class SimpleCacheProvider : ICacheProvider { private static SimpleCacheProvider _instance = null; private readonly object _lockObj=new object(); #region GetInstance /// <summary> /// 获取缓存实例 /// </summary> /// <returns></returns> public static SimpleCacheProvider GetInstance() { if (_instance == null) lock(_lockObj){_instance =_instance?? new SimpleCacheProvider()};//使用单例模式以确保并发时实例始终是同一个 return _instance; } #endregion private Dictionary<string, CacheItem> _caches; private SimpleCacheProvider() { this._caches = new Dictionary<string, CacheItem>(); } #region GetCache /// <summary> /// 获取缓存 /// </summary> /// <param name="key"></param> /// <returns></returns> public object GetCache(string key) { object obj = this._caches.ContainsKey(key) ? this._caches[key].Expired() ? null : this._caches[key].Value : null; return obj; } /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(String key) { object obj = GetCache(key); if (obj == null) { return default(T); } T result = (T)obj; return result; } #endregion #region SetCache /// <summary> /// 设置缓存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expire"></param> public void SetCache(string key, object value, int expire = 300) { this._caches[key] = new CacheItem(key, value, expire); } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DDSDK { /// <summary> /// 缓存接口 /// </summary> interface ICacheProvider { /// <summary> /// 获取缓存 /// </summary> /// <param name="key">缓存key</param> /// <returns>缓存对象或null,不存在或者过期返回null</returns> object GetCache(string key); /// <summary> /// 写入缓存 /// </summary> /// <param name="key">缓存key</param> /// <param name="value">缓存值</param> /// <param name="expire">缓存有效期,单位为秒,默认300</param> void SetCache(string key, object value, int expire = 300); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DDSDK { /// <summary> /// 缓存项 /// </summary> public class CacheItem { #region 属性 private object _value; public object Value { get { return _value; } set { _value = value; } } private string _key; public string Key { get { return _key; } set { _key = value; } } #endregion #region 内部变量 /// <summary> /// 插入时间 /// </summary> private DateTime _insertTime; /// <summary> /// 过期时间 /// </summary> private int _expire; #endregion #region 构造函数 /// <summary> /// 构造函数 /// </summary> /// <param name="key">缓存的KEY</param> /// <param name="value">缓存的VALUE</param> /// <param name="expire">缓存的过期时间</param> public CacheItem(string key, object value, int expire) { this._key = key; this._value = value; this._expire = expire; this._insertTime = DateTime.Now(); } #endregion #region Expired /// <summary> /// 是否过期 /// </summary> /// <returns></returns> public bool Expired() { return DateTime.Now() < this._insertTime.AddSeconds(_expire); } #endregion } }
代码中最关键的是缓存的单例GetInstance,这样确保了全局的一致性。如果需要进一步强化,可以考虑使用lock来实现更结实的单例模式。
下面我们来获取jsticket.
#region FetchJSTicket Function /// <summary> /// 获取JS票据 /// </summary> /// <param name="url"></param> /// <returns></returns> public static JSTicket FetchJSTicket() { var cache = SimpleCacheProvider.GetInstance(); var jsTicket = cache.GetCache<JSTicket>(ConstVars.CACHE_JS_TICKET_KEY); if (jsTicket == null||AccessToken.Begin.AddSeconds(ConstVars.CACHE_TIME) < DateTime.Now)//jsTicket为null表示不存在或过期,或AccessToken过期 { String apiurl = FormatApiUrlWithToken(Urls.get_jsapi_ticket);//该方法参看《钉钉开发系列(三)API的调用》 jsTicket = Analyze.Get<JSTicket>(apiurl); cache.SetCache(ConstVars.CACHE_JS_TICKET_KEY, jsTicket, ConstVars.CACHE_TIME-500);//增加500的时间差以防与AccessToken错位过期 } return jsTicket; } #endregion
namespace DDSDK { /// <summary> /// JSAPI时用的票据 /// </summary> public class JSTicket : ResultPackage { public string ticket { get; set; } public int expires_in { get; set; } } }
调用FetchJsTicket就可以得到JS票据了,并且内部已经作了相应的缓存处理。
欢迎打描左侧二维码打赏。
转载请注明出处。