ssm整合(纯注解方式)

一、ServletContext

   对于一个web应用,其部署在web容器(比如:tomcat)中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,它由web容器负责初始化,其为后面的spring容器提供宿主环境。
   ServletContext是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。ServletContext提供对应用程序中所有Servlet所共有的各种资源和功能的访问。

二、 RootWebApplicationContext和DispatcherServletWebApplicationContext

以下简称RootWebApplicationContext为:RootContext,DispatcherServletWebApplicationContext为:DispatcherServletContext。
  WebApplicationContext扩展了ApplicationContext,代表的Spring Web的应用上下文,RootContext由ContextLoaderListener创建,其中存放了各种注册到Spring的非Web组件的bean(比如service)。RootContext初始化完成后将其存储到ServletContext中,便于获取。在源码中你可以看到这样的代码:servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,this.context);//this.context就是RootContext
  接着是DispatcherServletContext的初始化,它会以RootContext为父上下文(在DispatcherServletContext中可以引用RootContext中的非web组件,而反过来不行。),然后初始化Web相关组件,比如控制器,视图解析器等。DispatcherServletContext初始化完毕后将自身存入ServletContext.

相关源码:在初始化DispatherServlet中,
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext()

WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());//获取RootContext(非web组件,比如service)
WebApplicationContext dispatcherServletContext = this.webApplicationContext;
dispatcherServletContext.setParent(rootContext);//以RootContext为父上下文
getServletContext().setAttribute(attrName, dispatcherServletContext);//将dispatcherServletContext存入ServletContext

