using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Web.Caching; using System.Web.Hosting; using FSLib.Network.Http; using Newtonsoft.Json; using TrainInfomationProviderService.StationInfo.Entities; namespace TrainInfomationProviderService.StationInfo { /// /// public class StationManager { private static readonly object _lockObject = new object(); private static StationManager _stationManager; public static StationManager Instance { get { if (_stationManager == null) { lock (_lockObject) { if (_stationManager == null) { _stationManager = new StationManager(); } } } return _stationManager; } } /// /// 创建 的新实例(StationManager) /// public StationManager() { Trace.TraceInformation("[STATION] 车站管理器对象已新建"); } private string _dataFilePath; /// /// 仓库 /// public StationStorage Storage { get { return _storage; } } public void Init() { Trace.TraceInformation("[STATION] 正在初始化"); _dataFilePath = PathUtility.Combine(RunTimeContext.DataStorageRoot, "stations.json"); Trace.TraceInformation("[STATION] 目标缓存文件路径:{0}", _dataFilePath); //if (RunTimeContext.IsWeb) //{ // Trace.TraceInformation("[STATION] WEB模式"); // InitWeb(); //} //else //{ Trace.TraceInformation("[STATION] 服务模式"); InitService(); //} } #region web环境 ///// ///// web环境初始化 ///// //void InitWeb() //{ // Trace.TraceInformation("[STATION] 初始化WEB模式"); // LoadCache(); //} //void LoadCache() //{ // Trace.TraceInformation("[STATION] 正在检查缓存刷新"); // _storage = null; // if (File.Exists(_dataFilePath)) // { // Trace.TraceInformation("[STATION] 正在加载缓存"); // _storage = JsonConvert.DeserializeObject(File.ReadAllText(_dataFilePath)); // Trace.TraceInformation("[STATION] 缓存加载完成"); // } // if (Storage != null) // { // Trace.TraceInformation("[STATION] 正在加入HttpRuntime缓存"); // HostingEnvironment.Cache.Add("_12306stations", Storage, new CacheDependency(_dataFilePath), // Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High, // (_1, _2, _3) => // { // Trace.TraceInformation("[STATION] HttpRuntime缓存已被清除,原因:{0},正在重新加载", _3); // LoadCache(); // }); // Trace.TraceInformation("[STATION] HttpRuntime缓存加入完成"); // } //} #endregion #region 服务模式 private Timer _checkStationTimer; private StationStorage _storage; /// /// 服务模式初始化 /// void InitService() { if (_dataFilePath.AsFileInfo().Exists) { Trace.TraceInformation("[STATION] 正在加载文件缓存数据"); _storage = JsonConvert.DeserializeObject(File.ReadAllText(_dataFilePath)); Trace.TraceInformation("[STATION] 文件缓存数据加载完成"); } var lastestVersion = GetLatestVersionFromWeb(); var needUpdate = _storage == null || _storage.Version < lastestVersion; Trace.TraceInformation("[STATION] 最新版本:{0}", lastestVersion); if (needUpdate) { Trace.TraceInformation("[STATION] 正在刷新缓存"); RefreshStationInfo(lastestVersion); SameStationManager.AutoRefreshFromSource(); Trace.TraceInformation("[STATION] 缓存数据已刷新"); } _checkStationTimer = new Timer(_ => CheckStationVersion(), null, new TimeSpan(0, 30, 0), Timeout.InfiniteTimeSpan); } void RefreshStationInfo(int version) { Trace.TraceInformation("[STATION] 正在获得最新车站信息"); var html = new HttpClient().Create(HttpMethod.Get, "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js", null, null, "").Send(); if (!html.IsValid()) { Trace.TraceError("[STATION] 车站信息获得失败。错误:{0}", html.Exception); return; } Trace.TraceInformation("[STATION] 正在分析车站信息"); var mcs = Regex.Matches(html.Result, @"@([^\|]+)\|([^\|]+)\|([^\|]+)\|([^\|]+)\|([^\|]+)\|(\d+)"); var result = new List(mcs.Count); foreach (Match mc in mcs) { var s = new StationDetailInfo() { Code = mc.GetGroupValue(3), Name = mc.GetGroupValue(2), Py = mc.GetGroupValue(5), PyFull = mc.GetGroupValue(4), Sort = mc.GetGroupValue(6).ToInt32() }; result.Add(s); } _storage = new StationStorage(version, result); Trace.TraceInformation("[STATION] 车站信息分析完成,{0} 车站。正在缓存车站信息", result.Count); //save File.WriteAllText(_dataFilePath, JsonConvert.SerializeObject(Storage)); Trace.TraceInformation("[STATION] 车站信息缓存完成。目标文件 {0}", _dataFilePath); } void CheckStationVersion() { var lastestVersion = GetLatestVersionFromWeb(); if (Storage == null || Storage.Version < lastestVersion) { RefreshStationInfo(lastestVersion); } _checkStationTimer.Change(new TimeSpan(0, 30, 0), Timeout.InfiniteTimeSpan); } /// /// 从网络加载最新的版本号 /// /// public int GetLatestVersionFromWeb() { var ctx = new HttpClient().Create(HttpMethod.Get, "https://kyfw.12306.cn/otn/leftTicket/init", "https://kyfw.12306.cn/otn/leftTicket/init").Send(); if (!ctx.IsValid()) return 0; var version = (int)(Regex.Match(ctx.Result, @"station_name\.js\?station_version=([\d\.]+)").GetGroupValue(1).ToSingle() * 100000); return version; } #endregion } }