Jetsever开源项目学习(四)Session学习

 

 接口Session.java

package org.menacheri.jetserver.app;

import java.util.List;

import org.menacheri.jetserver.communication.MessageSender;
import org.menacheri.jetserver.communication.MessageSender.Fast;
import org.menacheri.jetserver.communication.MessageSender.Reliable;
import org.menacheri.jetserver.event.Events;
import org.menacheri.jetserver.event.Event;
import org.menacheri.jetserver.event.EventDispatcher;
import org.menacheri.jetserver.event.EventHandler;


public interface Session
{
    /**
     * session status types
     */
    enum Status
    {
        NOT_CONNECTED, CONNECTING, CONNECTED, CLOSED
    }

    Object getId();

    void setId(Object id);

    void setAttribute(String key, Object value);

    Object getAttribute(String key);

    void removeAttribute(String key);

    void onEvent(Event event);

    EventDispatcher getEventDispatcher();


    boolean isWriteable();

    void setWriteable(boolean writeable);

    /**
     * A session would not have UDP capability when created. Depending on the
     * network abilities of the client, it can request UDP communication to be
     * enabled with the LOGIN_UDP and CONNECT_UDP events of the {@link Events}
     * class. Once UDP is enabled this flag will be set to true on the session.
     * 
     * @return Returns true if the a UDP {@link MessageSender} instance is
     *         attached to this session, else false.
     */
    boolean isUDPEnabled();
    
    /**
     * A session would not have UDP capability when created. Depending on the
     * network abilities of the client, it can request UDP communication to be
     * enabled with the LOGIN_UDP and CONNECT_UDP events of the {@link Events}
     * class. Once UDP {@link MessageSender} instance is attached to the
     * session, this method should be called with flag to true to signal that
     * the session is now UDP enabled.
     * 
     * @param isEnabled
     *            Should be true in most use cases. It is used to signal that
     *            the UDP {@link MessageSender} has been attached to session.
     */
    void setUDPEnabled(boolean isEnabled);
    
    boolean isShuttingDown();
    
    long getCreationTime();

    long getLastReadWriteTime();

    void setStatus(Status status);

    Status getStatus();

    boolean isConnected();

    void addHandler(EventHandler eventHandler);
    
    void removeHandler(EventHandler eventHandler);
    
    List<EventHandler> getEventHandlers(int eventType);
    
    void close();

    public abstract void setUdpSender(Fast udpSender);

    public abstract Fast getUdpSender();

    public abstract void setTcpSender(Reliable tcpSender);

    public abstract Reliable getTcpSender();
}

 

DefaultSession.java

package org.menacheri.jetserver.app.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.menacheri.jetserver.app.Session;
import org.menacheri.jetserver.communication.MessageSender.Fast;
import org.menacheri.jetserver.communication.MessageSender.Reliable;
import org.menacheri.jetserver.event.Event;
import org.menacheri.jetserver.event.EventDispatcher;
import org.menacheri.jetserver.event.EventHandler;
import org.menacheri.jetserver.event.impl.EventDispatchers;
import org.menacheri.jetserver.service.UniqueIDGeneratorService;
import org.menacheri.jetserver.service.impl.SimpleUniqueIdGenerator;


/**
 * The default implementation of the session class. This class is responsible
 * for receiving and sending events. For receiving it uses the
 * {@link #onEvent(Event)} method and for sending it uses the
 * {@link EventDispatcher} fireEvent method. The Method {@link #setId(Object)}
 * will throw {@link IllegalArgumentException} in this implementation class.
 * 
 * @author Abraham Menacherry
 * 
 */
public class DefaultSession implements Session
{
    /**
     * session id
     */
    protected final Object id;
    /**
     * event dispatcher
     */
    protected EventDispatcher eventDispatcher;

    /**
     * session parameters
     */
    protected final Map<String, Object> sessionAttributes;

    protected final long creationTime;

    protected long lastReadWriteTime;

    protected Status status;

    protected boolean isWriteable;

    /**
     * Life cycle variable to check if the session is shutting down. If it is, then no
     * more incoming events will be accepted.
     */
    protected volatile boolean isShuttingDown;
    
    protected boolean isUDPEnabled;
    
    protected Reliable tcpSender = null;
    
    protected Fast udpSender = null;
    
