SSM框架註解整合
1.ServletContext
對於一個web應用,其部署在web容器(比如:tomcat)中,web容器提供其一個全域性的上下文環境,這個上下文就是ServletContext,它由web容器負責初始化,其為後面的spring容器提供宿主環境。
ServletContext是一個全域性的儲存資訊的空間,伺服器開始,其就存在,伺服器關閉,其才釋放。ServletContext提供對應用程式中所有Servlet所共有的各種資源和功能的訪問。Servlet上下文API用於設定應用程式中所有Servlet共有的資訊,Servlet可能需要共享他們之間的共有資訊。運行於同一伺服器的Servlet有時會共享資源,如JSP頁面、檔案和其它Servlet。request,一個使用者可有多個;session,一個使用者一個;而servletContext在整個web應用中只有一個,所有使用者也只共用一個。所以,為了節省空間,提高效率,ServletContext中,要放必須的、重要的、所有使用者需要共享的執行緒又是安全的一些資訊。
換一種方式說吧,執行在Java虛擬機器中的每一個Web應用程式都有一個與之相關的Servlet上下文。ServletContext物件是Web伺服器中的一個已知路徑的根,Servlet上下文被定位於http://localhost:8080/專案名. 以 /專案名 請求路徑(稱為上下文路徑)開始的所有請求被髮送到與此ServletContext關聯的Web應用程式。一個ServletContext物件表示了一個Web應用程式的上下文。
舉例:做一個購物類的網站,要從資料庫中提取物品資訊,如果用session儲存這些物品資訊,每個使用者都訪問一便資料庫,效率就太低了;所以要用來Servlet上下文來儲存,在伺服器開始時,就訪問資料庫,將物品資訊存入Servlet上下文中,這樣,每個使用者只用從上下文中讀入物品資訊就行了。
2. RootWebApplicationContext和DispatcherServletWebApplicationContext
以下簡稱RootWebApplicationContext為:RootContext,DispatcherServletWebApplicationContext為:DispatcherServletContext。
WebApplicationContext擴充套件了ApplicationContext,代表的Spring Web的應用上下文,RootContext由ContextLoaderListener
接著是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
繼承結構圖:
log4j日誌軌跡:
3. WebApplicationContext和DispatcherServlet上下文初始化方式
初始化方式有兩種:Java配置和在web.xml配置,不管是哪種配置方式,所做的工作差別不大。
java配置:在servlet 3.0環境中,web容器會在類路徑中查詢實現了javax.servlet.ServletContainerInitializer介面的類,如果能找到此類就會用它來配置Servlet容器。Spring提供了這個介面的實現,名為SpringServletContainerInitializer,這個實現又查詢實現了WebApplicationInitializer介面的類。Spring 3.2引入了一個WebApplicationInitializer的一個便利的基礎實現類:AbstractAnnotationConfigDispatcherServletInitializer。它會建立DispatcherServleContext和RootContext,現在只需擴充套件它即可。
(1) SsmContextInitializer.java
(2) RootConfig.java
(3) WebConfig.java
來看看DispatcherServletContext和它的父上下文RootContext儲存的核心Bean:
1.DispatcherServletContext:
從圖中可以看出:DispatcherServletContext中儲存的Bean是與web相關的元件,比如檢視解析器,處理器對映等。
2.RootContext(在DispatcherServletContext可以看到它的父上下文Root):
從圖中可以看出:RootContext中儲存的Bean是非web元件,比如Service。
二、Mybatis
1.在獨立的Mybatis中的核心元件:
1.SqlSessionFactory:生成SqlSession(會話),由SqlSessionFactoryBuilder根據配置資訊建立。
2.SqlSession:一個既可以傳送SQL去執行並返回結果,也可以獲取Mapper的介面。
3.SQL Mapper:由mapper配置檔案(也可以是註解配置)和java介面構成,根據給出的mapper配置檔案來發送SQL去執行並返回結構
核心程式設計程式碼:
(1). MybatisConfig.xml
(2) UserMapper.xml
(3) Demo.java
2.在MyBatis-Spring中的核心元件:
為了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 編寫資料訪問物件 (DAO)的程式碼,MyBatis-Spring 提供了一個動態代理的實現:MapperFactoryBean。這個類 可以讓你直接注入資料對映器介面到你的 service 層 bean 中。當使用對映器時,你僅僅如調 用你的 DAO 一樣呼叫它們就可以了,但是你不需要編寫任何 DAO 實現的程式碼,因為 MyBatis-Spring 將會為你建立代理。MapperFactoryBean 建立的代理類實現了 UserMapper 介面,並且注入到應用程式中。 因為代理建立在執行時環境中,那麼指定的對映器必須是一個介面,而 不是一個具體的實現類。
注意:如果 UserMapper 有一個對應的 MyBatis 的 XML 對映器檔案, 如果 XML 檔案在類路徑的 位置和對映器類相同時, 沒有必要在去指定對映器,它會被 MapperFactoryBean 自動解析,反之亦然。我們一般會將Mapper介面的類完全限定名和Mapper.xml配置檔案的名稱空間寫成一致。
核心bean的建立:配置在非web元件(上文的RootConfig.java)中
1.javax.sql.DataSource:建立它的實現類即可,比如org.apache.ibatis.datasource.pooled.PooledDataSource;
解釋:配置url,driver,userName,password;
2.org.mybatis.spring.SqlSessionFactoryBean
解釋:配置SqlSessionFactory,主要提供資料來源和mapper配置檔案
3.org.mybatis.spring.mapper.MapperFactoryBean
解釋:為對應的Mapper介面建立代理
注意:在實際應用中肯定會有多個Dao,一個個去配置過於繁瑣,所以我們一般採用MapperScannerConfigurer,它將會查詢指定類路徑下的對映器並自動將它們建立成MapperFactoryBean。
3.org.mybatis.spring.mapper.MapperScannerConfigurer
解釋:配置mapper介面的掃描器,提供mapper介面所在的包名(必須的)
MapperScannerConfigurer中還有幾個常用到的屬性配置:
1.private Class<? extends Annotation> annotationClass:指定包中的介面若有指定的註解則掃描(認為它是Mapper)
例子:scannerConfigurer.setAnnotationClass(Repository.class);//若有此配置,Mapper掃描器會只掃描帶有@Repository註解的介面
2.private Class<?> markerInterface:指定包中的介面若實現了指定的介面則掃描(認為它是Mapper)
例子:scannerConfigurer.setmarkerInterface(IUserDao.class);//若有此配置,Mapper掃描器會只掃描帶有實現了IUserDao的介面
3個元件配置完畢後,你只需要直接注入資料對映器介面到你的 service 層 bean 中。直接呼叫資料對映器介面的方法即可:
service層程式碼:IUserDao介面沒有任何手動實現類,其實現由MapperFactoryBean建立並注入到程式中。
最後在web元件中建立Controller即可執行。