<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
專案的核心組成部分圖解:
Service是專案中用於處理業務邏輯的,因為每種資料在做某種操作時,應該都有某些規則:
這些規則是用於保障資料的有效性、安全性的,使得資料可以隨著我們設定的規則而產生或發生變化!
在專案中,關於Service的開發,通常是先定義介面,再定義類實現此介面,介面名通常使用“資料型別Service”這樣格式的名稱,而實現類通常是在介面名的基礎上再新增Impl
字尾。
在《阿里巴巴Java開發手冊》中的規約:
【強制】對於 Service 和 DAO 類,基於 SOA 的理念,暴露出來的服務一定是介面,內部 的實現類用 Impl 的字尾與介面區別。
則在專案的根包下建立service.IAlbumService
介面:
public interface IAlbumService {}
然後,在根包下建立service.impl.AlbumServiceImpl
類,此類需要實現以上的IAlbumService
介面:
public class AlbumServiceImpl implements IAlbumService {}
檔案結構如下圖所示:
然後,需要在介面中設計“新增相簿”的抽象方法:
xx xx(xx);
關於抽象方法的名稱:可以完全自定義,當前業務是“新增相簿”,可以使用addNew
、add
等。
關於抽象方法的參數列:大多引數是由使用者端提交到控制器,再由控制器呼叫時傳遞過來的引數,另外,也可能是控制器處理出來的某些資料(例如Session中的當前登入使用者資訊),本次的引數應該包含:相簿名稱、相簿簡介、相簿的排序序號,可以將這3個資料封裝到自定義的DTO類中,並使用DTO型別作為引數。
關於抽象方法的返回值型別:僅以操作成功為前提來設計返回值型別,如果操作失敗,將丟擲異常。
在專案的根包下建立pojo.dto.AlbumAddNewDTO
類:
public class AlbumAddNewDTO { private String name; private String description; private Integer sort; }
並在IAlbumService
介面中新增抽象方法:
void addNew(AlbumAddNewDTO albumAddNewDTO);
然後,在AlbumServiceImpl
中實現此抽象方法:
@Slf4j @Service public class AlbumServiceImpl implements IAlbumService { @Autowired private AlbumMapper albumMapper; public AlbumServiceImpl() { log.debug("建立業務物件:AlbumServiceImpl"); } @Override public void addNew(AlbumAddNewDTO albumAddNewDTO) { // 【稍後再實現】應該保證此相簿的名稱是唯一的 // 建立Album型別的物件 // 呼叫BeanUtils.copyProperties(源物件, 目標物件)將引數的屬性值複製到新建立的Album物件中 // 呼叫albumMapper的int insert(Album album)方法插入相簿資料 } }
初步實現為:
package cn.tedu.csmall.product.service.impl; import cn.tedu.csmall.product.mapper.AlbumMapper; import cn.tedu.csmall.product.pojo.dto.AlbumAddNewDTO; import cn.tedu.csmall.product.pojo.entity.Album; import cn.tedu.csmall.product.service.IAlbumService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Slf4j @Service public class AlbumServiceImpl implements IAlbumService { @Autowired private AlbumMapper albumMapper; public AlbumServiceImpl() { log.debug("建立業務物件:AlbumServiceImpl"); } @Override public void addNew(AlbumAddNewDTO albumAddNewDTO) { // 【稍後再實現】應該保證此相簿的名稱是唯一的 // 建立Album型別的物件 Album album = new Album(); // 呼叫BeanUtils.copyProperties(源物件, 目標物件)將引數的屬性值複製到新建立的Album物件中 BeanUtils.copyProperties(albumAddNewDTO, album); // 呼叫albumMapper的int insert(Album album)方法插入相簿資料 albumMapper.insert(album); } }
完成後,在src/test/java
下的根包下建立service.AlbumServiceTests
測試類,並在類中編寫、執行測試方法:
package cn.tedu.csmall.product.service; import cn.tedu.csmall.product.pojo.dto.AlbumAddNewDTO; import cn.tedu.csmall.product.pojo.entity.Album; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @Slf4j @SpringBootTest public class AlbumServiceTests { @Autowired IAlbumService service; @Test void addNew() { AlbumAddNewDTO album = new AlbumAddNewDTO(); album.setName("測試資料9998"); album.setDescription("測試資料的簡介"); album.setSort(99); // 注意:sort值必須是[0, 255]之間的 service.addNew(album); log.debug("新增資料完成!"); } }
在具體實現過程中,還應該保證此次嘗試新增的相簿的名稱是唯一的!
可以通過查詢資料庫來得知嘗試新增的相簿的名稱是否已經被使用,需要執行的SQL語句可以是:
select id from pms_album where name=?
select count(*) from pms_album where name=?
可以選擇使用以上第2種查詢來檢驗相簿名稱是否已經被使用,則應該在
AlbumMapper.java
介面中新增:
int countByName(String name);
並在AlbumMapper.xml
中設定SQL:
<!-- int countByName(String name); --> <select id="countByName" resultType="int"> SELECT count(*) FROM pms_album WHERE name=#{name} </select>
完成後,應該在AlbumMapperTests.java
中編寫並執行測試:
@Test void countByName() { String name = "測試資料"; int count = mapper.countByName(name); log.debug("根據名稱【{}】統計完成,結果:{}", name, count); }
接下來,可以在Service的實現過程中進行檢查,例如:
String albumName = albumAddNewDTO.getName(); int count = albumMapper.countByName(albumName); if (count > 0) { // 相簿名稱已經被使用,將不允許新增此相簿,應該丟擲異常 } else { // 相簿名稱沒有被使用,可以將此相簿資料插入到資料庫中 }
提示:以上程式碼中,由於滿足if
條件時將丟擲異常,所以,可以不必使用else
,並且,在後續的程式設計中,當需要執行某些判斷時,應該優先根據“丟擲異常”或“終止當前方法的執行”來設計if
的條件!即:
if (count > 0) {
// 相簿名稱已經被使用,將不允許新增此相簿,應該丟擲異常 }
// 相簿名稱沒有被使用,可以將此相簿資料插入到資料庫中
具體實現為:
@Override public void addNew(AlbumAddNewDTO albumAddNewDTO) { // 應該保證此相簿的名稱是唯一的 String albumName = albumAddNewDTO.getName(); int count = albumMapper.countByName(albumName); if (count > 0) { throw new RuntimeException(); } // 建立Album型別的物件 Album album = new Album(); // 呼叫BeanUtils.copyProperties(源物件, 目標物件)將引數的屬性值複製到新建立的Album物件中 BeanUtils.copyProperties(albumAddNewDTO, album); // 呼叫albumMapper的int insert(Album album)方法插入相簿資料 albumMapper.insert(album); }
為了避免測試時因為相簿名稱衝突出現異常而導致測試失敗,應該在測試時捕獲所丟擲的異常,例如:
@Test void addNew() { AlbumAddNewDTO album = new AlbumAddNewDTO(); album.setName("測試資料9998"); album.setDescription("測試資料的簡介"); album.setSort(99); // 注意:sort值必須是[0, 255]之間的 try { service.addNew(album); log.debug("新增資料完成!"); } catch (RuntimeException e) { log.debug("新增資料失敗!名稱已經被佔用!"); } }
關於以上實現過程中丟擲的異常,使用的是RuntimeException
,是不合適的!因為程式出現RuntimeException
的原因有很多,例如空指標異常、陣列下標越界異常、型別轉換異常,都屬於RuntimeException
,如果“相簿名稱被佔用”時丟擲RuntimeException
,則此方法的呼叫者很難區分出現異常的真正原因!
通常,建議自定義異常,並且,當視為失敗時,丟擲此自定義異常的物件!
則在根包下建立ex.ServiceException
類,繼承自RuntimeException
:
public class ServiceException extends RuntimeException {}
提示:本次自定義的異常應該繼承自RuntimeException。
然後,在AlbumServiceImpl
中新增相簿時,如果相簿名稱被使用,則丟擲ServiceException
型別的異常:
if (count > 0) { throw new ServiceException(); }
並且,在測試中,捕獲的異常也改為ServiceException
:
try { service.addNew(album); log.debug("新增資料完成!"); } catch (ServiceException e) { log.debug("新增資料失敗!名稱已經被佔用!"); }
到此這篇關於Spring Service功能作用詳細講解的文章就介紹到這了,更多相關Spring Service內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45