做者:nnngu
項目源代碼:https://github.com/nnngu/nguSeckill前端
首先在編寫Service
層代碼前,咱們應該首先要知道這一層究竟是幹什麼的。java
Service
層主要負責業務模塊的邏輯應用設計。一樣是首先設計接口,再設計其實現的類,接着在Spring
的配置文件中配置其實現的關聯。這樣咱們就能夠在應用中調用Service
接口來進行業務處理。Service
層的業務實現,具體要調用到已定義的dao
層的接口,封裝Service
層的業務邏輯有利於通用的業務邏輯的獨立性和重複利用性,程序顯得很是簡潔。git
在項目中要下降耦合的話,分層是一種很好的概念,就是各層各司其職,儘可能不作不相干的事,因此Service
層的話顧名思義就是業務邏輯,處理程序中的一些業務邏輯,以及調用dao
層的代碼,這裏咱們的dao
層就是鏈接數據庫的那一層,調用關係能夠這樣表達:github
View(頁面) > Controller(控制層) > Service(業務邏輯) > Dao(數據訪問) > Database(數據庫)web
首先仍是接口的設計,設計秒殺商品的接口,在com.nnngu.service.interfaces
包下創建SeckillService.java
接口文件,以下圖:spring
SeckillService.java
文件裏面的內容請參照項目的源代碼。數據庫
創建好接口以後咱們要寫實現類了,在寫實現類的時候咱們確定會碰到一個這樣的問題,你要向前端返回json數據的話,你是返回什麼樣的數據好?直接返回一個數字狀態碼或者文字?這樣設計確定是很差的,因此咱們應該向前端返回一個實體信息json,裏面包含了一系列的信息,不管是哪一種狀態都應該能夠應對,既然是與數據庫字段無關的類,那就不是PO了,因此咱們創建一個DTO數據傳輸類。關於常見的幾種對象個人解釋以下:json
PO:也就是咱們爲每一張數據庫表寫一個實體類併發
VO:對某個頁面或者展示層所須要的數據,封裝成一個實體類app
BO:業務對象
DTO:跟VO的概念有點混淆,也是至關於頁面須要的數據封裝成一個實體類
POJO:簡單的無規則java對象
在com.nnngu下創建dto包,而後創建Exposer類,這個類是秒殺時數據庫那邊處理的結果的對象
Exposer.java
文件裏面的內容請參照項目的源代碼。
定義一個基礎的異常,全部的子異常繼承這個異常SeckillException
package com.nnngu.exception; /** * 秒殺基礎的異常 * Created by nnngu */ public class SeckillException extends RuntimeException { // 代碼省略,請參照項目的源代碼 ... ... }
可能會出現秒殺關閉後被秒殺狀況,因此創建秒殺關閉異常SeckillCloseException
,須要繼承咱們前面寫的基礎異常
package com.nnngu.exception; /** * 秒殺已經關閉異常,當秒殺結束就會出現這個異常 * Created by nnngu */ public class SeckillCloseException extends SeckillException{ // 代碼省略,請參照項目的源代碼 ... ... }
定義重複秒殺異常RepeatKillException
package com.nnngu.exception; /** * 重複秒殺異常,不須要咱們手動去try catch * Created by nnngu */ public class RepeatKillException extends SeckillException{ // 代碼省略,請參照項目的源代碼 ... ... }
com.nnngu.service
包下建立SeckillServiceImpl.java
類,具體代碼請參照項目的源代碼。
在這裏咱們捕獲了運行時異常,這樣作的緣由就是Spring的事務默認發生了RuntimeException纔會回滾,能夠檢測出來的異常是不會致使事務的回滾的,這樣的目的就是你明知道這裏會發生異常,因此你必定要進行處理。若是隻是爲了讓編譯經過的話,那捕獲異常也沒意思,因此這裏要注意事務的回滾。
而後咱們還發現這裏存在硬編碼的現象,就是返回各類字符常量,例如秒殺成功,秒殺失敗等等,這些字符串是能夠被重複使用的,並且這樣維護起來也不方便,要處處去類裏面尋找這樣的字符串,全部咱們使用枚舉類來管理這樣狀態,在con.nnngu包下創建enums包,專門放置枚舉類,而後再創建SeckillStatEnum枚舉類。
枚舉類SeckillStatEnum.java
的代碼請參照項目的源代碼。
在resources/spring
下創建applicationContext-service.xml
文件,用來配置Service
層
applicationContext-service.xml
的代碼請參照項目的源代碼。
在這裏開啓了基於註解的事務,常見的事務操做有如下幾種方法:
在Spring早期版本中是使用ProxyFactoryBean+XMl方式來配置事務。
在Spring配置文件使用tx:advice+aop命名空間,好處就是一次配置永久生效,你無須去關心中間出的問題,不過出錯了你很難找出在哪裏出了問題。
序號 | 動態代理策略 | 不能被事務加強的方法 |
---|---|---|
1 | 基於JDK的動態代理 | 除了public 之外的全部方法,而且 public static 的方法也不能被加強 |
2 | 基於cglib的動態代理 | private ,static ,final 的方法 |
添加測試類SeckillServiceImplTest.java
,以下圖:
SeckillServiceImplTest.java
的代碼請參照項目的源代碼。
測試的方法:public void getSeckillList()
測試結果以下圖:
到此,咱們成功完成了Service層開發及測試。