DAO(Data Access Objects)設計模式是屬於J2EE體系架構中的數據層的操做。html
1、爲何要用DAO?java
比較在JSP頁面中使用JDBC來鏈接數據庫,這樣致使了JSP頁面中包含了大量的HTML代碼和JSP代碼,將顯示和功能代碼混在一塊兒,難以維護。而且在JSP頁面中使用JDBC代碼,必須導入相應的"java.sql.*"包。基於使得JSP頁面專一於數據的表現的思想,咱們只是但願JSP主要負責數據的顯示,而不須要關注數據的來源和途徑。同時在JSP進行JDBC操做,重複編碼太多。如,不一樣的頁面鏈接同一個數據庫時須要在每一個頁面中都進行JDBC編碼。mysql
DAO設計模式提供了一種通用的模式,來簡化大量的代碼,加強程序的可移植性。web
2、DAO組成sql
在這個模式中DAO主要完成數據的操做,客戶端依靠DAO接口進行操做,服務端要將接口進行具體實現。DAO的主要組成由如下幾個部分組成。數據庫
一、DatabaseConnection:專門負責數據庫打開與關閉操做的類。設計模式
二、VO:主要由屬性、setter、getter方法,VO類中的屬性與數據表中的字段相對應。每個VO對象至關於表中的一條記錄。session
三、DAO接口:主要定義數據庫操做的接口,定義數據庫的原子性操做,如增刪改,按ID查詢。架構
四、Impl:DAO的具體實現類,完成具體的數據庫操做,可是不負責數據庫的打開和關閉,接口類的名稱首字母用「I」,表示其是一個接口。app
五、Proxy:代理實現類。主要完成數據庫的打開和關閉,並調用Impl類對象(真實對象類)的操做,之因此增長代理類是爲了之後的拓展,若是一個程序能夠A-B,那麼中間最好加一個過渡,使用A-C-B的形式,能夠有效減小程序的耦合度,使開發結構更加清晰。
六、Factory:工廠類,經過工廠類取得一個DAO的實例化對象,編寫工廠類也是爲了下降代碼的耦合度,工廠類產生實例的方法一般是靜態函 數,這樣一來就能夠經過工廠類名直接生成實例。
一、數據庫鏈接類(DBConn):一個Java類。負責與後臺數據庫進行鏈接。提供了至少三個方法:
構造方法 public DataBaseConnection():進行數據庫鏈接,獲得一個Connection對象。
返回數據庫鏈接Connection的public Connection getConnection():提供一個外部獲取鏈接的方法,返回一個Connection對象。
關閉數據庫鏈接public void close():關閉數據庫鏈接,Connection對象調用close方法。。
在JDBC中,進行數據庫鏈接須要四個參數:數據庫驅動類DBDriver、數據庫鏈接URL、用戶名、密碼。
注意須要在項目的構建路徑下放入相應的數據庫鏈接驅動, mysql-connector-java-5.1.6-bin
鏈接MySQL數據庫下的test數據庫,用戶名爲root、密碼爲123456。
DataBaseConnection.java
// 本類只用於數據庫鏈接及關閉操做 package cn.hist.test.dbconn; import java.sql.* ; //主要功能就是鏈接數據庫、關閉數據庫 public class DataBaseConnection{ //定義數據庫驅動類 private final String DBDRIVER = "org.gjt.mm.mysql.Driver"; //定義數據庫鏈接URL private final String DBURL = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF8"; //定義數據庫鏈接用戶名 private final String DBUSER = "root"; //定義數據庫鏈接密碼 private final String DBPASSWORD = "123456"; //定義數據庫鏈接對象 private Connection conn = null ; //構造方法,加載驅動 public DataBaseConnection(){ try{ Class.forName(DBDRIVER) ; conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ; } catch (Exception e){ System.out.println("加載驅動失敗"); } } // 取得數據庫鏈接 public Connection getConnection() { return this.conn; } // 關閉數據庫鏈接 public void close(){ try{ conn.close() ; }catch (Exception e){ System.out.println("數據庫鏈接關閉失敗"); } } }
二、VO(Value Objects)值對象:與數據庫表一一對應的Java類。含有與數據庫表字段一一對應的屬性,相應屬性的getter和setter方法。甚至還有一些驗證方法。VO提供了一個面向對象的方法來操做數據庫。之後咱們的DAO接口就是經過調用VO來進行數據庫操做的。
例:對應於數據庫表T_User:三個字段,id、username、password。相應的VO類
User.java
package cn.hist.test.vo; public class User { // 用戶姓名 private String username; // 用戶密碼 private String password; // 得到用戶名 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; } }
三、DAO接口:定義了全部的用戶的操做,如添加記錄、刪除記錄和查詢記錄等。這不是一個具體的實現類,而是一個接口,僅僅定義了相應的操做(方法),這是給後來的具體實現提供一種靈活性和易維護性。具體的實現須要具體實現類實現這個接口的方法來實現。
UserDAO.java
package cn.hist.test.dao; import cn.hist.test.vo.User; //定義數據庫操做方法 public interface UserDAO { // 用戶名,密碼登陸 public boolean isLogin (User user) throws Exception ; }
四、DAO實現類:這裏纔是具體的操做的實現。須要實現DAO接口以及相應的方法。
UserDAOImpl.java
package cn.hist.test.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import cn.hist.test.dao.UserDAO; import cn.hist.test.vo.User; public class UserDAOImpl implements UserDAO { private Connection conn = null; private PreparedStatement pstmt = null; public UserDAOImpl(Connection conn) {//構造方法取得與數據庫鏈接 this.conn = conn; } // 用戶名,密碼登陸操做 public boolean isLogin(User user) throws Exception { boolean flag = false; String sql = "SELECT * FROM user" ; this.pstmt = this.conn.prepareStatement(sql); //預編譯 ResultSet rs = pstmt.executeQuery() ; String username = user.getUsername(); String password = user.getPassword(); while (rs.next()) { // 查詢出內容,分別與用戶輸入的用戶名和密碼進行比較 if (username.equals(rs.getString("username")) && password.equals(rs.getString("password"))) { flag = true; } } this.pstmt.close(); //關閉打開的操做 return flag; } }
五、Proxy:代理實現類。主要完成數據庫的打開和關閉,並調用Impl類對象(真實對象類)的操做,之因此增長代理類是爲了之後的拓展,若是一個程序能夠A-B,那麼中間最好加一個過渡,使用A-C-B的形式,能夠有效減小程序的耦合度,使開發結構更加清晰。
UserDAOProxy.java
package cn.hist.test.proxy;//代理類 import cn.hist.test.dao.UserDAO; import cn.hist.test.dbconn.DataBaseConnection; import cn.hist.test.impl.UserDAOImpl; import cn.hist.test.vo.User; public class UserDAOProxy implements UserDAO { private DataBaseConnection dbc = null; //定義數據庫鏈接類 private UserDAO userDAOImpl = null; //聲明DAO public UserDAOProxy() throws Exception { //構造方法中實例化鏈接與實例化DAO對象 this.dbc = new DataBaseConnection(); //鏈接數據庫 this.userDAOImpl = new UserDAOImpl(this.dbc.getConnection());//實例化真實類 } public boolean isLogin(User user) throws Exception { boolean flag = false; //首先要定義要返回的變量 try { flag = userDAOImpl.isLogin(user); //調用真實主題操做 } catch (Exception e) { throw e; } finally { dbc.close(); //關閉數據庫 } return flag; } }
六、DAO工廠類:在沒有DAO工廠類的狀況下,必須經過建立DAO實現類的實例才能完成數據庫的操做。這時要求必須知道具體的實現子類,對於後期的修改十分不便。如後期須要建立一個該DAO接口的Oracle實現類。這時就必須修改全部使用DAO實現類的代碼。若是使用DAO工廠類的一個靜態方法(不須要建立對象便可調用)來獲取DAO實現類實例,這時替換DAO實現類,只需修改DAO工廠類中的方法代碼,而不須要修改全部的調用DAO實現的代碼。
DAO工廠類是一個單例模式,這樣避免的數據庫的不一致。
例:經過DAO工廠類來獲取具體的DAO實現類。
DAOFactory.java
package cn.hist.test.factory;//工廠類(可以根據可以根據不一樣的參數信息獲得對象的實例) import cn.hist.test.dao.UserDAO; import cn.hist.test.proxy.UserDAOProxy; public class DAOFactory { public static UserDAO getUserDAOInstance() throws Exception { //取得DAO接口實例 return new UserDAOProxy(); //取得代理類的實例 } }
3、用戶登陸實例
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>2</title> <link rel="stylesheet" href=""> </head> <form id="form1" action="LoginCheck" method="post"> username: <input type="text" name="username" id="username" /> password: <input type="password" name="password" id="password" /> <input type="submit" value="登陸" id="send" /> </form> </body> </html>
LoginCheck.java
package cn.hist.test.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import cn.hist.test.dao.UserDAO; import cn.hist.test.factory.DAOFactory; import cn.hist.test.vo.User; public class LoginCheck extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); boolean flag = false; HttpSession session = req.getSession(); String username = req.getParameter("username"); String password = req.getParameter("password"); UserDAO userDAOProxy = null; try { userDAOProxy = DAOFactory.getUserDAOInstance(); } catch (Exception e1) { e1.printStackTrace(); } User user = new User(); user.setUsername(username); user.setPassword(password); try { flag = userDAOProxy.isLogin(user); if (flag) { session.setAttribute("user", user); resp.sendRedirect("success.jsp"); } else { resp.sendRedirect("fail.jsp"); } } catch (Exception e) { e.printStackTrace(); } } }
success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Test</title> <link rel="stylesheet" href=""> </head> <body> ${sessionScope.user.username} ,歡迎登陸。 <a href="Exit">退出</a> </body> </html>
fail.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>fail</title> <link rel="stylesheet" href=""> </head> <body> <p>登陸失敗!</p> </body> </html>
Exit.java
package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class Exit extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); session.removeAttribute("user"); resp.sendRedirect("login.jsp"); } }
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>LoginCheck</servlet-name> <servlet-class>cn.hist.test.servlet.LoginCheck</servlet-class> </servlet> <servlet> <servlet-name>Exit</servlet-name> <servlet-class>cn.hist.test.servlet.Exit</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginCheck</servlet-name> <url-pattern>/LoginCheck</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Exit</servlet-name> <url-pattern>/Exit</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>