    protected DefaultSession(SessionBuilder sessionBuilder)
    {
        // validate variables and provide default values if necessary. Normally
        // done in the builder.build() method, but done here since this class is
        // meant to be overriden and this could be easier.
        sessionBuilder.validateAndSetValues();
        this.id = sessionBuilder.id;
        this.eventDispatcher = sessionBuilder.eventDispatcher;
        this.sessionAttributes = sessionBuilder.sessionAttributes;
        this.creationTime = sessionBuilder.creationTime;
        this.status = sessionBuilder.status;
        this.lastReadWriteTime = sessionBuilder.lastReadWriteTime;
        this.isWriteable = sessionBuilder.isWriteable;
        this.isShuttingDown = sessionBuilder.isShuttingDown;
        this.isUDPEnabled = sessionBuilder.isUDPEnabled;
    }
    
    /**
     * This class is roughly based on Joshua Bloch's Builder pattern. Since
     * Session class will be extended by child classes, the
     * {@link #validateAndSetValues()} method on this builder is actually called
     * by the {@link DefaultSession} constructor for ease of use. May not be good
     * design though.
     * 
     * @author Abraham, Menacherry
     * 
     */
    public static class SessionBuilder
    {
        /**
         * Used to set a unique id on the incoming sessions to this room.
         */
        protected static final UniqueIDGeneratorService ID_GENERATOR_SERVICE = new SimpleUniqueIdGenerator();
        protected Object id = null;
        protected EventDispatcher eventDispatcher = null;
        protected Map<String, Object> sessionAttributes = null;
        protected long creationTime = 0L;
        protected long lastReadWriteTime = 0L;
        protected Status status = Status.NOT_CONNECTED;
        protected boolean isWriteable = true;
        protected volatile boolean isShuttingDown = false;
        protected boolean isUDPEnabled = false;// By default UDP is not enabled.
        
        public Session build()
        {
            return new DefaultSession(this);
        }
        
        /**
         * This method is used to validate and set the variables to default
         * values if they are not already set before calling build. This method
         * is invoked by the constructor of SessionBuilder. <b>Important!</b>
         * Builder child classes which override this method need to call
         * super.validateAndSetValues(), otherwise you could get runtime NPE's.
         */
        protected void validateAndSetValues(){
            if (null == id)
            {
                id = String.valueOf(ID_GENERATOR_SERVICE.generateFor(DefaultSession.class));
            }
            if (null == eventDispatcher)
            {
                eventDispatcher = EventDispatchers.newJetlangEventDispatcher(null,null);
            }
            if(null == sessionAttributes)
            {
                sessionAttributes = new HashMap<String, Object>();
            }
            creationTime = System.currentTimeMillis();
        }
        
        public Object getId()
        {
            return id;
        }
        public SessionBuilder id(final String id)
        {
            this.id = id;
            return this;
        }
        public SessionBuilder eventDispatcher(final EventDispatcher eventDispatcher)
        {
            this.eventDispatcher = eventDispatcher;
            return this;
        }
        public SessionBuilder sessionAttributes(final Map<String, Object> sessionAttributes)
        {
            this.sessionAttributes = sessionAttributes;
            return this;
        }
        public SessionBuilder creationTime(long creationTime)
        {
            this.creationTime = creationTime;
            return this;
        }
        public SessionBuilder lastReadWriteTime(long lastReadWriteTime)
        {
            this.lastReadWriteTime = lastReadWriteTime;
            return this;
        }
        public SessionBuilder status(Status status)
        {
            this.status = status;
            return this;
        }
        public SessionBuilder isWriteable(boolean isWriteable)
        {
            this.isWriteable = isWriteable;
            return this;
        }
        public SessionBuilder isShuttingDown(boolean isShuttingDown)
        {
            this.isShuttingDown = isShuttingDown;
            return this;
        }
        public SessionBuilder isUDPEnabled(boolean isUDPEnabled)
        {
            this.isUDPEnabled = isUDPEnabled;
            return this;
        }
    }
    
    @Override
    public void onEvent(Event event)
    {
        if(!isShuttingDown){
            eventDispatcher.fireEvent(event);
        }
    }

    @Override
    public Object getId()
    {
        return id;
    }

    @Override
    public void setId(Object id)
    {
        throw new IllegalArgumentException("id cannot be set in this implementation, since it is final");
    }

    @Override
    public EventDispatcher getEventDispatcher()
    {
        return eventDispatcher;
    }

    @Override
    public void addHandler(EventHandler eventHandler)
    {
        eventDispatcher.addHandler(eventHandler);
    }

    @Override
    public void removeHandler(EventHandler eventHandler)
    {
        eventDispatcher.removeHandler(eventHandler);
    }
    
