Pengontrol front-end adalah bagian paling inti dari seluruh kerangka kerja MVC. Ini terutama digunakan untuk mencegat permintaan eksternal yang memenuhi persyaratan dan mendistribusikan permintaan ke berbagai pengontrol untuk diproses. Menurut hasil pemrosesan pengontrol, itu menghasilkan tanggapan yang sesuai dan mengirimkannya ke klien. Pengontrol front-end dapat diimplementasikan menggunakan filter (Struts2 menggunakan metode ini) atau servlet (Spring MVC Framework).
Sebagai pra-pengontrol, DispatcherServlet adalah pintu masuk ke server web dan merupakan kelas paling penting dari MVC Spring. Melalui siklus hidupnya, pemahaman server web dapat diperdalam.
Siklus Hidup Servlet
Pertama, mari kita ingat siklus hidup servlet:
Siklus hidup servlet dibagi menjadi tiga tahap: [Penjelasan terperinci tentang siklus hidup servlet dan prinsip kerja]
1. Metode init () disebut init () pada fase inisialisasi. Setelah servlet dimuat, wadah servlet membuat instance servlet dan memanggil metode init servlet () untuk inisialisasi. Metode init () hanya disebut sekali selama seluruh kehidupan servlet.
2. Hubungi metode layanan () sebagai tanggapan terhadap tahap permintaan klien
3. Call Destroy () Metode pada tahap penghentian
Fase Inisialisasi Servlet
Pada saat -saat berikut, wadah servlet memuat servlet:
1. Ketika wadah servlet dimulai, beberapa servlet dimuat secara otomatis. Untuk mengimplementasikannya, Anda hanya perlu menambahkan kode berikut antara <servlet> </servlet> di file web.xml:
<Boadon-startup> 1 </loadon-startup>
2. Setelah wadah servlet dimulai, klien mengirimkan permintaan ke servlet untuk pertama kalinya
3. Setelah file kelas servlet diperbarui, muat ulang servlet
Struktur DispatcherServlet
Setelah meninjau pengetahuan di atas, mari kita lihat struktur DispatcherServlet:
DispatcherServlet mewarisi dari kelas abstrak: FramewArdervlet, secara tidak langsung mewarisi httpservlet (FramewArdervlet mewarisi dari httpservletbean, dan httpservletbean warisan dari httpservlet)
Inisialisasi servlet
Instrategies void yang dilindungi (ApplicationContext Context) {initmultipartresolver (konteks); // File unggahan dan parse. Jika jenis permintaan adalah multipart, unggah file dan parse melalui multipartresolver; initlocaleresolver (konteks); // lokalisasi parsing initthemeresolver (konteks); // Tema parsing inithandlermappings (konteks); // memetakan permintaan ke prosesor inithandleradapters (konteks); // Memetakan beberapa jenis prosesor inithandleRexceptionResolvers (konteks); // mendukung beberapa jenis prosesor melalui handlerapter; // Jika pengecualian ditemui selama eksekusi, itu akan diserahkan kepada HandLerExceptionResolver untuk parse initRequestToViewNametranslator (konteks); // Langsung parsing permintaan ke nama tampilan initviewResolvers (konteks); // menyelesaikan nama tampilan logis ke tampilan spesifik melalui viewResolver untuk mengimplementasikan initflashmapManager (konteks); // Flash Map Manager}Bagaimana menangani permintaan:
Metode layanan dari Servlet menangani permintaan HTTP.
Frameworkservlet.java mendefinisikan layanan dan menghancurkan metode servlet, seperti yang ditunjukkan di bawah ini:
/** * Mengesampingkan implementasi kelas induk untuk mencegat tambalan *. */ @Override Protected Void Service (permintaan httpservletRequest, respons httpservletResponse) melempar servletException, ioException {string method = request.getMethod (); if (method.equalsignorecase (requestMethod.patch.name ())) {ProcessRequest (Request, Response); } else {super.service (permintaan, respons); }}Kami tahu bahwa ada tujuh jenis jenis permintaan HTTP (ditambah opsi), yang didefinisikan sebagai berikut:
Public Enum RequestMethod {get, head, post, put, Patch, Delete, Options, Trace} Layanan () dari FrameWorkServlet menangani permintaan yang berbeda. Kami menggunakan posting umum untuk menggambarkan:
/*** Proses permintaan ini, menerbitkan acara terlepas dari hasilnya. * <p> Penanganan acara yang sebenarnya dilakukan dengan metode template abstrak * {@link #doService}. */ Proses Final Void ProcessRequest (permintaan httpservletRequest, respons httpservletResponse) melempar servletException, ioException {long starttime = system.currentTimeMillis (); FailureCause Throwable = NULL; LocaleContext PrewarislocaleContext = localecontextholder.getLocaleContext (); Localecontext localecontext = buildlocaleContext (request); RequestAttributes PriSterAttributes = RequestContextholder.getRequestAttributes (); ServletRequestAttributes requestAttributes = buildequestAttributes (permintaan, respons, priStertributes); Webasyncmanager asyncmanager = webasyncutils.getAsyncManager (permintaan); asyncmanager.registercallableinterceptor (frameworkservlet.class.getName (), new RequestBindingInterceptor ()); initContextholders (permintaan, localecontext, requestAttributes); coba {doservice (permintaan, respons); } catch (servletException ex) {failureCause = ex; lempar ex; } catch (ioException ex) {failureCause = ex; lempar ex; } catch (throwable ex) {failureCause = ex; Lempar NestedServletException baru ("Pemrosesan Permintaan Gagal", Kel); } akhirnya {resetContExtholders (permintaan, PriSterLocaleContext, PriSterAttributes); if (requestAttributes! = null) {requestAttributes.RequestCompeted (); } if (logger.isdebugeNabled ()) {if (failureCause! = null) {this.logger.debug ("tidak dapat menyelesaikan permintaan", failureCause); } else {if (asyncmanager.isconcurrenthandlingstarted ()) {logger.debug ("meninggalkan respons terbuka untuk pemrosesan bersamaan"); } else {this.logger.debug ("Permintaan yang berhasil diselesaikan"); }}} publishRequestHandLedEvent (permintaan, starttime, failureCause); }} FramewArdervlet secara abstrak mendefinisikan aliran pemrosesan, dan menyerahkannya ke subkelas untuk mengimplementasikan metode ini, dan melengkapi pemrosesan permintaan spesifik.
/** * Subkelas harus mengimplementasikan metode ini untuk melakukan pekerjaan penanganan permintaan, * menerima panggilan balik terpusat untuk mendapatkan, memposting, menempatkan, dan menghapus. * <p> Kontrak pada dasarnya sama dengan yang untuk * {@code doGet} atau {@code dopost} yang umumnya ditimpa dari httpservlet. * <p> Kelas ini mencegat panggilan untuk memastikan bahwa penanganan pengecualian dan * publikasi acara terjadi. * @param permintaan permintaan http saat ini * @param respons saat ini respons http * @throws pengecualian dalam kasus segala jenis kegagalan pemrosesan * @see javax.servlet.http.httpservlet#doGet * @see javax.servlet. Httpservletresponse respons) melempar pengecualian;Implementasi spesifik adalah sebagai berikut:
/** * Mengekspos atribut permintaan khusus DispatcherServlet dan delegasi ke {@link #dodispatch} * untuk pengiriman yang sebenarnya. */ @Override void doservice (permintaan httpservletrequest, respons httpservletResponse) melempar pengecualian {if (logger.isdebugeNabled ()) {string resumed = webasyncutils.getAsyncmanager (permintaan) .hasconCurrentRentRentRentRent ()? "dilanjutkan": ""; Logger.debug ("DispatcherServlet dengan nama '" + getServletName () + "'" + dilanjutkan + "pemrosesan" + request.getMethod () + "permintaan untuk [" + getRequesturi (request) + "]"); } // Simpan snapshot dari atribut permintaan jika termasuk, // untuk dapat mengembalikan atribut asli setelah disertakan. Peta <string, object> atributessNapshot = null; if (webutils.isincludeRequest (request)) {atributessNapshot = new HashMap <String, Object> (); Enumeration <?> Attrnames = request.getattributeNames (); while (attrNames.hasmoreElements ()) {string attrName = (string) attrNames.NextElement (); if (this.cleanUpafterinclude || attrname.startswith ("org.springframework.web.servlet")) {attributessNapshot.put (attrname, request.getAttribute (attrName)); }}}} // Buat objek kerangka kerja tersedia untuk penangan dan melihat objek. request.setAttribute (web_application_context_attribute, getWebApplicationContext ()); request.setAttribute (locale_resolver_attribute, this.localeresolver); request.setAttribute (tema_resolver_attribute, this.themeresolver); request.setAttribute (tema_source_attribute, getthemeSource ()); Flashmap inputFlashMap = this.flashmapManager.retrieveandupdate (permintaan, respons); if (inputFlashMap! = null) {request.setAttribute (input_flash_map_attribute, collections.unmodifiblemap (inputFlashMap)); } request.setAttribute (output_flash_map_attribute, flashmap baru ()); request.setAttribute (flash_map_manager_attribute, this.flashmapManager); coba {dodispatch (permintaan, respons); } akhirnya {if (webasyncutils.getasyncManager (request) .isconcurrenthandlingStarted ()) {return; } // Kembalikan snapshot atribut asli, dalam kasus termasuk. if (atributessNapshot! = null) {resteattributeFterinclude (request, attributessNapshot); }}}Sorotan, sebagai implementasi distributor permintaan:
Fungsi: 1. Mendistribusikan permintaan ke pawang (dapatkan hubungan pemetaan servlet dalam urutan konfigurasi); 2. Permintaan pawang pertama yang dapat diproses berdasarkan handleradapters yang dipasang oleh servlet; 3. Penangan pemicu pemrosesan permintaan
/*** Proses pengiriman yang sebenarnya ke pawang. * <p> Pawang akan diperoleh dengan menerapkan handlermappings servlet secara berurutan. * HandlerAdapter akan diperoleh dengan menanyakan handleradapters yang terpasang servlet * untuk menemukan yang pertama yang mendukung kelas pawang. * <p> Semua metode HTTP ditangani dengan metode ini. Handlapters atau pawang itu terserah untuk memutuskan metode mana yang dapat diterima. * @param permintaan permintaan http saat ini * @param respons saat ini respons http * @throws pengecualian dalam hal segala jenis kegagalan pemrosesan */ void dodispatch yang dilindungi (httpservletRequest, httpservletResponse response) Lempar Exception {httpservletRequest ProcessedRequest = permintaan; HandLerExecutionChain MappedHandler = null; Boolean MultipartrequestParsed = false; Webasyncmanager asyncmanager = webasyncutils.getAsyncManager (permintaan); coba {modelAndView mv = null; Pengecualian dispatchException = null; coba {ProcessedRequest = checkMultipart (permintaan); MultipartrequestParsed = (ProcessEdRequest! = Permintaan); // Tentukan pawang untuk permintaan saat ini. MappedHandler = GetHandler (ProcessedRequest); if (mappedHandler == null || mappedHandler.getHandler () == null) {noHandlerFound (ProcessedRequest, Response); kembali; } // Tentukan adaptor pawang untuk permintaan saat ini. HandlerAdapter ha = getHandlerAdapter (mappedHandler.getHandler ()); // Proses header yang dimodifikasi terakhir, jika didukung oleh pawang. String method = request.getMethod (); boolean isget = "get" .equals (metode); if (isGet || "head" .Equals (Method)) {long lastmodified = ha.getLastModified (request, mappedHandler.getHandler ()); if (logger.isdebugeNabled ()) {logger.debug ("Nilai terakhir yang dimodifikasi untuk [" + getRequesturi (permintaan) + "] adalah:" + lastmodified); } if (servletWebRequest baru (request, response) .checknotmodified (lastmodified) && isGet) {return; }} if (servletWebRequest baru (request, response) .checkNotModified (lastmodified) && isGet) {return; }} if (! MappedHandler.Applyprehandle (ProcessedRequest, Response)) {return; } coba {// benar -benar memohon pawang. mv = ha.handle (ProcessedRequest, Response, MappedHandler.getHandler ()); } akhirnya {if (asyncmanager.isconcurrenthandlingStarted ()) {return; }} applyDefaultViewName (request, mv); MappedHandler.Applyposthandle (ProcessedRequest, Response, MV); } catch (Exception ex) {DispatchException = ex; } ProcessDispatchResult (ProcessedRequest, Response, MappedHandler, MV, DispatchException); } catch (Exception ex) {triggerAfterCompletion (ProcessedRequest, Response, MappedHandler, EX); } catch (error err) {triggerAfterCompetionwittorror (ProcessedRequest, Response, MappedHandler, ERR); } akhirnya {if (asyncManager.isconcurrenthandlingStarted ()) {// bukan Posthandle dan afterkompletion mappedHandler.ApplyaftercurrenthandlingStarted (ProcessedRequest, Response); kembali; } // Bersihkan sumber daya apa pun yang digunakan oleh permintaan multipart. if (multipartrequestparsed) {cleanupmultipart (ProcessedRequest); }}}Penghancuran Servlet
/*** Tutup WebApplicationContext dari servlet ini. * @see org.springframework.context.configurableApplicationContext#close () */ @Override public void dashar () {getServletContext (). LOG ("Menghancurkan Spring FramewAnterServlet '" + getServletName () + ""); // Hanya hubungi tutup () di WebApplicationContext jika dikelola secara lokal ... if (this.webApplicationContext instanceof configurableApplicationContext &&! This.webApplicationContextInjected) {((configurableApplicationContext) this.webApplicationContext) .close (); }}ringkasan:
Karena keterbatasan bab ini, artikel ini hanya memperkenalkan proses pemrosesan permintaan dan tidak melakukan analisis kode yang mendalam. Artikel berikutnya akan dimulai dari detail dan menganalisis keindahan kode Spring.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.