JavaWeb三层架构详解

什么是三层架构?

三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。区分层次的目的即为了高内聚低耦合的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。微软推荐的分层式结构一般分为三层,从下至上分别为:数据访问层(又称为持久层)业务逻辑层(又或称为领域层)表示层

 

表示层(UI层):

表示层也称为界面层,位于最外层(最上层),离用户最近。用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。

 

业务逻辑层(BLL层):

负责关键业务的处理和数据的传递。复杂的逻辑判断和涉及到数据库的数据验证都需要在此做出处理。主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。

 

数据访问层(DAL层):

主要负责对数据库的直接访问为业务逻辑层提供数据,根据传入的值来操作数据库,增、删、改、查。

 

为什么要用三层架构呢?

1.团队开发,便于管理

三层架构使得合作开发成为可能,由于各层相互独立,一个小组只需负责一小块就可以。结构化的编程方法面对大型的项目会感到力不从心,因为结构化设计必定会使程序变的错综复杂。逻辑主要在BLL层,就使得UI层也就是客户端不承担太多的职责,即使更新业务逻辑,也无需修改客户端,不用重新部署。

 

2.解耦

上一层依赖于下一层,如果测试下一层没有问题,那么问题就只有可能发现在本层了,便于发现和改正BUG。体现了高内聚,低耦合的思想。比如楼房是分层的,我们要到哪一层楼非常方便,只需在电梯里按下那个楼层的层号即可。而三层架构就好比开发的软件“楼”,哪层出现Bug,哪层有问题,我们作为开发人员能够随时找到,并修正。 各个层次分工明确,将一个复杂问题简单拆分了。

 

 3.代码的复用和劳动成本的减少

 分层的根本在于代码的复用和劳动成本的减少。分层的最理想化的结果是实现层与层之间的互不依赖的内部实现,所谓的即插即用!

 

当然啦,三层架构也是有一定的缺点,但是总的来说,利大于弊。

 

那么下面写一个小项目来具体地深入了解一下三层架构

 

项目目录如下:

 

表示层Model:

package com.gpnu.book.entity;

public class Books {
	@Override
	public String toString() {
		return "Books [book_id=" + book_id + ", book_name=" + book_name + ", isbn=" + isbn + ", author=" + author + "]";
	}
	public Books() {
	}
	public Books(int book_id, String book_name, String isbn, String author) {
		super();
		this.book_id = book_id;
		this.book_name = book_name;
		this.isbn = isbn;
		this.author = author;
	}
	private int book_id;
	private String book_name;
	private String isbn;
	private String author;
	public int getBook_id() {
		return book_id;
	}
	public void setBook_id(int book_id) {
		this.book_id = book_id;
	}
	public String getBook_name() {
		return book_name;
	}
	public void setBook_name(String book_name) {
		this.book_name = book_name;
	}
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
}

 

表示层Controller:

BooksServlet.java

package com.gpnu.book.servlet;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gpnu.book.entity.Books;
import com.gpnu.book.service.BooksService;
import com.gpnu.book.service.impl.BooksServiceImpl;

/**
 * Servlet implementation class Books
 */
@WebServlet("/BooksServlet")
public class BooksServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
	BooksService booksService = BooksServiceImpl.getInstance();
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BooksServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String action = request.getParameter("action");
		System.out.println("action:" + action);
		if (action.equals("add")) {
			doAddBooks(request, response);
			response.sendRedirect("index.jsp");
		}else if (action.equals("select")) {
			response.sendRedirect(request.getContextPath() + "/Books/selBooks.jsp");
		}else if (action.equals("remove")) {
			doDelBooks(request, response);
			response.sendRedirect("SelBooksServlet");
		}
	}
	
	
	private void doAddBooks(HttpServletRequest request, HttpServletResponse response) throws IOException {
		Books book = new Books();
		//book.setBook_id(Integer.parseInt(request.getParameter("book_id")));
		book.setBook_name(request.getParameter("book_name"));
		book.setIsbn(request.getParameter("isbn"));
		book.setAuthor(request.getParameter("author"));
		int result = booksService.addBooks(book);
		if (result > 0)
			System.out.println("添加book成功");
		else
			System.out.println("添加book失败");
	}
	
	private void doDelBooks(HttpServletRequest request, HttpServletResponse response) throws IOException {
		int id = Integer.parseInt(request.getParameter("id"));
		int result = booksService.delBooks(id);
		if (result > 0)
			System.out.println("删除book成功");
		else
			System.out.println("删除book失败");

	}
}

 

SelBooksServlet.java

package com.gpnu.book.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gpnu.book.entity.Books;
import com.gpnu.book.service.BooksService;
import com.gpnu.book.service.impl.BooksServiceImpl;

/**
 * Servlet implementation class SelBooksServlet
 */
