一、什么是三层架构?

1.1概述

三层架构(3-tier architecture) 就是将整个业务应用划分为:

  • 界面层(User Interface layer) UI
  • 业务逻辑层(Business Logic Layer) BLL
  • 数据访问层(Data Access layer) DAL

在这里插入图片描述

1.2表示层

  • 表示层,又称界面层,是与用户交互的界面。位于最外层/最上层,离用户最近,用于接收用户输入的数据和显示处理后用户需要的数据。

  • 【接受请求,封装数据,调用业务逻辑层,响应数据(servlet,jsp)】

1.3业务逻辑层

  • 业务逻辑层,又称服务层,是表示层和数据访问层之间的桥梁。位于中间层,用来处理业务逻辑,具体包含:验证、计算、业务规则等等。

1.4数据访问层

  • 数据访问层,是对数据库访问的层。位于最里层/最下层,主要实现对数据的增、删、改、查。将存储在数据库中的数据提交给业务层,同时将业务层处理的数据保存到数据库

1.5层与层的关系

  • 表示层依赖于业务逻辑层
  • 业务逻辑层依赖于数据访问层

既然三层各司其责,那么怎么将三层联系起来?

这个时候实体层(Entity) 来了

  • Entity(实体层):它不属于三层中的任何一层,但是它是必不可少的一层
  • Entity在三层架构中的作用:
    • 1、实现面向对象思想中的"封装";
    • 2、贯穿于三层,在三层之间传递数据;(注:确切的说实体层贯穿于三层之间,来连接三层)
    • 3、每一层(UI—>BLL—>DAL)之间的数据传递(单向)是靠变量或实体作为参数来传递的,这样就构造了三层之间的联系,完成了功能的实现。

二、为什么需要三层架构?

三层架构的出现就是为了“高内聚,低耦合”

内聚:一个模块内各个元素的关联度。
耦合 :各个模块之间的关联度。
  • 高内聚 :尽可能一个类/模块只负责一个功能(一个模块内的元素关联度,越容易理解、修改和维护,出错就越少)。
  • 低耦合 :模块与模块之间的关联度要尽可能的低,避免牵一发而动全身
  • 从类角度来看:高内聚低耦合:减少类内部,对其他类的调用
  • 从功能块来看:高内聚低耦合:减少模块之间的交互复杂度

简单来说,就是解耦:减少模块之间的交互复杂度,自己做自己的事

三层: 发生在哪一层的变化,只需更改该层,不需要更改整个系统。层次清晰,分工明确,每层之间耦合度低——提高了效率,适应需求变化,可维护性高,可扩展性高

在这里插入图片描述

两层: 当任何一个地方发生变化时,都需要重新开发整个系统。“多层”放在一层,分工不明确耦合度高,难以适应需求变化,可维护性低、可扩展性低

在这里插入图片描述

三、层架构的应用

在这里插入图片描述

3.1原则

  • 上层依赖其下层,依赖关系不跨层
    • 表示层不能直接访问数据访问层
    • 上层调用下层的结果,取决于下层的实现
  • 下一层不能调用上一层
  • 下一层不依赖上一层
    • 上层的改变不会影响下一层
    • 下层的改变会影响上一层得到的结果
  • 在上一层中不能出现下一层的概念
    • 分工明确,各司其职

3.2例子:实现登录功能

表现层:jsp页面

	<body>
		<div class="container" style="margin-top:140px;height: 100px;">
			<div class="row">
				<div class="col-md-6 bg-primary">
					<h2 class="text-white">欢迎登录</h2>
					<p class="text-white">商城后台管理系统</p>
				</div>
				<div class="col-6 bg-white py-5">
					<form action="login.do" method="post" onsubmit="return myLogin()">
						<div class="mb-3">
							<label for="exampleInputEmail1" class="form-label">邮箱账号</label>
							<input placeholder="请输入邮箱账号" ptype="email" class="form-control" id="exampleInputEmail1"
								aria-describedby="emailHelp" name="username">
						</div>
						<div class="mb-3">
							<label for="exampleInputPassword1" class="form-label">密码</label>
							<input placeholder="请输入密码" type="password" class="form-control" id="exampleInputPassword1" name="password">
						</div>
						<div class="mb-3">
							<label for="exampleInputPassword1" class="form-label">验证码</label>
							<div class="input-group mb-3 " style="width: 200px;">
								<input id="yz" placeholder="请输入验证码" type="text" class="form-control">
								<button id="login" type="button" class="btn btn-primary">
									<span id="code" class="badge bg-danger">9888</span>
								</button>
							</div>
						</div>
						<button type="submit" class="btn btn-primary">登录</button>
					</form>
				</div>
			</div>
		</div>
	</body>