三、 WebApplicationContext和DispatcherServlet上下文初始化方式

   在servlet3.0规范中,提供了一个 javax.servlet.ServletContainerInitializer接口,来帮助我们做web应用的初始化操作,例如动态注册Servelt、Filter、Listener等 servlet3.0规范中,
   web容器在启动时可以通过 ServletContainerInitializer进行第三方组件初始化工作,例如注册servlet或者filtes等。
   
  当框架要使用 ServletContainerInitializer 就必须在对应的jar包的METAINF/services 目录创建一个名为 javax.servlet.ServletContainerInitializer 的文件,
  文件内容指定具体的ServletContainerInitializer`实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
   一般伴随着 ServletContainerInitializer 一起使用的还有@HandlesTypes注解,通过@HandlesTypes可以将感兴趣的一些类注入到 ServletContainerInitializerde 的onStartup方法作为参数传入。
   tomcat容器的 ServletContainerInitializer 机制的实现,主要交由Context容器和ContextConfig监听器共同实现,ContextConfig监听器负责在容器启动时读取每个web应用的 WEB-INF/lib 目录下包含的jar包的META-INF/services/javax.servlet.ServletContainerInitializer ,以及web根目录下的 META-INF/services/javax.servlet.ServletContainerInitializer ,通过反射完成这些
ServletContainerInitializer 的实例化,然后再设置到Context容器中,最后Context容器启动时就会分别调用每个 ServletContainerInitializer 的onStartup方法,并将感兴趣的类作为参数传入。

四、Spring的ServletContainerInitializer的实现类

   以spring mvc为例,我们可以在spring-web的jar包下的META.INF下的service目录查看到
javax.servlet.ServletContainerInitializer这个文件。在文件中定义了具体的ServletContainerInitializer的实现类SpringServletContainerInitializer

/**通过@HandlesTypes将实现了WebApplicationInitializer接口的对象注入到SpringServletContainerInitializer,
   以便容器初始化的时候,初始化我们配置好的实现类。即Spring容器和mvc的dispartcherServlet*/
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

    /**
      项目启动web容器会加载并调用该方法
     */
    @Override
    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {
        //定义一个集合存放注入的WebApplicationInitializer实现类
        List<WebApplicationInitializer> initializers = new LinkedList<>();

        if (webAppInitializerClasses != null) {
            for (Class<?> waiClass : webAppInitializerClasses) {

                //如果该类不是接口,且不是抽象类,而且实现了WebApplicationInitializer接口,将反射创建该类实例并存入集合   
                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");
        //便利集合中的实现类,调用实现类的onStartup进行初始化,例如我们配置的spring容器,mvc的dispartcherServlet等
        AnnotationAwareOrderComparator.sort(initializers);
        for (WebApplicationInitializer initializer : initializers) {
            initializer.onStartup(servletContext);
        }
    }

}

四、AppConfig,纯注解的web配置文件,用于替代web.xml

   当ServletContainerInitializer(servlet容器初始化器)执行时,会调用那个注入的WebApplicationInitializer实现类的onStartup方法,进行相关组件的初始化。


/**
 *
 * 1、ServletContext:web容器全局上下文对象 ,它由web容器负责初始化,为后面的spring容器提供宿主环境。
 *    addServlet:注册servlet,通过对应类的构造传入初始化参数
 *    addListener:注册监听器,通过对应类的构造传入初始化参数
 *    addFilter:注册过滤器,通过对应类的构造传入初始化参数、
 *    addMapping:添加匹配路径
 * 2、AnnotationConfigWebApplicationContext :该类为spring框架提供的配置文件注册类
 *     用于加载配置文件存储到web容器中的map集合中,以便初始化servlet、listener等web组件类时使用 
 *     register方法:用于注册配置类
 * 
 * */

@Configuration
public class AppConfig implements WebApplicationInitializer{

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        //1.1创建AnnotationConfigWebApplicationContext
        AnnotationConfigWebApplicationContext MvcContext = new AnnotationConfigWebApplicationContext();
        //1.2springMVC的注册配置类
        MvcContext.register(SpringMvcConfig.class);
        //1.3创建mvc核心控制器,并将注册的springMVC配置类传入
        Dynamic dispatcherServlet = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(MvcContext));
        //1.4为核心控制器配置拦截路径
        dispatcherServlet.addMapping("*.do");


        //2.1创建AnnotationConfigWebApplicationContext
        AnnotationConfigWebApplicationContext springContext = new AnnotationConfigWebApplicationContext();
        //2.2spring的配置类
        springContext.register(SpringConfig.class);
        //2.3创建初始化spring容器的监听器,并将注册的spring配置类传入
        servletContext.addListener(new ContextLoaderListener(springContext));


        //3.1注册解决乱码过滤器,设置字符集utf-8
        javax.servlet.FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("characterFilter",new CharacterEncodingFilter("utf-8"));
        //3.2添加拦截的类型
        EnumSet<DispatcherType> enumSet = EnumSet.noneOf(DispatcherType.class);
        enumSet.add(DispatcherType.REQUEST);
        enumSet.add(DispatcherType.FORWARD);
        //3.3添加拦截路径
        encodingFilter.addMappingForUrlPatterns(enumSet, true,"/*");

    }




}

五、Spring配置类

/**
 * 1、@Configuration :声明配置类
 * 2、@MapperScan    :扫描生成dao实现类:
 * 3、@EnableTransactionManagement :声明事物管理
 */
@Configuration
@MapperScan(basePackages="cn.it.travel.dao")
@EnableTransactionManagement
@ComponentScan(basePackages="cn.it.travel.service")
public class SpringConfig {

    /**
     *提供数据源
     * 
     */
    @Bean
    public DataSource getDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl("jdbc:oracle:thin:@192.168.109.128:1521:orcl");
        druidDataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        druidDataSource.setPassword("it");
        druidDataSource.setUsername("it");
        return  druidDataSource;
    };

    /**
     *创建SqlSessionFactoryBean工厂
     * 
     */
    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource da) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(da);
        return sqlSessionFactoryBean;
    }

    /**
     *声明事务管理器
     * 
     */
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dm = new DataSourceTransactionManager();
        dm.setDataSource(dataSource);
        return dm;
    }

}

六、springMVC的配置类

/**
 * 1、@Configuration :声明配置类
 * 2、@ComponentScan :开启包扫描
 * 3、@EnableWebMvc  :开启处理器映射器、映射器解析器
 */
@Configuration
@ComponentScan(basePackages="cn.it.travel.controller")
@EnableWebMvc
public class SpringMvcConfig {

    /**
     * 4.视图解析器
     * 
     */
    @Bean
    public InternalResourceViewResolver getInternalResourceViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setSuffix(".jsp");
        viewResolver.setPrefix("/WEB-INF/jsp/");
        return viewResolver;
    }

}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