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.mzph.cn/news/393191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络摄像头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 …

Elastic-job使用及原理

一、原理 elastic-job有lite版和cloud版&#xff0c;最大的区别是有无调度中心&#xff0c;笔者采用的是lite版本&#xff0c;无中心化。 tips: 第一台服务器上线触发主服务器选举。主服务器一旦下线&#xff0c;则重新触发选举&#xff0c;选举过程中阻塞&#xff0c;只有主服…

BeanShell自动装箱拆箱

“装箱”和“拆箱”是用来描述自动包装一个原始类型到一个包装类以及在必要时解开包装回到原始类型的术语。装箱是 Java 的特性&#xff08;SDK 1.5&#xff09;之一&#xff0c;且 BeanShell 已支持多年。 BeanShell 支持原始类型的装箱和拆箱。比如&#xff1a; int i5; Inte…

安装Docker step by step

1. 系统要求 centos7以上 使用cat /etc/redhat-release查看系统版本&#xff0c;我的Centos 7.6 centos-extra 仓库 enable&#xff0c;默认是打开的 2.安装docker docer安装分为联网安装和离线安装两种安装 方式&#xff0c; 第一种 在有外网环境下安装docker,一般使用yum安…

微信小程序 php配置,微信小程序的配置

我们使用app.json文件来对微信小程序进行全局配置&#xff0c;决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。以下是一个包含了所有配置选项的简单配置app.json{"pages": ["pages/index/index","pages/logs/index"],"wi…

PWA - service worker - Workbox(未完)

Get Started&#xff08;开始&#xff09; 只有get请求才能cache缓存吗&#xff1f;Create and Register a Service Worker File&#xff08;创建和注册 Service Worker&#xff09; Before we can use Workbox, we need to create a service worker file and register it to o…

System类入门学习

第三阶段 JAVA常见对象的学习 System类 System类包含一些有用的字段和方法&#xff0c;他不能被实例化 //用于垃圾回收 public static void gc()//终止正在运行的java虚拟机。参数用作状态码&#xff0c;根据惯例&#xff0c;非0表示异常终止 public static void exit(int stat…

gulpfile php,Laravel利用gulp如何构建前端资源详解

什么是gulp&#xff1f;gulp是新一代的前端项目构建工具&#xff0c;你可以使用gulp及其插件对你的项目代码(less,sass)进行编译&#xff0c;还可以压缩你的js和css代码&#xff0c;甚至压缩你的图片&#xff0c;gulp仅有少量的API&#xff0c;所以非常容易学习。 gulp 使用 st…

8-python自动化-day08-进程、线程、协程篇

本节内容 主机管理之paramiko模块学习 进程、与线程区别python GIL全局解释器锁线程语法join线程锁之Lock\Rlock\信号量将线程变为守护进程Event事件 queue队列生产者消费者模型Queue队列开发一个线程池进程语法进程间通讯进程池 转载&#xff1a;  http://www.cnblogs.co…

select查询语句执行顺序

查询中用到的关键词主要包含六个&#xff0c;并且他们的顺序依次为 select--from--where--group by--having--order by 其中select和from是必须的&#xff0c;其他关键词是可选的&#xff0c;这六个关键词的执行顺序 与sql语句的书写顺序并不是一样的&#xff0c;而是按照下面的…

Python的Virtualenv(虚拟环境)的使用(Windows篇)2

Python的Virtualenv(虚拟环境)的使用&#xff08;Windows篇&#xff09; 2018年04月13日 11:35:01 D_FallMoon 阅读数 771 版权声明&#xff1a;版权所有 装载请注明 …

创建邮箱过程中的问题及解决办法

转自白手起家博客 http://bbs.chinaunix.net/forum.php?modviewthread&tid770141 说明一下&#xff1a;Q代表安装过程中遇到的问题&#xff0c;或者是日志中出现的现象。A&#xff1a;代表解决方法。 Q&#xff1a; Jan 13 11:26:29 mail authdaemond: failed to connect …

跟我一起屏蔽百度搜索页面右侧的内容

苦恼百度搜索热点等冗杂信息很久了&#xff0c;然后今天下定决心解决这个问题了。 第一步&#xff1a;搜索&#xff0c;并安装插件Adblock Plus 第二步&#xff1a;使用拦截器 1.打开拦截器 2.具体使用 点击这一块 添加 转载于:https://www.cnblogs.com/smart-girl/p/11058774.…

鼠标拖拽吸附效果

JavaScript鼠标拖动自动吸附实例 学了几天的JavaScript&#xff0c;自己动手做了一个简单的鼠标拖动的实例&#xff0c;拖动过程中科自动检测与目标容器的距离&#xff0c;在一定的距离范围内可以自动将被拖动的元素加入到目标容器中&#xff0c;希望对开始学习javascript的童鞋…

php修改mysql数据库中的表格,如何修改mysql数据库表?

修改mysql数据库表的方法&#xff1a;使用“ALTER TABLE”语句&#xff0c;可以改变原有表的结构&#xff0c;例如增加字段或删减字段、修改原有字段数据类型、重新命名字段或表、修改表字符集等&#xff1b;语法“ALTER TABLE [修改选项]”。修改数据表的前提是数据库中已经存…

微软最新GDI漏洞MS08-052安全解决方案

微软最新GDI漏洞MS08-052安全解决方案 Simeon微软于九月九日凌晨爆出有史以来最大的安全漏洞MS08-052&#xff0c;通过该漏洞&#xff0c;攻击者可以将木马藏于图片中&#xff0c;网民无论是通过浏览器浏览、还是用各种看图软件打开、或者在即时聊天窗口、电子邮件、Office文档…

DEM轨迹后处理

方法一&#xff1a;直接在paraview中显示 首先在输出颗粒信息的时候保存global ID&#xff1a;然后在paraview中导入vtp数据&#xff08;不要导入pvd&#xff09;&#xff0c;并使用Temporal Particle To Pathlines这个filter&#xff08;可以直接ctrlspace调出搜索框搜索&…

LVS的四种模式的实现

LVS 是四层负载均衡&#xff0c;也就是说建立在 OSI 模型的第四层——传输层之上&#xff0c;传输层上有我们熟悉的 TCP/UDP&#xff0c;LVS 支持 TCP/UDP 的负载均衡。LVS 的转发主要通过修改 IP 地址&#xff08;NAT 模式&#xff0c;分为源地址修改 SNAT 和目标地址修改 DNA…

安卓系统换成linux系统软件,将旧安卓手机打造成“简易linux”机器,并部署AdGuardHome...

从原教程的安装Linux Deploy 完成后&#xff0c;在配置 Linux下载镜像的一些东西时有些许出入。首先&#xff0c;我是用的下载源地址是 http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports 清华的源挺好用的。 其他有出入的配置如图(记得把源地址改清华的&#xff0c;华中科大…

第一章:最小可行区块链

概览区块数据结构区块哈希创世块创建区块保存区块链验证区块完整性选择最长链节点间通信操作节点架构运行测试小结概览 区块链的基础概念非常简单, 说白了就是一个维护着一个持续增长的有序数据记录列表的这么一个分布式数据库。在此章节中我们将实现一个简单的玩具版的区块链。…