MVC+DAO設(shè)計(jì)模式下的設(shè)計(jì)流程詳解
DAO設(shè)計(jì) :
DAO層主要是做數(shù)據(jù)持久層的工作,負(fù)責(zé)與數(shù)據(jù)庫(kù)進(jìn)行聯(lián)絡(luò)的一些任務(wù)都封裝在此,DAO層的設(shè)計(jì)首先是設(shè)計(jì)DAO的接口,然后在Spring的配置文件中定義此接口的實(shí)現(xiàn)類,然后就可在模塊中調(diào)用此接口來(lái)進(jìn)行數(shù)據(jù)業(yè)務(wù)的處理,而不用關(guān)心此接口的具體實(shí)現(xiàn)類是哪個(gè)類,顯得結(jié)構(gòu)非常清晰,DAO層的數(shù)據(jù)源配置,以及有關(guān)數(shù)據(jù)庫(kù)連接的參數(shù)都在Spring的配置文件中進(jìn)行配置。
在該層主要完成對(duì)象-關(guān)系映射的建立,通過(guò)這個(gè)映射,再通過(guò)訪問(wèn)業(yè)務(wù)對(duì)象即可實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的訪問(wèn),使得開(kāi)發(fā)中不必再用SQL語(yǔ)句編寫(xiě)復(fù)雜的數(shù)據(jù)庫(kù)訪問(wèn)程序,這樣就簡(jiǎn)化了對(duì)數(shù)據(jù)庫(kù)的訪問(wèn),提高了開(kāi)發(fā)效率。同時(shí)通過(guò)對(duì)象-關(guān)系映射的配置,可以建立業(yè)務(wù)對(duì)象之間的復(fù)雜關(guān)系,如一對(duì)多、多對(duì)一、一對(duì)一、多對(duì)多等關(guān)系。這樣就不再需要在數(shù)據(jù)庫(kù)中建立表之間的復(fù)雜聯(lián)系,使得業(yè)務(wù)對(duì)象之間的關(guān)系和數(shù)據(jù)庫(kù)相分離,簡(jiǎn)化了數(shù)據(jù)庫(kù)的建立和維護(hù)。在這一層中主要使用Hibernate框架來(lái)實(shí)現(xiàn)。
針對(duì)以上問(wèn)題,產(chǎn)生了基于MVC模式Model層的DAO模式(Data Access Object),主要由工廠類(Factory)、代理類(Proxy)、實(shí)現(xiàn)類(DAOImpl)、DAO接口和值對(duì)象類(VO)以及數(shù)據(jù)庫(kù)連接類組成。
這里總結(jié)一下MVC+DAO的設(shè)計(jì)流程。通過(guò)MVC+DAO的設(shè)計(jì)模式,可以使項(xiàng)目在設(shè)計(jì)過(guò)程中結(jié)構(gòu)更為明晰,并且能夠方便的進(jìn)行修改。MVC是一個(gè)分層模型,即模型、視圖、控制器。DAO是一個(gè)數(shù)據(jù)庫(kù)訪問(wèn)模型,隔離數(shù)據(jù)庫(kù)操作。
環(huán)境說(shuō)明:
數(shù)據(jù)庫(kù):mysql
開(kāi)發(fā)語(yǔ)言:JSP + Servlet + Java
服務(wù)器:tomcat 7.x
包規(guī)劃:
entity 放置與數(shù)據(jù)庫(kù)中的表相對(duì)應(yīng)的實(shí)體類
dao 放置DAO設(shè)計(jì)模式下實(shí)現(xiàn)訪問(wèn)數(shù)據(jù)庫(kù)的接口
dao.impl 放置DAO對(duì)應(yīng)的接口實(shí)現(xiàn)類
servlet 放置Servlet
util 工具包
設(shè)計(jì)流程綜述:
0.設(shè)計(jì)數(shù)據(jù)庫(kù)以及視圖頁(yè)面(VIEW)
1.設(shè)計(jì)數(shù)據(jù)庫(kù)的工具類
2.設(shè)計(jì)符合java bean標(biāo)準(zhǔn)的entity類 (MODEL)
3.設(shè)計(jì)訪問(wèn)數(shù)據(jù)庫(kù)的DAO接口
4.設(shè)計(jì)實(shí)現(xiàn)DAO接口的實(shí)現(xiàn)類
5.創(chuàng)建Servlet響應(yīng)請(qǐng)求(CONTROLLER)
例子:以一個(gè)簡(jiǎn)單的登錄頁(yè)面設(shè)計(jì)為例
0.設(shè)計(jì)數(shù)據(jù)庫(kù)以及視圖頁(yè)面
數(shù)據(jù)庫(kù)設(shè)計(jì):
CREATE TABLE `NewTable` ( `id` int(10) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT , `name` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL , `password` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL , PRIMARY KEY (`id`) )
頁(yè)面視圖:
index.jsp的核心代碼如下:
<form action="/iMath/servlet/AdminServlet?method=login" method="post"> <table border='1' align="center"> <caption>USER LOGIN</caption> <tr> <th>username</th> <th><input type="text" name="username" /></th> </tr> <tr> <th>password</th> <th><input type="password" name="password" /></th> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="submit" /></td> </tr> </table> </form>
核心代碼就是一個(gè)form表單,用于提供視圖,為用戶提供輸入的接口。核心是指定action和method屬性。這應(yīng)該是最簡(jiǎn)單的一步,下面的工作則進(jìn)入真正的代碼編寫(xiě)階段。
轉(zhuǎn)發(fā)頁(yè)面:
message.jsp核心代碼如下:其實(shí)就句話
<body> ${message} </body>
1.設(shè)計(jì)數(shù)據(jù)庫(kù)的工具類
這步的操作應(yīng)該是大同小異的,目的只是抽取公共代碼,簡(jiǎn)化程序流程。
dbConfig.properties 文件存放數(shù)據(jù)庫(kù)的配置文件,這么做的優(yōu)點(diǎn)的是可以項(xiàng)目編譯后也能方便的修改數(shù)據(jù)庫(kù)配置的相關(guān)信息。
driver = com.mysql.jdbc.Driver url = jdbc:mysql://127.0.0.1:3306/imath?useUnicode=true&characterEncoding=utf-8 user = root password =1234
DBUtil類設(shè)計(jì):該類用實(shí)現(xiàn)建立數(shù)據(jù)庫(kù)連接和關(guān)閉數(shù)據(jù)庫(kù)連接的公共操作。
代碼如下:
package cn.imath.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public final class DBUtil { private static String driver; private static String url; private static String user; private static String password; /** * load the property file */ static{ Properties props = new Properties(); //get the class loader InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("cn/imath/util/dbConfig.properties"); try { props.load(is); } catch (Exception e) { e.printStackTrace(); } driver = props.getProperty("driver"); url = props.getProperty("url"); user = props.getProperty("user"); password = props.getProperty("password"); } /** * register the driver */ static{ try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * OPEN THE DATABASE CONNECTION * @return */ public static Connection getConn(){ Connection conn = null; try { conn = DriverManager.getConnection(url, user, password); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * CLOSE THE DATABASE CONNECTION * @param rs */ public static void closeAll(ResultSet rs,Statement stmt,Connection conn){ close(rs); close(stmt); close(conn); } public static void close(ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } public static void close(Statement stmt){ if(stmt!=null){ try { stmt.close(); } catch (Exception e) { e.printStackTrace(); } } } public static void close(Connection conn){ if(conn!=null){ try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } } }
這里要注意的是:導(dǎo)入的包均為java.sql包。這里建立了兩個(gè)核心方法,后面會(huì)經(jīng)常用到 getConn() 和 closeAll()方法,分別用于取得數(shù)據(jù)庫(kù)連接和關(guān)閉數(shù)據(jù)庫(kù)連接。
2.設(shè)計(jì)符合java bean標(biāo)準(zhǔn)的entity類
這里的entity類對(duì)應(yīng)于上面的admin表。因此設(shè)計(jì)Admin類如下:
package cn.imath.entity; public class Admin { private int id; private String name; private String password; 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; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
entity類的設(shè)計(jì)是為了實(shí)現(xiàn)對(duì)數(shù)據(jù)的封裝,只要對(duì)照數(shù)據(jù)庫(kù)設(shè)計(jì)來(lái)就行,然后最好符合java bean的設(shè)計(jì)標(biāo)準(zhǔn),用getter/setter實(shí)現(xiàn)訪問(wèn)。
3.設(shè)計(jì)訪問(wèn)數(shù)據(jù)庫(kù)的DAO接口
dao接口的設(shè)計(jì)非常簡(jiǎn)單,目的是為后面的具體的業(yè)務(wù)方法提供一個(gè)模版。
AdminDao接口如下:
package cn.imath.dao; import cn.imath.entity.Admin; public interface AdminDao { /** * LOGIN METHOD * @param username * @param password * @return INSTANCE OF Admin */ public Admin login(String username,String password); }
4.設(shè)計(jì)實(shí)現(xiàn)DAO接口的實(shí)現(xiàn)類
接下來(lái)設(shè)計(jì)上面DAO接口的實(shí)現(xiàn)類,用于實(shí)現(xiàn)具體的業(yè)務(wù)。這里就能體現(xiàn)上面模版的作用。
package cn.imath.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import cn.imath.dao.AdminDao; import cn.imath.entity.Admin; import cn.imath.util.DBUtil; public class AdminDaoImpl implements AdminDao { /** * LOGIN METHOD */ public Admin login(String username, String password) { String sql = "select * from admin where name=? and password=? "; Connection conn = DBUtil.getConn(); try { PreparedStatement pstmt = conn.prepareStatement(sql); //set the query parameters pstmt.setString(1,username); pstmt.setString(2, password); ResultSet rs = pstmt.executeQuery(); if(rs.next()){ int id = rs.getInt(1); Admin ad = new Admin(); ad.setId(id); ad.setPassword(password); ad.setName(username); return ad; } } catch (SQLException e) { e.printStackTrace(); } return null; } }
dao的實(shí)現(xiàn)類實(shí)現(xiàn)了具體的業(yè)務(wù)方法,封裝了sql的相關(guān)操作。
5.創(chuàng)建Servlet響應(yīng)請(qǐng)求
Servlet負(fù)責(zé)處理請(qǐng)求。
package cn.imath.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.imath.dao.AdminDao; import cn.imath.dao.impl.AdminDaoImpl; import cn.imath.entity.Admin; public class AdminServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String method = request.getParameter("method"); if(method!=null){ if("login".equals(method)){ this.login(request,response); } } } private void login(HttpServletRequest request, HttpServletResponse response) { String username = request.getParameter("username"); String password = request.getParameter("password"); AdminDao dao = new AdminDaoImpl(); Admin ad = dao.login(username, password); if(ad!=null){ request.setAttribute("message", "Login Success"); }else{ request.setAttribute("message", "Login Failed"); } try { request.getRequestDispatcher("/message.jsp").forward(request, response); } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
這里將login方法獨(dú)立于doPost方法,這樣有助于對(duì)功能的擴(kuò)充。
這里介紹的只是MVC+DAO的設(shè)計(jì)流程,通過(guò)這種模式可以改進(jìn)項(xiàng)目的設(shè)計(jì),使項(xiàng)目結(jié)構(gòu)更為清晰,有了合理的方法,具體的項(xiàng)目才不致太混亂。最后,說(shuō)一下需要改進(jìn)的地方:
1.數(shù)據(jù)庫(kù)的連接控制,可以用連接池進(jìn)行改進(jìn),如DBCP或C3P0
2.數(shù)據(jù)庫(kù)操作可以用common dbutils進(jìn)行改進(jìn)
總結(jié)
以上就是本文關(guān)于MVC+DAO設(shè)計(jì)模式下的設(shè)計(jì)流程詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。歡迎參閱:Spring MVC實(shí)現(xiàn)的登錄攔截器代碼分享、SpringMVC使用MultipartFile 實(shí)現(xiàn)異步上傳方法介紹、Spring SpringMVC在啟動(dòng)完成后執(zhí)行方法源碼解析等,有什么問(wèn)題,可以隨時(shí)留言指出。感謝大家!
相關(guān)文章
Java時(shí)區(qū)轉(zhuǎn)換及Date類實(shí)現(xiàn)原理解析
這篇文章主要介紹了Java時(shí)區(qū)轉(zhuǎn)換及Date類實(shí)現(xiàn)原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java基于PDFbox實(shí)現(xiàn)讀取處理PDF文件
PDFbox是一個(gè)開(kāi)源的、基于Java的、支持PDF文檔生成的工具庫(kù),它可以用于創(chuàng)建新的PDF文檔,修改現(xiàn)有的PDF文檔,還可以從PDF文檔中提取所需的內(nèi)容。本文將具體介紹一下PDFbox讀取處理PDF文件的示例代碼,感興趣的可以學(xué)習(xí)一下2022-02-02MyBatis-Puls插入或修改時(shí)某些字段自動(dòng)填充操作示例
這篇文章主要為大家介紹了MyBatis-Puls插入或修改時(shí)某些字段自動(dòng)填充操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Springboot整合GuavaCache緩存過(guò)程解析
這篇文章主要介紹了springboot整合GuavaCache緩存過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02解決spring懶加載以及@PostConstruct結(jié)合的坑
這篇文章主要介紹了解決spring懶加載以及@PostConstruct結(jié)合的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Junit Mockito實(shí)現(xiàn)單元測(cè)試方法介紹
JUnit是用于編寫(xiě)和運(yùn)行可重復(fù)的自動(dòng)化測(cè)試開(kāi)源測(cè)試項(xiàng)目框架,這樣可以保證我們的代碼按與其工作。JUnit可廣泛用于工業(yè)和作為支架(從命令行)或IDE(如IDE)內(nèi)單獨(dú)的java程序2022-09-09