一:三层架构的概述
三层架构(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;
}
@Override
public 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();//里氏替换原则
@Override
public boolean login(User u) {
// TODO Auto-generated method stub
return 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");
}
%>