模拟Springboot一:(零xml配置搭建SSM项目)

 在spring官网文档中无论是spring的基础文档,还是spring-mvc文档都推荐我们使用javaconfig的方式来搭建项目 间接说明

(优点:javaconfig配置>xml配置) 其实 springboot内部就是通过这种方式来做的而我们可以通过这种方式来搭一般的ssm项目,

甚至自己手动内嵌一个tomcat搭建一个简单的springboot项目都是可以的 。早在servlet3.0开始就能实现零xml配置搭建项目了

(现在最新servlet4.0,下面也会说到为什么从3.0开始可以实现springmvc的零xml配置),也就是说 通过xml搭建项目对于现在而言确实比较老了 。。。

 

1、首先创建一个maven的web项目  

 (1)、pom依赖 (后面需要其他的再加) :servlet依赖是用来使用servlet3.0 SCI新特性 实现 零xml 配置的

  

(2)目录结构

  

       创建WebApplication                 类 等于:web.xml

        创建SpringApplicationContext类 等于spring-context.xml 容器

  (3)首先通过javaconfig方式配置spring容器(为什么先配置spring容器就不再说了) 

  

  只需要 两个注解 就能实现对spring容器的配置 包括在启动容器时实例化对象、提供注解的支持、DI等

   @Configuration:表示是一个spring容器

        @ComponentScan("com.it") 包扫描 ,这里我只创建了com.it.controller(路径的颗粒度也是可以任意配置的,官网文档有介绍)    

         注意 : 从spring4.0 开始 ,就只需设置包扫描 就能完成对spring核心的配置了  ,无需额外打开 注解、驱动之类的设置 

    这些在spring-core源码包中都有体现 至此就完成了对spring最基本的配置。。。

  (4)如果现在需要测试的话 , 以前是用ClassPathXmlApplicationContext 来加载xml 实例spring容器  ,

       现在在main方法通过AnnotationConfigApplicationContext 加载spring容器就完事了 (这里就不测试了,整合完了SpringMVC再测试 )

 (5)  配置spring-mvc ,官网文档中写的很清楚

      

  web.xml主要配置包括两部分  配置spring容器和 配置speingMVC这里也是一样

     A、在实例化 spring容器时使用AnnotationConfigWebApplicationContext的register方法来注册,而AnnotationConfigApplicationContext

                通过构造器来实例化spring容器, 其实AnnotationConfigApplicationContext 的构造器(下图) 的源码中ClassPathXmlApplicationContext

                都是 通过register()这种方法   ,然后refresh() 实例化spring的 容器的

       

        B、spring整合springMVC无非就是 管理DispactcherServlet ,然后再将DispactcherServlet 对象放入tomcat容器,在tomcat启动的时候 加载

        setOnStartUp(1) :在项目启动的时候就将dispatcherServlet加载

        addMapping("/")    : 拦截的请求

  (6)、部署项目运行tomcat 就能从页面访问项目了(自己写controller测试)  访问:http://localhost:8080/项目名/RequestMapping   

    

   (7) 下面 来提一个问题 ,进而引入 servlet3.0  SCI 特性 ,我们知道 web.xml是项目的主入口 , 在tomcat启动的时候会加载项目的

              WEB-INF/web.xml这个文件  。由于web.xml 配置配置了spring、springMVC 通过解析xml 和  反射技术就能打到对spring容器的创建

      问题 :现在只是自己创建了一个WebApplication  类 ,tomcat 也不知道我们具体定义的是什么类放在什么地方,他是如何加载到的呢?

  分析源码可以知晓 下图: 

              

  

                    A、ServletContainerInitializer接口 简称 SCI :作用是 tomcat启动容器阶段通过编程风格将filter、Servlet、Listener添加至servlet

        容器从而取代web.xml中的filter、Servlet、Listener的配置

 

                    B、tomcat启动阶段 ,来获取ServletContainerInitializer的实现类然后执行其onStartUp()方法 ,

        springSpringServletContainerInitializer 实现了此方法并执行他的onStartUp()方法 ,那么问题来了

        ServletAPI也不知道 spring 是用 哪个类 实现这个 ServletContainerInitializer接口的并且tomcat(tomcat中内嵌servlet)

         和spring两个项目是分开的(没有耦合),那么tomcat是如何加载到 SpringServletContainerInitializer类的呢?          

         SCI规范在一个类型实现了ServletContainerInitializer时,项目启动的时候 会将实现这个接口的所有的实现类的 权限定的类名写到

         META-INF/services/javax.servlet.ServletContainerInitializer文件中 ,maven依赖可以看到:

                       org.springframework.web.SpringServletContainerInitializer

           

      SpringServletContainerInitializer类的实例是通过反射加载这个文件下的全限定类名得到的,根据上面的流程图

       SpringServletContainerInitializer类中的onStartUp方法中 会执行WebApplicationInitializer接口的onStartUp()方法,

      根据多态,我们自己项目中 定的WebApplication 类的 onStartUp方法执行 , 才能实现spring容器的初始化,然后管理springMVC          

 1 @HandlesTypes(WebApplicationInitializer.class)//注解用于注入实现WebApplicationInitializer接口的类的对象,
 2 //放入onStartUp()方法的set集合中然后遍历执行实现类中的onStartUp()
 3 public class SpringServletContainerInitializer implements ServletContainerInitializer {
 4     @Override
 5     public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
 6             throws ServletException {
 7 
 8         List<WebApplicationInitializer> initializers = new LinkedList<>();
 9 
10         if (webAppInitializerClasses != null) {
11             for (Class<?> waiClass : webAppInitializerClasses) {
12                 // Be defensive: Some servlet containers provide us with invalid classes,
13                 // no matter what @HandlesTypes says...
14                 if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
15                         WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
16                     try {
17                         initializers.add((WebApplicationInitializer)
18                                 ReflectionUtils.accessibleConstructor(waiClass).newInstance());
19                     }
20                     catch (Throwable ex) {
21                         throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
22                     }
23                 }
24             }
25         }
26 
27         if (initializers.isEmpty()) {
28             servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
29             return;
30         }
31 
32         servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
33         AnnotationAwareOrderComparator.sort(initializers);
34         for (WebApplicationInitializer initializer : initializers) {
35             initializer.onStartup(servletContext);
36         }
37     }

  @HandlesTypes(WebApplicationInitializer.clas)注解: 上面的一段代码是 SpringServletContainerInitializer类的源码 ,

   当onStartUp执行的时候 会将实现WebApplicationInitializer接口的类也就是项目中中自定义的

     WebApplication类 注入到当前类中并用Set参数接收

   

 (8)整合Mybatis

   (1)整合Mybatis相关依赖

    

