你真的了解Service吗

Service:

业务,它是Mapper的调用者,也是被Controller调用的组件。

Service的主要作用是设计业务流程、业务逻辑,以保障数据的有效性、安全性、完整性。

Service在代码中的表现通常包含接口与实现类。

Service的方法声明原则:

返回值类型:仅以操作成功为前提来设计 失败将通过抛出异常来表示 方法名称:自定义 参数列表:通常根据客户端提交的数据来设计,对于相关的数据,可以封装 添加相册--Service 业务规则:相册名称必须唯一。

需要实现“检查相册名称是否被占用”的检查功能,可以通过数据库查询来实现,相关的SQL语句大致是:

select * from pms_album where name=?

或者:

select count(*) from pms_album where name=? 在AlbumMapper.java接口中添加新的抽象方法:

int countByName(String name); 在AlbumMapper.xml中配置以上抽象方法映射的SQL语句:

<!-- int countByName(String name); -->

在AlbumMapperTests中编写并执行测试:

在项目的根包下创建pojo.dto.AlbumAddNewDTO类,用于封装客户端提交的数据(客户端会把数据提交到Controller,而Controller会使用这些数据来调用Service的方法):

@Data
public class AlbumAddNewDTO implements Serializable {
    private String name;
    private String description;
    private Integer sort;
}

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

public interface IAlbumService {
    void addNew(AlbumAddNewDTO albumAddNewDTO);
}

在项目的根包下创建service.impl.AlbumServiceImpl类,实现以上接口:

@Service public class AlbumServiceImpl implements IAlbumService {

@Autowired
private AlbumMapper albumMapper;

public void addNew(AlbumAddNewDTO albumAddNewDTO) {
    // 调用参数对象的getName()得到尝试添加的相册的名称
    // 调用Mapper对象的countByName()执行统计查询
    // 判断统计结果是否大于0
    // -- 是:名称被占用,抛出异常,例如:throw new RuntimeException()
    
    // 创建Album对象
    // 调用BeanUtils.copyProperties(源,目标)将参数对象中的属性复制到Album对象中
    // 调用Mapper对象的insert()执行插入相册数据
}

}

完成后,在src/test/java的根包下创建service.AlbumServiceTests测试类,编写并执行测试:

@Slf4j

@SpringBootTest

public class AlbumServiceTests {

@Autowired
IAlbumService service;

@Test
void xxx() {
    
}

}

关于异常

为了避免捕获并处理异常时产生歧义,在Service的实现过程中,如果需要通过抛出异常来表示某种“失败”,应该抛出自定义异常!

在项目的根包下创建ex.ServiceException类,继承自RuntimeException:

package cn.tedu.csmall.product.ex;

public class ServiceException extends RuntimeException { }

关于继承自RuntimeException,主要原因有:

第1点:因为Spring MVC框架有统一处理异常的机制,所以,Service方法始终抛出异常,Controller方法也始终抛出异常,则没有必要通过throws关键字声明抛出,如果继承的父级异常不是RuntimeException,必须在各Service方法和Controller方法上都声明抛出 第2点:Spring JDBC处理事务时,只会根据RuntimeException执行回滚 添加相册-Controller 首先,需要在pom.xml中添加spring-boot-starter-web依赖项,目前,项目中已经添加spring-boot-starter依赖项,而spring-boot-starter-web包含此依赖项,所以,只需要将现有的spring-boot-starter改为spring-boot-starter-web即可:

<!-- Spring Boot支持Spring MVC的依赖项 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

在项目的根包下创建controller.AlbumController类,添加@RestController,表示此类是一个响应数据的控制器类,并在类中自动装配IAlbumService接口类型的对象,在类中添加方法处理“添加相册”的请求:

@RestController

public class AlbumController {

@Autowired
private IAlbumService albumService;

// http://localhost:8080/album/add-new?name=test001&description=hahahaha&sort=100
// http://localhost:8080/album/add-new
@RequestMapping("/album/add-new")
public int addNew(AlbumAddNewDTO albumAddNewDTO) {
    try {
        albumService.addNew(albumAddNewDTO);
        return 1;
    } catch (ServiceException e) {
        return 0;
    }
}

 }

关于以上处理请求的方法:

返回值类型:根据期望响应到客户端的信息类型来设计,如果返回值类型是自定义的数据类型,则响应时会由Spring MVC框架自动转换成JSON格式的字符串

方法名称:自定义 参数列表: 关于响应结果类型 在项目的根包下创建web.JsonResult类,在类中声明需要响应到客户端的数据对应的属性:

@Data public class JsonResult implements Serializable {

private Integer state;
private String message;

然后,在控制器类中,在处理请求的方法上,将返回值类型改为以上类型,并在方法中返回此类型的对象:

@RequestMapping("/album/add-new")
public JsonResult addNew(AlbumAddNewDTO albumAddNewDTO) {
    try {
        albumService.addNew(albumAddNewDTO);
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(1);
        jsonResult.setMessage("添加相册成功!");
        return jsonResult;
    } catch (ServiceException e) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(0);
        jsonResult.setMessage("添加相册失败,相册名称已经被占用!");
        return jsonResult;
    }
}

完成后,重启项目,再次访问,可以看到服务器端响应了JSON格式的结果

以上代码中,使用了较多的代码来完成“创建对象、为属性赋值”,非常臃肿,可以考虑简化:

在JsonResult中添加全参数构造方法

在JsonResult中设计链式的Setter

或直接在类上添加@Accessors(chain = true)

在JsonResult中添加静态方法

例如,在JsonResult中添加静态方法:

public static JsonResult ok() {
    JsonResult jsonResult = new JsonResult();
    jsonResult.state = 1;
    return jsonResult;
}

public static JsonResult fail(Integer state, String message) {
    JsonResult jsonResult = new JsonResult();
    jsonResult.state = state;
    jsonResult.message = message;
    return jsonResult;
}

则控制器类中处理请求的方法可以调整为:

@RequestMapping("/album/add-new")
public JsonResult addNew(AlbumAddNewDTO albumAddNewDTO) {
    try {
        albumService.addNew(albumAddNewDTO);
        return JsonResult.ok();
    } catch (ServiceException e) {
        return JsonResult.fail(0, "添加相册失败,相册名称已经被占用!");
    }
}

根据ID删除相册--Mapper 实现此功能需要执行的SQL语句大致是:

delete from pms_album where id=?

根据ID删除相册--Service 在IAlbumService中添加抽象方法:

void delete(Long id);

在AlbumServiceImpl中实现以上抽象方法:

public void delete(Long id) { // 调用Mapper对象的getStandardById()执行查询 // 判断查询结果是否为null // 是:数据不存在,抛出异常

// 调用Mapper对象的deleteById()方法执行删除

 }

在AlbumServiceTests中编写并执行测试:

根据ID删相册--Controller 在AlbumController中添加处理此请求的方法:

// http://localhost:8080/album/delete?id=1
@RequestMapping("/album/delete")
public JsonResult delete(Long id) {
    try {
        albumService.delete(id);
        return JsonResult.ok();
    } catch (ServiceException e) {
        return JsonResult.fail(0, "删除相册失败,尝试删除的相册数据不存在!");
    }
}

希望对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值