@WebServlet("/SelBooksServlet")
public class SelBooksServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	BooksService booksService = BooksServiceImpl.getInstance();
	
    /**
     * @see HttpServlet#HttpServlet()
     */
    public SelBooksServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	private static String keyword = "";
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		keyword = request.getParameter("keyword");
		System.out.println("keyword:" + keyword);
		if (keyword == "")
			doSelAllBooks(request, response);
		else
			doSelBooks(request, response);
	}

	private void doSelAllBooks(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		List<Books> list = booksService.selAllBooks();
		request.setAttribute("books", list);
		System.out.println("查询所有");
		RequestDispatcher view = request.getRequestDispatcher("/Books/selResult.jsp");
		view.forward(request, response);
	}  
 
	private void doSelBooks(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		Books book = booksService.selBooks(keyword);
		List list = new ArrayList();
		list.add(book);
		request.setAttribute("books", list);
		System.out.println("条件查询");
		RequestDispatcher view = request.getRequestDispatcher("/Books/selResult.jsp");
		view.forward(request, response);
	}
	
}

 

表示层View:

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="Books/addBooks.jsp">添加</a>
<a href="BooksServlet?action=select">查询</a>
</body>
</html>

addBooks.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/book/BooksServlet?action=add" method="post">
<table border="1" cellspacing="0" cellpadding="0" style="align:center;">
    <tr><td>图书名称:</td><td><input type="text" name="book_name"></td></tr>
    <tr><td>国际标准书号:</td><td><input type="text" name="isbn"></td></tr>
    <tr><td>作者:</td><td><input type="text" name="author"></td></tr>
    <tr><td><input type="submit" value="提交"></td><td><input type="button" value="返回"></td>
 	</tr>
 </table>
 </form>
</body>
</html>

selBooks.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/book/SelBooksServlet" method="post">
<input type="text" name="keyword"><input type="submit" value="查询">
</form>
</body>
</html>

selResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="com.gpnu.book.entity.Books,java.util.List" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="Books/addBooks.jsp">新增</a>
<br>
<table border="1" cellspacing="0" cellpadding="0" style="align:center;">
    <tr bgcolor="ff9900" style="font-weight:bold;">
    <th>图书编号</th><th>图书名称</th><th>国际标准号</th><th>作者</th></tr>
<%
	List<Books> book = (List)request.getAttribute("books");
	if(book.size()!=0){
    	for(int i=0;i<book.size();i++) {
       		pageContext.setAttribute("book",book.get(i)); 
%>  
	<tr>
      <td>${book.book_id }</td>    
      <td>${book.book_name }</td>
      <td>${book.isbn }</td>
      <td>${book.author }</td>
      <td>|<a href="BooksServlet?action=remove&id=${book.book_id }" onclick='return confirm("确定要删除吗?")'
          >删除</a></td>
   </tr> 
     <%
      }
    }else{
     %>
<tr><td colspan="6">数据库中没有数据!</td></tr>
    <%
    }
    %>
</table>
</body>
</html>

 

持久层接口:

package com.gpnu.book.dao;

import java.util.List;

import com.gpnu.book.entity.Books;

public interface BooksDao {
	List<Books> selAllBooks();
	Books selBooks(String keyword);
	int addBooks(Books book);
	int delBooks(int book_id);
	int booksCount();
}

 

持久层实现类:

package com.gpnu.book.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.gpnu.book.dao.BooksDao;
import com.gpnu.book.entity.Books;
import com.gpnu.book.common.DBUtils;

public class BooksDaoImpl implements BooksDao {

	private Connection conn;
	
	public BooksDaoImpl(Connection conn) {
		this.conn = conn;
	}
	
	@Override
	public List<Books> selAllBooks() {
		List list = new ArrayList();
		PreparedStatement pstam = null;
		ResultSet rs = null;
		Books book = null;		try {
			pstam = conn.prepareStatement("select * from tbl_book");
			rs = pstam.executeQuery();
			while (rs.next()) {
				book = new Books();
				book.setBook_id(rs.getInt("book_id"));
				book.setBook_name(rs.getString("book_name"));
				book.setIsbn(rs.getString("isbn"));
				book.setAuthor(rs.getString("author"));
				list.add(book);
			}
		} catch (SQLException e) {
			System.out.println("在查询全部book的时候出错了.错误信息是 :" + e.getMessage());
		} finally {
			DBUtils.closeStatement(rs, pstam);
		}
		return list;
	}