控制器Servlet

Servler通常作为控制器位于服务层和表示层之间,处理请求并相应地调用服务层方法执行业务逻辑

@WebServlet("/login.do")
public class LoginServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 设置编码
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		// 获取参数
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		// 处理请求
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		//实例化业务逻辑层对象
		IUserService ius=new UserServiceImpl();
		User login = ius.login(username, password);
		System.out.println(login);
		if (login != null) {
			session.setAttribute("Login", login);
			out.println("<script>alert('登录成功');location.href='good.jsp'</script>");
		} else {
			out.println("<script>alert('账号或密码错误');location.href='login.jsp'</script>");
		}

	}
}

业务逻辑层

/**
 * 业务逻辑层
 * 定义接口类
 * @author 许潜行
 *
 */
public interface IUserService {
	/**
	 * 用户登录方法
	 * @param uname
	 * @param upwd
	 * @return
	 */
	public User login(String uname,String upwd);
}

/**
 * 业务逻辑层
 * 实现接口类
 * @author 许潜行
 *
 */
public class UserServiceImpl implements IUserService {

	//实例化数据访问层对象
	private IUsersDao iud=new UsersDaoImpl();
	@Override
	public User login(String uname, String upwd) {
		return iud.login(uname, upwd);
	}

}

数据访问层

/**
 * 数据访问层
 * 定义接口
 * @author 许潜行
 *
 */
public interface IUsersDao {
	/**
	 * 用户登录方法
	 * @param uname
	 * @param upwd
	 * @return
	 */
	public User login(String uname,String upwd);
}


/**
 * 数据访问层
 * 实现接口类
 * @author 许潜行
 *
 */
public class UsersDaoImpl extends BaseDao implements IUsersDao {
	Connection conn = null;
	PreparedStatement ps = null;
	ResultSet rs = null;

	 public User login(String uname,String upwd) {
	        User u=null;
	        String sql="select * from tb_user where username=? and password=?";
	        try {
	        	rs=this.executeQuery(sql, new Object[] {uname,upwd});
	            if(rs.next()) {
	                u=new User(rs.getInt(1), rs.getString(2), rs.getString(3));
	            }
	        } catch (Exception e) {
	            e.printStackTrace();
	        } finally {
	            DBHelper.myClose(conn, ps, rs);
	        }
	        return u;
	    }
	    public static void main(String[] args) {
			User login = new UsersDaoImpl().login("user123@qq.com", "a12345");
			System.out.println(login);
		}

}

	

实体类:

public class User {
	private Integer id;
	private String username;
	private String password;

	public User() {
		// TODO Auto-generated constructor stub
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public User(Integer id, String username, String password) {
		super();
		this.id = id;
		this.username = username;
		this.password = password;
	}

	public User(String username, String password) {
		super();
		this.username = username;
		this.password = password;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
	}

}

BaseDao

/**
	 *增删改通用方法
	 * @param sql
	 * @param obj
	 * @return
	 */
	public int execute(String sql,Object...obj) {
		int n=0;
		try {
			//建立连接
			conn=DBHelper.getConn();
			//传入sql并执行
			ps=conn.prepareStatement(sql);
			//占位符赋值
			if (obj!=null) {
				for (int i = 0; i < obj.length; i++) {
					ps.setObject(i+1, obj[i]);
				}
			}
			//返回结果
			n=ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//关闭资源
			DBHelper.myClose(conn, ps, rs);
		}
		return n;
	}
	/**
	 * 查询通用方法
	 * @param sql
	 * @param obj
	 * @return
	 */
	public ResultSet executeQuery(String sql,Object...obj) {
		try {
			//建立连接
			conn=DBHelper.getConn();
			//传入sql并执行
			ps=conn.prepareStatement(sql);
			//占位符赋值
			if (null!=obj) {
				for (int i = 0; i < obj.length; i++) {
					ps.setObject(i+1, obj[i]);
				}
			}
			//返回结果
			rs=ps.executeQuery();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return rs;
	}


Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