在Java项目开发中,随着项目规模的增大,代码量随之增大,开发和维护的难度也会增加,因此我们需要一种低耦合、高内聚,可读性和可维护性好的开发方式,也就是三层开发模式
Java项目中的三层开发可以分为:
用户的指令以UI层为起点,发送命令到业务逻辑层,业务逻辑层完成整个指令的解析、利用持久化层的方法来完成整个指令
也就是用户所看到的界面,比如说一个简单的学生信息管理系统,用户所看到的界面如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dtc7yCaK-1673268524139)(C:\Users\李文波\AppData\Roaming\Typora\typora-user-images\image-20230109200553012.png)]
用户可以根据自己的需求来操作界面,界面会根据用户输入的信息(比如用户选择2,根据编号查找年级),将用户输入的内容发送到业务逻辑层,由业务逻辑层进行接下来的操作:
case 2:
System.out.print("请输入需要查找的年级编号:");
id = input.nextInt();
Grade grade = gradeService.getGradeById(id);//调用了业务层的gerGradeById()方法
System.out.println(grade);
System.out.println("按任意键继续...");
line = input.nextLine();
line = input.nextLine();
continue;
业务逻辑层会接收到UI层发送过来的指令,刚才UI层发送过来的指令:
Grade grade = gradeService.getGradeById(id);//调用了业务层的gerGradeById()方法
会在业务逻辑层来执行:
@Override
public Grade getGradeById(int id) {
return gradeDao.getGradeById(id);//调用了持久层(数据层、Dao层)的getGradeById()方法
}
我们可以看到,业务逻辑层完成这个指令其实是依赖持久层(数据层、Dao层)的方法来实现的
当业务逻辑层调用了持久层的方法之后,持久层会访问数据库来进行增删改查操作完成对应请求;
/*
* @Author: 钢铁豪侠胡图图
* @Date: 2023/1/9 11:22
* Description: 根据传入id查询Grade表中的数据
* @return: Grade对象
*/
@Override
public Grade getGradeById(int id) {
Grade grade = new Grade();
String sql = "select * from grade where gradeid = ?";
Connection conn = DBUtil.getConnection();
PreparedStatement ppstmt = null;
ResultSet rs = null;
try {
//执行SQL查询语句并使用rs接收
ppstmt = conn.prepareStatement(sql);
ppstmt.setObject(1, id);
rs = ppstmt.executeQuery();
//遍历结果集
while (rs.next()) {
//获取数据
int gradeid = rs.getInt(1);
String gradename = rs.getString(2);
int state = rs.getInt(3);
//封装到实体类
grade = new Grade(gradeid, gradename, state);
//如果报错,那么方法会返回最后的null
return grade;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.closeAll(conn, ppstmt, rs);
}
return null;
}
由此我们可以看到,真正的功能实现实际上是在持久层完成的
也就是说,用户使用三层结构的系统发送一条指令,可以拆分为三个步骤:
因为我们系统的功能归根结底还是对数据库中的表进行操作,因此,我们需要将数据库中的一张张表进行实体化:
比如说:假设我们需要向student学生表中添加一个学生的信息,那么把name、id、age、sex…等一条条属性罗列出来进行添加显然可读性不高,也不符合Java面向对象开发的规则
所以我们需要创建一个Student学生类,将一个学生的所有信息封装到一个学生类的对象中传入到业务逻辑层和数据层(虽然在数据层还是会对该对象进行拆解),这样做的好处的符合我们面向对象开发的思想、提高了代码的可读性和可维护性。
假设你要开发一个根据学号id查找学生的功能,那么需要一个方法去实现它,显然,这个方法的传入参数是学生id,返回值是一个Student对象,因此,可以先在数据层接口中定义一个这样的方法
因为是对Student表进行操作,所以我们将接口命名为StudentDao:
/**
* @Author: 李文波
* @Date: 2023/1/9 10:40
* Description: 定义持久化接口,用于约束操作数据库的方法
* 子类必须实现这些方法,企业开发中,会编写多个实现类
* 用于解决不同数据库访问的问题
* @return:
*/
public interface StudentDao {
//查询所有学生信息,返回一个学生列表
public List<Student> findAll();
//根据id查找执行学生信息
public Grade getStudentById(int id);
}
public Student findById(int id);
这样做的意义是:可以先在接口中定义数据层的顶层逻辑框架,定义完框架之后程序员只需要根据这个接口中的方法来一个个去实现增删改查的数据库操作功能,将逻辑和代码分开,达到项目解耦的效果
然后我们只需要在相应实现类中实现这样的方法就行
实现类的命名叫做StudentDaoImpl,impl是实现类的意思
业务逻辑层接口中的方法和Dao层如出一辙
public interface StudentService {
//查询所有学生信息,返回一个学生列表
public List<Student> findAll();
//根据id查找执行学生信息
public Grade getStudentById(int id);
}
但是同一个方法getStudentById(int id)
在Dao层的含义是:在数据库中根据id值来查找学生信息
在业务逻辑层的含义是:使用StudentDaoImpl这个工具来完成**根据id查找学生信息的功能
**
public class StudentServiceImpl implements StudentService {
StudentDao studentDao = new StudentDaoMysqlImpl();
@Override
public List find() {
//业务逻辑代码......
return studentDao.find();
}
@Override
public Student get StudentById(int id) {
//业务逻辑代码......
return studentDao.get StudentById(id);
}
}
和Dao层最大的不同是,业务逻辑层中多了业务逻辑代码部分,也就是说它不光是能通过使用StudentDaoImpl数据层完成查找功能,它还能根据查找出来的结果进行一系列的业务逻辑操作,比如该学生是不是跟别人重名、有没有考试不及格…等
。。。。。。因为博主本人能力所限,目前还只能通过控制台开发UI