论坛首页 编程语言技术论坛

网络相册开发(2)——Spring,SPA,Hibernate框架

浏览 2088 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-03-12  

搭建java代码框架


 

引入辅助类和基类



 

PKgen为 PK 生成器

package net.sw.util;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 
 * 用来生成唯一的PK
 * 该 PK 生成器生成 19 位的唯一 long 值,精确到万分之一秒,
 * 最后一位为尾数,用来在集群环境下保证PK的唯一性。
 *  
 * 该PK生成虽然依赖于时间,但是在运行过程中改变时间不会影响PK,
 * 但是如果将系统时间后调,然后重新启动,有可能造成PK重复。
 * 
 * 该 PK 生成器不依赖于数据库,相比依赖数据表的PK生成器,速度快,而且值可读
 * 
 * @author <a href="mailto:yang_y@sysnet.com.cn">Young Yang</a>
 */

public class PKgen {

	/**
	 *  PK生成锁,用来限定同一时刻只有一个线程进入PK生成计算
	 */
	private final Lock LOCK = new ReentrantLock();
	/**
	 * 初始化时的毫秒数,因为该时间会随系统时间的改变而改变,
	 *  所以计算方法为该时间加上通过 nanoTime 计算出来的时间差
	 */
	private final static Long startMilli = System.currentTimeMillis();
	/**
	 * 初始化时的纳秒数,用来计量时间差,nanoTime不会随着系统时间的修改而改变
	 */
	private final static long startNano = System.nanoTime();
	/**
	 *  记录上一次生成 的 PK,如果新生成的PK和上次相等,则需要再次生成
	 */
	private volatile long lastPK = -1;
	//private final static SimpleDateFormat dateFormat = new SimpleDateFormat(
	//		"yyyyMMddHHmmssSSS");
	private final static SimpleDateFormat dateFormat = new SimpleDateFormat(
	"yyMMddHHmmssSSS");
	/**
	 * 返回的long PK的尾数,尾数可以用来在集群环境中判断该PK由哪一个节点产生
	 * 尾数通过配置设定
	 */
	private int suffix = 0;
	private static final Map<Integer, PKgen> instanceMap = new HashMap<Integer, PKgen>();
	// 必须提供正确的参数,以保证 suffix 在机群环境的唯一性
	private PKgen(int suffix) {
		this.suffix = suffix;
	}
	public synchronized static PKgen getInstance() {
		return getInstance(0);
	}
	/**
	 * 单机环境下,应该保证用相同的 suffix
	 * 在集群环境中,不同的机器必须提供不同的 suffix 来保证生成的ID的唯一性
	 * @param suffix
	 *            唯一标识好
	 */
	public synchronized static PKgen getInstance(int suffix) {
		PKgen pkgen;
		if (!instanceMap.containsKey(suffix)) {
			pkgen = new PKgen(suffix);
			instanceMap.put(suffix, pkgen);
		}
		else {
			pkgen = instanceMap.get(suffix);
		}
		return pkgen;
	}
	/**
	 * 返回下一个 long 型 PK, format: 2006111423361344491 <br>
	 * yyyyMMddHHmmssSSS + Macro Seconds + suffix
	 * @return long PK
	 */
	public long nextPK() {
		LOCK.lock();
		try {
			long newPK;
			do {
				long pastNano = System.nanoTime() - startNano; // 纳秒时间差
				long milliTime = pastNano / 1000000; // 取得毫秒差
				long macroTime = (pastNano / 100000) % 10; // 取得微秒第一位,
				// 计算出来的long PK,精度到万分之一秒(百微妙),加上尾数,一共19位,这是 Long.MAX_VALUE的最大位数了
				newPK = Long.parseLong(dateFormat.format(new Date(startMilli
						+ milliTime))
						+ macroTime + suffix);
			}
			while (lastPK == newPK); // 如果生成的相同,则再次计算
			lastPK = newPK; // 设置 lastPK
			return newPK;
		}
		finally {
			LOCK.unlock();
		}
	}
	public static void main(String[] args) throws Exception {
		PKgen pkg = PKgen.getInstance(0);
		int i = 0;
		long now = System.currentTimeMillis();
		while (i++ < 10) {
			System.out.println(pkg.nextPK());
		}
		System.out.println("Time: " + (System.currentTimeMillis() - now));
	}
}

 
如注释所述该 PK 生成器生成 19 位的long值,java中的Long在Flex中将转换为Number。Flex的Nubmer类型能精确处理的数据只有17位,所以注意43到46行,我在此处做了一点改动屏蔽了年的前两位,这样生成的 PK 实际上位17位。

 

BaseDomain

package net.sw.base.domain;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/**
 * 领域对象基类
 * 
 * @author vyyv
 * 
 */

@SuppressWarnings("serial")
@MappedSuperclass
public abstract class BaseDomain implements java.io.Serializable {

	public BaseDomain() {
// 对象有可能是在客户端由flex生成,不会执行这个构造方法,所以不能在此处添加ID
//		this.id = PKgen.getInstance(0).nextPK();
		this.id=new Long(0);
	}


	/**
	 * 领域对象编码
	 */
	@Id
	@Column
	Long id;

	/**
	 * 领域对象名称
	 */
	@Column
	String name;
	
	/**
	 * 领域对象描述
	 */
	@Column
	String description;
	
	/**
	 * 领域对象创建时间
	 */	
	@Column
	Date createtime;	

            (setter getter 略)
         ...........     ............

}

 

 

GenericDao

package net.sw.base.dao;

import java.io.Serializable;
import java.util.List;

/**
 *  
 * @author vyyv
 * @param <T>
 *            a type variable
 * @param <PK>
 *            the primary key for that type
 */
public interface GenericDao<T, PK extends Serializable> {

	/**
	 * 获取所有对象实例
	 * @return 由所有对象实例组成的List
	 */
	List<T> getAll();


	/**
	 * 获取一个对象实例
	 * 如果不存在抛出ObjectRetrievalFailureException
	 * @param id 对象ID
	 * @return 一个对象实例
	 * @see org.springframework.orm.ObjectRetrievalFailureException
	 */
	T get(PK id);

	/**
	 * 判断对象实例是否存在
	 *@param id 对象ID
	 * @return - 存在返回true,不存在返回false
	 */
	boolean exists(PK id);

	/**
	 * 保存对象实例 - 新建或更新
	 * @param object 需要保存的对象
	 * @return  保存之后的对象(保存的动作可能会修改对象,例如:ID,createtime)
	 */
	T save(T object);

	/**
	 * 删除对象实例
	 * @param id 
	 */
	void remove(PK id);

}

 GenericManager

package net.sw.base.service;

import java.io.Serializable;
import java.util.List;

/**
 * 
 * @author vyyv</a>
 * @param <T>
 *            a type variable
 * @param <PK>
 *            the primary key for that type
 */
public interface GenericManager<T, PK extends Serializable> {

	/**
	 * 获取所有对象实例
	 * @return 由所有对象实例组成的List
	 */
	List<T> getAll();

	/**
	 * 根据ID获取一个对象实例
	 * @param id 对象ID
	 * @return 一个对象实例
	 */
	T get(PK id);

	/**
	 * 判断对象实例是否存在
	 *@param id 对象ID
	 * @return - 存在返回true,不存在返回false
	 */
	boolean exists(PK id);

	/**
	 * 保存对象实例 - 新建或更新
	 * @param object 需要保存的对象
	 * @return  保存之后的对象(保存的动作可能会修改对象,例如:ID,createtime)
	 */
	T save(T object);

	/**
	 * 删除对象实例
	 * @param id 
	 */
	void remove(PK id);
}

 

  • 大小: 18.5 KB
  • 大小: 28.4 KB
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics