Spring中WebApplicationInitializer的理解

現在JavaConfig配置方式在逐步取代xml配置方式。而WebApplicationInitializer可以看做是Web.xml的替代,它是一個接口。通過實現WebApplicationInitializer,在其中可以添加servlet,listener等,在加載Web項目的時候會加載這個接口實現類,從而起到web.xml相同的作用。下面就看一下這個接口的詳細內容。

? ? ?首先打開這個接口,如下:

public interface WebApplicationInitializer {void onStartup(ServletContext var1) throws ServletException;
}

只有一個方法,看不出什么頭緒。但是,在這個包下有另外一個類,SpringServletContainerInitializer。它的實現如下:

package org.springframework.web;import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {public SpringServletContainerInitializer() {}public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {List<WebApplicationInitializer> initializers = new LinkedList();Iterator var4;if(webAppInitializerClasses != null) {var4 = webAppInitializerClasses.iterator();while(var4.hasNext()) {Class<?> waiClass = (Class)var4.next();if(!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {try {initializers.add((WebApplicationInitializer)waiClass.newInstance());} catch (Throwable var7) {throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);}}}}if(initializers.isEmpty()) {servletContext.log("No Spring WebApplicationInitializer types detected on classpath");} else {servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");AnnotationAwareOrderComparator.sort(initializers);var4 = initializers.iterator();while(var4.hasNext()) {WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();initializer.onStartup(servletContext);}}}
}

這個類就比較有意思了,先不管其他的,讀一下這段代碼,可以得到這樣的意思。

? ? ? ? ? ? ?先判斷webAppInitializerClasses這個Set是否為空。如果不為空的話,找到這個set中不是接口,不是抽象類,并且是

WebApplicationInitializer接口實現類的類,將它們保存到list中。當這個list為空的時候,拋出異常。不為空的話就按照一定的順序排序,并將它們按照一定的順序實例化。調用其onStartup方法執行。到這里,就可以解釋WebApplicationInitializer實現類的工作過程了。但是,在web項目運行的時候,SpringServletContainerInitializer這個類又是怎樣被調用的呢。

? ? ? ? ? ?它只有一個接口,ServletContainerInitializer,通過它就可以解釋SpringServletContainerInitializer是如何被調用的。它的內容如下:

package javax.servlet;import java.util.Set;public interface ServletContainerInitializer {void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
}

首先,這個接口是javax.servlet下的。官方的解釋是這樣的:為了支持可以不使用web.xml。提供了ServletContainerInitializer,它可以通過SPI機制,當啟動web容器的時候,會自動到添加的相應jar包下找到META-INF/services下以ServletContainerInitializer的全路徑名稱命名的文件,它的內容為ServletContainerInitializer實現類的全路徑,將它們實例化。既然這樣的話,那么SpringServletContainerInitializer作為ServletContainerInitializer的實現類,它的jar包下也應該有相應的文件。打開查看如下:

哈,現在就可以解釋清楚了。首先,SpringServletContainerInitializer作為ServletContainerInitializer的實現類,通過SPI機制,在web容器加載的時候會自動的被調用。(這個類上還有一個注解@HandlesTypes,它的作用是將感興趣的一些類注入到ServletContainerInitializerde), 而這個類的方法又會掃描找到WebApplicationInitializer的實現類,調用它的onStartup方法,從而起到啟動web.xml相同的作用。

? ? ? ? ?然后,我們自己通過一個實例來實現相同的功能,通過一樣的方式來訪問一個servlet。

? ? ? ??

? ? ? ? ?1、定義接口WebParameter,它就相當于WebApplicationInitializer。內容如下:

public interface WebParameter {void loadOnstarp(ServletContext servletContext);
}

可以在這里面添加servlet,listener等。

2、定義Servlet。

public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("TestSetvlet");}
}

3、定義MyWebParameter作為WebParameter的實現類,將Servlet添加到上下文,并設置好映射。

public class MyWebParameter implements WebParameter {public void loadOnstarp(ServletContext servletContext) {ServletRegistration.Dynamic testSetvelt=servletContext.addServlet("test","com.test.servlet.MyServlet");testSetvelt.setLoadOnStartup(1);testSetvelt.addMapping("/test");}
}

當然,也可以把第2步和第3步合在一起:

public class MyServlet extends HttpServlet implements WebParameter {@Overridepublic void loadOnstarp(ServletContext servletContext) {ServletRegistration.Dynamic testSetvelt=servletContext.addServlet("test","com.test.servlet.MyServlet");testSetvelt.setLoadOnStartup(1);testSetvelt.addMapping("/test");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("TestSetvlet");}
}

