我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring Service功能作用详细讲解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring Service功能作用详细讲解

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

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

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 {}

文件结构如下图所示:

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

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);
    }
}

完成后,在class="lazy" data-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内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring Service功能作用详细讲解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring Service功能作用详细讲解

service层测试较简单,目前大多数测试主要是针对public方法进行的。依据测试方法划分,可以分为两种:基于mock的隔离测试和基于dbunit的普通测试
2022-12-08

Spring Service功能有什么作用

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

Spring IOC容器使用详细讲解

IOC-Inversion of Control,即控制反转。它不是什么技术,而是一种设计思想。这篇文章将为大家介绍一下Spring控制反转IOC的原理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2022-12-21

Spring@ComponentScan注解使用案例详细讲解

@ComponentScan注解的作用可以简述为:将项目中所有被@Component注解直接或者间接标记的类---->组装成BeanDefinition---->然后以key=beanName,value=BeanDefinition的形式存储,为后续生成bean对象做准备
2023-03-10

Spring 4.0新功能:@Conditional注解详细介绍

前言最近在学习spring,抽空会将学习的知识总结下面,本文我们会接触spring 4的新功能:@Conditional注解。在之前的spring版本中,你处理conditions只有以下两个方法: 在3.1版本之前,你需要使用sprin
2023-05-31

JavaScriptPromise与async/await作用详细讲解

Promise是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果
2023-01-14

Fragment通过FragmentManager实现通信功能详细讲解

这篇文章主要介绍了Fragment通过FragmentManager实现通信功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-01-13

详细阐述ERP含义、功能及作用

今天我们来聊聊ERP。因为信息时代,ERP已是企业管理大势所趋,很多公司决定要上,但老板其实并没有真正了解过ERP到底是什么,看到别的企业从中获益,就觉得不能落后,赶紧跟风上套系统,等到发现与企业实际相差较远,砸进去的真金白银却再也收不回
2023-06-05

Spring Cloud Gateway 服务网关的部署与使用详细讲解

这篇文章主要介绍了Spring Cloud Gateway 服务网关的部署与使用详细介绍,本文给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-05-14

微信小程序JSON配置文件详细讲解作用

JSON是一种数据格式,在实际开发中,JSON总是以配置文件的形式出现。小程序项目中也不例外:通过不同的Json配置文件,可以对小程序项目进行不同级别的配置
2022-11-13

win8.1操作系统关闭uac对话框但不关闭uac功能的方法图文详细讲解

win8.1的uac虽然有时候很烦,但完全关闭uac还可能导致Metro许多功能不能使用,而且出于安全考虑小编劝大家还是不要完全关闭,那有没有关闭uac对话框而不关闭uac功能的方法呢? 操作步骤1. 下载并安装微软官方工具 Microso
2022-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录