转载构建高性能插件式Web框架
基于MVC插件模式构建支持数据库集群、数据实时同步、数据发布与订阅的Web框架系统。如下图:
1、基于插件式开发
采用插件模式开发的优点是使得系统框架和业务模式有效地进行分离,系统更新也比较简单,只需更新业务插件,不需要动整个框架,开发人员无需关心整个框架结构。
但插件模式调试稍微麻烦一点,比不采用插件模式开发的效率上也要差一点,因为它采用反射进行动态加载插件。
登录插件示例:
namespace LoginPlugin { public class Plugin : NetUML.Portal.Framework.AbstractPlugin { public Plugin() { this.Title = "系统登录"; this.Description = "登录插件"; } public override string Name { get { return "LoginPlugin"; } set { } } public override int StartLevel { get { return 2; } set { } } public override void Start(NetUML.Portal.Framework.IBundleContext context) { } public override void Stop(NetUML.Portal.Framework.IBundleContext context) { } public override string SymbolicName { set { } get { return "System.Login"; } } public override List<NetUML.Portal.Framework.MenuItem> MenuItems { get { return null; } } public override NetUML.Portal.Framework.PluginType PluginType { get { return NetUML.Portal.Framework.PluginType.Login; } } public override string Title { get; set; } public override string Description { get; set; } } }
所有插件必须实现 NetUML.Portal.Framework.AbstractPlugin 这个插件抽象类。
当加载插件的时候会执行Start方法,停止插件的时候会执行Stop方法。
2、数据库引擎
数据库引擎NetUML.DataEngine类,采用IBatisNet底层访问数据库原理,动态创建IDbConnection连接池,核心代码如下
1 namespace NetUML.DataEngine 2 { 3 public class DbSession : MarshalByRefObject, IDalSession 4 { 5 6 #region Fields 7 private IDataSource _dataSource = null; 8 private bool _isTransactionOpen = false; 9 private bool _consistent = false; 10 private IDbConnection _connection = null; 11 private IDbTransaction _transaction = null; 12 #endregion 13 public DbSession(IDataSource dataSource) 14 { 15 _dataSource = dataSource; 16 } 17 public IDataSource DataSource 18 { 19 get { return _dataSource; } 20 } 21 22 public System.Data.IDbConnection Connection 23 { 24 get { return _connection; } 25 } 26 27 public System.Data.IDbTransaction Transaction 28 { 29 get { return _transaction; } 30 } 31 32 public bool IsTransactionStart 33 { 34 get { return _isTransactionOpen; } 35 } 36 private bool Consistent 37 { 38 set { _consistent = value; } 39 } 40 public void Complete() 41 { 42 this.Consistent = true; 43 } 44 45 public void OpenConnection() 46 { 47 this.OpenConnection(_dataSource.ConnectionString); 48 } 49 public void OpenConnection(string connectionString) 50 { 51 if (_connection == null) 52 { 53 CreateConnection(connectionString); 54 try 55 { 56 _connection.Open(); 57 //if (_logger.IsDebugEnabled) 58 //{ 59 // _logger.Debug(string.Format("Open Connection \"{0}\" to \"{1}\".", _connection.GetHashCode().ToString(), _dataSource.DbProvider.Description)); 60 //} 61 } 62 catch (Exception ex) 63 { 64 //DataMapperException 65 throw new Exception(string.Format("Unable to open connection to \"{0}\".", _dataSource.DbProvider.Description), ex); 66 } 67 } 68 else if (_connection.State != ConnectionState.Open) 69 { 70 try 71 { 72 _connection.Open(); 73 //if (_logger.IsDebugEnabled) 74 //{ 75 // _logger.Debug(string.Format("Open Connection \"{0}\" to \"{1}\".", _connection.GetHashCode().ToString(), _dataSource.DbProvider.Description)); 76 //} 77 } 78 catch (Exception ex) 79 { 80 throw new Exception(string.Format("Unable to open connection to \"{0}\".", _dataSource.DbProvider.Description), ex); 81 } 82 } 83 } 84 public void CreateConnection() 85 { 86 CreateConnection(_dataSource.ConnectionString); 87 } 88 /// <summary> 89 /// Create the connection 90 /// </summary> 91 public void CreateConnection(string connectionString) 92 { 93 _connection = _dataSource.DbProvider.CreateConnection(); 94 _connection.ConnectionString = connectionString; 95 } 96 97 public void CloseConnection() 98 { 99 if ((_connection != null) && (_connection.State != ConnectionState.Closed)) 100 { 101 _connection.Close(); 102 //if (_logger.IsDebugEnabled) 103 //{ 104 // _logger.Debug(string.Format("Close Connection \"{0}\" to \"{1}\".", _connection.GetHashCode().ToString(), _dataSource.DbProvider.Description)); 105 //} 106 _connection.Dispose(); 107 } 108 _connection = null; 109 } 110 111 public void BeginTransaction() 112 { 113 this.BeginTransaction(_dataSource.ConnectionString); 114 } 115 116 public void BeginTransaction(string connectionString) 117 { 118 if (_connection == null || _connection.State != ConnectionState.Open) 119 { 120 this.OpenConnection(connectionString); 121 } 122 _transaction = _connection.BeginTransaction(); 123 //if (_logger.IsDebugEnabled) 124 //{ 125 // _logger.Debug("Begin Transaction."); 126 //} 127 _isTransactionOpen = true; 128 } 129 public void BeginTransaction(bool openConnection) 130 { 131 if (openConnection) 132 { 133 this.BeginTransaction(); 134 } 135 else 136 { 137 if (_connection == null || _connection.State != ConnectionState.Open) 138 { 139 this.OpenConnection(); 140 } 141 _transaction = _connection.BeginTransaction(); 142 //if (_logger.IsDebugEnabled) 143 //{ 144 // _logger.Debug("Begin Transaction."); 145 //} 146 _isTransactionOpen = true; 147 } 148 } 149 public void BeginTransaction(System.Data.IsolationLevel isolationLevel) 150 { 151 this.BeginTransaction(_dataSource.ConnectionString, isolationLevel); 152 } 153 public void BeginTransaction(string connectionString, System.Data.IsolationLevel isolationLevel) 154 { 155 if (_connection == null || _connection.State != ConnectionState.Open) 156 { 157 this.OpenConnection(connectionString); 158 } 159 _transaction = _connection.BeginTransaction(isolationLevel); 160 //if (_logger.IsDebugEnabled) 161 //{ 162 // _logger.Debug("Begin Transaction."); 163 //} 164 _isTransactionOpen = true; 165 } 166 public void BeginTransaction(bool openConnection, System.Data.IsolationLevel isolationLevel) 167 { 168 this.BeginTransaction(_dataSource.ConnectionString, openConnection, isolationLevel); 169 } 170 public void BeginTransaction(string connectionString, bool openConnection, System.Data.IsolationLevel isolationLevel) 171 { 172 if (openConnection) 173 { 174 this.BeginTransaction(connectionString, isolationLevel); 175 } 176 else 177 { 178 if (_connection == null || _connection.State != ConnectionState.Open) 179 { 180 //DataMapperException 181 throw new Exception("SqlMapSession could not invoke StartTransaction(). A Connection must be started. Call OpenConnection() first."); 182 } 183 _transaction = _connection.BeginTransaction(isolationLevel); 184 //if (_logger.IsDebugEnabled) 185 //{ 186 // _logger.Debug("Begin Transaction."); 187 //} 188 _isTransactionOpen = true; 189 } 190 } 191 public void CommitTransaction() 192 { 193 //if (_logger.IsDebugEnabled) 194 //{ 195 // _logger.Debug("Commit Transaction."); 196 //} 197 _transaction.Commit(); 198 _transaction.Dispose(); 199 _transaction = null; 200 _isTransactionOpen = false; 201 202 if (_connection.State != ConnectionState.Closed) 203 { 204 this.CloseConnection(); 205 } 206 } 207 208 public void CommitTransaction(bool closeConnection) 209 { 210 if (closeConnection) 211 { 212 this.CommitTransaction(); 213 } 214 else 215 { 216 //if (_logger.IsDebugEnabled) 217 //{ 218 // _logger.Debug("Commit Transaction."); 219 //} 220 _transaction.Commit(); 221 _transaction.Dispose(); 222 _transaction = null; 223 _isTransactionOpen = false; 224 } 225 } 226 227 public void RollBackTransaction() 228 { 229 //if (_logger.IsDebugEnabled) 230 //{ 231 // _logger.Debug("RollBack Transaction."); 232 //} 233 _transaction.Rollback(); 234 _transaction.Dispose(); 235 _transaction = null; 236 _isTransactionOpen = false; 237 if (_connection.State != ConnectionState.Closed) 238 { 239 this.CloseConnection(); 240 } 241 } 242 243 public void RollBackTransaction(bool closeConnection) 244 { 245 if (closeConnection) 246 { 247 this.RollBackTransaction(); 248 } 249 else 250 { 251 //if (_logger.IsDebugEnabled) 252 //{ 253 // _logger.Debug("RollBack Transaction."); 254 //} 255 _transaction.Rollback(); 256 _transaction.Dispose(); 257 _transaction = null; 258 _isTransactionOpen = false; 259 } 260 } 261 262 public IDbCommand CreateCommand(CommandType commandType) 263 { 264 IDbCommand command = _dataSource.DbProvider.CreateCommand(); 265 command.CommandType = commandType; 266 command.Connection = _connection; 267 if (_transaction != null) 268 { 269 try 270 { 271 command.Transaction = _transaction; 272 } 273 catch 274 { } 275 } 276 if (_connection != null) 277 { 278 try 279 { 280 command.CommandTimeout = _connection.ConnectionTimeout; 281 } 282 catch (NotSupportedException e) 283 { 284 //if (_logger.IsInfoEnabled) 285 //{ 286 // _logger.Info(e.Message); 287 //} 288 } 289 } 290 return command; 291 } 292 293 public System.Data.IDbDataParameter CreateDataParameter() 294 { 295 return _dataSource.DbProvider.CreateDataParameter(); 296 } 297 public System.Data.IDbDataAdapter CreateDataAdapter() 298 { 299 return _dataSource.DbProvider.CreateDataAdapter(); 300 } 301 public System.Data.IDbDataAdapter CreateDataAdapter(System.Data.IDbCommand command) 302 { 303 IDbDataAdapter dataAdapter = null; 304 dataAdapter = _dataSource.DbProvider.CreateDataAdapter(); 305 dataAdapter.SelectCommand = command; 306 return dataAdapter; 307 } 308 public void Dispose() 309 { 310 //if (_logger.IsDebugEnabled) 311 //{ 312 // _logger.Debug("Dispose SqlMapSession"); 313 //} 314 if (_isTransactionOpen == false) 315 { 316 if (_connection.State != ConnectionState.Closed) 317 { 318 this.CloseConnection(); 319 } 320 } 321 else 322 { 323 if (_consistent) 324 { 325 this.CommitTransaction(); 326 _isTransactionOpen = false; 327 } 328 else 329 { 330 if (_connection.State != ConnectionState.Closed) 331 { 332 this.RollBackTransaction(); 333 _isTransactionOpen = false; 334 } 335 } 336 } 337 } 338 } 339 }
程序结构如下图:
3、数据库集群服务
NetUML.DataEngine支持多数据库连接,主持数据库读写分离操作,哪些数据表需要读写分离可以进行相应的配置和管理,类似于MVC中的路由概念,咱们可以配置多条路由表,路由表内容包括数
据表名,数据对象关键词以及数据库信息,用户保存数据的时候,系统根据要保存的数据表以及数据对象去寻找路由,再根据路由中的配置信息进行提交到数据库。
进在开发中。。。。。。。。
4、数据同步、发布和订阅服务
如果第三方系统接入当前系统当中来,当前系统中的数据发生变化,需要立马通知接入进来的系统,把变化的数据提交给第三方系统,第三方系统接入到数据进行相应的处理。
第三方系统只需要提供给当前系统一个URL地址,当前系统把数据POST到URL地址。
进在开发中。。。。。。。。
5、插件管理
系统框架支持上传插件包,不需要到服务器进行更新程序,上传完插件包之后,系统自动把插件包解压出来,进行动态编译加载插件。
系统框架也支持停止和卸载插件。如下图:
6、海量文档资料+全文搜索插件
文档管理插件支持office等文档在线浏览以及文件转换,把文档转换成HTML文件,支持全文解析和全文搜索功能
进在开发中。。。。。。。。
7、微信公共帐号订制插件
进在开发中。。。。。。。。
8、待续.....