Spring Service功能有什么作用

发布时间:2022-12-09 09:51:24 作者:iii
来源:亿速云 阅读:119

本文小编为大家详细介绍“Spring Service功能有什么作用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring Service功能有什么作用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

1. Spring项目中的核心组成部分

项目的核心组成部分图解:

Spring Service功能有什么作用

2. Spring项目中的Service

2.1 Service的功能作用

Service是项目中用于处理业务逻辑的,因为每种数据在做某种操作时,应该都有某些规则:

这些规则是用于保障数据的有效性、安全性的,使得数据可以随着我们设定的规则而产生或发生变化!

在项目中,关于Service的开发,通常是先定义接口,再定义类实现此接口,接口名通常使用“数据类型Service”这样格式的名称,而实现类通常是在接口名的基础上再添加Impl后缀。

在《阿里巴巴Java开发手册》中的规约:

【强制】对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部 的实现类用 Impl 的后缀与接口区别。

2.2 Service的实现

则在项目的根包下创建service.IAlbumService接口:

public interface IAlbumService {}

然后,在根包下创建service.impl.AlbumServiceImpl类,此类需要实现以上的IAlbumService接口:

public class AlbumServiceImpl implements IAlbumService {}

文件结构如下图所示:

Spring Service功能有什么作用

然后,需要在接口中设计“添加相册”的抽象方法:

xx xx(xx);

关于抽象方法的名称:可以完全自定义,当前业务是“添加相册”,可以使用addNewadd等。

关于抽象方法的参数列表:大多参数是由客户端提交到控制器,再由控制器调用时传递过来的参数,另外,也可能是控制器处理出来的某些数据(例如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功能有什么作用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. Spring中IoC的详细介绍
  2. 基于Spring的应用配置怎么迁移至阿里云应用配置管理ACM

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring service

上一篇:Python中的if __name__ == __main__是什么

下一篇:Vue如何实现动态渲染input输入框

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》