【SpringBootWeb入门-8】分层解耦-三层架构

发布时间 2023-12-09 22:55:51作者: hiker0412

1、架构前言

在讲解三层架构之前,我们先来看一段Controller代码段,代码如下:

package com.hiker.controller;

import com.hiker.pojo.Emp;
import com.hiker.pojo.Result;
import com.hiker.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


@RestController
public class EmpController {
    @RequestMapping("/listEmp")
    public Result list(){
        //1. 加载并解析emp.xml
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);

        //2. 对数据进行转换处理 - gender, job
        empList.stream().forEach(emp -> {
            //处理 gender 1: 男, 2: 女
            String gender = emp.getGender();
            if("1".equals(gender)){
                emp.setGender("男");
            }else if("2".equals(gender)){
                emp.setGender("女");
            }

            //处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
            String job = emp.getJob();
            if("1".equals(job)){
                emp.setJob("讲师");
            }else if("2".equals(job)){
                emp.setJob("班主任");
            }else if("3".equals(job)){
                emp.setJob("就业指导");
            }
        });

        //3. 响应数据
        return Result.success(empList);
    }
}
View Code

这段Controller代码段作用是加载并解析xml文件里面的数据,然后对数据进行转换处理,最后返回了一个统一响应结果。

这段代码能够完成了一个功能实现,但是回过头看,所有的功能实现代码都写在了一个Controller代码里面,且里面存在了数据操作、逻辑处理,这样的代码复用性差,如果所有的代码都这么写,那么整个项目将会难以维护。

那么上述问题要怎么解决它呢?我们可以通过分层解耦的方式来解决,本篇分层解耦先讲解web开发的三层架构。

在接触三层架构之前,我们先看回上面的代码段,这段代码大致可以分为三个模块:

我们在进行软件开发的时候,尽量让每一个接口、类或者方法它的职责更加单一,也就是一个类/方法,它就只做一件事情,只负责一块功能,就是所谓的单一职责原则,这样就会使得我们的接口、类、方法复杂度更低,可读性更好,也易于维护。基于此,才有web开发的三层架构。

2、架构解析

  • controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。
  • service:业务逻辑层,处理具体的业务逻辑。
  • dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查。

前端发起的一个请求,先到达Controller层,Controller接收到请求后,要去调用Service业务逻辑层,逻辑处理的前提是要拿到数据进行处理,所以Service层要去调用dao数据层,dao层再去操作文件数据,数据拿到后再返回Service,Service层拿到数据后再进行逻辑处理,处理完成后再将结果返回Controller层,Controller再响应数据返回给前端页面。这样分层的好处是:如果需要修改业务处理的逻辑,我们就不需要修改其他层的代码,增加代码的可维护性扩展性。

3、架构改造

下面我们来对上面的Controller代码按照三层架构进行改造。

 dao层:创建接口EmpDao以及其实现类

接口EmpDao:

1 package com.hiker.dao;
2 import com.hiker.pojo.Emp;
3 import java.util.List;
4 public interface EmpDao {
5     //获取员工列表数据
6     public List<Emp> listEmp();
7 }
View Code

 实现类EmpDaoA:

package com.hiker.dao.impl;

import com.hiker.dao.EmpDao;
import com.hiker.pojo.Emp;
import com.hiker.utils.XmlParserUtils;
import java.util.List;

public class EmpDaoA implements EmpDao {
    @Override
    public List<Emp> listEmp() {
        //1. 加载并解析emp.xml
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
        return empList;
    }
}
View Code

service层:创建接口EmpService以及其实现类

接口EmpService:

package com.hiker.service;

import com.hiker.pojo.Emp;

import java.util.List;

public interface EmpService {
    //获取员工列表
    public List<Emp> listEmp();
}
View Code

实现类EmpServiceA:

package com.hiker.service.impl;

import com.hiker.dao.EmpDao;
import com.hiker.dao.impl.EmpDaoA;
import com.hiker.pojo.Emp;
import com.hiker.service.EmpService;
import java.util.List;

public class EmpServiceA implements EmpService {

    private EmpDao empDao = new EmpDaoA();

    @Override
    public List<Emp> listEmp() {
        //1. 调用dao, 获取数据
        List<Emp> empList = empDao.listEmp();

        //2. 对数据进行转换处理 - gender, job
        empList.stream().forEach(emp -> {
            //处理 gender 1: 男, 2: 女
            String gender = emp.getGender();
            if("1".equals(gender)){
                emp.setGender("男");
            }else if("2".equals(gender)){
                emp.setGender("女");
            }

            //处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
            String job = emp.getJob();
            if("1".equals(job)){
                emp.setJob("讲师");
            }else if("2".equals(job)){
                emp.setJob("班主任");
            }else if("3".equals(job)){
                emp.setJob("就业指导");
            }
        });
        return empList;
    }
}
View Code

Controller层请求处理改造:

package com.hiker.controller;

import com.hiker.dao.EmpDao;
import com.hiker.pojo.Emp;
import com.hiker.pojo.Result;
import com.hiker.service.EmpService;
import com.hiker.service.impl.EmpServiceA;
import com.hiker.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


@RestController
public class EmpController {
    private EmpService empService=new EmpServiceA();

    @RequestMapping("/listEmp")
    public Result list(){
        //1. 调用service, 获取数据
        List<Emp> empList = empService.listEmp();

        //3. 响应数据
        return Result.success(empList);
    }

}
View Code

 

至此,原先代码改造成三层架构的已完成,最后拆分前后的对比图如下:

 下一篇我们讲解三层架构的劣势以及分层解耦。