阿里技術專家帶你使用Spring框架快速搭建Web工程項目
雲棲君導讀:Spring 框架是一個開源的 Java 平台,它為容易而快速的開發出耐用的 Java 應用程序提供了全面的基礎設施。藉助於Spring框架可以快速搭建Web工程項目,本文中阿里巴巴高級開發工程師嵛山就帶大家一起入門Spring框架。
視頻回顧地址:http://click.aliyun.com/m/49796/
演講嘉賓簡介:
呂德慶(花名:嵛山), 阿里巴巴高級開發工程師,武漢大學地信碩士,有豐富的系統開發經驗,目前就職於阿里巴巴代碼中心團隊,負責後端開發。
本文首先將介紹Spring框架的相關概念,其次將藉助Spring Web示例工程帶大家學習如何快速開發Spring Web應用。
一、Spring介紹
Spring是一個開源的Java企業應用開發框架,其誕生的目標就是簡化Java應用開發。下圖中是早期Spring版本的模塊圖,可以看到Spring框架的基座是Spring Core模塊,其支撐了Spring的上層模塊AOP、DAO、ORM等,而Spring Core的核心就是IOC容器。其實整個Spring框架的核心主要有兩個:IOC和AOP。
IOC
IOC,即Inversion of Control,也就是控制反轉。控制反轉的概念從字面上比較晦澀難懂,而且每個Spring開發工程師對於這個概念也都有不同的理解。想要理解控制反轉,首先要弄清楚控制指的是什麼的控制,反轉又指的反轉什麼。
首先看正常程序的偽代碼,在這段代碼中有一個Process進程類,實例化之後還有一個Thread線程類,由於進程必須有一個主線程才能正常運行,所以進程是依賴於線程的,那麼就需要在進程中設置主線程。代碼中將實例化的線程對象設置進去,這樣進程才完整並且能夠運行起來。
這裡的控制就是通過編碼的形式控制了對象的實例化,通過編碼主動設置對象的依賴並最終得到一個可以運行的對象。假如在正常的套路裡面劇情出現了反轉,但是反轉的結果還是能夠得到一個正常運行的進程,那麼能夠反轉的部分就是實例化的部分以及依賴設置的部分。將實例化以及依賴關係的設置的控制權反轉就需要IOC容器接收控制權,讓IOC容器來控制對象的實例化以及依賴關係的設置。
上圖中還有一段關於IOC的偽代碼。首先需要一個IOC容器,通過new去實例化一個,然後告訴容器其所需要控制的類的信息。在Process類裡面通過某種配置或者聲明的方式告訴IOC容器Process類裡面需要依賴於Thread類。當向IOC容器請求一個Process對象的時候,IOC會實例化一個Process,同時也會實例化一個Thread類,根據Process裡面聲明的依賴將Thread設置到Process裡面,並最終給用戶一個可以正常運行的Process。
那麼IOC是如何知道類的信息以及類之間的依賴關係的呢?現實的做法就是通過配置,配置可以為配置文件,也可以通過Java的註解進行實現。這樣只需要定義類並通過配置聲明依賴關係,就不用去關心類的對象的串接了,這些統統交由IOC進行處理,這樣就簡化了開發的工作量,同時通過配置可以靈活地配置對象之間的依賴關係。
這裡還涉及到的一個概念就是依賴注入,依賴注入是一個比較易懂的概念。所謂的依賴注入就是將對象之間的依賴關係通過容器進行注入,避免在代碼上直接設置依賴。其實依賴注入和控制反轉表達的是同樣的思想,但是依賴注入更加簡潔明了,便於理解。
AOP
AOP,Aspect Oriented Programming,也就是面向切面編程。在AOP的概念里需要理解兩個小的概念:切面和切點。
首先,所謂切面就是刀切開之後所看到的平面,而切點則是刀切的位置。那麼如何理解面向切面編程呢?在生活中的例子就是「肉夾饃」,在製作肉夾饃時首先需要將饃切開,之後在切面上放上肉並蓋好,這樣在吃的時候不僅能夠吃到饃還能夠吃到肉。而在做的時候需要關注這個饃應該怎麼切,當然是橫著切的,而且其切點位於邊上,切完之後還需要選擇放什麼肉。
那麼將Java中的類比喻成饃,那麼類可以怎麼切呢?其切點又在哪裡呢?Java裡面已經定義了類是可以切的,其切點只能是方法。將方法作為切點,那麼其切面就只能是方法的前和後,那麼所謂的肉就是需要添加的代碼。那麼在執行對象的方法時在進入方法前會執行切入的一段代碼,在方法執行之後還會執行切入的另外一段代碼,這樣面向切面編程的理解就是將代碼切入到類的指定方法、指定位置的編程思想。面向切面編程是面向對象編程思想的補充,可以通過面向切面編程將與類不相關的行為提取出來進行共享,並以切點的方式加入到不同的對象當中。一旦行為發生變化只需要修改行為而沒有必要修改對象,其典型用法有日誌列印、性能統計以及異常處理等。這裡的日誌列印就是當進入某一個方法的時候希望列印方法的一個參數信息,當退出方法的時候希望在日誌中列印方法的返回值;性能統計就是統計方法的執行時間,在方法前記錄一個時間戳,在方法後記錄一個時間戳,以此得出方法的執行時間來統計方法的性能;異常處理可以定義該方法拋出異常的切面上面應該對於異常進行怎樣的處理。
二、Spring Web開發
接下來將通過Spring Web的工程進行學習幫助大家了解如何快速開發Spring Web應用。在這個過程中也會加深大家對於IOC和AOP思想的理解。此外還將了解Web MVC架構模式的使用方式。
在正式開始之前需要設計代碼層級的結構,整個Spring Web工程將主要分為5個模塊:view、controller、service、model和AOP,這些模塊是具有層級關係的,view最靠近瀏覽器端,所以在層級上面屬於最上層,瀏覽器發送請求並由controller響應請求並調用底下的service,由service層去操作數據,controller將得到service的返回結果並將數據傳遞給view層,最終view層輸出給瀏覽器,而AOP將作為通用模塊使用。
首先,示例工程使用Maven管理,這裡首先定義了Spring Boot的依賴。Spring Boot是集成了Spring框架的開發套件,它將幫助開發者更快地開發Spring Web的應用。同時在依賴中還可以看到Web依賴、AOP依賴以及模板引擎Thymeleaf的依賴。
示例工程下主要有aop包、controller包、model包和service包,這與前面所提到的代碼層級模式是一致的。
下圖所展現的是WebApplication主程序類,在WebApplication中存在一個main函數,而main函數中只有一句代碼就是SpringApplication.run(),然後將WebApplication類的信息作為參數傳遞進去。那麼SpringApplication.run()的背後就是Spring的核心,即IOC容器的初始化以及其他工作。在IOC容器初始化完成之後,將收到WebApplication類的信息,同時因為@SpringBootApplication註解,IOC容器將開啟對demo包以及其下面的子包中所有類的掃描,通過掃描IOC容器將發現很多需要用到的類並將這些類注入進去。
如下圖所示的是UserController類,在其上面可以看到@Controller的註解,因為這個註解,UserController的信息將被注入到IOC容器中。在UserController中可以看到UserService的一個成員變數,這個成員變數在整個UserController並沒有得到初始化。因為有一個@Autowired註解,這個UserController就可以在初始化之後會產生由於@Autowired註解聲明的依賴,這個依賴將由IOC容器負責注入。其所注入的是UserService介面的實現。
對於UserService介面而言,其具有一個實現類,在實現類中有一個@Service註解,因為這個註解,UserService的實現類將被注入到IOC容器中,最終IOC容器可以初始化UserService的實現類的一個對象,並將對象注入到UserController裡面,這樣就可以通過IOC拿到一個完整的UserController對象,並且依賴已經自動裝配好了。這也就是IOC的作用。在所有的代碼中都沒有UserService的實例化,這些都是由SpringBoot和IOC共同完成的。
在aop包下的LogAspect類裡面可以看到面向切面的編程思想。首先在log()函數之前可以看到一個名為@Pointcut的註解,因為這個註解,這個log()函數將代表一個切點,同時可以看到在@Pointcut註解裡面有一個表達式,該表達式標明了切點的位置,其將把demo.controller包下面的所有類以及所有公開的方法都作為切點進行切面編程。在doBefore()方法上面有一個函數註解,該註解就定義了一個切面,該切面位於切點之前,也就是在執行切點之前需要執行這段代碼。同時還有一個切面是位於函數執行之後,將列印函數返回值輸出的代碼。
因為LogAspect的存在,將導致後續代碼在執行controller裡面的所有公有方法的時候都會在之前進行方法參數列印,以及方法後返回值的輸出。這就是AOP面向切面編程思想所帶來的好處。
接下來將與大家分享WebMVC這種架構模式的使用,首先需要理解MVC中的M、V、C分別都代表什麼。M指的是Model,也就是數據模型。如下圖所示的User類,Model就是數據的載體。
V指的是View視圖,在這裡的視圖是templates文件夾下定義的兩個html模板文件,這些模板文件最終將由引入的依賴Thymeleaf模板引擎進行讀。在這裡其實可以將模板文件理解為Java的一個類。
C也就是Controller控制器,如下圖所示的UserController。
接下來分享視圖層、控制器的作用。首先,視圖層的主要作用是將視圖最終轉化成一個包含真實數據的頁面,並返回給瀏覽器由瀏覽器展現這個結果。控制器則主要是對請求進行響應,其會根據請求的地址和請求方式不同將請求分發到不同的方法上面,由方法執行對應的代碼,然後對於請求做出對應的響應。
可以通過運行main函數執行整個Spring Boot程序,如下所示Spring Boot便已啟動成功。Spring Boot在啟動的時候就已經同時啟動了一個Tomcat,Tomcat作為Web的容器,將可以對外提供Web服務,其將監聽8080埠。根據埠以及UserController定義的地址可以通過瀏覽器進行訪問。通過localhost:8080/users地址發起一個請求,在後台中由於做了切面編程,可以看到後台中UserController中的getUsers這個方法被執行了。而且這個方法的返回值是users。之所以會執行getUsers方法是因為在Controller中配置的@RequestMapping註解,當使用GET請求/users這個地址的時候,請求就會轉發到這個方法中,這個方法會操作底層的users數據並返回,通過modelMap將數據和userList這個Key進行綁定並最終返回綁定的字元串users。由於框架的緣故,其會觸發模板引擎來解釋模板文件。同時由於modelMap的關係,它將給userList賦予後台的用戶數據,在最終的模板文件里將會進行轉化,使用真實的數據進行替代並渲染出真實的網頁出來。
接下來可以嘗試創建用戶,在前端頁面點擊「創建用戶」,後台將會調用相應的用戶創建方法,其將有一個modelMap並將返回userCreate,由於模板的關係,其將會將modelMap中的數據帶到模板中來,這個模板就是添加用戶的頁面,然後可以實現數據值的錄入。
通過提交按鈕將以POST方式請求,這樣之後數據就添加成功了。
同時頁面也已經重定向了用戶列表的頁面了。
可以看下後台的實現,首先調用了createUser方法,createUser方法將拿到由瀏覽器返回的錄入的數據,並進行user創建。在具體進行創建的時候會插入一個具體的數據。在創建完成之後通過網頁的重定向,讓網頁重新定向到users頁面,進而觸發一個新的請求並由getUsersPage重新響應,並返回users數據,並由模板引擎進行渲染進而顯示一個真實的數據。整個請求的路由以及後端的MVC實現就是如上述所分析的。
其實在整個過程中都是在定義一個類,通過註解進行配置,在整個過程中並沒有通過類實例化一個對象,這些都是因為控制反轉的緣故交由IOC處理了。由於Spring Boot的緣故,也無需定義一個Tomcat,Spring Boot已經默認定義好了一個Tomcat來對外提供服務,這就是Spring Boot所帶來的好處,可以幫助我們非常快速地開發Web的應用。
end
※阿里雲專有宿主機發布
※ICDE:POLARDB定義雲原生資料庫
TAG:雲棲社區 |