<!-- 添加mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

        <!--mybatis-spring依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.7.RELEASE</version>
        </dependency>

 

   (2)、SpringApplicationContext.java 配置 (思路是跟.xml 一样的)

           数据源的配置可以写到 .yml 文件中然后再写个工具类解析的,这里为了方便就直接硬编码带代码里了 

      。另外这里只配置了 最基本的需要,如果下配置如事物、aop、上传等 使用@Bean注入即可

@Configuration
@ComponentScan("com.it")
public class SpringApplicationContext {

    //创建数据源
   @Bean("dataSource")
    public DataSource getDataSource() {
       BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/t1?useUnicode=true&characterEncoding=UTF-8");
        dataSource.setUsername("root");
        dataSource.setPassword("xxx");

        dataSource.setInitialSize(3);
        dataSource.setMaxIdle(10);
        dataSource.setMaxWait(1000);//最长等待时间
        return dataSource;
    }

    //管理mybatis的selSessionBean
    @Bean("sqlSessionFactoryBean") //value :为创建的 bean取别名,默认是方法名首字母小写
    //参数DataSource :sqlSessionFactoryBean 依赖参数DataSource
    public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //mapper配置 "classpath*:mapping/*Mapper.xml"
        Resource[] resources = null;
         try{
             resources = new PathMatchingResourcePatternResolver().getResources("classpath*:com/it/dao/mapping/*Mapper.xml");
         }catch (Exception e){
            e.printStackTrace();
         }
        sqlSessionFactoryBean.setMapperLocations(resources);
        return  sqlSessionFactoryBean;
    }

    //扫描mapper创建dao代理
    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.it.dao");
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
        return mapperScannerConfigurer;
    }

}

 下一篇:在此基础上 内置tomcat  来模仿 Springoot main方法启动web项目

    

  

             

 
 
 
 
 
 

 

     

 

 

       

 

         

  

 

   

     

 

 

 

 

     

  

    

            

  

 

 

  

 

   

 

转载于:https://www.cnblogs.com/bbdong/p/10189401.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值