一、树状菜单加载
这是js的一个典型应用,使用zTree插件能够完成该项任务http://www.ztree.me/v3/main.php
我是用的版本:zTree2.5
使用方法:
<%@ page language="java" isELIgnored="false" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>导航菜单</title>
<link rel="stylesheet" href="${pageContext.servletContext.contextPath}/css/menu.css" type="text/css">
<link rel="stylesheet" href="${pageContext.servletContext.contextPath}/css/ztree/zTreeStyle/zTreeStyle.css" type="text/css">
<%@ include file="/jsp/common.jsp" %>
<script type="text/javascript" src="${pageContext.servletContext.contextPath}/js/ztree/jquery-ztree-2.5.js"></script>
<script type="text/javascript" src="${pageContext.servletContext.contextPath}/js/menu_tree.js"></script>
</head> <body>
<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>
</body>
</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,是加载树形插件的关键。
树形菜单的加载方式分为两种,一种是一次性加载,另外一种就是单击触发式的加载。一次性加载的方法比较简单,但是面对大数据菜单的时候响应速度慢,用户体验很不好,所以这里使用了单击触发式的加载。
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="width: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即可。