可能软件开发中很多地方都会用到三层结构,不过由于我首先是在Java web中接触到的三层结构,那么我就结合Java web 的注册登录系统为实例,好好讲讲三层结构。感觉三层架构弄明白了MVC也就触类旁通了。
一、什么是三层架构
三层架构就是把整个软件系统分为三个层次
至于为什么要分层?我通过查阅书籍,网上浏览,询问老师得出来大概以下的优点:
总之优点很多的样子,不过分层给我最直观的感受是,代码逻辑清晰了很多。
二,各个层次的任务
不知道大家和我有没有同样的困惑:为什么中间要有业务逻辑层?为什么数据访问层不能对数据进行逻辑处理呢?少了中间一层不是减少了代码量吗?
我后来想了很久,查了很多资料,突然有所感悟,试着用自己语言描述下其中缘由。
这样的话,当大型个软件系统中出现问题时就可以很方便的解决问题
三、三层架构之间如何联系起来?
一般来说都是通过实体层(entity layer)贯穿三个层次之间。实体层不属于三层架构中的任意一层。
四、通过实例讲解三层架构
就拿最简单的学生注册登录系统来说吧。
1、实体层:首先我们需要实体层来对应数据库中的表。
在本例中 用Student类对应数据库中的Student表,Student类对象作为连接三层架构的桥梁。
public class Student{String id;//学生的学号String name; //学生的姓名String password; //学生的登录密码public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}
2、数据访问层:这一层主要是利用sql语言直接对数据库进行最基础的操作如:“增,删,改,查”等等。不涉及更深一步的逻辑上的处理。
public class DAOsupport {static Connection connection;//声明Connection对象 static String driver ="com.mysql.jdbc.Driver";//驱动程序名 static String url = "jdbc:mysql://119.23.79.90:3306/survey"; //URL指向要访问的数据库名mydata static String username = "root";//MySQL配置时的用户名 static String password = "MYSQL";//MySQL配置时的密码 public DAOsupport(){try {Class.forName(driver);} catch (ClassNotFoundException e) {System.out.println("加载数据库驱动出错");e.printStackTrace();} try {connection= (Connection) DriverManager.getConnection(url, username, password);} catch (SQLException e) {System.out.println("连接数据库出错");e.printStackTrace();}}}
编写一个DAOsuport类,为其他的DAO类提供最基础的代码(比如连接数据库),减少代码的重复。
接着针对于学生类编写,StudentDAO类。该类继承DAOsuport类。
public class StudentDAO extends DAOsupport{public Student student; //对用户类进行数据库的操作前,先要获取用户对象public StudentDAO(Student student){super();this.student=student;} //返回实参 public Student get_Stu(){ retrun student; }//增加用户student public void save(){String sql="insert into student(id,name,password,)"+"values(?,?,?)";PreparedStatement pStatement;try {pStatement = connection.prepareStatement(sql);//为SQl参数赋值pStatement.setString(1, student.getId());pStatement.setString(2, student.getName());pStatement.setString(3, student.getPassword());//向user表插入记录pStatement.executeUpdate();//关闭pStatement.close();} catch (SQLException e) {System.out.println("保存用户时出错");e.printStackTrace();}}//删除用户student public void delete() throws SQLException{String sql="delete from user where id=?";PreparedStatement pStatement=connection.prepareStatement(sql);pStatement.setString(1, student.getId());pStatement.executeUpdate();pStatement.close();}//更新用户student public void update(){// TODO Auto-generated method stubString sql="update user set password=? where id="+student .getId();try {PreparedStatement preparedStatement=(PreparedStatement)connection.prepareStatement(sql);preparedStatement.setString(1,student.getPassword());preparedStatement.executeUpdate();} catch (SQLException e) {System.out.println("更新用户时出错");e.printStackTrace();}}//通过学号查找用户public Student getStuById() {Student student =new Student ();String sql="select * from student where id="+id;try {PreparedStatement preparedStatement=connection.prepareStatement(sql);ResultSet rs=preparedStatement.executeQuery();rs.next();student.setId(id);student.setName(rs.getString(2));student.setPassword(rs.getString(3));} catch (SQLException e) {System.out.println("通过ID查询用户时出错");e.printStackTrace();}return student ;}}
3、业务逻辑层
public class StudentService {public StudentDAO studentDAO;public StudentService(StudentDAO studentDAO){this.studentDAO=studentDAO;} //注册就是将student对象加入数据库public void rgister(){studentDAO.save();} //登录就是查看登录时填写的账号和密码是否和数据库中的账号和密码一致。public boolean login() throws Exception{boolean flag=false; //获取数据库中这个学生的密码 Student stu=studentDAO.getStuById(); String password=stu.getPassword();/* 实际上可以直接写成,上述代码只是为方便理解。 String password=studentDAO.getStuById().getPassword(); */if(password.equals(null)){throw new Exception("不存在");} /*studentDAO.getStu()得到的是由登录信息实例化的学生对象,不是存在数据库的记录*/else if(!password.equals(studentDAO.getStu().getPassword())){throw new Exception("密码不正确");}else if(password.equals(studentDAO.getStu().getPassword())){flag=true;}return flag;} //注销该学生public void delete(){studentDAO.delete();} //更新该学生public void updte(){studentDAO.update();}}
测试代码:
在这里为了方便测试,我就不写出表示层,表示层也就是在注册登录的时候,采集学生的学号,姓名,密码等信息。
public class test(){ public static void main(String args[]){ //实例化一个实体层类对象 Student student =new Student(); //为对象设置学号,姓名,密码等等。 student.setId("20171008"); student.setName("刘耀"); student.setPassword("5461"); //实例化一个数据访问层对象,参数为实体层类对象。 StudentDAO studentDAO=new StudentDAO(student); //实例化一个业务逻辑层对象,参数为数据访问层对象。 StudentService studentService=new StudentService(studentDAO) //学生注册 studentService.register(); }}
在学生注册测试中,我们可以看到:
业务逻辑层注册方法studentService.register()里面并没有SQL语句对数据库进行操作。而只是调用了数据访问层studentDAO.save()方法,在数据访问层的studentDAO.save()方法中写SQL语句 对数据库进行操作。
可能会有人说那这样业务逻辑层只是对数据访问层的简单嵌套啊,不急,我们接着看学生登录的测试代码,在学生注册之后就能登陆了。
public class test(){ public static void main(String args[]){ //实例化一个实体层类对象 Student student =new Student(); //为对象设置学号,密码等等。 student.setId("20171008"); student.setPassword("5461"); //实例化一个数据访问层对象,参数为实体层类对象。 StudentDAO studentDAO=new StudentDAO(student); //实例化一个业务逻辑层对象,参数为数据访问层对象。 StudentService studentService=new StudentService(studentDAO) //学生登录 if(studentService.login()){ system.out.println("登录成功"); } else{ system.out.println("学号或密码错误"); }}
在登录测试代码中业务逻辑层studentService.login()方法中调用了数据访问层studentDAO.getStuById()方法得到数据库中的学生记录(查)。至于验证登录时填写的学号和密码是否和数据库中存储的是否一致,这个逻辑关系则是由业务逻辑层自己判断的。
小结一下:表现层的代码只是起到和用户交互的一个功能,采集信息反馈结果。
:业务逻辑层是通过数据访问层拿到存在数据库里的原始数据,然后再对数据进行逻辑上的处理,比如说验证。
:数据访问层的代码都是对数据库数据的“增删改查”,是原子性的不可以再细分的
:实体层不是三层架构中的任意一层,它起到一个贯穿三层架构的作用。在上述例子中Student的对象就贯穿了业务逻辑层和数据访问层。至于为什么要用一个类来贯穿三层架构,而不是直接用变量来连接,是因为有的时候变量可能会很多,如学生在后期可能要添加了“省份”,“学校”,“年级”,“班级”等等属性,那么就会很麻烦,但是面向对象编程的话,就可以很轻松地把属性封装在一个对象里,传递参数也方便。
如果还有不会的朋友 可以私信我 我这里有Java各种资料 以及大数据 人工智能的资料 免费发给大家 谢谢啦