    @Override
    public List<EventHandler> getEventHandlers(int eventType)
    {
        return eventDispatcher.getHandlers(eventType);
    }

    @Override
    public Object getAttribute(String key)
    {
        return sessionAttributes.get(key);
    }

    @Override
    public void removeAttribute(String key)
    {
        sessionAttributes.remove(key);
    }

    @Override
    public void setAttribute(String key, Object value)
    {
        sessionAttributes.put(key, value);
    }

    @Override
    public long getCreationTime()
    {
        return creationTime;
    }

    @Override
    public long getLastReadWriteTime()
    {
        return lastReadWriteTime;
    }

    public void setLastReadWriteTime(long lastReadWriteTime)
    {
        this.lastReadWriteTime = lastReadWriteTime;
    }

    @Override
    public Status getStatus()
    {
        return status;
    }

    @Override
    public void setStatus(Status status)
    {
        this.status = status;

    }

    @Override
    public boolean isConnected()
    {
        return this.status == Status.CONNECTED;
    }

    @Override
    public boolean isWriteable()
    {
        return isWriteable;
    }

    @Override
    public void setWriteable(boolean isWriteable)
    {
        this.isWriteable = isWriteable;
    }

    /**
     * Not synchronized because default implementation does not care whether a
     * duplicated message sender is created.
     * 
     * @see org.menacheri.jetserver.app.Session#isUDPEnabled()
     */
    @Override
    public boolean isUDPEnabled()
    {
        return isUDPEnabled;
    }
    
    @Override
    public void setUDPEnabled(boolean isEnabled)
    {
        this.isUDPEnabled = isEnabled;
    }
    
    @Override
    public synchronized void close()
    {
        isShuttingDown = true;
        eventDispatcher.close();
        if(null != tcpSender){
            tcpSender.close();
            tcpSender = null;
        }
        if(null != udpSender){
            udpSender.close();
            udpSender = null;
        }
        this.status = Status.CLOSED;
    }
    
    @Override
    public boolean isShuttingDown()
    {
        return isShuttingDown;
    }

    public Map<String, Object> getSessionAttributes()
    {
        return sessionAttributes;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DefaultSession other = (DefaultSession) obj;
        if (id == null)
        {
            if (other.id != null)
                return false;
        }
        else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public Reliable getTcpSender()
    {
        return tcpSender;
    }

    @Override
    public void setTcpSender(Reliable tcpSender)
    {
        this.tcpSender = tcpSender;
    }

    @Override
    public Fast getUdpSender()
    {
        return udpSender;
    }

    @Override
    public void setUdpSender(Fast udpSender)
    {
        this.udpSender = udpSender;
    }
}

 

 

PlayerSession.java

这个接口是玩家和服务器间的通信模型,他声明了一些方法,设置和获取用户,游戏房间以及session所使用的通信协议

package org.menacheri.jetserver.app;

import org.menacheri.jetserver.event.Event;
import org.menacheri.jetserver.protocols.Protocol;


/**
 * This interface model's a human player's session to jetserver. It declares
 * methods to get and set the {@link Player}, the {@link GameRoom} to which
 * this session will connect and the network {@link Protocol} that will be used
 * for communication.
 * 
 * @author Abraham Menacherry
 * 
 */
public interface PlayerSession extends Session
{
    /**
     * Each session is associated with a {@link Player}. This is the actual
     * human or machine using this session.
     * 
     * @return Returns that associated Player object or null if it is not
     *         associated yet.
     */
    public abstract Player getPlayer();

    /**
     * Each user session is attached to a game room. This method is used to retrieve that
     * game room object.
     * 
     * @return Returns the associated game room object or null if none is
     *         associated.
     */
    public abstract GameRoom getGameRoom();

    /**
     * Method used to set the game room for a particular session.
     * 
     * @param gameRoom
     *            The gameRoom object to set.
     */
    public abstract void setGameRoom(GameRoom gameRoom);

    /**
     * Get the {@link Protocol} associated with this session.
     * 
     * @return Returns the associated protocol instance.
     */
    public Protocol getProtocol();

    /**
     * Set the network protocol on the user session.
     * 
     * @param protocol
     *            The {@link Protocol} to set.
     */
    public void setProtocol(Protocol protocol);
    
