• 【Java EE 学习 56】【酒店会员管理系统技术点总结】


    一、树状菜单加载

      这是js的一个典型应用,使用zTree插件能够完成该项任务http://www.ztree.me/v3/main.php

      我是用的版本:zTree2.5

      使用方法:

     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="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="230px; overflow:auto;"></ul>
                    </TD>
                </TR>
        </TABLE>

      最重要的就是ul标签了,该标签的id属性值为tree,是加载树形插件的关键。

      树形菜单的加载方式分为两种,一种是一次性加载,另外一种就是单击触发式的加载一次性加载的方法比较简单,但是面对大数据菜单的时候响应速度慢,用户体验很不好,所以这里使用了单击触发式的加载。

    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方法以及在异步请求的情况下默认展开菜单的处理方法。

    二、定时器的设计方法

      普通的定时器实现方法有好多种,一开始我使用了监听器和Servlet的方法,但是实现起来都不是那么得心应手,因为需要考虑到诸如目标对象创建时间问题等等麻烦问题,最好的方式是确定目标对象一定创建完成之后再调用相关的方法。现在目标对象是RoomServiceImpl,我的需求是需要该对象纳入Spring容器管理之后调用该类中的一个初始化定时器的一个方法。很明显,最好的实现方法是使用@PostConstruct注解,该注解的作用就是当对象在Spring中创建之后自动调用一个方法。该方法的调用时间在构造方法之后。

      

    @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容器的问题了。

        最关键的就是该方法调用的时机和定时器的使用方法。

    三、日期插件的使用。

      日期插件很多,但是像样的却没有几个。这里使用了老牌的日期插件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="300px"/>

      

      2.只是有年月日的使用方法,这种方法是最常规的使用方式

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

      

    四、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;
        }
    }

    五、实数的精度控制问题

      使用DecimalFormat类能够很方便的实现精度控制,以精确到小数点后两位为例:

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

    六、日期处理问题

      写了一个日期处理的工具类实现很方便的日期处理

    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));
        }
    }

    七、使用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方法代替。

      特别是接口类型的引用更应该如此。否则的话一定会报错。

    八、fckEditor插件的使用问题

      借用demo即可。

      http://ckeditor.com/download

  • 相关阅读:
    Sizzle引擎原理与实践(四)
    Sizzle引擎原理与实践(一)
    Sizzle引擎原生getElementsByClassName对选择结果的影响(jQuery)
    【翻译】HTML5开发——轻量级Web Database存储库html5sql.js
    【翻译】向后兼容的DOM事件绑定
    软件工程实践2019第二次作业
    软件工程实践2019第一次作业
    软件工程实践2019第四次作业
    发表文章
    Web设计
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/4944559.html
Copyright © 2020-2023  润新知