前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring mvc基于编码配置的原理

spring mvc基于编码配置的原理

作者头像
java达人
发布2018-01-31 18:21:57
9220
发布2018-01-31 18:21:57
举报
文章被收录于专栏:java达人

使用spring mvc的时候需要注册DispatcherServlet,DispatcherServlet是一个前端控制器,主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。我们配置DispatcherServlet最典型的是使用web.xml文件。如下:

代码语言:js
复制
 <servlet>
   <servlet-name>dispatcher</servlet-name>
   <servlet-class>
     org.springframework.web.servlet.DispatcherServlet
   </servlet-class>
   <init-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>/WEB-INF/spring/spring-mvc.xml</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <url-pattern>/</url-pattern>
 </servlet-mapping>

但spring3.1引入了WebApplicationInitializer接口,有了它,我们不需要配置web.xml初始化web应用,只需要继承该接口,通过编码实现相应的配置:

代码语言:js
复制
public class Initializer implements WebApplicationInitializer {
@Override
 public void onStartup(ServletContext servletContext) throws ServletException {
 AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
  ctx.register(WebAppConfig.class);
  servletContext.addListener(new ContextLoaderListener(ctx));
  ctx.setServletContext(servletContext);
  Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
  servlet.addMapping("/");
  servlet.setLoadOnStartup(1);
}
}

那通过编码方式有什么好处呢?它可以充分利用编译器,在编译期间检查出配置中的错误,另外,这增强了配置的灵活性和可控性,你可以在启动过程中自定义需要的检查验证条件。

Spring mvc是跟着更底层的接口标准servlet走的,servlet3+以后引入ServletContainerInitializer接口,这为去web.xml,基于代码配置提供了一种途径:

代码语言:js
复制
public interface ServletContainerInitializer {
 public void onStartup(Set<Class<?>> c, ServletContext ctx)
     throws ServletException; 
}

Spring的SpringServletContainerInitializer 类实现了该接口:

//HandlesTypes注解标识SpringServletContainerInitializer 类启动时需要处理的类,此处专门标识了WebApplicationInitializer,正如前面所展示的,我们正是通过实现WebApplicationInitializer接口.来作一些配置工作的。

代码语言:js
复制
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
 public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
  List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
 //以下代码对前面我们实现的WebApplicationInitializer作了循环,实例化,调用onStartUp 等   操作。
  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) 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;
  }
  Collections.sort(initializers, new AnnotationAwareOrderComparator());
  servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);
  for (WebApplicationInitializer initializer : initializers) {
   initializer.onStartup(servletContext);
  }
 }
}  

tomcat7以后采用了servlet3标准,我们启动tomcat7(servlet3容器)时,容器通过JAR Services API 机制,探测到spring-web包下的一个文件META-INF/services/javax.servlet.ServletContainerInitializer,文件内声明实现类,进而调用其onStartup方法,如果以后我们要自己实现ServletContainerInitializer ,也需要在相应jar包的 META-INF/services目录下放置这样一个以接口的全限定名命名的文件。

程序员局限于框架的使用,将始终停留于浅层次的水平,只有深入框架,理解原理,甚至阅读优化其中的源码,才是升级打怪的王道,大家有空可以去看看源码,我们随时讨论。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档