而且以后可以將Spring的applicationContext.xml與web.xml融合在一個類中。即注解為@Configuration,并實現WebApplicationInitializer。

4、定義好WebConfig作為ServletContainerInitializer的實現類,它的作用是掃描找到WebParameter的實現類,并調用其方法。

@HandlesTypes({WebParameter.class})
public class WebConfig implements ServletContainerInitializer {public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {Iterator var4;if (set!=null){var4=set.iterator();while(var4.hasNext()){Class<?> clazz= (Class<?>) var4.next();if (!clazz.isInterface()&& !Modifier.isAbstract(clazz.getModifiers())&&WebParameter.class.isAssignableFrom(clazz)){try {((WebParameter) clazz.newInstance()).loadOnstarp(servletContext);}catch (Exception e){e.printStackTrace();}}}}}
}

??5、根據SPI機制,定義一個META-INF/services文件夾,并在其下定義相關文件名稱,并將WebConfig的類全名稱填入其中。

6、最終結果:

?

?

?

本文轉自:https://blog.csdn.net/zq17865815296/article/details/79464403

轉載于:https://www.cnblogs.com/nizuimeiabc1/p/11031150.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393191.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393191.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393191.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用fetch封裝請求_關于如何使用Fetch API執行HTTP請求的實用ES6指南

使用fetch封裝請求In this guide, I’ll show you how to use the Fetch API (ES6) to perform HTTP requests to an REST API with some practical examples you’ll most likely encounter.在本指南中&#xff0c;我將向您展示如何使用Fetch API(ES6 )來執行對REST API的 HTT…

hadoop集群中客戶端修改、刪除文件失敗

這是因為hadoop集群在啟動時自動進入安全模式 查看安全模式狀態&#xff1a;hadoop fs –safemode get 進入安全模式狀態&#xff1a;hadoop fs –safemode enter 退出安全模式狀態&#xff1a;hadoop fs –safemode leave轉載于:https://www.cnblogs.com/lishengnan/p/a123.ht…

OpenStack nova-network 支持多vlan技術實現片段代碼

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748

Rest API

什么是接口測試 接口測試又稱 API 測試 Application Programming Interface 接口測試是測試系統組件間接口的一種測試。重點關注數據傳遞。 接口測試一般會用于多系統間交互開發&#xff0c;或者擁有多個子系統的應用系統開發的測試。 為什么要做接口測試 很多系統關聯都是基于…

php循環checkbox,php循環刪除checkbox | 學步園

一、首先要了解sql語句$SQLdelete from user where id in (1,2,4);表單大概是&#xff1a;form action methodpost input nameID_Dele[] typecheckbox idID_Dele[] value1input nameID_Dele[] typecheckbox idID_Dele[] value2input nameID_Dele[] type首先要了解sql語句$SQL&q…

leetcode1451. 重新排列句子中的單詞(排序)

「句子」是一個用空格分隔單詞的字符串。給你一個滿足下述格式的句子 text : 句子的首字母大寫 text 中的每個單詞都用單個空格分隔。 請你重新排列 text 中的單詞&#xff0c;使所有單詞按其長度的升序排列。如果兩個單詞的長度相同&#xff0c;則保留其在原句子中的相對順序…

Java+Oracle實現事務——JDBC事務

J2EE支持JDBC事務、JTA事務和容器事務事務&#xff0c;這里說一下怎樣實現JDBC事務。 JDBC事務是由Connection對象所控制的&#xff0c;它提供了兩種事務模式&#xff1a;自己主動提交和手動提交&#xff0c;默認是自己主動提交。 自己主動提交就是&#xff1a;在JDBC中。在一個…

開源項目貢獻者_我如何從一名貢獻者轉變為一個開源項目維護者

開源項目貢獻者by Dhanraj Acharya通過Dhanraj Acharya 我如何從一名貢獻者轉變為一個開源項目維護者 (How I went from being a contributor to an Open Source project maintainer) I was a lone software developer. When I was in college, I attended the KDE conference…

網絡攝像頭CVE

CVE-2018-9995 rtsp未授權訪問 rtsp后綴整理&#xff1a; Axis&#xff08;安訊士&#xff09; rtsp:// 192.168.200.202/axis-media/media.amp?videocodech264&resolution1280x720 rtsp://IP地址/mpeg4/media.amp rtsp://IP地址/安迅士/AXIS-media/media.amp123D-Link …

