前端卷Java系列之一个接口的诞生

56 阅读6分钟
  1. 摘要

本文以若依框架为例,阐述使用Java后端的一系列技术实现一个后端接口,为什么要基于若依框架,因为还是想从真实工程的角度描述Java后端实现接口的流程,如果仅仅是实现一个简单的接口,我相信你可以用很多技术实现,比如用原生Node的Http模块或者使用Express、Koa等前端框架。虽然网上对若依框架褒贬不一样,但是学东西还是要用人之长的眼光去看待。标题名称虽然是前端卷Java,并不代表是Java小白系列文章,因为笔者工作偏向前端,所以标题是前端卷Java,不过还是需要一些Java基础的,另外这是一篇Java技术普及的文章,揭示真实工程中实现一个接口到底用到了哪些Java技术,对于某个技术的深入研究,笔者后续会慢慢拆解。

  1. 目标聚焦

实现一个根据Id查询一条问候语的接口,熟悉接口开发流程和使用的框架,接口如下:

560928daa2f6d92e7d32fe898fbfbc86.png

这是一个GET接口,通过在url上拼接查询参数id向后端传递参数,以便查询这条id对应的问候语,没错就是这么简单,我们的重点是熟悉基本的开发流程和使用的框架,因此例子越简单越好。

  1. 具体实现

先看下这个接口在代码中的实现如下所示:

@RestController
@RequestMapping("/system/greeting")
public class GreetingController {
    @Resource
    private GreetingService greetingService;
    @GetMapping("/getGreetingById")
    public CommonResult<GreetingDO> getGreetingById(@RequestParam("id") Long id) {
        GreetingDO greeting = greetingService.getGreetingById(id);
        return success(greeting);
    }}

这里牵扯到很多注解(@开头的),我们先不看,最核心的代码是第11句,调用了greetingService的getGreetingById方法查询得到了一条问候语。greetingService是一个GreetingService的实例(对象),这里为什么没有new呢,为什么没有创建这个对象,这是因为Spring框架帮我们自动创建了一个,得益于@Resource这个注解,Spring有个魔法叫依赖注入,就是你需要什么样的对象,你不用自己创建,你就告诉Spring,Spring帮你创建。不过这有个前提,就是你要告诉Spring这个对象是什么样子的,也就是GreetingService。

GreetingService如下:

public interface GreetingService {
    GreetingDO  getGreetingById(Long id);
}

这是一个接口,类似TypeScript中的接口一样,定义了这个对象的形状,但这个仅仅是对象的形状,就像是一个汽车的结构图一样,缺少具体的实现,我们需要一个具体的模子,让Spring用这个模子,造一个汽车出来,这个具体的模子是GreetingServiceImpl,它实现了GreetingService这个接口。

GreetingServiceImpl如下:

@Service
public class GreetingServiceImpl implements GreetingService{
    @Resource
    private GreetingMapper greetingMapper;
    @Override
    public GreetingDO getGreetingById(Long id) {
        return greetingMapper.selectById(id);
    }
}

GreetingServiceImpl这个类中最关键的是第5句使用了greetingMapper调用了selectById方法查询问候语,那greetingMapper是从哪里来的呢,没错,通过第4句的声明,Spring帮我们创建造出来的,同样我们也需要一个GreetingMapper的模子告诉Spring照着这个模子造一个greetingMapper实例(对象)出来。

GreetingMapper如下所示:

@Mapper
public interface GreetingMapper extends BaseMapperX<GreetingDO> {
}

懵了,为什么没有selectById这个方法,聪明的你肯定发现了extends(继承),这个方法是从BaseMapperX继承过来,BaseMapperX是若依框架封装的,它在MybatisPlus的BaseMapper又添加了一些方法。MyBatis-Plus是MyBatis的增强版,MyBatis是一个Java持久层框架,意思就是它帮你把内存中处理操作的对象放到数据库中保存起来或者从数据库中查询到你需要的数据放到内存中来,也就是我们在数据库中保存的问候语数据。至此,这个方法基本结束。

  1. 整体流程

我把步骤3的流程绘制成了如下的UML交互图,以便更清晰的描述整个接口实现的流程。

从这个图可以看出,这是一个典型的三层架构,分为Controller层、Service层、DAL层

Controller层(控制层):接受客户端的请求,调用Service层的方法的得到结果,将结果返回给客户端。

Service层(业务逻辑层):接受控制层的传参,处理业务逻辑,调用DAL层的方法,将结果返回给Controller层。

DAL层(数据访问层或叫Mapper):接受Service层的传参,调用JDBC完成数据库的数据操作,将结果返回给Service层。

上图中还有一些模块没有介绍

GreetingSaveReqVO:问候语请求实体对象,用于接受客户端传递过来的问候语实体,就是一个Java类。

GreetingDO: 问候语数据对象,是和数据库表中的字段一一对象的Java原生对象,有些规范中叫PO,也是一个Java类。

BaseDO:若依框架封装的一个DO,包含了一个公用的字段比如createTime创建时间、updateTime更新时间、creator创建人、updater更新人、deleted逻辑删除字段。

关于这些O的概念,我总结了一下:

全称简称中文用途是否暴漏给前端是否映射数据库
Plain Old Java ObjectPOJO简单Java对象无特殊限制的普通Java类
Persistent ObjectPO持久化对象与数据库表一一对象,通常与ORM映射
View ObjectVO视图对象展示层数据,用于向前端返回数据
Business ObjectBO业务对象封装核心业务逻辑的对象
Data Transfer ObjectDTO数据传输对象用于不同层或服务之间传递数据
Data Access ObjectDAO数据访问对象与数据库交互的接口或类,负责持久化操作

POJO:泛指Java中的对象,其他对象如PO、BO、DTO等都可以是POJO

PO:与数据库表一一映射,通常使用JPA注解或MyBatis注解

DO: 数据对象,业务对象,领域模型,用于业务处理,有些项目会当PO使用。

VO: 用于返回给前端展示的数据结构,可以包含多个对象的组合数据

BO: 封装业务逻辑的对象,通常用于Service层内部处理

DTO:用于接口参数传递和跨层数据传输,如Controller接受前端传递过来对象,或者微服务之间调用传参

DAO:用于操作数据库的接口或类。

为了更清楚地展现整体流程,方便理解,我绘制了时序图如下所示:

上面这个图应该清晰地展现了getGreetingById接口牵扯到的各个模块(类)之间的调用流程。

人生是一个漫长而艰辛的接力赛,有时领先,有时落后,但是你只要在路上,就有机会,及时行乐,就像是一支兴奋剂,它能够点燃幸福的华彩,也能加速生命的衰败,所以人还是要适当的有一些节制。