执行按钮点击回传事件或者验证事件,如果有多个按钮,根据回发过来的按钮的 name来判断触发哪个按钮的事件,或者触发该控件的验证事件
10.触发PerformPreRenderComplete事件 循环遍历控件树中所有的控件,根据每个控件生成对应的Html代码,把服务器控件渲染成普通的html控件。
11.触发事件SaveAllState事件 将服务器端ViewState集合中的内容(开发者自己加的数据或控件状态信息等)序列化然后Base64编码然后设置到客户端隐藏域__ViewState中
12.RenderControl(this.CreateHtmlTextWriter(this.Response.Output)) 把要发送到客户端浏览器的内容设置到Response.Output,应用程序将它发送 到客户端浏览器。
看到这里不知道大家是否已经可以清晰地回答开篇提到的几个问题了,其实就是这些事件执行的先后顺序,页面生命周期了。”前人植树,后人乘凉了"
最后附上生命周期ProcessRequest源码
ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) 2 { { 5 HttpContext context = this.Context; 6 string str = null; 7 if (includeStagesBeforeAsyncPoint) 8 { 9 if (this.IsInAspCompatMode) 10 { 11 AspCompatApplicationStep.OnPageStartSessionObjects(); 12 } 13 if (this.PageAdapter != null) 14 { 15 this._requestValueCollection = this.PageAdapter.DeterminePostBackMode(); 16 if (this._requestValueCollection != null) 17 { 18 this._unvalidatedRequestValueCollection = this.PageAdapter.DeterminePostBackModeUnvalidated(); 19 } 20 } { 23 this._requestValueCollection = this.DeterminePostBackMode(); 24 if (this._requestValueCollection != null) 25 { 26 this._unvalidatedRequestValueCollection = this.DeterminePostBackModeUnvalidated(); 27 } 28 } 29 string callbackControlID = string.Empty; 30 if (this.DetermineIsExportingWebPart()) 31 { 32 if (!RuntimeConfig.GetAppConfig().WebParts.EnableExport) 33 { InvalidOperationException(SR.GetString()); 35 } ]; 37 if (string.IsNullOrEmpty(str)) 38 { InvalidOperationException(SR.GetString()); 40 } ], , StringComparison.OrdinalIgnoreCase)) 42 { 43 this._pageFlags.Set(4); 44 } ]; 46 if (str3 == null) 47 { 48 str3 = string.Empty; 49 } 50 this.Request.QueryStringText = str3; 51 context.Trace.IsEnabled = false; 52 } 53 if (this._requestValueCollection != null) 54 { ] != null) 56 { 57 this.ContainsEncryptedViewState = true; 58 } ]; 60 if ((callbackControlID != null) && (this._request.HttpVerb == HttpVerb.POST)) 61 { 62 this._isCallback = true; 63 } (!this.IsCrossPagePostBack) 65 { 66 VirtualPath path = null; ] != null) 68 { { ], Purpose.WebForms_Page_PreviousPageID)); 72 } { 75 this._pageFlags[8] = true; 76 } 77 if ((path != null) && (path != this.Request.CurrentExecutionFilePathObject)) 78 { 79 this._pageFlags[8] = true; 80 this._previousPagePath = path; 81 } 82 } 83 } 84 } 85 if (this.MaintainScrollPositionOnPostBack) 86 { 87 this.LoadScrollPosition(); 88 } 89 if (context.TraceIsEnabled) 90 { , ); 92 } 93 if (EtwTrace.IsTraceEnabled(5, 4)) 94 { 95 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_ENTER, this._context.WorkerRequest); 96 } 97 this.PerformPreInit(); 98 if (EtwTrace.IsTraceEnabled(5, 4)) 99 { 100 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_LEAVE, this._context.WorkerRequest); 101 } 102 if (context.TraceIsEnabled) 103 { , ); 105 } 106 if (context.TraceIsEnabled) 107 { , ); 109 } 110 if (EtwTrace.IsTraceEnabled(5, 4)) 111 { 112 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_ENTER, this._context.WorkerRequest); 113 } 114 this.InitRecursive(null); 115 if (EtwTrace.IsTraceEnabled(5, 4)) 116 { 117 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_LEAVE, this._context.WorkerRequest); 118 } 119 if (context.TraceIsEnabled) 120 { , ); 122 } 123 if (context.TraceIsEnabled) 124 { , ); 126 } 127 this.OnInitComplete(EventArgs.Empty); 128 if (context.TraceIsEnabled) 129 { , ); 131 } 132 if (this.IsPostBack) 133 { 134 if (context.TraceIsEnabled) 135 { , ); 137 } 138 if (EtwTrace.IsTraceEnabled(5, 4)) 139 { 140 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_ENTER, this._context.WorkerRequest); 141 } 142 this.LoadAllState(); 143 if (EtwTrace.IsTraceEnabled(5, 4)) 144 { 145 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_LEAVE, this._context.WorkerRequest); 146 } 147 if (context.TraceIsEnabled) 148 { , ); , ); 151 } 152 if (EtwTrace.IsTraceEnabled(5, 4)) 153 { 154 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_ENTER, this._context.WorkerRequest); 155 } 156 this.ProcessPostData(this._requestValueCollection, true); 157 if (EtwTrace.IsTraceEnabled(5, 4)) 158 { 159 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_LEAVE, this._context.WorkerRequest); 160 } 161 if (context.TraceIsEnabled) 162 { , ); 164 } 165 } 166 if (context.TraceIsEnabled) 167 { , ); 169 } 170 this.OnPreLoad(EventArgs.Empty); 171 if (context.TraceIsEnabled) 172 { , ); 174 } 175 if (context.TraceIsEnabled) 176 { , ); 178 } 179 if (EtwTrace.IsTraceEnabled(5, 4)) 180 { 181 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_ENTER, this._context.WorkerRequest); 182 } 183 this.LoadRecursive(); 184 if (EtwTrace.IsTraceEnabled(5, 4)) 185 { 186 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_LEAVE, this._context.WorkerRequest); 187 } 188 if (context.TraceIsEnabled) 189 { , ); 191 } 192 if (this.IsPostBack) 193 { 194 if (context.TraceIsEnabled) 195 { , ); 197 } 198 this.ProcessPostData(this._leftoverPostData, false); 199 if (context.TraceIsEnabled) 200 { , ); , ); 203 } 204 if (EtwTrace.IsTraceEnabled(5, 4)) 205 { 206 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_ENTER, this._context.WorkerRequest); 207 } 208 this.RaiseChangedEvents(); 209 if (EtwTrace.IsTraceEnabled(5, 4)) 210 { 211 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_LEAVE, this._context.WorkerRequest); 212 } 213 if (context.TraceIsEnabled) 214 { , ); , ); 217 } 218 if (EtwTrace.IsTraceEnabled(5, 4)) 219 { 220 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_ENTER, this._context.WorkerRequest); 221 } 222 this.RaisePostBackEvent(this._requestValueCollection); 223 if (EtwTrace.IsTraceEnabled(5, 4)) 224 { 225 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_LEAVE, this._context.WorkerRequest); 226 } 227 if (context.TraceIsEnabled) 228 { , ); 230 } 231 } 232 if (context.TraceIsEnabled) 233 { , ); 235 } 236 this.OnLoadComplete(EventArgs.Empty); 237 if (context.TraceIsEnabled) 238 { , ); 240 } 241 if (this.IsPostBack && this.IsCallback) 242 { 243 this.PrepareCallback(callbackControlID); 244 } (!this.IsCrossPagePostBack) 246 { 247 if (context.TraceIsEnabled) 248 { , ); 250 } 251 if (EtwTrace.IsTraceEnabled(5, 4)) 252 { 253 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_ENTER, this._context.WorkerRequest); 254 } 255 this.PreRenderRecursiveInternal(); 256 if (EtwTrace.IsTraceEnabled(5, 4)) 257 { 258 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_LEAVE, this._context.WorkerRequest); 259 } 260 if (context.TraceIsEnabled) 261 { , ); 263 } 264 } 265 } 266 if ((this._legacyAsyncInfo == null) || this._legacyAsyncInfo.CallerIsBlocking) 267 { 268 this.ExecuteRegisteredAsyncTasks(); 269 } 270 this.ValidateRawUrlIfRequired(); 271 if (includeStagesAfterAsyncPoint) 272 { 273 if (this.IsCallback) 274 { 275 this.RenderCallback(); 276 } (!this.IsCrossPagePostBack) 278 { 279 if (context.TraceIsEnabled) 280 { , ); 282 } 283 this.PerformPreRenderComplete(); 284 if (context.TraceIsEnabled) 285 { , ); 287 } 288 if (context.TraceIsEnabled) 289 { 290 this.BuildPageProfileTree(this.EnableViewState); , ); 292 } 293 if (EtwTrace.IsTraceEnabled(5, 4)) 294 { 295 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_ENTER, this._context.WorkerRequest); 296 } 297 this.SaveAllState(); 298 if (EtwTrace.IsTraceEnabled(5, 4)) 299 { 300 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_LEAVE, this._context.WorkerRequest); 301 } 302 if (context.TraceIsEnabled) 303 { , ); , ); 306 } 307 this.OnSaveStateComplete(EventArgs.Empty); 308 if (context.TraceIsEnabled) 309 { , ); , ); 312 } 313 if (EtwTrace.IsTraceEnabled(5, 4)) 314 { 315 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_ENTER, this._context.WorkerRequest); 316 } 317 if (str != null) 318 { 319 this.ExportWebPart(str); 320 } { 323 this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output)); 324 } 325 if (EtwTrace.IsTraceEnabled(5, 4)) 326 { 327 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_LEAVE, this._context.WorkerRequest); 328 } 329 if (context.TraceIsEnabled) 330 { , ); 332 } 333 this.CheckRemainingAsyncTasks(false); 334 } 335 } 336 } 337 catch (ThreadAbortException exception1) 338 { 339 HttpApplication.CancelModuleException exceptionState = exception1.ExceptionState as HttpApplication.CancelModuleException; 340 if ((((includeStagesBeforeAsyncPoint & includeStagesAfterAsyncPoint) && (this._context.Handler == this)) && ((this._context.ApplicationInstance != null) && (exceptionState != null))) && !exceptionState.Timeout) 341 { 342 this._context.ApplicationInstance.CompleteRequest(); 343 ThreadResetAbortWithAssert(); 344 } { 347 this.CheckRemainingAsyncTasks(true); 348 throw; 349 } 350 } 351 catch (ConfigurationException) 352 { 353 throw; 354 } 355 catch (Exception exception2) 356 { 357 PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST); 358 PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL); 359 if (!this.HandleError(exception2)) 360 { 361 throw; 362 } 363 } 364 } ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) 370 { { 373 HttpContext context = this.Context; 374 string str = null; 375 if (includeStagesBeforeAsyncPoint) 376 { 377 if (this.IsInAspCompatMode) 378 { 379 AspCompatApplicationStep.OnPageStartSessionObjects(); 380 } 381 if (this.PageAdapter != null) 382 { 383 this._requestValueCollection = this.PageAdapter.DeterminePostBackMode(); 384 if (this._requestValueCollection != null) 385 { 386 this._unvalidatedRequestValueCollection = this.PageAdapter.DeterminePostBackModeUnvalidated(); 387 } 388 } { 391 this._requestValueCollection = this.DeterminePostBackMode(); 392 if (this._requestValueCollection != null) 393 { 394 this._unvalidatedRequestValueCollection = this.DeterminePostBackModeUnvalidated(); 395 } 396 } 397 string callbackControlID = string.Empty; 398 if (this.DetermineIsExportingWebPart()) 399 { 400 if (!RuntimeConfig.GetAppConfig().WebParts.EnableExport) 401 { InvalidOperationException(SR.GetString()); 403 } ]; 405 if (string.IsNullOrEmpty(str)) 406 { InvalidOperationException(SR.GetString()); 408 } ], , StringComparison.OrdinalIgnoreCase)) 410 { 411 this._pageFlags.Set(4); 412 } ]; 414 if (str3 == null) 415 { 416 str3 = string.Empty; 417 } 418 this.Request.QueryStringText = str3; 419 context.Trace.IsEnabled = false; 420 } 421 if (this._requestValueCollection != null) 422 { ] != null) 424 { 425 this.ContainsEncryptedViewState = true; 426 } ]; 428 if ((callbackControlID != null) && (this._request.HttpVerb == HttpVerb.POST)) 429 { 430 this._isCallback = true; 431 } (!this.IsCrossPagePostBack) 433 { 434 VirtualPath path = null; ] != null) 436 { { ], Purpose.WebForms_Page_PreviousPageID)); 440 } { 443 this._pageFlags[8] = true; 444 } 445 if ((path != null) && (path != this.Request.CurrentExecutionFilePathObject)) 446 { 447 this._pageFlags[8] = true; 448 this._previousPagePath = path; 449 } 450 } 451 } 452 } 453 if (this.MaintainScrollPositionOnPostBack) 454 { 455 this.LoadScrollPosition(); 456 } 457 if (context.TraceIsEnabled) 458 { , ); 460 } 461 if (EtwTrace.IsTraceEnabled(5, 4)) 462 { 463 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_ENTER, this._context.WorkerRequest); 464 } 465 this.PerformPreInit(); 466 if (EtwTrace.IsTraceEnabled(5, 4)) 467 { 468 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_LEAVE, this._context.WorkerRequest); 469 } 470 if (context.TraceIsEnabled) 471 { , ); 473 } 474 if (context.TraceIsEnabled) 475 { , ); 477 } 478 if (EtwTrace.IsTraceEnabled(5, 4)) 479 { 480 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_ENTER, this._context.WorkerRequest); 481 } 482 this.InitRecursive(null); 483 if (EtwTrace.IsTraceEnabled(5, 4)) 484 { 485 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_LEAVE, this._context.WorkerRequest); 486 } 487 if (context.TraceIsEnabled) 488 { , ); 490 } 491 if (context.TraceIsEnabled) 492 { , ); 494 } 495 this.OnInitComplete(EventArgs.Empty); 496 if (context.TraceIsEnabled) 497 { , ); 499 } 500 if (this.IsPostBack) 501 { 502 if (context.TraceIsEnabled) 503 { , ); 505 } 506 if (EtwTrace.IsTraceEnabled(5, 4)) 507 { 508 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_ENTER, this._context.WorkerRequest); 509 } 510 this.LoadAllState(); 511 if (EtwTrace.IsTraceEnabled(5, 4)) 512 { 513 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_LEAVE, this._context.WorkerRequest); 514 } 515 if (context.TraceIsEnabled) 516 { , ); , ); 519 } 520 if (EtwTrace.IsTraceEnabled(5, 4)) 521 { 522 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_ENTER, this._context.WorkerRequest); 523 } 524 this.ProcessPostData(this._requestValueCollection, true); 525 if (EtwTrace.IsTraceEnabled(5, 4)) 526 { 527 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_LEAVE, this._context.WorkerRequest); 528 } 529 if (context.TraceIsEnabled) 530 { , ); 532 } 533 } 534 if (context.TraceIsEnabled) 535 { , ); 537 } 538 this.OnPreLoad(EventArgs.Empty); 539 if (context.TraceIsEnabled) 540 { , ); 542 } 543 if (context.TraceIsEnabled) 544 { , ); 546 } 547 if (EtwTrace.IsTraceEnabled(5, 4)) 548 { 549 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_ENTER, this._context.WorkerRequest); 550 } 551 this.LoadRecursive(); 552 if (EtwTrace.IsTraceEnabled(5, 4)) 553 { 554 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_LEAVE, this._context.WorkerRequest); 555 } 556 if (context.TraceIsEnabled) 557 { , ); 559 } 560 if (this.IsPostBack) 561 { 562 if (context.TraceIsEnabled) 563 { , ); 565 } 566 this.ProcessPostData(this._leftoverPostData, false); 567 if (context.TraceIsEnabled) 568 { , ); , ); 571 } 572 if (EtwTrace.IsTraceEnabled(5, 4)) 573 { 574 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_ENTER, this._context.WorkerRequest); 575 } 576 this.RaiseChangedEvents(); 577 if (EtwTrace.IsTraceEnabled(5, 4)) 578 { 579 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_LEAVE, this._context.WorkerRequest); 580 } 581 if (context.TraceIsEnabled) 582 { , ); , ); 585 } 586 if (EtwTrace.IsTraceEnabled(5, 4)) 587 { 588 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_ENTER, this._context.WorkerRequest); 589 } 590 this.RaisePostBackEvent(this._requestValueCollection); 591 if (EtwTrace.IsTraceEnabled(5, 4)) 592 { 593 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_LEAVE, this._context.WorkerRequest); 594 } 595 if (context.TraceIsEnabled) 596 { , ); 598 } 599 } 600 if (context.TraceIsEnabled) 601 { , ); 603 } 604 this.OnLoadComplete(EventArgs.Empty); 605 if (context.TraceIsEnabled) 606 { , ); 608 } 609 if (this.IsPostBack && this.IsCallback) 610 { 611 this.PrepareCallback(callbackControlID); 612 } (!this.IsCrossPagePostBack) 614 { 615 if (context.TraceIsEnabled) 616 { , ); 618 } 619 if (EtwTrace.IsTraceEnabled(5, 4)) 620 { 621 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_ENTER, this._context.WorkerRequest); 622 } 623 this.PreRenderRecursiveInternal(); 624 if (EtwTrace.IsTraceEnabled(5, 4)) 625 { 626 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_LEAVE, this._context.WorkerRequest); 627 } 628 if (context.TraceIsEnabled) 629 { , ); 631 } 632 } 633 } 634 if ((this._legacyAsyncInfo == null) || this._legacyAsyncInfo.CallerIsBlocking) 635 { 636 this.ExecuteRegisteredAsyncTasks(); 637 } 638 this.ValidateRawUrlIfRequired(); 639 if (includeStagesAfterAsyncPoint) 640 { 641 if (this.IsCallback) 642 { 643 this.RenderCallback(); 644 } (!this.IsCrossPagePostBack) 646 { 647 if (context.TraceIsEnabled) 648 { , ); 650 } 651 this.PerformPreRenderComplete(); 652 if (context.TraceIsEnabled) 653 { , ); 655 } 656 if (context.TraceIsEnabled) 657 { 658 this.BuildPageProfileTree(this.EnableViewState); , ); 660 } 661 if (EtwTrace.IsTraceEnabled(5, 4)) 662 { 663 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_ENTER, this._context.WorkerRequest); 664 } 665 this.SaveAllState(); 666 if (EtwTrace.IsTraceEnabled(5, 4)) 667 { 668 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_LEAVE, this._context.WorkerRequest); 669 } 670 if (context.TraceIsEnabled) 671 { , ); , ); 674 } 675 this.OnSaveStateComplete(EventArgs.Empty); 676 if (context.TraceIsEnabled) 677 { , ); , ); 680 } 681 if (EtwTrace.IsTraceEnabled(5, 4)) 682 { 683 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_ENTER, this._context.WorkerRequest); 684 } 685 if (str != null) 686 { 687 this.ExportWebPart(str); 688 } { 691 this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output)); 692 } 693 if (EtwTrace.IsTraceEnabled(5, 4)) 694 { 695 EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_LEAVE, this._context.WorkerRequest); 696 } 697 if (context.TraceIsEnabled) 698 { , ); 700 } 701 this.CheckRemainingAsyncTasks(false); 702 } 703 } 704 } 705 catch (ThreadAbortException exception1) 706 { 707 HttpApplication.CancelModuleException exceptionState = exception1.ExceptionState as HttpApplication.CancelModuleException; 708 if ((((includeStagesBeforeAsyncPoint & includeStagesAfterAsyncPoint) && (this._context.Handler == this)) && ((this._context.ApplicationInstance != null) && (exceptionState != null))) && !exceptionState.Timeout) 709 { 710 this._context.ApplicationInstance.CompleteRequest(); 711 ThreadResetAbortWithAssert(); 712 } { 715 this.CheckRemainingAsyncTasks(true); 716 throw; 717 } 718 } 719 catch (ConfigurationException) 720 { 721 throw; 722 } 723 catch (Exception exception2) 724 { 725 PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST); 726 PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL); 727 if (!this.HandleError(exception2)) 728 { 729 throw; 730 } 731 } 732 } 733 734
View Code
如果觉得本文对你有所帮助不妨点一下【推荐】! 如果文中有不妥或者错误的地方还望指出,以免误人子弟。
作者:张一辉
出处:
本文以学习、研究和分享为主,版权归作者和博客园共有,欢迎转载,但必须在文章页面明显位置给出此段申明。