三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合”的思想。
表现层(UI) | 主要是指与用户交互的界面,用于接收用户输入的数据和显示处理后用户需要的数据 |
业务逻辑层(BLL) | 表示层和数据库访问层之间的桥梁,实现业务逻辑,具体包含:验证、计算、业务规则等等 |
数据访问层(DAL) | 与数据库打交道,主要实现对数据的增、删、改、查 |
数据库实体类(Entity) | 对数据对象进行封装,也有一些简单的功能 |
各个层次的作用:
表现层(UI) | 主要表示WEB方式,也可以表示成WINFORM方式,WEB方式也可以表现成:aspx,如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务 |
业务逻辑层(BLL) |
主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。 |
数据访问层(DAL) | 主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务 |
两层结构将界面展示、业务逻辑、数据访问等都写到一起,如果用户需求变化,就需要对整个项目进行大量修改,系统的维护和升级极其不利;而且界面层直接访问数据库,还会有安全隐患。
所以基于两层结构的局限性,三层结构就出现了。三层结构符合“高内聚、低耦合”的特点,每个层职责明确。利用分层,降低了层间依赖,使系统的耦合更加松散,从而使系统更加容易维护和复用。
比如:如果需求有变化,只需要更改相应的业务逻辑层;或者要改变数据库的时候,只需要将原来的数据访问层替换掉或者增加新的就可以了,而不需要牵扯到整个项目。
三层架构虽好,但是也不是每个项目都必须采用这种结构,三层结构用于比较复杂的大型系统,如果系统比较小,则没必要将问题复杂化。
业务处理的代码与JSP代码混在一起,不易于阅读,不易于代码维护,采用三层软件设计架构后,软件系统在可扩展性和可复用性方面得到极大提高
结构说明:
三层架构就是为了符合“高内聚,低耦合”思想,把各个功能模块划分为表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构,各层之间采用接口相互访问,并通过对象模型的实体类(Model)作为数据传递的载体,不同的对象模型的实体类一般对应于数据库的不同表,实体类的属性与数据库表的字段名一致。
高内聚 :尽可能类的每个成员方法只完成一件事
低耦合 :减少类内部,一个成员方法调用另一个成员方法
从类角度来看, 高内聚低耦合:减少类内部,对其他类的调用
从功能块来看, 高内聚低耦合:减少模块之间的交互复杂度
简单来说,就是 解耦 :只做自己功能内的事
业务逻辑层通过调用数据访问层的各种操作方法,将这些方法按一定的逻辑组合起来实现具体需求,将这个过程比作搭积木的过程。
【职责】数据加工处理、处理DAO完成业务实现
比如在数据访问层定义了一些操作数据的方法,即增、删、改、查的方法,将这些方法比作一块块的积木。
【职责】想业务层提供数据,将业务层加工后的数据同步到数据库
实体类库是数据库表的映射对象,即将一个**数据表映射成一个实体类,表中的每一个记录封装为该实体类的对象,表中的每个字段对应实体对象中的一个属性**。实体类库主要用于封装表中数据方便在表示层、业务逻辑层以及数据访问层之间进行传输,实现各个结构层的`参数传输`。
相关层的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层接口的实现类 |
每一层都有自己的职责
上一层不用关心下一层的实现细节,上一层通过下一层提供的对外接口来使用其功能
上一层调用下一层的功能,下一层不能调用上一层功能
发生在哪一层的变化,只需更改该层,不需要更改整个系统。层次清晰,分工明确,每层之间耦合度低, 提高了效率,适应需求变化,可维护性高,可扩展性高
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();
}
}
}
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 + "]";
}
}
package com.dao;
import com.entity.User;
public interface IUserDao {
//登录
boolean login(User u);
}
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;
}
}
package com.biz;
import com.entity.User;
public interface IUserBiz {
//登录
boolean login(User u);
}
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"%>
Insert title here
中转界面:
<%@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");
}
%>