Springboot 三层架构(Controller(控制层)、Dao(数据访问层)、Service(业务逻辑层))


开发Stringboot一个功能的流程

开发流程:
查看页面原型明确需求(一般为项目经理提供) >> 阅读接口文档 >> 思路分析 >> 接口开发 >> 接口测试 >> 前后端联调
在这里插入图片描述

Springboot 三层架构

概念:当有大量的对数据的逻辑处理时,会发现代码会有大量的重复性,且非常的繁琐,这时可以使用三层架构去将代码进行拆分成三个架构(Controller(控制器)、Service(服务)、Dao(数据访问)。
软件设计原则:高内聚底耦合,那什么高内聚底耦合呢?
内聚:软件中各个功能模块内部的功能联系。
耦合:衡量软件中各个 层 / 模块 之间的依赖、关联的程度。
为什么要创建三层架构:在实际开发中要如何满足高内聚低耦合呢?这时就可以用到了Springboot中的三层架构,可以有效的避免耦合,而提高内聚,所以在开发Springboot时我们一般都会使用三层架构形式去创建项目。
注意:在后期的开发中我们一般会是一个对象负责一个作用,尽量遵守“单一职责原则”。

一、Controller(控制层)

Controller(控制层)的作用

Controller(控制层、又称:表现层)一般是用来接收前端发来的请求,并对此请求进行判断需要调用Service(业务逻辑层)中的那个实体类方法,调用完之后Service会返回处理完之后的数据给Controller(控制层、又称:表现层),此时它在返回数据给前端做出响应,(且返回的类型为JSON类型,也就是满足HTTP协议的返回值,一般会创建一个Result类进行规范返回类型)

1、如何创建Controller(控制层)

  1. 创建Controller类并标注注解@RestController

@RestController此注解是在运行代码时,容器会提供该类型的bean对象,并赋值改变变量——简单来说就是将调用容器中的变量

//实例:
@RestController
public class DeptController {

}
  1. 再次类中创建一个属性用来连接Service并使用@Autowired注解进行标注

@Autowired此注解是用来调用Service在Bean容器中所存储的数据。

//实例:
@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;
}
  1. 创建一个返回值为Result的方法,并使用@RequestMapping注解进行标注,并给此属性赋值

@RequestMapping此注解是设置指定的访问的URL,且返回值必须是满足HTTP协议格式的数据,一般会设定为JSON格式。
Result是自己定义的一个类,而此类中是严格按照HTTP协议来进新编写的。

//实例:
@RestController
public class DeptController {
    @Autowired
    private DeptService deptService;
    @RequestMapping("/depts")
    public Result list(){
    }
}
//Result代码实例:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Integer code;//响应码,1 代表成功; 0 代表失败
    private String msg;  //响应信息 描述字符串
    private Object data; //返回的数据

    //增删改 成功响应
    public static Result success(){
        return new Result(1,"success",null);
    }
    //查询 成功响应
    public static Result success(Object data){
        return new Result(1,"success",data);
    }
    //失败响应
    public static Result error(String msg){
        return new Result(0,msg,null);
    }
}

  1. 在上面的方法中去调用Service中的方法来去返回值

当客户端进行访问到此方法时,表明是需要返回数据或者对数据的修改等,所以再次方法中就要去调用Service中可以完成此要求的对应的方法。
(注意:在Service中可以完成此操作的方法也是需要自己在Service层去创建,因为Controller层只做接收前端请求和响应完成好的数据,所以此方法要交给Service层进行数据处理。)

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;
    
    @RequestMapping("/depts")
    public Result list(){
        List<Dept> DeptList = deptService.listDept();//此Service中的方法是查询数据的方法,所以返回的数据会是一个数组或者字典
        return Result.success(DeptList);
    }
}

2、在Controller(控制层)中如何调用Service(业务逻辑层)

在你写SpringBoot项目时你可能会有疑问,控制层到底是通过什么来去访问业务逻辑层的,其实此疑问在上面已经给出答案了,就是使用注解@Autowired来去调用的,但是它并不是去直接调用的,它是去调用业务逻辑层储存在Bean容器中的方法,哪为什么不直接去调用业务逻辑层中实体类的方法呢?这个其实上面也给出了答案,在开发软件时我们所遵守的原则是高内聚低耦合,如果去直接调用的话就会违背了低耦合的原则,所以需要去使用Bean容器进行存储与调用,这样子就避免了耦合

二、Service(业务逻辑层)

Service(业务逻辑层)的作用:

业务逻辑层一般是对从数据库中所拿到的数据进行逻辑处理,再将处理完之后的数据存储在Bean容器中,这样可有有效的避免耦合性。

1、创建Service(业务逻辑层)

  1. 创建一个接口,并在创建一个方法,方便后面的实体类使用。

此接口是为了方便后续业务逻辑层的复用性。

//代码实例:
public interface DeptService {
    public List<Dept> listDept();
}
  1. 创建一个由@Service注解标记的类去实现上面的接口

@Service注解是用来,将此类中的方法及属性都存放在Bean容器中,

//代码实例:
@Service
public class DeptServiceImpl implements DeptService {
}
  1. 创建属性并使用@Autowired注解标识,获取到数据访问层中的数据

调用方式也是从Bean容器中调用的。

@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
}
  1. 进行重写接口中的方法,此方法是用来完成单个业务逻辑。

注意在这里可以使用@Override注解可以避免在重写方法时发生错误。

//代码实例
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
    @Override
    public List<Dept> listDept() {
    //......
    }
}

2、为什么要去创建接口Service与实体Service

业务逻辑层中一般都会创建一个接口和多个实体类,而为什么要创建接口,而不是直接去创建一个类来将业务逻辑层中的代码写进此类里面?因为当你去以一个类来去存储所有的业务逻辑层的代码时,会有
弊端:
1、你会发现每一个实现逻辑方法中都会用大量重复的代码。
2、在你去调用业务逻辑层的方法时你会发现没有统一的类去接收业务逻辑层中的数据。
3、而且他也违反了“单一职责原则(一个类只办一件事)。
而使用接口业务逻辑层可以奖上面的缺点都完美的补全。所以一般在创建业务逻辑层时都会先创建接口再去创建实体类。
(创建接口业务逻辑层是如何补全上面的缺点的):
1、在使用接口业务逻辑层时可以,直接在接口中创建规范方法来去避免重复创建方法的弊端。
2、这里再调用业务逻辑层时可以直接使用多态来去避免上面的弊端“2”
3、而上述弊端“3”可以创建多个类进行避免。

3、如何确定调用的是哪一个实体Service(业务逻辑层)的方法?

当你在写SpringBoot项目时肯定会遇到,有很多的实体类Service(也就相当于有许多的逻辑方法),而此时我要如何去调用我所想要的哪一个方法?
这个时候再调用Service时就要去了解依赖注入是什么了:

依赖注入(Dependency Injection,简称:DI)

概念:**“容器”**为应用程序提供运行时,所依赖的资源,称作“依赖注入
DI的简单使用:当需要调用Bean里面的对象时,再代码上方使用功能@Autowired(自动接线)标记

Bean注入类型:

  1. @Autowired

概念:默认是按照类型进行连接,如果存在多个相同类型的bean,将会报错。
使用方法:在需要调用的类上面进行标识即可

代码实例:

//Controller层调用Service层代码
@Autowired
private EmpService empService;//Service层的类型
  1. @Primary

概念:当有两个相同类型时,可以使用此注解进行标识对应的类。
使用方法:这个注解需要配合@Autowired注解一起使用,当@Autowired注解已经标识后,再去找你所需要Service层对应的实体类进行标识,并在此类上面进行标识

代码实例:

//Controller层调用Service层代码
@Autowired
private EmpService empService;//Service层的类型
//Service实体类代码进行标识
@Primary//使用此标识之后在调用Service层时就会执行此类
@Service //口岸个当前类交给ICO容器管理,成为IOC容器的bean
public class EmpServiceA implements EmpService{
//...(Service实现逻辑的方法代码)
}
  1. @Qualifier

概念:当有多个相同类型时,可以使用此注解进行选定所需要bean对象。
使用方法:在@Autowired的基础上再添加此注解@Qualifer,并在给他进行赋上你所需要调用的Service层中的实体类对应的bean名。(bean名默认是类名首字母小写)
【原理就是使用spring架构中的BeanFactory.getBean(“beanName”,Object.clss)方法,在原有的根据类型查找对象的@Autowired注解上,增加了通过beanName来进行查找】

代码实例:

//Controller层调用Service层代码
@Qualifier("empServiceA")//输入Service的bean名(默认bean名首字母小写)
@Autowired
private EmpService empService;//Service层的类型
  1. @Resourcce

概念:当有多个相同类型时,可以使用此注解进行选定所需要bean对象。
使用方法:此注解不需要与@Autowired注解联合使用,它可以直接进行调用,当有多个相同类型时,可以使用此注解中的name属性赋值(对应的bean名)即可调用。

代码实例:

//Controller层调用Service层代码
@Resourcce(name = "empServiceA")//将注解@Resource的name属性赋值
private EmpService empService;//Service层的类型

@Autowired与@Resource的区别:

  1. @Autowired是Spring框架提供的注解,而@Resource是JDK提供的注解。
  2. @Autowired默认是按照类型注入,而@Resource默认是按照名称注入。(若是了解过Spring的话就知道这里的原理就是先根据[BeanFactory.getBean(“name”/Object.class)] 类型\名称 去找到相对应的对象,再去进行注入[创建bean.xml,在进行注入])

三、Dao(Data Access Object:数据访问层)[也称:持久层]

Dao(Data Access Object:数据访问层)[也称:持久层] 的作用:

数据访问层此层是用来对数据库中的数据进行增删改查,并将整理好的数据进行动态的将数据存放在Bean容器中。也就是在我前面几章中所讲的Mybatis,它就是持久层中的一种类型,当然还有其他类型的操作类型,这里只讲Mybatis这款持久型架构。

1、如何创建Dao(数据访问层/持久层)

这里因为在前面几个章节已经详细的讲解了如何创建持久层(Mybatis)这里就不在做演示了,若是不太熟悉Mybatis的可以看前面的几个关于Mybatis的章节,相信应该会对你有一些帮助。

2、持久层是如何将数据存储在Bean容器中

持久层是使用注解@Mapper来去完成将数据动态的将数据存储在Bean容器中。
@Mapper(映射):映射的作用是:在运行时,会自动生成该接口的实现类对象(代理对象),并且将该对象交给IOC容器管理

三层架构、客户端之间的关系

概述

客户端向服务端发起请求,由控制层接收并调用业务逻辑层中的方法,在处理逻辑时会对数据库中的数据进行调用,这时就要去调用数据访问层数据访问层将会把查询到的数据进行传递给业务逻辑层,而此时的数据需要做逻辑处理,处理完毕之后,在传递给控制层,这时客户端的数据已经拿到了,但是不能直接去传递,需要将数据以HTTP协议的规范进行传递(可以直接创建一个Result类进行单独处理),规范完之后,在传递给客户端
注意:上述中的“传递”是将数据存储在Bean容器后,在去调用Bean容器中对应的数据,不是直接进行传递,因为这样会有耦合

图形化示意图

在这里插入图片描述

Spring IOC与Bean容器

在Spring中,构成应用程序主干并由SpringIOC容器管理的对象称为bean。 bean是一个由SpringIOC容器实例化、组装和管理的对象。 否则,bean只是应用程序中许多对象之一。 bean以及它们之间的依赖关系反映在容器使用的配置元数据中。
你可以理解为:IOC容器是用来管理bean对象的,但是IOC并没有实体化,他更像是抽象化的概念,而多个bean对象是此抽象化的实体化。
若是想深入了解 Spring IOC与Bean容器,可以去观看“大白话讲解Spring的@bean注解”这篇文章。


上述文章是我查看一些资料之后,在结合自己的理解进行编写的,所以可能会有一些不足,还请谅解,若是发现了一些错误还请大佬们指出,我会非常感谢!!!

### Spring Boot 三层架构概述 Spring Boot 应用程序通常遵循经典的分架构设计模式,这种结构有助于提高应用程序的可维护性和扩展性。典型的三层架构包括表示业务逻辑以及持久化。 #### 表示 (Controller ) 这一负责处理来自客户端的请求并返回响应给前端页面或其他服务消费者。通过控制器类接收 HTTP 请求并将这些请求映射到具体的服务方法上,在此过程中可以进行参数验证等工作[^1]。 ```java @RestController @RequestMapping("/api/users") public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @GetMapping("/{id}") public ResponseEntity<User> getUserById(@PathVariable Long id){ User user = userService.findById(id); return ResponseEntity.ok(user); } } ``` #### 业务逻辑 (Service ) 该次包含了应用的核心功能实现,即所谓的“业务规则”。这里定义了所有的操作流程和服务接口,确保数据的有效转换和加工处理,并协调其他各之间的交互过程。 ```java @Service public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } public User findById(Long id){ return userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User not found")); } // Other service methods... } ``` #### 数据访问层 (Repository/DAO ) 最后一专注于数据库的操作,比如查询、保存或删除实体对象等动作。借助于 JPA 或 MyBatis 这样的框架可以让开发者更方便地完成 CRUD 操作而无需编写复杂的 SQL 语句。 ```java @Repository public interface UserRepository extends JpaRepository<User,Long> { } ``` ### 架构图示意 由于无法直接绘制图形图像,以下是文字描述的一个典型 Spring Boot 三层架构: - **最外**:Web 控制器(`@RestController`),用于接受外部 API 请求; - **中间**:服务组件(`@Service`),封装核心业务逻辑; - **最内**:仓库接口(`@Repository`),提供对底存储系统的抽象访问; 每一之间相互协作又保持松散耦合的关系,使得整个系统更加模块化易于管理。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值