在 Java 应用程序中,三层架构(Three-Tier Architecture)是一种常见的设计模式,用于分离应用程序的表示层、业务逻辑层和数据访问层。这种架构有助于提高代码的可维护性、可扩展性和可重用性。以下是详细解释 Java 应用程序中使用 MySQL 的三层架构:
### 一、三层架构简介
1. **表示层(Presentation Layer)**:
    - 负责与用户交互,包括用户界面(UI)的展示和用户输入的处理。
    - 通常包含 JSP、Servlet 或其他前端技术(如 Thymeleaf、Angular、React 等)。
2. **业务逻辑层(Business Logic Layer)**:
    - 处理应用程序的业务逻辑,执行具体的业务操作。
    - 通常包含服务类(Service)、业务对象(BO)等。
3. **数据访问层(Data Access Layer)**:
    - 负责与数据库进行交互,执行数据的持久化操作。
    - 通常包含数据访问对象(DAO)类。
### 二、示例应用程序
假设我们有一个简单的应用程序,用于管理用户信息,包括用户的 `id` 和 `name`。以下是使用 MySQL 的三层架构示例。
#### 1. 数据库表
首先,创建一个 MySQL 数据库表 `users`:
```sql
 CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (
     id INT AUTO_INCREMENT PRIMARY KEY,
     name VARCHAR(100) NOT NULL
 );
 ```
#### 2. 数据访问层(DAO)
定义一个数据访问对象(DAO)类,用于与数据库进行交互。
```java
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
public class UserDAO {
     private String jdbcURL = "jdbc:mysql://localhost:3306/testdb";
     private String jdbcUsername = "root";
     private String jdbcPassword = "yourpassword";
    private static final String INSERT_USERS_SQL = "INSERT INTO users (name) VALUES (?);";
     private static final String SELECT_USER_BY_ID = "SELECT id, name FROM users WHERE id = ?";
     private static final String SELECT_ALL_USERS = "SELECT * FROM users";
     private static final String DELETE_USER_SQL = "DELETE FROM users WHERE id = ?;";
     private static final String UPDATE_USER_SQL = "UPDATE users SET name = ? WHERE id = ?;";
    protected Connection getConnection() {
         Connection connection = null;
         try {
             Class.forName("com.mysql.cj.jdbc.Driver");
             connection = DriverManager.getConnection(jdbcURL, jdbcUsername, jdbcPassword);
         } catch (SQLException | ClassNotFoundException e) {
             e.printStackTrace();
         }
         return connection;
     }
    public void insertUser(User user) throws SQLException {
         try (Connection connection = getConnection();
              PreparedStatement preparedStatement = connection.prepareStatement(INSERT_USERS_SQL)) {
             preparedStatement.setString(1, user.getName());
             preparedStatement.executeUpdate();
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
    public User selectUser(int id) {
         User user = null;
         try (Connection connection = getConnection();
              PreparedStatement preparedStatement = connection.prepareStatement(SELECT_USER_BY_ID)) {
             preparedStatement.setInt(1, id);
             ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                 String name = rs.getString("name");
                 user = new User(id, name);
             }
         } catch (SQLException e) {
             e.printStackTrace();
         }
         return user;
     }
    public List<User> selectAllUsers() {
         List<User> users = new ArrayList<>();
         try (Connection connection = getConnection();
              PreparedStatement preparedStatement = connection.prepareStatement(SELECT_ALL_USERS)) {
             ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                 int id = rs.getInt("id");
                 String name = rs.getString("name");
                 users.add(new User(id, name));
             }
         } catch (SQLException e) {
             e.printStackTrace();
         }
         return users;
     }
    public boolean deleteUser(int id) throws SQLException {
         boolean rowDeleted;
         try (Connection connection = getConnection();
              PreparedStatement statement = connection.prepareStatement(DELETE_USER_SQL)) {
             statement.setInt(1, id);
             rowDeleted = statement.executeUpdate() > 0;
         }
         return rowDeleted;
     }
    public boolean updateUser(User user) throws SQLException {
         boolean rowUpdated;
         try (Connection connection = getConnection();
              PreparedStatement statement = connection.prepareStatement(UPDATE_USER_SQL)) {
             statement.setString(1, user.getName());
             statement.setInt(2, user.getId());
             rowUpdated = statement.executeUpdate() > 0;
         }
         return rowUpdated;
     }
 }
 ```
#### 3. 业务逻辑层(Service)
定义一个服务类,处理应用程序的业务逻辑。
```java
 import java.sql.SQLException;
 import java.util.List;
public class UserService {
     private UserDAO userDAO;
    public UserService() {
         userDAO = new UserDAO();
     }
    public void addUser(User user) {
         try {
             userDAO.insertUser(user);
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
    public User getUser(int id) {
         return userDAO.selectUser(id);
     }
    public List<User> getAllUsers() {
         return userDAO.selectAllUsers();
     }
    public void updateUser(User user) {
         try {
             userDAO.updateUser(user);
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
    public void deleteUser(int id) {
         try {
             userDAO.deleteUser(id);
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
 }
 ```
#### 4. 表示层(Servlet)
使用 Servlet 处理用户请求和响应。
```java
 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;
@WebServlet("/")
 public class UserServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
     private UserService userService;
    public void init() {
         userService = new UserService();
     }
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         String action = request.getServletPath();
        try {
             switch (action) {
                 case "/new":
                     showNewForm(request, response);
                     break;
                 case "/insert":
                     insertUser(request, response);
                     break;
                 case "/delete":
                     deleteUser(request, response);
                     break;
                 case "/edit":
                     showEditForm(request, response);
                     break;
                 case "/update":
                     updateUser(request, response);
                     break;
                 default:
                     listUser(request, response);
                     break;
             }
         } catch (SQLException ex) {
             throw new ServletException(ex);
         }
     }
    private void listUser(HttpServletRequest request, HttpServletResponse response)
             throws SQLException, IOException, ServletException {
         List<User> listUser = userService.getAllUsers();
         request.setAttribute("listUser", listUser);
         RequestDispatcher dispatcher = request.getRequestDispatcher("user-list.jsp");
         dispatcher.forward(request, response);
     }
    private void showNewForm(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         RequestDispatcher dispatcher = request.getRequestDispatcher("user-form.jsp");
         dispatcher.forward(request, response);
     }
    private void showEditForm(HttpServletRequest request, HttpServletResponse response)
             throws SQLException, ServletException, IOException {
         int id = Integer.parseInt(request.getParameter("id"));
         User existingUser = userService.getUser(id);
         RequestDispatcher dispatcher = request.getRequestDispatcher("user-form.jsp");
         request.setAttribute("user", existingUser);
         dispatcher.forward(request, response);
     }
    private void insertUser(HttpServletRequest request, HttpServletResponse response)
             throws SQLException, IOException {
         String name = request.getParameter("name");
         User newUser = new User(name);
         userService.addUser(newUser);
         response.sendRedirect("list");
     }
    private void updateUser(HttpServletRequest request, HttpServletResponse response)
             throws SQLException, IOException {
         int id = Integer.parseInt(request.getParameter("id"));
         String name = request.getParameter("name");
        User user = new User(id, name);
         userService.updateUser(user);
         response.sendRedirect("list");
     }
    private void deleteUser(HttpServletRequest request, HttpServletResponse response)
             throws SQLException, IOException {
         int id = Integer.parseInt(request.getParameter("id"));
         userService.deleteUser(id);
         response.sendRedirect("list");
     }
 }
 ```
#### 5. 用户实体类(User)
定义一个用户实体类,表示数据库表 `users` 中的记录。
```java
 public class User {
     private int id;
     private String name;
    public User(int id, String name) {
         this.id = id;
         this.name = name;
     }
public User(String name) {
         this.name = name;
     }
    public int getId() {
         return id;
     }
    public void setId(int id) {
         this.id = id;
     }
    public String getName() {
         return name;
     }
    public void setName(String name) {
         this.name = name;
     }
 }
 ```
#### 6. JSP 页面
定义两个 JSP 页面:一个用于显示用户列表,另一个用于用户表单。
**user-list.jsp**:
```jsp
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <!DOCTYPE html>
 <html>
 <head>
     <meta charset="UTF-8">
     <title>User List</title>
 </head>
 <body>
 <h2>User List</h2>
 <a href="new">Add New User</a>
 <table border="1">
     <tr>
         <th>ID</th>
         <th>Name</th>
         <th>Actions</th>
     </tr>
     <c:forEach var="user" items="${listUser}">
         <tr>
             <td>${user.id}</td>
             <td>${user.name}</td>
             <td>
                 <a href="edit?id=${user.id}">Edit</a>
                 <a href="delete?id=${user.id}">Delete</a>
             </td>
         </tr>
     </c:forEach>
 </table>
 </body>
 </html>