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层代码又依赖数据层代码

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

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

相关推荐
cat三三4 小时前
java之异常
java·开发语言
浙江第二深情4 小时前
前端性能优化终极指南
java·maven
养乐多07224 小时前
【Java】IO流
java
俊男无期4 小时前
超效率工作法
java·前端·数据库
中国胖子风清扬4 小时前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
月明长歌5 小时前
【码道初阶】牛客TSINGK110:二叉树遍历(较难)如何根据“扩展先序遍历”构建二叉树?
java·数据结构·算法
用户2190326527355 小时前
Spring Boot + Redis 注解极简教程:5分钟搞定CRUD操作
java·后端
Alice5 小时前
linux scripts
java·linux·服务器
Filotimo_5 小时前
Spring Data JPA 方法名查询特性的使用
java·开发语言·windows
代码栈上的思考5 小时前
MyBatis:注解方式实现数据库 CRUD 全操作
java·开发语言·mybatis