【Java EE 學習 56】【酒店會員管理系統技術點總結】

1、樹狀菜單加載javascript

  這是js的一個典型應用,使用zTree插件可以完成該項任務http://www.ztree.me/v3/main.phpphp

  我是用的版本:zTree2.5css

  使用方法:html

 1 <%@ page language="java" isELIgnored="false" import="java.util.*" pageEncoding="UTF-8"%>
 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6       <meta http-equiv="content-type" content="text/html;charset=utf-8">
 7     <title>導航菜單</title>
 8     <link rel="stylesheet" href="${pageContext.servletContext.contextPath}/css/menu.css" type="text/css">
 9     <link rel="stylesheet" href="${pageContext.servletContext.contextPath}/css/ztree/zTreeStyle/zTreeStyle.css" type="text/css">
10     <%@ include file="/jsp/common.jsp" %>
11     <script type="text/javascript" src="${pageContext.servletContext.contextPath}/js/ztree/jquery-ztree-2.5.js"></script>
12     <script type="text/javascript" src="${pageContext.servletContext.contextPath}/js/menu_tree.js"></script>
13   </head>
14   
15   <body>
16     <TABLE border=0 height=600px align=left>
17             <TR>
18                 <TD width=230px align=left valign=top style="BORDER-RIGHT: #999999 1px dashed">
19                     <ul id="tree" class="tree" style="width:230px; overflow:auto;"></ul>
20                 </TD>
21             </TR>
22     </TABLE>
23   </body>
24 </html>
zTree插件使用的html代碼

  核心代碼:前端

 <TABLE border=0 height=600px align=left>
            <TR>
                <TD width=230px align=left valign=top style="BORDER-RIGHT: #999999 1px dashed">
                    <ul id="tree" class="tree" style="width:230px; overflow:auto;"></ul>
                </TD>
            </TR>
    </TABLE>

  最重要的就是ul標籤了,該標籤的id屬性值爲tree,是加載樹形插件的關鍵。java

  樹形菜單的加載方式分爲兩種,一種是一次性加載,另一種就是單擊觸發式的加載一次性加載的方法比較簡單,可是面對大數據菜單的時候響應速度慢,用戶體驗很很差,因此這裏使用了單擊觸發式的加載。node

var tree={
        zTree:'',//經過調用post方法返回的對象
        pNode:'',//父節點
          setting:{
                isSimpleData: true,
                treeNodeKey: "mid",
                treeNodeParentKey: "pid",
                showLine: true,
                root:{ 
                    isRoot:true,
                    nodes:[]
                },
                callback:{
                    expand:function(event, treeId, treeNode){
                        tree.pNode=treeNode;//共享以後就不須要傳遞參數了。
                        treeNode.isParent=true,
                        tree.loadNodeByPNode();
                    }
                }
        },
        //加載樹根的方法
        loadRoot:function(){
                var parameters={
                    //首先加載父節點爲0的樹,即第一級目錄
                    pid:0    
                };
                $.post("Menuitem_showMenuItemsByPid.action",parameters,function(data){
                    tree.zTree=$("#tree").zTree(tree.setting,data.menuitems);
                    var node=tree.zTree.getNodeByParam("mid","1");
                    tree.pNode=node;
                    tree.loadNodeByPNode();
                    tree.zTree.expandNode(node,true);
              });
        },
        loadNodeByPNode:function(){
            var parameters={
                    //首先加載父節點爲0的樹,即第一級目錄
                    pid:tree.pNode.mid
                };
            //這裏須要先進行判斷當前節點是否有子節點
            if(!tree.zTree.getNodeByParam('pid',tree.pNode.mid)){
                $.post("Menuitem_showMenuItemsByPid.action",parameters,function(data){
//                $("#tree").zTree(tree.setting,data.menuItems);
                    tree.zTree.addNodes(tree.pNode,data.menuitems,true);
                    if(tree.pNode.mid==1){
                        var node=tree.zTree.getNodeByParam("mid","11");
                        tree.pNode=node;
                        tree.loadNodeByPNode();
                        tree.zTree.expandNode(node,true);
                    }
                });
            }
        }
};
$().ready(function(){
    tree.loadRoot();
});

    採用面面向對象的方法編程層次結構更加清晰,這裏涉及到了向數據庫發起異步請求的ajax方法以及在異步請求的狀況下默認展開菜單的處理方法。jquery

2、定時器的設計方法git

  普通的定時器實現方法有好多種,一開始我使用了監聽器和Servlet的方法,可是實現起來都不是那麼駕輕就熟,由於須要考慮到諸如目標對象建立時間問題等等麻煩問題,最好的方式是肯定目標對象必定建立完成以後再調用相關的方法。如今目標對象是RoomServiceImpl,個人需求是須要該對象歸入Spring容器管理以後調用該類中的一個初始化定時器的一個方法。很明顯,最好的實現方法是使用@PostConstruct註解,該註解的做用就是當對象在Spring中建立以後自動調用一個方法。該方法的調用時間在構造方法以後。github

  

@PostConstruct
    public void init() {
        //設置一個定時器,天天00:00的時候對房間狀態進行更新
        System.out.println("天天00:00進行定時更新");
        Calendar calendar=Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY,24);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND, 1);
        Timer timer=new Timer();
        timer.schedule(new TimerTask(){
            @Override
            public void run() {
                //天天00:00準時刷新數據
                refreshRoomState();
            }
        }, calendar.getTime(),24*60*60*1000);
    }

    refreshRoomState方法是最終將要定時執行的方法,該方法將使用到該對象中的某些對象屬性。因此初始化對象的同時必須還要將屬性值設置好,這就是spring容器的問題了。

    最關鍵的就是該方法調用的時機和定時器的使用方法。

3、日期插件的使用。

  日期插件不少,可是像樣的卻沒有幾個。這裏使用了老牌的日期插件DatePicker http://www.my97.net/dp/down.asp

  個人項目中的使用版本是最新的版本:https://github.com/kdyzm/HotelMembersManagement/tree/master/WebRoot/js/datePicker

  使用該日期插件的好處就是可以很方便的顯示時分秒

  1.顯示時分秒的使用方法:

<input type="text" id="d241" onfocus="WdatePicker({dateFmt:'yyyy年MM月dd日 HH時mm分ss秒'})" class="Wdate" style="width:300px"/>

  

  2.只是有年月日的使用方法,這種方法是最常規的使用方式

<input id="d11" type="text" onClick="WdatePicker()"/>

  

 

4、DAO層和Action層代碼重用

  1.首先DAO的頂層接口:BaseDao

import java.io.Serializable;
import java.util.Collection;

public interface BaseDao<T>{
    public Collection<T> getAllEntry();
    public T getEntryById(Serializable id);
    public void saveEntry(T t);
    public void deleteEntry(T t);
    public void updateEntry(T t);
}

  實現該接口的頂層父類:BaseDaoImpl,全部的DAO實現類都要繼承該父類

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import javax.annotation.Resource;

import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.kdyzm.dao.base.BaseDao;

public class BaseDaoImpl<T> implements BaseDao<T>{

    //泛型的真實類型
    private Class<T> clazz;
    @Resource(name="hibernateTemplate")
    public HibernateTemplate hibernateTemplate;
    
    public BaseDaoImpl() {
        //在默認構造方法中獲得真實的類型
        //ParameterizedType就是泛型
        ParameterizedType pt=(ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz=(Class) pt.getActualTypeArguments()[0];//獲得實際的參數類型,<T>
//        System.out.println(clazz.getSimpleName());
//        System.out.println(pt.getRawType());//打印聲明該方法的類或者接口類型,BaseServiceImpl
    }
    
    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

    @Override
    public Collection<T> getAllEntry() {
        Collection<T> collection= this.hibernateTemplate.find("from "+clazz.getName());
        return collection;
    }

    @Override
    public T getEntryById(Serializable id) {
        return (T) this.hibernateTemplate.get(clazz, id);
    }

    @Override
    @Transactional(readOnly=false)
    public void saveEntry(T t) {
        this.hibernateTemplate.save(t);
    }

    @Override
    @Transactional(readOnly=false)
    public void deleteEntry(T t) {
        this.hibernateTemplate.delete(t);
    }

    @Transactional(readOnly=false)
    @Override
    public void updateEntry(T t) {
        this.hibernateTemplate.update(t);
    }
}

  其中最重要的就是在構造方法中的語句

public BaseDaoImpl() {
        //在默認構造方法中獲得真實的類型
        //ParameterizedType就是泛型
        ParameterizedType pt=(ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz=(Class) pt.getActualTypeArguments()[0];//獲得實際的參數類型,<T>
//        System.out.println(clazz.getSimpleName());
//        System.out.println(pt.getRawType());//打印聲明該方法的類或者接口類型,BaseServiceImpl
    }

  兩句代碼是最重要的核心代碼。

  2.Action同理

import java.lang.reflect.ParameterizedType;

import org.apache.struts2.json.annotations.JSON;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class BaseAction<T> extends ActionSupport implements ModelDriven<T>{
    private static final long serialVersionUID = -1344990340960028510L;
    private T t;
    private Class<T> clazz;
    //使用構造方法建立T對象
    public BaseAction(){
        ParameterizedType parameterizedType=(ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz=(Class<T>) parameterizedType.getActualTypeArguments()[0];
        System.out.println(parameterizedType.getRawType());
        try {
            this.t=(T) this.clazz.newInstance();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
    public static final String LIST_ACTION="listAction";
    public static final String ADDUI="addUI";
    public static final String UPDATEUI="updateUI";
    public static final String ACTIONTOACTION="actionToAction";
    public static final String AJAXRESPONSE="ajaxResponse";
    public String listAction=LIST_ACTION;
    public String addUI=ADDUI;
    public String updateUI=UPDATEUI;
    public String actionToAction=ACTIONTOACTION;
    public String ajaxResponse=AJAXRESPONSE;
    @Override
    @JSON(serialize=false)
    public T getModel() {
        return t;
    }
}

5、實數的精度控制問題

  使用DecimalFormat類可以很方便的實現精度控制,以精確到小數點後兩位爲例:

public class DecimalUtils {
    public static String pattern="#.00";
    public static String get(double source){
        DecimalFormat df=new DecimalFormat(pattern);
        return df.format(source);
    }
}

6、日期處理問題

  寫了一個日期處理的工具類實現很方便的日期處理

package com.kdyzm.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日期處理工具類
 * @author kdyzm
 *
 */
public class DateUtils {
    //默認的日期格式
    private static String pattern="yyyy-MM-dd HH:mm:ss";
    public static void resetDefault(){
        pattern="yyyy-MM-dd HH:mm:ss";
    }
    public static void setPattern(String p){
        pattern=p;
    }
    public static String getPattern(){
        return pattern;
    }
    //日期格式對象轉換成字符串
    public static String dateToString(Date date){
        SimpleDateFormat sdf=new SimpleDateFormat(pattern);
        String dateString=sdf.format(date);
        return dateString;
    }
    //字符串格式轉化成日期對象
    public static Date stringToDate(String dateString){
        SimpleDateFormat sdf=new SimpleDateFormat(pattern);
        Date date=null;
        try {
            date=sdf.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
    //獲取年月日的方法,日期格式是yyyy-MM-dd HH:mm:ss
    public static String getYMDByDateString(String dateString){
        return dateString.split(" ")[0];
    }
    //獲取小時的方法,日期格式是yyyy-MM-dd HH:mm:ss
    public static String getHHByDateString(String dateString){
        return dateString.split(" ")[1].split(":")[0];
    }
    //測試工具類
    public static void main(String[] args) {
        DateUtils.setPattern("yyyy年MM月dd日 HH時mm分ss秒");
        String dateString="2015年10月8日 13時15分28秒";
        Date date =new Date();
        System.out.println(DateUtils.stringToDate(dateString));
        System.out.println(DateUtils.dateToString(date));
    }
}

7、使用struts2jar包實現前端和struts2交互的問題

  使用的jar包版本頗有問題,版本不正確各類問題都會出現。這裏使用的版本是2.1.8

  必須加入三個jar包:https://github.com/kdyzm/HotelMembersManagement/tree/master/WebRoot/WEB-INF/lib/json

  使用方法就是在Action中加入一個String類型的字段,並提供get和set方法

private String message;
public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }

  在前端獲取該響應信息:

$.post("Json_CardAction_isCardExists.action",parameter,function(data){
            if(data.message=="1"){
       }else{
        }

  Action中全部不須要返回到前端的數據的get方法以前必定要加上@JSON(serialize=false)註解。

  方法名稱儘可能不要使用getXXX,而要使用showXXX方法代替。

  特別是接口類型的引用更應該如此。不然的話必定會報錯。

8、fckEditor插件的使用問題

  借用demo便可。

  http://ckeditor.com/download

相關文章
相關標籤/搜索