SpringMVC annotation 方式配置的核心配置

详细的点,都写到了注释里了。简单介绍一下下面的自定义的配置类

继承于Spring的AbstractAnnotationConfigDispatcherServletInitializer,至于Spring怎么接入tomcat的,可以参考Servlet API。

当然,代码的注释中也有一部分说明。

package com.evan.demo.configure;

import com.evan.demo.web.servlet.MyServlet;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.*;
import java.nio.charset.StandardCharsets;

/**
 * 最顶层接口是org.springframework.web.WebApplicationInitializer
 * 而他是由SpringServletContainerInitializer接入tomcat的,该类实现了
 * javax.servlet.ServletContainerInitializer(@see Servlet API 3.x)
 * 该接口实际上相当于web.xml的配置改为JavaConfig方式。
 *
 * SpringServletContainerInitializer会调用所有继承于WebApplicationInitializer的类
 * 并执行其初始化方法。但要切记,该初始化为WEB容器级别的。
 */
public class DefaultWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class[] getRootConfigClasses() {
        // Spring IoC容器配置, 也就是spring的配置文件applicationContext.xml的事。
        // 该配置负责初始化Spring父上下文,并且注册到ServletContext
        // 通常除了controller,其他spring管理的组件如Service,Dao等等都会由它负责管理。
        // spring查找bean的顺序是先在当前上下文中找,找不到再到父上下文找。
        // 而dispatchServlet的上下文的父上下文就是这里配置的全局上下文。
        return new Class[]{DefaultRootInitializer.class};
    }

    @Override
    protected Class[] getServletConfigClasses() {
        // DispatcherServlet的配置,相当于dispatch-servlet.xml
        return new Class[]{DefaultWebConfigure.class};
    }

    @Override
    protected String[] getServletMappings() {
        // DispatchServlet拦截请求匹配
        return new String[]{"/"};
    }

    @Override
    protected Filter[] getServletFilters() {
        HiddenHttpMethodFilter fl = new HiddenHttpMethodFilter();
        return new Filter[]{fl};
    }

    /**
     * 这个方法会在加载Spring的上下文之前执行,因为这个方法是在监听到应用启动的时候就执行了
     * 所以在这里是无法获取spring上下文的
     * WebApplicationInitializer对应用的初始化,早于监听器ContextLoaderListener的初始化
     * @param servletContext
     * @throws ServletException
     */
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 1. 调用getRootConfigClasses创建AnnotationConfigWebApplicationContext
        //    (因为是用注解配置的,当然会对应注解上下文),并作为入参。
        //    创建ContextLoaderListener并注册到servletContext,该监听器会监听WEB应用的生命周期。
        //    注意:这里还没有将全局上下文注册到WEB容器
        // 2. 调用getServletConfigClasses获取DispatchServlet上下文的配置文件,
        //    创建AnnotationConfigWebApplicationContext并注册当前的配置实例
        // 3. 创建dispatcherServlet,并持有步骤2的上下文,
        //    注意:这里还没有将全局上下文注册到WEB容器
        // 4. 调用getServletMappings,配置指定拦截的URL
        // 5. 调用getServletFilters,配置过滤器,并注册到WEB容器。这说明该配置的过滤器为WEB容器级别
        /**
         * ContextLoaderListener负责初始化父上下文,初始化后注册到WEB容器。当然是在本方法执行完成之后,在tomcat层
         * 的应用启动事件发布后被调用ContextLoaderListener的contextInitialized方法中调用context.refresh完成的。
         * 而dispatchServlet的上下文是在servlet的init方法初始化的,先设置父上下文,随后加载扫描注解完成上下文的初始化,
         * 然后注册到servletContext。init方法同样是tomcat调用的。tomcat就是servlet容器,管理servlet生命周期自然不在话下。
         */
        super.onStartup(servletContext);
        // 配置其他的 servlet 和 filter
        FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);
        encodingFilter.setInitParameter("encoding", String.valueOf(StandardCharsets.UTF_8));
        encodingFilter.setInitParameter("forceEncoding", "true");
        encodingFilter.addMappingForUrlPatterns(null, false, "/*");

        // 此配置等价于在该类上注解@WebServlet(name = "myServlet", urlPatterns = "/servlet/*")
        // 但是需要注意,这里是直接使用servletAPI的,即直接注册到ServletContext
        // 因为不会像Controller/DispatchServlet那样被Spring管理起来
        ServletRegistration.Dynamic myServlet =
                servletContext.addServlet("myServlet", new MyServlet());
        myServlet.setLoadOnStartup(10);
        myServlet.addMapping("/servlet/*");

    }
}

 

你可能感兴趣的:(SSM)