	@Override
	public int booksCount() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Books selBooks(String keyword) {
		Books book = new Books();
		PreparedStatement pStatement = null;
		ResultSet rSet = null;
		try {
			pStatement = conn.prepareStatement("select * from tbl_book where book_name like ?");
			pStatement.setString(1, "%" + keyword + "%");
			rSet = pStatement.executeQuery();
			if (rSet.next()) {
				book.setBook_id(rSet.getInt("book_id"));
				book.setBook_name(rSet.getString("book_name"));	
				book.setIsbn(rSet.getString("isbn"));
				book.setAuthor(rSet.getString("author"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtils.closeStatement(rSet, pStatement);
		}
		return book;
	}

	@Override
	public int addBooks(Books book) {
		int result = 0;
		PreparedStatement pstam = null;
		try {
			pstam = conn.prepareStatement("insert into tbl_book(book_name,isbn,author) values(?,?,?)");
			//pstam.setInt(1, book.getBook_id());
			pstam.setString(1, book.getBook_name());
			pstam.setString(2, book.getIsbn());
			pstam.setString(3, book.getAuthor());
			result = pstam.executeUpdate();
		} catch (SQLException e) {
			System.out.println("添加book出错.错误信息是 :" + e.getMessage());
		} finally {
			DBUtils.closeStatement(null, pstam);
		}
		return result;
	}

	@Override
	public int delBooks(int book_id) {
		int result = 0;
		PreparedStatement pstam = null;
		try {
			pstam = conn.prepareStatement("DELETE FROM tbl_book WHERE book_id =?");
			pstam.setInt(1, book_id);
			result = pstam.executeUpdate();
		} catch (SQLException e) {
			System.out.println("删除book出错.错误信息是 :" + e.getMessage());
		} finally {
			DBUtils.closeStatement(null, pstam);
		}
		return result;
	}

}

 

业务逻辑层接口:

package com.gpnu.book.service;

import java.util.List;

import com.gpnu.book.entity.Books;

public interface BooksService {
	List<Books> selAllBooks();
	Books selBooks(String keyword);
	int addBooks(Books book);
	int delBooks(int book_id);
}

 

业务逻辑层实现类

package com.gpnu.book.service.impl;

import java.sql.Connection;
import java.util.List;

import com.gpnu.book.entity.Books;
import com.gpnu.book.service.BooksService;
import com.gpnu.book.common.DBUtils;
import com.gpnu.book.dao.BooksDao;
import com.gpnu.book.dao.impl.BooksDaoImpl;

public class BooksServiceImpl implements BooksService {

	private static final BooksService instance = new BooksServiceImpl();
	public static BooksService getInstance() {
		return instance;
	}
	
	@Override
	public List<Books> selAllBooks() {
		Connection conn = null;
		List list = null;
		try {
			conn = DBUtils.getConnection();
			DBUtils.beginTransaction(conn);
			BooksDao booksDao = new BooksDaoImpl(conn);
			list = booksDao.selAllBooks();
			DBUtils.commit(conn);
		} catch (Exception e) {
			System.out.println("查询所有books错误" + e.getMessage());
		} finally {
			DBUtils.closeConnection(conn);
		}
		return list;
	}

	@Override
	public Books selBooks(String keyword) {
		Connection conn = null;
		Books book = null;
		try {
			conn = DBUtils.getConnection();
			DBUtils.beginTransaction(conn);
			BooksDao booksDao = new BooksDaoImpl(conn);
			book = booksDao.selBooks(keyword);
			DBUtils.commit(conn);
		} catch (Exception e) {
			System.out.println("条件查询books错误" + e.getMessage());
		} finally {
			DBUtils.closeConnection(conn);
		}
		return book;
	}

	@Override
	public int addBooks(Books book) {
		Connection conn = null;
		int result = 0;
		try {
			conn = DBUtils.getConnection();
			DBUtils.beginTransaction(conn);
			BooksDao booksDao = new BooksDaoImpl(conn);
			result = booksDao.addBooks(book);
			DBUtils.commit(conn);
		} catch (Exception e) {
			System.out.println("增加books错误" + e.getMessage());
		} finally {
			DBUtils.closeConnection(conn);
		}
		return result;
	}

	@Override
	public int delBooks(int book_id) {
		Connection conn = null;
		int result = 0;
		try {
			conn = DBUtils.getConnection();
			DBUtils.beginTransaction(conn);
			BooksDao booksDao = new BooksDaoImpl(conn);
			result = booksDao.delBooks(book_id);
			DBUtils.commit(conn);
		} catch (Exception e) {
			System.out.println("删除books错误" + e.getMessage());
		} finally {			DBUtils.closeConnection(conn);
		}
		return result;
	}

}

 

我们启动一下项目,我们作为用户直接看到的就是表示层的视图了

 

而当我们点击查询,会跳转到查询的视图

 

点击查询,我们会跳转到表示层的控制器,也就是Servlet,此时Servle会调用业务逻辑层的方法

 

而业务逻辑层则会调用持久层(DAO层)的方法

 

最后持久层连接到数据库,读取数据库的数据,保存为一个Model类

 

将结果原路返回给表示层的视图View

 

整个运行过程可以浓缩为一张图:

 

 

 

  • 95
    点赞
  • 474
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值