Centos中不從skel目錄里向其中復制任何文件錯誤的解決方法

[rootlocalhost www]# useradd -d /webserver/www/ ithovcom useradd&#xff1a;警告&#xff1a;此主目錄已經存在。 不從 skel 目錄里向其中復制任何文件。 [rootlocalhost www]# ls -a .&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp; .. 發現沒…

leetcode91. 解碼方法

一條包含字母 A-Z 的消息通過以下方式進行了編碼&#xff1a; ‘A’ -> 1 ‘B’ -> 2 … ‘Z’ -> 26 給定一個只包含數字的非空字符串&#xff0c;請計算解碼方法的總數。 示例 1: 輸入: “12” 輸出: 2 解釋: 它可以解碼為 “AB”&#xff08;1 2&#xff09;或者…

php 系統平均負載,Linux_解析Linux系統的平均負載概念,一、什么是系統平均負載(Load a - phpStudy...

解析Linux系統的平均負載概念一、什么是系統平均負載(Load average)&#xff1f;在Linux系統中&#xff0c;uptime、w、top等命令都會有系統平均負載load average的輸出&#xff0c;那么什么是系統平均負載呢&#xff1f;系統平均負載被定義為在特定時間間隔內運行隊列中的平均…

Elastic-job使用及原理

一、原理 elastic-job有lite版和cloud版&#xff0c;最大的區別是有無調度中心&#xff0c;筆者采用的是lite版本&#xff0c;無中心化。 tips: 第一臺服務器上線觸發主服務器選舉。主服務器一旦下線&#xff0c;則重新觸發選舉&#xff0c;選舉過程中阻塞&#xff0c;只有主服…

構建持續交付_如何使交付成為您的重點將如何幫助您構建高質量的應用程序

構建持續交付by Simon Schwartz西蒙施瓦茨(Simon Schwartz) 如何使交付成為您的重點將如何幫助您構建高質量的應用程序 (How making delivery your focus will help you build quality applications) I was recently asked by our company’s executive team why our team was…

微信退款通知,退款回調數據解密.SHA256簽名AEAD_AES_256_GCM解密

$xmlResult file_get_contents("php://input");//獲取微信的數據$result $this->xmlToArray($xmlResult);//將xml轉成數組 // 將加密的數據解密,方法在下面$reqInfo $this->refund_decrypt($result[req_info]); /** 退款通知解密* Author WangZhaoBo* param…

BeanShell自動裝箱拆箱

“裝箱”和“拆箱”是用來描述自動包裝一個原始類型到一個包裝類以及在必要時解開包裝回到原始類型的術語。裝箱是 Java 的特性&#xff08;SDK 1.5&#xff09;之一&#xff0c;且 BeanShell 已支持多年。 BeanShell 支持原始類型的裝箱和拆箱。比如&#xff1a; int i5; Inte…

leetcode816. 模糊坐標

我們有一些二維坐標&#xff0c;如 “(1, 3)” 或 “(2, 0.5)”&#xff0c;然后我們移除所有逗號&#xff0c;小數點和空格&#xff0c;得到一個字符串S。返回所有可能的原始字符串到一個列表中。 原始的坐標表示法不會存在多余的零&#xff0c;所以不會出現類似于"00&q…

IO流入門-第十二章-ObjectInputStream_ObjectOutputStream

DataInputStream和DataOutputStream基本用法和方法示例&#xff0c;序列化和反序列化 import java.io.Serializable; //該接口是一個“可序列化”的 &#xff0c;沒有任何方法&#xff0c;是一個標識接口&#xff0c;還有Cloneable /*標識接口的作用&#xff1a;標識作用…

matlab pca重構,Matlab – PCA分析和重建多維數據

這是一個快速的演練.首先我們創建一個隱藏變量的矩陣.它有100個觀察,有兩個特點.>> Y randn(100,2);現在創建一個加載矩陣.這將把隱藏的變量映射到觀察到的變量上.說你觀察到的變量有四個特征.那么你的加載矩陣需要是24>> W [1 1; 1 -1; 2 1; 2 -1];這告訴你,觀察…

文檔對象模型dom_什么是文檔對象模型,以及為什么應該知道如何使用它。

文檔對象模型domby Leonardo Maldonado萊昂納多馬爾多納多(Leonardo Maldonado) 什么是文檔對象模型&#xff0c;以及為什么應該知道如何使用它。 (What’s the Document Object Model, and why you should know how to use it.) So, you’ve studied HTML, you’ve created y…