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>