DispatcherServlet配置及源码分析

DispatcherServlet配置及源码分析

DispatcherServlet是前端控制器,它负责拦截特定类型得请求并分发至对应的Controller。DispatcherServlet和其它Servlet一样,需要在Java配置类或者web.xml

里进行声明和配置映射。反过来,DispatcherServlet也利用Spring配置来寻找组件、视图解析或者异常处理等。

配置DispatcherServlet

利用Java配置类

这种方法可以直接被Spring容器检测到

    public class MyWebApplicationInitializer implements WebApplicationInitializer {
    
        @Override
        public void onStartup(ServletContext servletCxt) {
    
            // 读取Spring配置类
            AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
            ac.register(AppConfig.class);
            ac.refresh();
    
            // 创建并注册DispatcherServlet
            DispatcherServlet servlet = new DispatcherServlet(ac);
            ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
            registration.setLoadOnStartup(1);
            registration.addMapping("/app/*");
        }
    }

那么这背后发生了什么呢?

第一行AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();

创建了一个AnnotationConfigWebApplicationContext对象。

在这里插入图片描述

可以看到,该类是接口WebApplicationContext的一个实现。

第二行ac.register(AppConfig.class);

字面意思上看,它是对Spring配置类进行一个解析和注册。

在这里插入图片描述

进入方法去看,第一行是来一个断言,表示应该至少有一个被注解的类被传进方法。第二行是将这些类添加到这个叫annotatedClasses的LinkedHashSet中,注意,此时还没有真正开始注册,所以方法上面的注释写道,一定要在之后调用refresh()方法;还有由于Set这个数据结构的特点,里面的元素没有重复的。

第三行ac.refresh();

这个refresh()方法是接口ConfigurableApplicationContext的,由于类AnnotationConfigApplicationContext继承了类GenericApplicationContext,GenericApplicationContext又继承了抽象类AbstractApplicationContext,而AbstractApplicationContext实现了接口ConfigurableApplicationContext并对该方法进行实现,所以类AnnotationConfigApplicationContext也有这个方法但没有对其进行重写,而是直接调用。

在这里插入图片描述

来看接口ConfigurableApplicationContext中的声明,这个方法的作用就是字面意思——“刷新”。目的是加载或者刷新配置,它会销毁所有已存在的单例,这个方法执行后,只有两种情况发生,一是实例化所有单例;二是没有单例被实例化。同时,该方法还应考虑执行失败的收尾清理工作。

第四行DispatcherServlet servlet = new DispatcherServlet(ac);

在这里插入图片描述

通过有参构造,传入一个WebApplicationContext,创建一个DispatcherServlet对象。上面我们提到AnnotationConfigWebApplicationContext是接口WebApplicationContext的一个实现,所以这操作没毛病。构造方法的第一行呢,是调用了它的父类FrameworkServlet(抽象类)的有参构造。

在这里插入图片描述

第二行它明显设置了一个flag,为true的时候表示HTTP的Option请求会和其他普通请求一样走常规调度链,就是会走doService()方法

在这里插入图片描述

DispatcherServlet类里面有这样一个静态代码块,作用是从属性文件中导入默认的策略实现,并且不接受DIY。

最后三行就是JavaEE的常规操作了,这里不作深入分析。

利用web.xml

    <web-app>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/app-context.xml</param-value>
        </context-param>
    
        <servlet>
            <servlet-name>app</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value></param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>app</servlet-name>
            <url-pattern>/app/*</url-pattern>
        </servlet-mapping>
    
    </web-app>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值