經典項目,練手必備。
- 圖書管理系統
需求分析(大致,並不專業):1.需要有用戶管理;
1.1 用戶注冊;
1.2 用戶登錄;
1.3 用戶信息修改;
1.4 用戶修改密碼;
2.需要有書本管理;
2.1 添加書籍;
2.2 借出書籍;
2.3 歸還書籍;
2.4 修改/更新書籍信息;
3.需要權限管理;
3.1 普通用戶與管理員的區別;
3.2 擁有不同權限可瀏覽不同的頁面;
實現技術:1.struts2表現層框架;
2.hibernate持久層框架;
3.tomcat web容器;
4.c3p0數據庫連接池;
5.msql數據庫;
6.jquery開源包;
7.ajax技術;
8.css/html頁面設計。
- 准備階段
配置環境:配置struts2,hibernate環境,配上tomcat服務器,安裝mysql服務器;
表設計:本項目設計四張表:user,book,borrow,description
系統總體設計:
頁面設計:
- 實現
采用mvc的設計模式,頁面請求到action,action開啟服務service,service調用dao來操作數據庫。最后將結果返回到頁面上呈現。
tips:1.連接池使用listener啟動,因為它啟動得最早,而且spring也是使用listener來初始化bean工廠;
2.filter用來做權限控制;
3.action實現modeldriven接口,需要新建一些映射表單的類;
4.業務寫多了會無聊,並且邏輯都一樣,所以我選擇只實現了一半;
頁面圖:
index.jsp
register.jsp
findpassword.jsp
message頁面,統一樣式
main.jsp
userBook.jsp
就實現了這些功能,寫業務比算法無聊很多,所以大致掌握了就行了,反正練手。
- 技術筆記
頁面延遲n秒跳轉
//自動跳轉的輪子 function delayURL(url, time) { setTimeout("top.location.href='" + url + "'", time); }
在html中加入
<script type="text/javascript"> delayURL("findPasswd.jsp", 3000); </script>
初始化請求
在頁面載入成功后請求服務器拿初始化數據,並生成表格。
//初始化請求--將當前頁和總頁面初始化 和 list $(document).ready(function(){ pagerRequest(currentPage); });
使用數據生成表格。
//將數據放在頁面上 function putOnTable(list) { var table = $('#content'); $("#content tr:not(:first)").remove(); for ( var k in list) { var tr = $("<tr></tr>"); tr.appendTo(table); var book = new Object(); var td; book.bookid = list[k]['bookid']; book.bookname = list[k]['bookname']; book.authorname = list[k]['authorname']; book.publisher = list[k]['publisher']; book.pub_date = list[k]['pub_date']; td = $("<td>" + book.bookid + "</td>"); td.appendTo(tr); td = $("<td>" + book.bookname + "</td>"); td.appendTo(tr); td = $("<td>" + book.authorname + "</td>"); td.appendTo(tr); td = $("<td>" + book.publisher + "</td>"); td.appendTo(tr); td = $("<td>" + book.pub_date + "</td>"); td.appendTo(tr); td = $("<td><button id=btn"+book.bookid +">借書</button>|<button value=''>查看詳情</button>"); td.appendTo(tr); addEvent('btn'+book.bookid,book.bookid);//此處添加事件 } }
分頁查詢
//點擊按鈕發送ajax請求 function pagerRequest(need) { $.post("pager", "need=" + need , function(result) { size = result['size']; count = result['count']; booklist = result['booklist']; $('#current').text(currentPage); var n1; var n2; n1 = count / size; n2 = count % size; n1 = Math.floor(n1); pageNumber = n1; if (n2 !== 0) pageNumber = pageNumber + 1; $('#total').text(pageNumber); putOnTable(booklist); }); }
<!-- 分頁查詢動作--> <action name="pager" class="Action.BookPageSelectAction" method="Pager"> <result type="json"> <!-- 這里指定將被Struts2序列化的屬性,該屬性在action中必須有對應的getter方法 --> <param name="root">dataMap</param> </result> </action>
package Action; import java.util.HashMap; import java.util.List; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; import Model.book; import Service.bookService; public class BookPageSelectAction extends ActionSupport{ private HashMap<String,Object> dataMap; private List<book> bookList; private int size=10; public List<book> getUserList() { return bookList; } public void setUserList(List<book> bookList) { this.bookList = bookList; } public HashMap<String, Object> getDataMap() { return dataMap; } public void setDataMap(HashMap<String, Object> dataMap) { this.dataMap = dataMap; } //ajax請求頁 public String Pager(){ dataMap = new HashMap<String,Object>(); bookService pager = new bookService(); int count = pager.getBookCount(); String req = ServletActionContext.getRequest().getParameter("need"); Integer value = new Integer(req); int need = value.intValue(); List list = pager.pageSelectService(need, size); dataMap.put("booklist",list); dataMap.put("size", size); dataMap.put("count", count); return SUCCESS; } }
//分頁查詢 public List pageSelectService(int start,int size){ Session session = SFactoryGenerator.getSession(); Transaction tx = session.beginTransaction(); List list = null; try{ int need = (start-1)*size; list = bookDAO.pageSelect(session,need, size); }catch (Exception e) { // TODO: handle exception tx.rollback(); }finally{ session.close(); } return list; }
//分頁查詢 public static List<book> pageSelect(Session session,int start,int size){ String hql = "from book"; Query<?> query = session.createQuery(hql); query.setFirstResult(start);//開始索引 query.setMaxResults(size);//取幾條 List list = query.list(); return list; }
刪除所有表格條目,只留下表頭
$("#content tr:not(:first)").remove();
綁定事件
$('#'+btnid).bind("click",function(){});
添加通知欄
別人的輪子
//添加通知框 function pop_init(title,content) { //取當前瀏覽器窗口大小 var windowWidth=document.body.clientWidth; var windowHeight=document.body.clientHeight; //彈窗的大小 var weight=250; var height=132; $("body").append( "<div id='pop_div'style='display:none;position:absolute;border:1px solid #e0e0e0;z-index:99;width:"+weight+"px;height:"+height+"px;top:"+(windowHeight-height-132)+"px;left:"+(windowWidth-weight)+"px'>"+ "<div style='line-height:32px;background:#F4A460;border-bottom:1px solid #e0e0e0;font-size:14px;padding:0 0 0 10px;'>" + "<div style='float:left;'><b>"+title+"</b></div><div style='float:right;cursor:pointer;'><b onclick='pop_close()'>×</b></div>" + "<div style='clear:both'></div>"+ "</div>" + "<div id='content' style='background:#EED8AE;height:100px;'>" + content+ "</div>"+ "</div>" ); } function pop_close(){ $('#pop_div').fadeOut(400); }
前端校驗
非空校驗,長度校驗,用戶名是否存在校驗等等
/** * 用作注冊校驗以及ajax服務端校驗 */ //非空校驗 長度校驗 function verificationUsername(){ var data = $('#username').val(); if(data.length === 0) { $('#registerErrorMsg1').text("用戶名不能為空"); return false; } else if(data.length <3 || data.length>12) { $('#registerErrorMsg1').text("長度需要在3-12位"); return false; } return true; } //密碼校驗 var passwordVer1 = false; var passwordVer2 = false; function verificationPassword(){ var data = $('#password').val(); var again = $('#password1').val(); if(data.length === 0) { $('#registerErrorMsg2').text("密碼不能為空"); return ; } else if(data.length <6 || data.length>20) { $('#registerErrorMsg2').text("長度需要在6-20位"); return ; } passwordVer1 = true; } //ajax校驗 function ServerVerification(){ var data = $('#username').val(); $.get("userExist","username="+data,function(result){ if(result === "true"){ $('#registerErrorMsg1').text("用戶名已存在"); return false; } else { $('#registerErrorMsg1').text("此用戶名可以注冊"); return true; } }); } //用戶名校驗 $(document).ready(function(){ $('#username').blur(function(){ if(verificationUsername()) ServerVerification(); }); }); $(document).ready(function(){ $('#username').focus(function(){ $('#registerErrorMsg1').text(""); }); }); //密碼校驗 $(document).ready(function(){ $('#password').blur(function(){ verificationPassword(); }); }); $(document).ready(function(){ $('#password').focus(function(){ $('#registerErrorMsg2').text(""); }); }); //兩次輸入密碼校驗 $(document).ready(function(){ $('#password1').blur(function(){ if($('#password1').val() !== $('#password').val()) { $('#registerErrorMsg2').text("密碼輸入不一致"); return ; }else { $('#registerErrorMsg2').text(""); passwordVer2 = true; } }); }); //提交時候需要驗證 $(document).ready(function(){ $("#registerform").submit(function(){ verificationPassword(); console.log("-----3------"); if(verificationUsername() && passwordVer1 && passwordVer2) { return true; }else return false; }); });
查找書本
使用hql的都是這樣寫,被划了橫線了好像是過期方法
//查找書本 public static book findByName(Session session,String name){ String hql = "from book where bookname = ?"; Query<?> query = session.createQuery(hql); query.setParameter(0, name); List list = query.list(); book book = null; if(list.size() != 0) book =(book) list.get(0); return book; }
使用count計算條目
//獲取書本的條數 public static int getBookCount(Session session){ String hql="SELECT COUNT(*) FROM book"; Query<?> query = session.createQuery(hql); return ((Number)query.uniqueResult()).intValue(); }
自定類聯合查詢
不會join,用的where and。新建一個類不需要添加mapping也能封裝成object。
//獲取借書列表 public static List user_bookList(Session session,int userid){ String hql = "select new Model.user_book(b.bookid,b.bookname,b.publisher,bo.date) from book b,borrow bo where bo.user_id = ? and bo.book_id = b.bookid"; Query query =session.createQuery(hql); query.setParameter(0, userid); List list = query.list(); if(list.size() == 0) return null; return list; }
request
request的attribute和parameter是兩個東西,已parameter是跟在請求后面的參數,attribute是類似於session這種存儲在request范圍內的屬性。
標准的獲取形式為
//獲取請求響應 HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse();
- 總結
個人覺得不寫之前很簡單,寫了之后也很簡單。但是寫的過程有很多的不懂,所以項目還是要做一下不然抱着demo不知道怎么用。因為s和h框架很少用了,所以不專注於寫這個項目了。關鍵是網站的大部分的功能如何構建,換了框架和數據庫一樣是這樣實現。自己做一做小項目會增長很多的本事。寫了代碼也要多多總結,比如剛寫css的時候就感覺越寫越多,很多重復功能,因為不主攻前端,所以讓它變成臭雞蛋吧,這樣的感覺。
action的配置我覺得挺方便的,反而是注釋開發,好像不能一眼看完所有的controller,然而action太侵入性,所以已經有些過時。hibernate用了之后我覺得各有利弊吧,我還是喜歡jdbc的感覺。接下來就該細致地寫spring的項目了。