    /**
     * The event to be send to the {@link GameRoom} to which the PlayerSession
     * belongs. Behavior is unspecified if message is sent when a room change is
     * taking place.
     * 
     * @param event The event to send to the {@link GameRoom}
     */
    public void sendToGameRoom(Event event);
}

 

 

DefaultPlayerSession.java

package org.menacheri.jetserver.app.impl;

import org.jetlang.channels.MemoryChannel;
import org.menacheri.jetserver.app.GameRoom;
import org.menacheri.jetserver.app.Player;
import org.menacheri.jetserver.app.PlayerSession;
import org.menacheri.jetserver.concurrent.LaneStrategy.LaneStrategies;
import org.menacheri.jetserver.event.Event;
import org.menacheri.jetserver.event.EventDispatcher;
import org.menacheri.jetserver.event.impl.EventDispatchers;
import org.menacheri.jetserver.protocols.Protocol;

/**
 * This implementation of the {@link PlayerSession} interface is used to both
 * receive and send messages to a particular player using the
 * {@link #onEvent(org.menacheri.jetserver.event.Event)}. Broadcasts from the
 * {@link GameRoom} are directly patched to the {@link EventDispatcher} which
 * listens on the room's {@link MemoryChannel} for events and in turn publishes
 * them to the listeners.
 * 
 * @author Abraham Menacherry
 * 
 */
public class DefaultPlayerSession extends DefaultSession implements
        PlayerSession
{

    /**
     * Each session belongs to a Player. This variable holds the reference.
     */
    final protected Player player;

    /**
     * Each incoming connection is made to a game room. This reference holds the
     * association to the game room.
     */
    protected GameRoom parentGameRoom;
    /**
     * This variable holds information about the type of binary communication
     * protocol to be used with this session.
     */
    protected Protocol protocol;

    protected DefaultPlayerSession(PlayerSessionBuilder playerSessionBuilder)
    {
        super(playerSessionBuilder);
        this.player = playerSessionBuilder.player;
        this.parentGameRoom = playerSessionBuilder.parentGameRoom;
        this.protocol = playerSessionBuilder.protocol;
    }

    public static class PlayerSessionBuilder extends SessionBuilder
    {
        protected Player player = null;
        protected GameRoom parentGameRoom;
        protected Protocol protocol;

        public PlayerSession build()
        {
            return new DefaultPlayerSession(this);
        }

        public PlayerSessionBuilder player(Player player)
        {
            this.player = player;
            return this;
        }

        public PlayerSessionBuilder parentGameRoom(GameRoom parentGameRoom)
        {
            if (null == parentGameRoom)
            {
                throw new IllegalArgumentException(
                        "GameRoom instance is null, session will not be constructed");
            }
            this.parentGameRoom = parentGameRoom;
            return this;
        }

        @Override
        protected void validateAndSetValues()
        {
            if (null == eventDispatcher)
            {
                eventDispatcher = EventDispatchers.newJetlangEventDispatcher(
                        parentGameRoom, LaneStrategies.GROUP_BY_ROOM);
            }
            super.validateAndSetValues();
        }

        public PlayerSessionBuilder protocol(Protocol protocol)
        {
            this.protocol = protocol;
            return this;
        }
    }

    @Override
    public Player getPlayer()
    {
        return player;
    }

    public GameRoom getGameRoom()
    {
        return parentGameRoom;
    }

    public void setGameRoom(GameRoom gameRoom)
    {
        this.parentGameRoom = gameRoom;
    }

    @Override
    public Protocol getProtocol()
    {
        return protocol;
    }

    @Override
    public void setProtocol(Protocol protocol)
    {
        this.protocol = protocol;
    }

    @Override
    public synchronized void close()
    {
        if (!isShuttingDown)
        {
            super.close();
            parentGameRoom.disconnectSession(this);
        }
    }

    @Override
    public void sendToGameRoom(Event event) {
        parentGameRoom.send(event);
    }
    
    @Override
    public String toString()
    {
        return "PlayerSession [id=" + id + "player=" + player
                + ", parentGameRoom=" + parentGameRoom + ", protocol="
                + protocol + ", isShuttingDown=" + isShuttingDown + "]";
    }
}

 

GameRoomSession.java

package org.menacheri.jetserver.app.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;

import org.menacheri.jetserver.app.Game;
import org.menacheri.jetserver.app.GameRoom;
import org.menacheri.jetserver.app.Player;
import org.menacheri.jetserver.app.PlayerSession;
import org.menacheri.jetserver.app.Session;
import org.menacheri.jetserver.concurrent.LaneStrategy;
import org.menacheri.jetserver.concurrent.LaneStrategy.LaneStrategies;
import org.menacheri.jetserver.event.Event;
import org.menacheri.jetserver.event.EventHandler;
import org.menacheri.jetserver.event.NetworkEvent;
import org.menacheri.jetserver.event.impl.EventDispatchers;
import org.menacheri.jetserver.event.impl.NetworkEventListener;
import org.menacheri.jetserver.protocols.Protocol;
import org.menacheri.jetserver.service.GameStateManagerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public abstract class GameRoomSession extends DefaultSession implements GameRoom
{
    private static final Logger LOG = LoggerFactory.getLogger(GameRoomSession.class);
    
    /**
     * The name of the game room, preferably unique across multiple games.
     */
    protected String gameRoomName;
    /**
     * The parent {@link SimpleGame} reference of this game room.
     */
    protected Game parentGame;
    /**
     * Each game room has separate state manager instances. This variable will
     * manage the state for all the {@link DefaultPlayer}s connected to this game room.
     */
    protected GameStateManagerService stateManager;

    /**
     * The set of sessions in this object.
     */
    protected Set<PlayerSession> sessions;
    
    /**
     * Each game room has its own protocol for communication with client.
     */
    protected Protocol protocol;
    
    protected GameRoomSession(GameRoomSessionBuilder gameRoomSessionBuilder)
    {
        super(gameRoomSessionBuilder);
        this.sessions = gameRoomSessionBuilder.sessions;
        this.parentGame = gameRoomSessionBuilder.parentGame;
        this.gameRoomName = gameRoomSessionBuilder.gameRoomName;
        this.protocol = gameRoomSessionBuilder.protocol;
        if(null == gameRoomSessionBuilder.eventDispatcher)
        {
            this.eventDispatcher = EventDispatchers.newJetlangEventDispatcher(
                    this, gameRoomSessionBuilder.laneStrategy);
        }
    }
    
    public static class GameRoomSessionBuilder extends SessionBuilder
    {
        protected Set<PlayerSession> sessions;
        protected Game parentGame;
        protected String gameRoomName;
        protected Protocol protocol;
        protected LaneStrategy<String, ExecutorService, GameRoom> laneStrategy;
        
        @Override
        protected void validateAndSetValues()
        {
            if (null == id)
            {
                id = String.valueOf(ID_GENERATOR_SERVICE.generateFor(GameRoomSession.class));
            }
            if(null == sessionAttributes)
            {
                sessionAttributes = new HashMap<String, Object>();
            }
            if (null == sessions)
            {
                sessions = new HashSet<PlayerSession>();
            }
            if (null == laneStrategy)
            {
                laneStrategy = LaneStrategies.GROUP_BY_ROOM;
            }
            creationTime = System.currentTimeMillis();
        }
        
        public GameRoomSessionBuilder sessions(Set<PlayerSession> sessions)
        {
            this.sessions = sessions;
            return this;
        }
        
        public GameRoomSessionBuilder parentGame(Game parentGame)
        {
            this.parentGame = parentGame;
            return this;
        }
        
        public GameRoomSessionBuilder gameRoomName(String gameRoomName)
        {
            this.gameRoomName = gameRoomName;
            return this;
        }
        
        public GameRoomSessionBuilder protocol(Protocol protocol)
        {
            this.protocol = protocol;
            return this;
        }
        
        public GameRoomSessionBuilder laneStrategy(
                LaneStrategy<String, ExecutorService, GameRoom> laneStrategy)
        {
            this.laneStrategy = laneStrategy;
            return this;
        }
    }
    
    @Override
    public PlayerSession createPlayerSession(Player player)
    {
        PlayerSession playerSession = getSessionInstance(player);
        return playerSession;
    }
    
    @Override
    public abstract void onLogin(PlayerSession playerSession);
    
    @Override
    public synchronized boolean connectSession(PlayerSession playerSession)
    {
        if (!isShuttingDown)
        {
            playerSession.setStatus(Session.Status.CONNECTING);
            sessions.add(playerSession);
            playerSession.setGameRoom(this);
            LOG.trace("Protocol to be applied is: {}",protocol.getClass().getName());
            protocol.applyProtocol(playerSession,true);
            createAndAddEventHandlers(playerSession);
            playerSession.setStatus(Session.Status.CONNECTED);
            afterSessionConnect(playerSession);
            return true;
            // TODO send event to all other sessions?
        }
        else
        {
            LOG.warn("Game Room is shutting down, playerSession {} {}",
                    playerSession,"will not be connected!");
            return false;
        }
    }

    @Override
    public void afterSessionConnect(PlayerSession playerSession)
    {
            
    }
    
    public synchronized boolean disconnectSession(PlayerSession playerSession)
    {
        final boolean removeHandlers = this.eventDispatcher.removeHandlersForSession(playerSession);
        //playerSession.getEventDispatcher().clear(); // remove network handlers of the session.
        return (removeHandlers && sessions.remove(playerSession));
    }

    @Override
    public void send(Event event) {
        onEvent(event);
    }
    
    @Override
    public void sendBroadcast(NetworkEvent networkEvent)
    {
        onEvent(networkEvent);
    }

    @Override
    public synchronized void close()
    {
        isShuttingDown = true;
        for(PlayerSession session: sessions)
        {
            session.close();
        }
    }
    
    public PlayerSession getSessionInstance(Player player)
    {
        PlayerSession playerSession = Sessions.newPlayerSession(this,player);
        return playerSession;
    }
    
    @Override
    public Set<PlayerSession> getSessions()
    {
        return sessions;
    }

    @Override
    public void setSessions(Set<PlayerSession> sessions)
    {
        this.sessions = sessions;
    }
    
    @Override
    public String getGameRoomName()
    {
        return gameRoomName;
    }

    @Override
    public void setGameRoomName(String gameRoomName)
    {
        this.gameRoomName = gameRoomName;
    }

    @Override
    public Game getParentGame()
    {
        return parentGame;
    }

    @Override
    public void setParentGame(Game parentGame)
    {
        this.parentGame = parentGame;
    }

    @Override
    public void setStateManager(GameStateManagerService stateManager)
    {
        this.stateManager = stateManager;
    }
    
    @Override
    public GameStateManagerService getStateManager()
    {
        return stateManager;
    }

    @Override
    public Protocol getProtocol()
    {
        return protocol;
    }

    @Override
    public void setProtocol(Protocol protocol)
    {
        this.protocol = protocol;
    }
    
    @Override
    public boolean isShuttingDown()
    {
        return isShuttingDown;
    }

    public void setShuttingDown(boolean isShuttingDown)
    {
        this.isShuttingDown = isShuttingDown;
    }

    /**
     * Method which will create and add event handlers of the player session to
     * the Game Room's EventDispatcher.
     * 
     * @param playerSession
     *            The session for which the event handlers are created.
     */
    protected void createAndAddEventHandlers(PlayerSession playerSession)
    {
        // Create a network event listener for the player session.
        EventHandler networkEventHandler = new NetworkEventListener(playerSession);
        // Add the handler to the game room's EventDispatcher so that it will
        // pass game room network events to player session session.
        this.eventDispatcher.addHandler(networkEventHandler);
        LOG.trace("Added Network handler to "
                + "EventDispatcher of GameRoom {}, for session: {}", this,
                playerSession);
    }
}

 

1.做了一张UML图纸,梳理一下Session实现的架构。

 

2.梳理一下Builder实现方式的要点:

