Spring去除web.xml,使用Java配置Servlet的原理,SPI
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Spring去除web.xml,使用Java配置Servlet的原理,SPI,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4276字,纯文字阅读大概需要7分钟。
内容图文
![Spring去除web.xml,使用Java配置Servlet的原理,SPI](/upload/InfoBanner/zyjiaocheng/757/398c2b7254824c9091eaefbcbf7c6f40.jpg)
Spring去除web.xml,使用Java配置Servlet的原理,SPI
1. spring使用java配置Servlet代码如下
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
public class WebServletConfiguration implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext ctx) {
AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
// 注册context
webCtx.register(ApplicationConfig.class);
// 设置context
webCtx.setServletContext(ctx);
// 定义Servlet
ServletRegistration.Dynamic servlet = ctx.addServlet("spring", new DispatcherServlet(webCtx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
这段代码配置了一个名为spring的Servlet, 所有的请求(/)都映射到这个Servlet中。
2. spring的源码
在上一点中,可以看到关键的代码是现实了WebApplicationInitializer
这个接口,很容易的找到这个接口唯一被引用的地方,即org.springframework.web.SpringServletContainerInitializer
// HandlesTypes注解再这里的作用是tomcat回去扫描所有的WebApplicationInitializer的实现类,包括抽象类。
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
// webAppInitializerClasses参数返回的就是所有的WebApplicationInitializer的实现类
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
// 传入servletContext给WebApplicationInitializer的实现类,并调用onStartup方法,此方法又定义Servlet
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
3. tomcat源码
继续根据实现的接口ServletContainerInitializer
追溯到tomcat源码中。
再org.apache.catalina.startup.ContextConfig#processServletContainerInitializers
方法中对ServletContainerInitializer
的实现类进行了扫描,也就是扫描到了SpringServletContainerInitializer
/**
* Scan JARs for ServletContainerInitializer implementations.
*/
protected void processServletContainerInitializers() {
List<ServletContainerInitializer> detectedScis;
try {
WebappServiceLoader<ServletContainerInitializer> loader = new WebappServiceLoader<>(context);
detectedScis = loader.load(ServletContainerInitializer.class);
} catch (IOException e) {
log.error(sm.getString(
"contextConfig.servletContainerInitializerFail",
context.getName()),
e);
ok = false;
return;
}
// 省略一堆源码
}
到这里需要知道SPI(Service Provider Interface),简单的说就是一个服务发现的解决方案,这个方案有JDK的实现和tomcat的实现,上面源码中的WebappServiceLoader就是tomcat的实现。
SPI中不得不说的配置文件就是spring-web
包下META-INFO/services
目录下的javax.servlet.ServletContainerInitializer
文件,内容如下
org.springframework.web.SpringServletContainerInitializer
原理是,文件名称是服务发现的接口全路径名称,内容是接口实现类的全路径名称。SPI会创建这个实现类的实例,并通过接口调用org.springframework.web.SpringServletContainerInitializer#onStartup
方法。
4.总结
- 整个过程就不再追溯到tomcat的再往上的源码了,我们已经可以了解到tomcat和spring是怎么样实现了不使用web.xml配置Servlet的了。
- 如果有继续想要了解JDK的SPI实现,可以看下
java.util.ServiceLoader
- 如果看完spring的这个实现还不是很懂,可以看
logback
日志框架的ch.qos.logback.classic.servlet.LogbackServletContainerInitializer
实现。
内容总结
以上是互联网集市为您收集整理的Spring去除web.xml,使用Java配置Servlet的原理,SPI全部内容,希望文章能够帮你解决Spring去除web.xml,使用Java配置Servlet的原理,SPI所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。