欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Service功能作用詳細(xì)講解

 更新時(shí)間:2022年12月08日 16:41:10   作者:居然天上樓  
service層測(cè)試較簡單,目前大多數(shù)測(cè)試主要是針對(duì)public方法進(jìn)行的。依據(jù)測(cè)試方法劃分,可以分為兩種:基于mock的隔離測(cè)試和基于dbunit的普通測(cè)試

1. Spring項(xiàng)目中的核心組成部分

項(xiàng)目的核心組成部分圖解:

2. Spring項(xiàng)目中的Service

2.1 Service的功能作用

Service是項(xiàng)目中用于處理業(yè)務(wù)邏輯的,因?yàn)槊糠N數(shù)據(jù)在做某種操作時(shí),應(yīng)該都有某些規(guī)則:

  • 例如用戶嘗試登錄時(shí),涉及的規(guī)則可能包含:用戶名對(duì)應(yīng)的用戶信息必須存在、提交的密碼必須與數(shù)據(jù)庫中存儲(chǔ)的密碼是匹配的……
  • 例如用戶嘗試修改密碼時(shí),涉及的規(guī)則可能包含:當(dāng)前用戶賬號(hào)必須存在且處于正常狀態(tài)、提交的原密碼必須與數(shù)據(jù)庫中存儲(chǔ)的密碼是匹配的……
  • 例如用戶嘗試注冊(cè)時(shí),涉及的規(guī)則可能包含:提交的用戶名必須在數(shù)據(jù)庫不存在,提交的手機(jī)號(hào)碼必須在數(shù)據(jù)庫中不存在,提交的電子郵箱必須在數(shù)據(jù)庫中不存在……

這些規(guī)則是用于保障數(shù)據(jù)的有效性、安全性的,使得數(shù)據(jù)可以隨著我們?cè)O(shè)定的規(guī)則而產(chǎn)生或發(fā)生變化!

在項(xiàng)目中,關(guān)于Service的開發(fā),通常是先定義接口,再定義類實(shí)現(xiàn)此接口,接口名通常使用“數(shù)據(jù)類型Service”這樣格式的名稱,而實(shí)現(xiàn)類通常是在接口名的基礎(chǔ)上再添加Impl后綴。

在《阿里巴巴Java開發(fā)手冊(cè)》中的規(guī)約:

【強(qiáng)制】對(duì)于 Service 和 DAO 類,基于 SOA 的理念,暴露出來的服務(wù)一定是接口,內(nèi)部 的實(shí)現(xiàn)類用 Impl 的后綴與接口區(qū)別。

2.2 Service的實(shí)現(xiàn)

則在項(xiàng)目的根包下創(chuàng)建service.IAlbumService接口:

public interface IAlbumService {}

然后,在根包下創(chuàng)建service.impl.AlbumServiceImpl類,此類需要實(shí)現(xiàn)以上的IAlbumService接口:

public class AlbumServiceImpl implements IAlbumService {}

文件結(jié)構(gòu)如下圖所示:

然后,需要在接口中設(shè)計(jì)“添加相冊(cè)”的抽象方法:

xx xx(xx);

關(guān)于抽象方法的名稱:可以完全自定義,當(dāng)前業(yè)務(wù)是“添加相冊(cè)”,可以使用addNew、add等。

關(guān)于抽象方法的參數(shù)列表:大多參數(shù)是由客戶端提交到控制器,再由控制器調(diào)用時(shí)傳遞過來的參數(shù),另外,也可能是控制器處理出來的某些數(shù)據(jù)(例如Session中的當(dāng)前登錄用戶信息),本次的參數(shù)應(yīng)該包含:相冊(cè)名稱、相冊(cè)簡介、相冊(cè)的排序序號(hào),可以將這3個(gè)數(shù)據(jù)封裝到自定義的DTO類中,并使用DTO類型作為參數(shù)。

關(guān)于抽象方法的返回值類型:僅以操作成功為前提來設(shè)計(jì)返回值類型,如果操作失敗,將拋出異常。

在項(xiàng)目的根包下創(chuàng)建pojo.dto.AlbumAddNewDTO類:

public class AlbumAddNewDTO {
    private String name;
    private String description;
    private Integer sort;
}

并在IAlbumService接口中添加抽象方法:

void addNew(AlbumAddNewDTO albumAddNewDTO);

然后,在AlbumServiceImpl中實(shí)現(xiàn)此抽象方法:

@Slf4j
@Service
public class AlbumServiceImpl implements IAlbumService  {
    @Autowired
    private AlbumMapper albumMapper;
    public AlbumServiceImpl() {
        log.debug("創(chuàng)建業(yè)務(wù)對(duì)象:AlbumServiceImpl");
    }
    @Override
    public void addNew(AlbumAddNewDTO albumAddNewDTO) {
        // 【稍后再實(shí)現(xiàn)】應(yīng)該保證此相冊(cè)的名稱是唯一的
        // 創(chuàng)建Album類型的對(duì)象
        // 調(diào)用BeanUtils.copyProperties(源對(duì)象, 目標(biāo)對(duì)象)將參數(shù)的屬性值復(fù)制到新創(chuàng)建的Album對(duì)象中
		// 調(diào)用albumMapper的int insert(Album album)方法插入相冊(cè)數(shù)據(jù)
    }
}

初步實(shí)現(xiàn)為:

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("創(chuàng)建業(yè)務(wù)對(duì)象:AlbumServiceImpl");
    }
    @Override
    public void addNew(AlbumAddNewDTO albumAddNewDTO) {
        // 【稍后再實(shí)現(xiàn)】應(yīng)該保證此相冊(cè)的名稱是唯一的
        // 創(chuàng)建Album類型的對(duì)象
        Album album = new Album();
        // 調(diào)用BeanUtils.copyProperties(源對(duì)象, 目標(biāo)對(duì)象)將參數(shù)的屬性值復(fù)制到新創(chuàng)建的Album對(duì)象中
        BeanUtils.copyProperties(albumAddNewDTO, album);
        // 調(diào)用albumMapper的int insert(Album album)方法插入相冊(cè)數(shù)據(jù)
        albumMapper.insert(album);
    }
}

完成后,在src/test/java下的根包下創(chuàng)建service.AlbumServiceTests測(cè)試類,并在類中編寫、執(zhí)行測(cè)試方法:

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("測(cè)試數(shù)據(jù)9998");
        album.setDescription("測(cè)試數(shù)據(jù)的簡介");
        album.setSort(99); // 注意:sort值必須是[0, 255]之間的
        service.addNew(album);
        log.debug("添加數(shù)據(jù)完成!");
    }
}

在具體實(shí)現(xiàn)過程中,還應(yīng)該保證此次嘗試添加的相冊(cè)的名稱是唯一的!

可以通過查詢數(shù)據(jù)庫來得知嘗試添加的相冊(cè)的名稱是否已經(jīng)被使用,需要執(zhí)行的SQL語句可以是:

select id from pms_album where name=?
select count(*) from pms_album where name=?

可以選擇使用以上第2種查詢來檢驗(yàn)相冊(cè)名稱是否已經(jīng)被使用,則應(yīng)該在

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>

完成后,應(yīng)該在AlbumMapperTests.java中編寫并執(zhí)行測(cè)試:

@Test
void countByName() {
    String name = "測(cè)試數(shù)據(jù)";
    int count = mapper.countByName(name);
    log.debug("根據(jù)名稱【{}】統(tǒng)計(jì)完成,結(jié)果:{}", name, count);
}

接下來,可以在Service的實(shí)現(xiàn)過程中進(jìn)行檢查,例如:

String albumName = albumAddNewDTO.getName();
int count = albumMapper.countByName(albumName);
if (count > 0) {
    // 相冊(cè)名稱已經(jīng)被使用,將不允許添加此相冊(cè),應(yīng)該拋出異常
} else {
    // 相冊(cè)名稱沒有被使用,可以將此相冊(cè)數(shù)據(jù)插入到數(shù)據(jù)庫中
}

提示:以上代碼中,由于滿足if條件時(shí)將拋出異常,所以,可以不必使用else,并且,在后續(xù)的編程中,當(dāng)需要執(zhí)行某些判斷時(shí),應(yīng)該優(yōu)先根據(jù)“拋出異常”或“終止當(dāng)前方法的執(zhí)行”來設(shè)計(jì)if的條件!即:

if (count > 0) {

// 相冊(cè)名稱已經(jīng)被使用,將不允許添加此相冊(cè),應(yīng)該拋出異常 }

// 相冊(cè)名稱沒有被使用,可以將此相冊(cè)數(shù)據(jù)插入到數(shù)據(jù)庫中

具體實(shí)現(xiàn)為:

@Override
public void addNew(AlbumAddNewDTO albumAddNewDTO) {
    // 應(yīng)該保證此相冊(cè)的名稱是唯一的
    String albumName = albumAddNewDTO.getName();
    int count = albumMapper.countByName(albumName);
    if (count > 0) {
        throw new RuntimeException();
    }
    // 創(chuàng)建Album類型的對(duì)象
    Album album = new Album();
    // 調(diào)用BeanUtils.copyProperties(源對(duì)象, 目標(biāo)對(duì)象)將參數(shù)的屬性值復(fù)制到新創(chuàng)建的Album對(duì)象中
    BeanUtils.copyProperties(albumAddNewDTO, album);
    // 調(diào)用albumMapper的int insert(Album album)方法插入相冊(cè)數(shù)據(jù)
    albumMapper.insert(album);
}

為了避免測(cè)試時(shí)因?yàn)橄鄡?cè)名稱沖突出現(xiàn)異常而導(dǎo)致測(cè)試失敗,應(yīng)該在測(cè)試時(shí)捕獲所拋出的異常,例如:

@Test
void addNew() {
    AlbumAddNewDTO album = new AlbumAddNewDTO();
    album.setName("測(cè)試數(shù)據(jù)9998");
    album.setDescription("測(cè)試數(shù)據(jù)的簡介");
    album.setSort(99); // 注意:sort值必須是[0, 255]之間的
    try {
        service.addNew(album);
        log.debug("添加數(shù)據(jù)完成!");
    } catch (RuntimeException e) {
        log.debug("添加數(shù)據(jù)失??!名稱已經(jīng)被占用!");
    }
}

關(guān)于以上實(shí)現(xiàn)過程中拋出的異常,使用的是RuntimeException,是不合適的!因?yàn)槌绦虺霈F(xiàn)RuntimeException的原因有很多,例如空指針異常、數(shù)組下標(biāo)越界異常、類型轉(zhuǎn)換異常,都屬于RuntimeException,如果“相冊(cè)名稱被占用”時(shí)拋出RuntimeException,則此方法的調(diào)用者很難區(qū)分出現(xiàn)異常的真正原因!

通常,建議自定義異常,并且,當(dāng)視為失敗時(shí),拋出此自定義異常的對(duì)象!

則在根包下創(chuàng)建ex.ServiceException類,繼承自RuntimeException

public class ServiceException extends RuntimeException {}

提示:本次自定義的異常應(yīng)該繼承自RuntimeException。

然后,在AlbumServiceImpl中添加相冊(cè)時(shí),如果相冊(cè)名稱被使用,則拋出ServiceException類型的異常:

if (count > 0) {
    throw new ServiceException();
}

并且,在測(cè)試中,捕獲的異常也改為ServiceException

try {
    service.addNew(album);
    log.debug("添加數(shù)據(jù)完成!");
} catch (ServiceException e) {
    log.debug("添加數(shù)據(jù)失??!名稱已經(jīng)被占用!");
}

到此這篇關(guān)于Spring Service功能作用詳細(xì)講解的文章就介紹到這了,更多相關(guān)Spring Service內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java基礎(chǔ)之詳解基本數(shù)據(jù)類型的使用

    Java基礎(chǔ)之詳解基本數(shù)據(jù)類型的使用

    今天給大家?guī)淼氖顷P(guān)于Java基礎(chǔ)的相關(guān)知識(shí),文章圍繞著基本數(shù)據(jù)類型的使用展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java實(shí)現(xiàn)雙端鏈表LinkedList

    Java實(shí)現(xiàn)雙端鏈表LinkedList

    本文主要介紹了Java實(shí)現(xiàn)雙端鏈表LinkedList,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • SpringMvc框架的簡介與執(zhí)行流程詳解

    SpringMvc框架的簡介與執(zhí)行流程詳解

    MVC是一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到一個(gè)組件里面,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫業(yè)務(wù)邏輯,MVC分層有助于管理和架構(gòu)復(fù)雜的應(yīng)用程序
    2021-06-06
  • SpringCache之 @CachePut的使用

    SpringCache之 @CachePut的使用

    這篇文章主要介紹了SpringCache之 @CachePut的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • SpringMVC+Mybatis實(shí)現(xiàn)的Mysql分頁數(shù)據(jù)查詢的示例

    SpringMVC+Mybatis實(shí)現(xiàn)的Mysql分頁數(shù)據(jù)查詢的示例

    本篇文章主要介紹了SpringMVC+Mybatis實(shí)現(xiàn)的Mysql分頁數(shù)據(jù)查詢的示例,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù)

    idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù)

    在開發(fā)的時(shí)候我們通常在本地代碼上debug程序,但是服務(wù)部署到了開發(fā)環(huán)境服務(wù)器上,如何遠(yuǎn)程調(diào)試,本文主要介紹了idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Java動(dòng)態(tài)代理語法Proxy類原理詳解

    Java動(dòng)態(tài)代理語法Proxy類原理詳解

    這篇文章主要介紹了Java動(dòng)態(tài)代理語法Proxy類原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • spring boot裝載自定義yml文件

    spring boot裝載自定義yml文件

    這篇文章主要為大家詳細(xì)介紹了spring boot裝載自定義yml文件的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Java實(shí)現(xiàn)求數(shù)組最長子序列算法示例

    Java實(shí)現(xiàn)求數(shù)組最長子序列算法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)求數(shù)組最長子序列算法,涉及java針對(duì)數(shù)組的遞歸遍歷、判斷相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • 如何把本地idea上的項(xiàng)目上傳到github上(推薦)

    如何把本地idea上的項(xiàng)目上傳到github上(推薦)

    這篇文章主要介紹了如何把本地idea上的項(xiàng)目上傳到github上,本文通過圖文的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評(píng)論