Ringkasan
Untuk pengembang web, model MVC sangat akrab bagi semua orang. Di SpringMVC, permintaan yang memenuhi persyaratan memasuki DispatcherServlet yang bertanggung jawab atas distribusi permintaan. DispatcherServlet memetakan URL permintaan ke pengontrol (simpan di handlermapping). Handlermapping akhirnya mengembalikan handleRexecutionChain, yang berisi penangan objek pemrosesan spesifik (yaitu, apa yang kami tulis ketika kami memprogramnya). Pengontrol) dan serangkaian pencegat. Pada saat ini, DispatcherServlet akan menemukan handleradapter yang mendukung jenis prosesor ini berdasarkan pawang di pawang di handlerexecutionchain yang dikembalikan. Di adaptor prosesor, pada akhirnya akan memanggil metode respons permintaan pengontrol dan mengembalikan tampilan hasil (ModelAndView). Setelah mendapatkan tampilan hasil, hasilnya ditampilkan melalui metode render.
Sistem Warisan Handermapping:
SpringMVC meminta distribusi ke prosesor pawang. Langkah ini diselesaikan melalui modul handlermapping. Handlermapping juga menangani pencegat.
Mari kita lihat pohon warisan dari handlermapping terlebih dahulu
Anda dapat secara kasar membuat klasifikasi seperti ini:
1. Antarmuka handlermapping, tentukan API: handleRexecutionChain getHandler (permintaan httpservletrequest) melempar pengecualian;
2. Kelas abstrak dasar: terutama mempersiapkan lingkungan konteks, menyediakan kait getHandlerinternal, merangkum pencegat ke handleRexecutionChain
3. Penggunaan @Controller, @RequestMapping berdasarkan anotasi
4. Mengkonfigurasi SimpleUrlHandlermapping dari URL ke pawang di file konfigurasi
5. BeanNameUrlHandLermapping diimplementasikan secara default
6. Pemetaan subkelas pengontrol
Mari kita lihat handlermapping, hanya API GetHandler sangat sederhana.
// handlermappingpackage org.springframework.web.servlet; antarmuka publik handlermapping {handleRexecutionchain getHandler (permintaan httpservletrequest) melempar pengecualian;} Abstracthandlermapping tidak sesederhana itu
Pertama -tama lihat kelas yang diwarisi dengan abstracthandlermapping dan antarmuka yang diimplementasikan
Paket org.springframework.web.servlet.handler; kelas abstrak publik abstracthandlermapping memperluas webapplicationObjectsupportImplements handlermapping, dipesan {// ...} WebApplicationObjectSupport digunakan untuk menyediakan ApplicationContext dan ServletContext.
Ada juga metode InitiPlicationContext di sini, yang sering digunakan di masa depan. Abstracthandlermapping secara langsung ditimpa.
Antarmuka ApplicationContextAware dan ServletContextAware masih diimplementasikan di kelas induk, dan konsep Spring sangat disatukan.
Dipesan digunakan untuk penyortiran koleksi.
Mari kita terus lihat sifat -sifatnya
// abstracthandlermapping // pesanan memberikan nilai maksimum, dan prioritas adalah pesanan int pribadi terkecil = integer.max_value; // default: same as non-Ordered// The default Handler, the Obejct used here and subclass implementation, use HandlerMethod, HandlerExecutionChain and other private Object defaultHandler;// Auxiliary class for url calculation private UrlPathHelper urlPathHelper = new UrlPathHelper();// Path matching is based on ant, and solves private PathMatcher pathMatcher = new AntPathMatcher();// Interceptor configuration:,HandlerMapping property setting;,extendInterceptors set private final List<Object> interceptors = new ArrayList<Object>();// parse from interceptors and add it directly to all handlerprivate final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<HandlerInterceptor>();// Before use, you need to match the URL, dan hanya jika pertandingan dilewati akan digunakan Daftar Akhir Pribadi <MappedInterceptor> MappedInterceptors = New ArrayList <MappedInterceptor> ();
Lihat inisialisasi pencegat:
// abstracthandlermapping@overrideprotected void initApplicationContext () melempar BeansException {ExtentInterceptors (this.Interceptors); DetectMappedInterceptors (This.PappedInterceptors); InitInterceptors ();}/*** Disediakan untuk subkelas Extension Extension Interceptors, tetapi Sayangnya tidak ada di Subseptors, tetapi sayangnya tidak ada di subkelas. {}/*** Pindai MappedInterceptors di bawah aplikasi dan tambahkan mereka ke MappedInterceptors*/Protected Void DetectMappedInterceptors (Daftar <MappedInterceptor> MappedInterceptors) {MappedInterceptors.addall (beanfactoryutils.beansOfTyPludedEcestors (getApplicationContext (), MappedCinterCoreCoreCorcoreCorcore (getapplicationConter () (), mappedCintercorycorseCorseCorseCorscors (getapplicationcine () false) .values ());}/*** kumpulkan dipetakan dan beradaptasi dengan handlerInterceptor dan webRequestInterceptor*/void initInterceptors () {if (! this.interceptors.isempty () {for (int i =; i <this.interceptors.size (); i ++) {intercepors. null) {lempar baru ilegalArgumentException ("nomor entri" + i + "di array interceptor adalah null");} if (Interceptor instance dari dipetakan) {mappedinterceptors.add ((pemetaan) interseptor);} {adaptedEnteptorsceptors.add (adaptCepor (mappedPerCepor);} else {adaptedInterceptorsceptors.add (adaptcepor (mappedPercepor); adaptInterceptor(Object interceptor) {if (interceptor instanceof HandlerInterceptor) {return (HandlerInterceptor) interceptor;}else if (interceptor instanceof WebRequestInterceptor) {return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);}else {throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass (). getName ());}}Lalu ada implementasi GetHandler (permintaan httpservletRequest), dan di sini juga cadangan GetHandlerinternal (permintaan httpservletRequest) untuk implementasi subkelas.
// abstracthandlermappingPublic final handlerexecutionchain gethandler (permintaan httpservletrequest) melempar pengecualian {objek handler = getHandlerinternal (permintaan); if (handler == null) {handler = getDefaulThandler ();} if (handler == nuller) {handller null; null; instanceof string) {string handlerName = (string) handler; handler = getAppLicationContext (). getBean (handlerName);} return getHandleRexecutionChain (handler, request);} objek abstrak yang dilindungi getHandlerinternal (httpservletRequest permintaan) Lemparan pengecualian; Akhirnya, merangkum interseptor ke handleRexecutionChain
Tambahkan AdaptedInterceptors secara langsung
Mappedinterceptors perlu ditambahkan setelah dicocokkan sesuai dengan URL
// abstracthandlermapping handlerexecutionChain gethandlexecutionchain (pawang objek, permintaan httpservletRequest) {handleRexecutionChain rantai = (Contoh pawang dari handleRexecutionChain) Handler: HandLerExecutionChain (handler) baru; rantai.AddInterceptors (getAdaPtedInterceptors ()); string lookuppath = urlpathhelper.getLookuppathForRequest (request); for (dipetakan mapapedcenteptor: mappedInterceptors) {if (mappedIntercepTor.matchePor (lookuppath, pathmatcher) {craincorpore.addintepor (lookuppath, pathmatcher) {craincorpore.addintepor. rantai;} Pemetaan subkelas pengontrol, cabang ini pertama kali melihat warisan kelas
Mari kita bicara tentang tanggung jawab utama setiap kategori di sini
1. Abstracthandlermapping Mempersiapkan lingkungan konteks; Menyediakan kait getHandlerinternal; Encapsulate Interceptor ke HandLerExecutionChain
2. Abstrakurlandlermapping mengimplementasikan metode pendaftaran penangan untuk penggunaan subkelas; Implement GetHandlerinternal, dan menemukan handler berdasarkan informasi konfigurasi yang diinisialisasi oleh subkelas.
3. AbstractDetectingUrlHandlermapping memindai objek di bawah aplikasi, dan setelah iterasi, berikan metode hook menentukan untuk menentukan cara menentukan cara memfilternya.
4. AbstractControllerUrlHandLermapping mengimplementasikan DefitedUrlsForHandler, menambahkan operasi penangan (konfigurasi file konfigurasi), dan cadangan metode Hook BuildUrlsForHandler untuk implementasi subkelas; Pada saat yang sama menilai subclass pengontrol
5. ControllerbeanNameHandLermapping menghasilkan url berdasarkan nama kacang
ControllerClassNameHandLermapping menghasilkan URL berdasarkan nama kelas
Mari kita mulai dengan AbstracTurlhandlermapping. Di sini kita hanya melihat kode secara kasar. Jika Anda perlu menganalisisnya dengan hati -hati, silakan pindah ke <SpringMVC Sumber Code Interpretation - Handlermapping - AbstractURLHandLermapping Series Distribution>
Pendaftaran Handler
Lindung void registerhandler (string [] urlpaths, string beanname) melempar beansException, ilegalstateException {} void lindung yang dilindungi (string urlpath, handler objek) melempar beancexception, illegalstateException {} Pencarian penangan
objek yang dilindungi getHandlerinternal (permintaan httpservletrequest) melempar pengecualian {} // temukan handler yang diprotes pencarian objek (string urlpath, httpservletRequest permintaan) lempar {} // verifikasi handler yang diprotes voidhandler (handler objek, httpsver {httpsver oPExcervon opler {httpscervon oPExcreon {httpservon {httpservion {httpservion oPECTRECTED {httpservion oPECREVESD (httpscervon {{} {} httpservion {httpservion oPECREVEST {{{{httpservion HandleRexecutionChainProtected Object BuildPathexpositingHandler (Object Rawhandler, String BestMatchingPattern, String PathWithInmapping, Map <String, String> UrItemplatEvariables) {}AbstractDetectingUrlHandlermapping, ini tidak diperluas, silakan bergerak secara detail <Interpretasi Kode Sumber SpringMVC - Handlermapping - AbstractDetTectingUrlHandLermapping Series Initialization>
Apa yang Harus Dilakukan:
1. Hubungi detecthandlers untuk memindai objct dengan menimpa init applicationContext
2. Memberikan metode pengait yang menentukan untuk subkelas untuk menghasilkan URL menurut Handler
3. Hubungi Registerhandler dari kelas induk untuk mendaftar
@Overridepublic void initApplicationContext () melempar ApplicationContextException {super.InitApplicationContext (); detecthandlers ();} void void detecthandlers () Lempar (*lemparan handler {// ...}/*** Tentukan urls untuk tangan yang diberikan (*powlering. Beanname); AbstractControllerUrlHandlermapping, ini tidak diperluas, silakan pindahkan detail <Interpretasi Kode Sumber SpringMVC - Handlermapping - AbstractDettingUrlHandLermapping Series Initialization> Apa yang harus dilakukan secara spesifik;
1. Timpa DESTIRURLSFORHANDLER untuk menambahkan logika untuk menghapus beberapa kelas, dan menggunakan CLUSUDEDClasses dan ExcludedPackages yang dikonfigurasi dalam file konfigurasi.
2. Tentukan apakah subkelas pengontrol
3. Cadangan BuildurlsForHandler untuk menghasilkan URL untuk subkelas
@Overrideprotected String [] DefectUrlsForHandler (String beanname) {class beanClass = getApplicationContext (). GetType (beanname); if (isEnligibleFormapping (beanName, beanclass)) {return buildurlsforHandler (beanName, beanname, beanclass)) {return noDurlsforHandler (beanName, beanName, oleAncass); isEnligibleFormapping (string beanname, class beansclass) {} protected boolean isControllerType (class beanClass) {} protected abstract string [] buildUrlsForHandler (string beanname, class beanClass); ControllerbeanNameHandLermapping dan ControllerClassNameHandLermapping melihat kode sumber secara langsung, atau pindah pada <SpringMVC Sumber Code Interpretation - Handlermapping - AbstractDettectingUrlHandLermapping Series Initialization> SimpleUrlHandLermapping secara langsung mengkonfigurasi URL ke Handler di file konfigurasi, yaitu menggunakan registerhandlers untuk mendaftar handler di dokumen konfigurasi, membaca kode secara langsung atau memindahkan <Interpretasi Kode Sumber SpringMVC - HandLermapping - Inisialisasi SimpleUrlHandLermapping>
BeanNameUrlHandlermapping mengimplementasikan DeflementsForHandler untuk menghasilkan URL, lihat kode secara langsung atau memindahkan <Interpretasi Kode Sumber SpringMVC - Handlermapping - AbstractDetectingUrlHandLermapping Series Initialization>
Penggunaan @Controller, @RequestMapping berdasarkan anotasi
Tulang yang paling sulit
Mari kita lihat warisan kelas dulu
Mari kita bicara tentang tanggung jawab setiap kategori. Untuk analisis khusus, silakan pindah ke artikel berikut
<SpringMVC Interpretasi Kode Sumber - Handlermapping - Inisialisasi REVERVINGMAPPINGHANDLermapping>
<Interpretasi Kode Sumber SpringMVC - Handlermapping - Distribusi Permintaan Permintaan Mendapat
1. Abstracthandlermethodmaping mendefinisikan proses inisialisasi dan cara memetakannya saat meminta
Inisialisasi:
1.1.1 Pindai objek di bawah aplikasi
1.1.2 Cadangan metode kait ishandler untuk subkelas untuk menentukan apakah objeknya handler
1.1.3 Memindai setiap penangan secara iteratif untuk menemukan metode yang memenuhi persyaratan. Penilaian di sini masih diserahkan kepada subkelas untuk mengimplementasikan GetMappingFormethod
1.1.4 Saat mendaftarkan prosesor yang ditemukan, Anda perlu memastikan bahwa kondisi yang cocok dengan permintaanmappappinginsinfo hanya dapat memetakan ke penangan
1.1.5 Dapatkan URL sesuai dengan kondisi pencocokan, dan hal yang sama hanya untuk menentukan prosesnya. Algoritma spesifik diserahkan kepada subkelas untuk mengimplementasikan getmappingpathpatterns
Pemrosesan Distribusi Minta:
1.2.1 Metode pencocokan string langsung, cari penangan
1.2.2 Pencarian Kondisi Pencocokan, algoritma spesifik di sini diserahkan kepada subkelas untuk mendapatkan penambahan
1.2.3 Urutkan dan dapatkan penangan yang cocok. Metode penyortiran di sini masih merupakan subkelas pemrosesan getMappingConParator
1.2.4 Enkapsulasi pencocokan dan tidak cocok dengan penangan
2. RequestMappingInfoHandlermapping menggunakan permintaanmappappingInfo untuk mengimplementasikan kondisi pencocokan, dan inisialisasi requestMappingInfo diserahkan kepada subkelas
2.1 Hasilkan URL -> GetMappingPathPatterns Menurut RequestMappingInfo
2.2 Temukan Handler Menggunakan Kondisi Pencocokan -> GetMatchingMapping
2.3 Algoritma Pembanding -> GetMappingComparator
2.4 Timpa HandleMatch dan Cache N Beberapa informasi untuk diminta
Pola Daftar, Pola Pencocokan Terbaik, Parsed Parameter dalam URL, Parameter Multi-Nilai Diuraikan dalam URL, Mediatype
2.1.5 Timpa Handlernomatch, cobalah untuk mencocokkannya lagi setelah perjuangan terakhir
3. RequestMappingHandLermapping menghasilkan requestMappingInfo sesuai dengan anotasi @controller @requestmapping dan verifikasi Ishandler
3.1 Timpa AfterPropertiesset dan tambahkan sufiks file untuk menilai
3.2 Menerapkan ISHandler, dan salah satu anotasi pada kelas adalah benar.
3.3 Menganalisis konten anotasi dan menghasilkan instance requestMappingInfo