  • Session接口中的方法都是包级保护的(不带任何修饰符)
  • PlayerSession接口中的方法都是Public的
  • DefaultSession中的属性都是protected的
  • DefaultSession的构造器是protected的
  • DefaultSession的内部类(SessionBuilder)是public static的。
  • DefaultSession内部类(SessionBuilder)中的属性是protected的,validateAndSetValues()方法是protected的,提供给子类调用(注意子类需调用这个 validateAndSetValues方法,否则会出现NPE。因为这个函数是用来初始化三个空引用,如果子类中只是初始化了其中的一个或几个,就需要调用父类的这个方法)
  • DefaultSession内部类(SessionBuilder)中其他设置属性的方法都是public的
  • DefaultPlayerSession和GameRoomSession是DefaultSession的子类,域和方法包括内部类的访问权限和DefaultSession设置的差不多。

3.对isShuttingDown变量进行了学习,这个voliate变量是在DefaultSession中定义的

Life cycle variable to check if the session is shutting down. If it is, then no more incoming events will be accepted.

GameRoomSession中isShuttingDown是GameRoomSession的生命周期标志位,主要是在更新PlayerSession结合的时候需要访问到。如果对话终止则不能接受新的PlayerSession

4.GameRoomSession同步块的学习

GameRoomSession中主要有三个同步块方法,主要是对PlayerSession集合(sessions对象)的访问进行了同步

转载于:https://www.cnblogs.com/Guoyutian/p/5094863.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值