一:三层架构的概述
三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合”的思想。
表现层(UI) | 主要是指与用户交互的界面,用于接收用户输入的数据和显示处理后用户需要的数据 |
业务逻辑层(BLL) | 表示层和数据库访问层之间的桥梁,实现业务逻辑,具体包含:验证、计算、业务规则等等 |
数据访问层(DAL) | 与数据库打交道,主要实现对数据的增、删、改、查 |
数据库实体类(Entity) | 对数据对象进行封装,也有一些简单的功能 |
各个层次的作用:
表现层(UI) | 主要表示WEB方式,也可以表示成WINFORM方式,WEB方式也可以表现成:aspx,如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务 |
业务逻辑层(BLL) |
主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。 |
数据访问层(DAL) | 主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务 |
为什么要用三层架构:
两层结构将界面展示、业务逻辑、数据访问等都写到一起,如果用户需求变化,就需要对整个项目进行大量修改,系统的维护和升级极其不利;而且界面层直接访问数据库,还会有安全隐患。
所以基于两层结构的局限性,三层结构就出现了。三层结构符合“高内聚、低耦合”的特点,每个层职责明确。利用分层,降低了层间依赖,使系统的耦合更加松散,从而使系统更加容易维护和复用。
??比如:如果需求有变化,只需要更改相应的业务逻辑层;或者要改变数据库的时候,只需要将原来的数据访问层替换掉或者增加新的就可以了,而不需要牵扯到整个项目。
??三层架构虽好,但是也不是每个项目都必须采用这种结构,三层结构用于比较复杂的大型系统,如果系统比较小,则没必要将问题复杂化。
业务处理的代码与JSP代码混在一起,不易于阅读,不易于代码维护,采用三层软件设计架构后,软件系统在可扩展性和可复用性方面得到极大提高
结构说明:
三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。
高内聚 :尽可能类的每个成员方法只完成一件事
低耦合 :减少类内部,一个成员方法调用另一个成员方法
从类角度来看, 高内聚低耦合:减少类内部,对其他类的调用
从功能块来看, 高内聚低耦合:减少模块之间的交互复杂度
简单来说,就是 解耦 :只做自己功能内的事
表示层(UI) web层 显示层
表示层又称表现层或视图层或用户界面层 UI(User Interface layer):就是实现与用户交互的功能,将用户的需求传达和反馈,即用于接受用户输入的数据,同时反馈相关的输出数据展示给用户。
【职责】收集用户的数据和需求、展示数据
业务逻辑层(BLL)
业务逻辑层 BLL(Business Logic Layer):是连接表示层和数据访问层的桥梁,实现业务逻辑的功能。可以对接受到的数据进行处理、执行相关的计算等一些逻辑操作。
业务逻辑层通过调用数据访问层的各种操作方法,将这些方法按一定的逻辑组合起来实现具体需求,将这个过程比作搭积木的过程。
【职责】数据加工处理、处理DAO完成业务实现
数据访问层(DAL )
数据访问层又称持久层 DAL (Data access layer):主要用来操作数据库中的数据,实现数据的增加、删除、修改、查询等操作,并将操作结果反馈到业务逻辑层 BBL。
比如在数据访问层定义了一些操作数据的方法,即增、删、改、查的方法,将这些方法比作一块块的积木。
【职责】想业务层提供数据,将业务层加工后的数据同步到数据库
[实体类]()库(Entity)
实体类库是数据库表的映射对象,即将一个**数据表映射成一个实体类,表中的每一个记录封装为该实体类的对象,表中的每个字段对应实体对象中的一个属性**。实体类库主要用于封装表中数据方便在表示层、业务逻辑层以及数据访问层之间进行传输,实现各个结构层的`参数传输`。
例如:用户需要计算功能
用户在 UI 层输入用于计算的数据,然后传递给 BLL,在 BLL 进行计算操作,最后再将结果返回给 UI 层,通过UI 层展示给用户。
即:UI —> BLL —> UI
例如:用户登录功能
用户在 UI 层输入相关的登录信息,然后传递给 BLL,在 BLL 进行相关的逻辑验证后将需要操作的指令传递给DAL,DAL根据接收到的指令对数据库中的数据进行相关的操作,然后将操作结果反馈给 BLL,BLL进一步反馈给 UI层,在 UI层展示用户需要的信息。
即:UI —> BLL —> DAL —> BLL —>UI
命名规则:
相关层的Java包命名规则 | 对应的层 |
com.xxx.项目名.utils | 保存相关工具类 |
com.xxx.项目名.entity | 保存 javabean 标准类(实体类) |
com.xxx.项目名.dao | 保存dao层接口 (数据访问层) |
com.xxx.项目名.dao.impl | 保存dao层接口的实现类 |
com.xxx.项目名.service | 保存service层接口 (业务逻辑层) |
com.xxx.项目名.service.impl | 保存service层接口的实现类 |
三层架构的特征:
每一层都有自己的职责
上一层不用关心下一层的实现细节,上一层通过下一层提供的对外接口来使用其功能
上一层调用下一层的功能,下一层不能调用上一层功能
发生在哪一层的变化,只需更改该层,不需要更改整个系统。层次清晰,分工明确,每层之间耦合度低, 提高了效率,适应需求变化,可维护性高,可扩展性高
案例:三层架构的演示
util类-----DBHelper
package com.util;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;import oracle.jdbc.driver.OracleDriver;public class DBHelper {static {try {Class.forName("oracle.jdbc.driver.OracleDriver");} catch (ClassNotFoundException e) {e.printStackTrace();}}private static final String URL="jdbc:oracle:thin:@localhost:1521:orcl";public static Connection getCon() {Connection con=null;try {con=DriverManager.getConnection(URL,"scott","123");} catch (SQLException e) {e.printStackTrace();}return con;}public static void myClose(Connection con,PreparedStatement ps,ResultSet rs) {try {if(con!=null&&!con.isClosed())con.close();if(ps!=null)ps.close();if(rs!=null)rs.close();} catch (Exception e) {e.printStackTrace();}}}
entity类------user
package com.entity;import java.io.Serializable;public class User implements Serializable {private String name;private String pwd;private String sex;private String ah;private String address;private String bz;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAh() {return ah;}public void setAh(String ah) {this.ah = ah;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getBz() {return bz;}public void setBz(String bz) {this.bz = bz;}public User() {// TODO Auto-generated constructor stub}public User(String name, String pwd, String sex, String ah, String address, String bz) {super();this.name = name;this.pwd = pwd;this.sex = sex;this.ah = ah;this.address = address;this.bz = bz;}@Overridepublic String toString() {return "User [name=" + name + ", pwd=" + pwd + ", sex=" + sex + ", ah=" + ah + ", address=" + address + ", bz="+ bz + "]";}}
dao类-----UserDao
package com.dao;import com.entity.User;public interface IUserDao {//登录boolean login(User u);}
Impl类----UserDaoImpl
package com.dao.impl;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;import com.dao.IUserDao;
import com.entity.User;
import com.util.DBHelper;public class UserDao implements IUserDao{public boolean login(User u) {Connection con=null;PreparedStatement ps=null;ResultSet rs=null;String sql="SELECT * FROM TB_USER WHERE NAME=? AND PWD=?";try {con=DBHelper.getCon();ps=con.prepareStatement(sql);ps.setString(1, u.getName());ps.setString(2, u.getPwd());rs=ps.executeQuery();if(rs.next()) {return true;}} catch (Exception e) {e.printStackTrace();}return false;}}
biz类----IUserbiz
?
package com.biz;import com.entity.User;public interface IUserBiz {//登录boolean login(User u);
}?
Impl类----UserBizImpl
package com.biz.impl;import com.biz.IUserBiz;
import com.dao.IUserDao;
import com.dao.impl.UserDao;
import com.entity.User;public class UserBiz implements IUserBiz{IUserDao ud=new UserDao();//里氏替换原则@Overridepublic boolean login(User u) {// TODO Auto-generated method stubreturn ud.login(u);}}
登录操作:
?
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body><form action="dologin.jsp" method="post">姓名:<input name="uname"> <br>密码: <input type="password" name="upwd"><button>点我登录</button></form></body>
</html>?
中转界面:
?
?
<%@page import="com.entity.User"%>
<%@page import="com.biz.impl.UserBiz"%>
<%@page import="com.biz.IUserBiz"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%request.setCharacterEncoding("utf-8");String name=request.getParameter("uname");String pwd=request.getParameter("upwd");IUserBiz ub=new UserBiz();//里氏替换原则User u=new User();u.setName(name);u.setPwd(pwd);out.print(u);if(ub.login(u)){out.print("ok");}else{out.print("no");}
%>??