JAVA技巧(客戶(hù)訪(fǎng)問(wèn)限制管理器)

字號(hào):

前段時(shí)間開(kāi)發(fā)短信收發(fā)系統(tǒng),遇到一個(gè)問(wèn)題,就是有n個(gè)對(duì)象都可以通過(guò)Mobile對(duì)象發(fā)短信,但同一時(shí)刻只允許一個(gè)對(duì)象進(jìn)行操作。所以設(shè)計(jì)了一個(gè)客戶(hù)限制管理器的對(duì)象來(lái)解決,但由于種種原因沒(méi)有用到實(shí)際系統(tǒng)中。后來(lái)經(jīng)過(guò)仔細(xì)考慮,發(fā)現(xiàn)它不僅可以用于端口的管理,還可用于其他需要針對(duì)客戶(hù)訪(fǎng)問(wèn)數(shù)量進(jìn)行限制的各種服務(wù)中去。----這里的“客戶(hù)”是指要操作該管理器的對(duì)象
    /**
    * 客戶(hù)限制管理器的抽象類(lèi)
    * 此抽象類(lèi)實(shí)現(xiàn)了對(duì)客戶(hù)訪(fǎng)問(wèn)的限制,當(dāng)一個(gè)客戶(hù)訪(fǎng)問(wèn)該服務(wù)時(shí),可以通過(guò)halt(long guestid)方法阻止其他客戶(hù)進(jìn)行
    * 訪(fǎng)問(wèn),防止多個(gè)客戶(hù)同時(shí)訪(fǎng)問(wèn)產(chǎn)生的沖突。例如:對(duì)通訊端口的訪(fǎng)問(wèn)等。
    */
    public abstract class GuestManager {
    /**
    * 時(shí)間:一分鐘
    */
    protected static final long ONE_MINUTE = 60L * 1000L;
    /**
    * 時(shí)間:一小時(shí)
    */
    protected static final long ONE_HOUR = 60L * ONE_MINUTE;
    /**
    * 自動(dòng)清理客戶(hù)記錄的間隔時(shí)間
    */
    private long cleanInterval;
    /**
    * 客戶(hù)記錄<客戶(hù)標(biāo)識(shí),最近訪(fǎng)問(wèn)時(shí)間>
    */
    private Hashtable guests;
    /**
    * 當(dāng)前限制的客戶(hù)
    */
    private long limitGuest;
    /**
    * 自動(dòng)清除過(guò)期客戶(hù)的線(xiàn)程
    */
    private Thread autoCleanThread;
    /**
    * 客戶(hù)注冊(cè)
    *
    * @return 返回分配給客戶(hù)端的標(biāo)識(shí),如果注冊(cè)失敗,返回-1
    */
    public long login() {
    long guestid = -1L;
    // 增加客戶(hù)記錄
    Hashtable guests = getGuests();
    if (guests != null) {
    guestid = System.currentTimeMillis();
    guests.put("" + guestid, "" + guestid);
    update(guestid);
    // if (guests.size() == 1)
    // connect();
    }
    return guestid;
    }
    /**
    * 檢查客戶(hù)是否已經(jīng)注冊(cè)
    *
    * @param guestid
    * 客戶(hù)標(biāo)識(shí)
    * @return 如果客戶(hù)已經(jīng)注冊(cè)返回true,否則返回false
    */
    public boolean isLogin(long guestid) {
    boolean flag = false;
    if (guestid > 0) {
    Hashtable guests = getGuests();
    if (guests != null)
    flag = guests.containsKey("" + guestid);
    if (flag)
    update(guestid);
    }// end if (guestid > 0)
    return flag;
    }
    /**
    * 注銷(xiāo)客戶(hù)
    * 如果仍有其他客戶(hù)在使用此對(duì)象,則僅僅注銷(xiāo)guestid客戶(hù),否則調(diào)用disconnect()方法關(guān)閉連接。
    *
    * @param guestid
    * 客戶(hù)標(biāo)識(shí)
    * @return 返回是否成功注銷(xiāo)
    */
    public void logout(long guestid) {
    Hashtable guests = getGuests();
    if (guests != null) {
    if (guestid > 0 && guests.containsKey("" + guestid)) {
    guests.remove("" + guestid);
    }// end if (guestid > 0 && getGuests().containsKey("" +
    // guestid))
    }// end if (guests != null)
    }
    /**
    * 限制
    * 如果某一客戶(hù)調(diào)用了該方法,那么其他客戶(hù)將無(wú)法訪(fǎng)問(wèn),直至該客戶(hù)調(diào)用resume()釋放。
    *
    * @param guestid
    * 中斷標(biāo)識(shí)
    * @return 返回是否成功中斷
    */
    public boolean limit(long guestid) {
    boolean flag = false;
    if (isLogin(guestid)) {
    update(guestid);
    if (isLimit(guestid))
    return flag;
    limitGuest = guestid;
    flag = true;
    }// end if (isLogin(guestid))
    return flag;
    }
    /**
    * 釋放
    *
    * @param guestid
    * 客戶(hù)標(biāo)識(shí)
    * @return 返回是否釋放成功
    */
    public boolean resume(long guestid) {
    boolean flag = false;
    if (isLogin(guestid)) {
    update(guestid);
    if (limitGuest == guestid) {
    limitGuest = -1L;
    }// end if(haltGuest == guestid)
    flag = !isLimit();
    }
    return flag;
    }
    /**
    * 是否限制其他客戶(hù)調(diào)用
    *
    * @return 返回是否限制其他客戶(hù)調(diào)用
    */
    protected boolean isLimit() {
    boolean flag = false;
    if (limitGuest > 0) {
    long lasttime = Long.parseLong((getGuests().get(
    "" + limitGuest)));
    if (lasttime > 0) {
    // 如果10分鐘內(nèi)無(wú)響應(yīng),則注釋放該客戶(hù)的中斷
    long time = System.currentTimeMillis() - 10L
    * ONE_MINUTE;
    if (time < lasttime)
    flag = true;
    else
    limitGuest = -1;
    }
    }// end if(this.id <= 0)
    return flag;
    }
    /**
    * 該客戶(hù)是否被限制訪(fǎng)問(wèn)
    *
    * @param haltId
    * 客戶(hù)標(biāo)識(shí)
    * @return 返回true表示禁止訪(fǎng)問(wèn),false表示可以訪(fǎng)問(wèn)
    */ public boolean isLimit(long guestid) {
    boolean flag = true;
    if (isLogin(guestid)) {
    update(guestid);
    flag = isLimit();
    if (flag) {
    if (guestid > 0 && limitGuest == guestid)
    flag = false;
    }// end if(flag)
    }
    return flag;
    }
    /**
    * 取得當(dāng)前限制客戶(hù)的標(biāo)識(shí)(該標(biāo)識(shí)是該管理器為客戶(hù)分配的一個(gè)標(biāo)識(shí))
    *
    * @return 返回當(dāng)前限制客戶(hù)的標(biāo)識(shí)
    */
    protected long getLimitGuest() {
    return limitGuest;
    }
    /**
    * 更新客戶(hù)最近使用時(shí)間
    *
    * @param guestid
    * 客戶(hù)標(biāo)識(shí)
    */
    protected void update(long guestid) {
    runThread();
    Hashtable guests = getGuests();
    if (guests != null && guests.containsKey("" + guestid))
    guests.put("" + guestid, ""
    + System.currentTimeMillis());
    }
    /**
    * 運(yùn)行監(jiān)聽(tīng)線(xiàn)程
    */
    protected void runThread() {
    // 客戶(hù)自動(dòng)清理線(xiàn)程
    if (autoCleanThread != null && !autoCleanThread.isAlive())
    autoCleanThread = null;
    if (autoCleanThread == null) {
    autoCleanThread = new AutoCleanThread();
    autoCleanThread.start();
    }// end if (autoCleanThread == null)
    }
    /**
    * 設(shè)置自動(dòng)清理客戶(hù)記錄的間隔時(shí)間
    *
    * @param time
    * 間隔時(shí)間(毫秒)
    */
    public void setCleanInterval(long time) {
    if (time > 0)
    cleanInterval = time;
    }
    /**
    * 取得自動(dòng)清理客戶(hù)記錄的間隔時(shí)間
    *
    * @return 返回自動(dòng)清理客戶(hù)記錄的間隔時(shí)間(毫秒)
    */
    public long getCleanInterval() {
    return cleanInterval;
    }
    /**
    * 取得客戶(hù)記錄
    *
    * @return 返回客戶(hù)記錄。格式為<客戶(hù)標(biāo)識(shí),最近訪(fǎng)問(wèn)時(shí)間>
    */
    protected Hashtable getGuests() {
    if (guests == null)
    guests = new Hashtable();
    return guests;
    }
    /**
    * 輸出錯(cuò)誤信息
    *
    * @param err
    */
    public abstract void trace(String err);
    /**
    * 自動(dòng)清除超時(shí)的客戶(hù)端的線(xiàn)程
    *
    */
    private class AutoCleanThread extends Thread {
    public void run() {
    trace("AutoCleanThread thread start runing...");
    long interval = ONE_HOUR / 4L;
    if (getCleanInterval() > 0)
    interval = getCleanInterval();
    while (autoCleanThread == this && getGuests().size() > 0) {
    long time = System.currentTimeMillis()
    - ONE_HOUR / 2L;
    Enumeration keys = getGuests().keys();
    while (keys.hasMoreElements()) {
    String key = (String) keys.nextElement();
    if (key != null) {
    long lasttime = Long.parseLong(getGuests()
    .get(key));
    if (time > lasttime)
    // 超時(shí)
    getGuests().remove(key);
    }// end if (key != null)
    }// end while (keys.hasMoreElements())
    try {
    Thread.sleep(interval);
    } catch (InterruptedException e) {
    e.printStackTrace();
    trace("error - " + e.toString());
    }
    }// end while (mobiles != null && mobiles.size() > 0)
    trace("AutoCleanThread thread end...");
    }
    }
    }
    /**
    * 通訊端口的客戶(hù)端限制管理器的抽象類(lèi)
    * 該類(lèi)繼承自GuestManager類(lèi),增加了connect()、disconnect()等方法
    *
    * @author none
    *
    */
    public abstract class PortGuestManager extends GuestManager {
    /**
    * 連接
    *
    * @return 返回是否連接成功
    */
    protected abstract boolean connect();
    /**
    * 斷開(kāi)
    *
    * @return 返回是否斷開(kāi)成功
    */
    protected abstract boolean disconnect();
    /**
    * 是否已經(jīng)連接
    *
    * @return 返回端口是否已經(jīng)連接
    */
    protected abstract boolean isConnected();
    public long login() {
    long guestid = -1L;
    if (!isConnected())
    connect();
    if (isConnected())
    guestid = super.login();
    return guestid;
    }
    public boolean limit(long guestid) {
    boolean flag = false;
    if (isConnected())
    flag = super.limit(guestid);
    return flag;
    }
    public void logout(long guestid) {
    super.logout(guestid);
    Hashtable guests = getGuests();
    if (guests != null)
    if (guests.size() <= 0)
    disconnect();
    }
    public boolean isLimit(long guestid) {
    boolean flag = true;
    if (isConnected())
    flag = super.isLimit(guestid);
    return flag;
    }
    }