struts2+hibernate 項目實戰:圖書管理系統


經典項目,練手必備。

  • 圖書管理系統

    需求分析(大致,並不專業):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的項目了。

 

    

 

 

 

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM