模擬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項目

    

  

             

 
        
 
        
 
        

 

     

 

 

       

 

         

  

 

   

     

 

 

 

 

     

  

    

            

  

 

 

  

 

   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM