SpringBootWeb极速入门-分层解耦(03)

案例分析

我们先看一个spring-boot-web开发的接口

java 复制代码
package com.shixiaoshi.controller;

import com.shixiaoshi.pojo.Emp;
import com.shixiaoshi.pojo.Result;
import com.shixiaoshi.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);
        System.out.println(empList.stream());
        //2. 对数据进行转换处理 - gender, job
        empList.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);
    }
}

上述代码定义了一个名为listEmp的接口,它对项目中的xml文件进行了解析,然后返回了解析后的数据。

上述代码并没有什么逻辑错误,但如果业务逻辑增加时,所有处理都放在EmpController类中进行处理是愚蠢的。我们需要对这个项目进行优化,让他更适合维护和拓展。

架构优化

什么是三层架构

我们可以将上述代码的功能分成三层结构

我们在设计接口、类或方法时,尽量要让他们的功能单一,只做一件事情,这就是设计模式中的单一职责原则

单一职责的设计模式会让我们的程序更易维护和拓展,因此,在javaweb开发中,有了三层架构的开发原则。

三层架构的内容

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

代码拆分

我们根据三层架构的原则,对原有项目进行拆分优化。首先,和创建dao包service包。

注:项目路径一定不能有中文,否则程序执行会报错

dao数据访问层

数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查,最终被service调用。

其访问的数据类型有很多,如文件中的数据、数据库中的数据 、别人接口中的数据。 我们要想灵活的实现这些方式的切换,可以使用面向接口的方式编程。

所以,我们先在dao包内定义一个EmpDao接口,增强其灵活性和可拓展性。

java 复制代码
package com.shixiaoshi.dao;
import com.shixiaoshi.pojo.Emp;
import java.util.List;

public interface EmpDao {
    //获取员工列表数据  listEmp 是接口中定义的抽象方法,需要子类实现
    public List<Emp> listEmp();
}

现在,我们来实现这个接口。首先,我们创建impl.EmpDaoA类,然后实现 EmpDao这个接口

alt + shift + p快捷实现类中的方法,然后从EmpController中复制其对应的数据处理方法

java 复制代码
package com.shixiaoshi.dao.imp;

import com.shixiaoshi.dao.EmpDao;
import com.shixiaoshi.pojo.Emp;
import com.shixiaoshi.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;
    }
}

现在,我们dao层的数代码逻辑就完成。

service业务逻辑层

service的业务逻辑处理方式和bao层是一致的。我们先在service包内创建一个EmpService接口。

然后,我们创建impl.EmpServiceA这个类实现EmpService接口。同样的,我们从EmpController中复制数据处理逻辑

此时,我们会发现empList及其相关的方法报错了。这很正常,因为empList的值现在在dao层的EmpDaoA类中储存着,我们需要从这个类中获取empList

java 复制代码
private EmpDao empDao = new EmpDaoA();

List<Emp> empList = empDao.listEmp();

完整代码如下

java 复制代码
package com.shixiaoshi.service.impl;

import com.shixiaoshi.dao.EmpDao;
import com.shixiaoshi.dao.impl.EmpDaoA;
import com.shixiaoshi.pojo.Emp;
import com.shixiaoshi.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.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;
    }
}

现在,我们已经将代码已经改造完毕,我们对接口进行测试

总结

上述教程中,我们通过单一职责原理,将代码封装成了三层结构,每层结构只专注自己的事情。相比一开始所有代码写在一起,优化后的代码结构复用性强,利于拓展,便于维护!

但该项目改造后,还是存在一定的缺陷,比如我们的controller层代码依赖service代码

service层代码又依赖数据层代码

这三层结构数据耦合程度比较高,如果其中一个控制层的类名发生变化,对其耦合的数据层也会造成影响。

因此,该项目还可以进一步的进行解耦优化!

相关推荐
公贵买其鹿25 分钟前
List深拷贝后,数据还是被串改
java
xlsw_4 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹4 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭5 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫5 小时前
泛型(2)
java
超爱吃士力架5 小时前
邀请逻辑
java·linux·后端
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石5 小时前
12/21java基础
java
李小白665 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp6 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea