8 Разработка игрового веб-сервера на Java. Усовершенствованный пример системы обмена сообщениями на Java

В этом посте приведен примерный код системы обмена сообщениями после рефакторинга.

Пакет base

src/base/Abonent.java

package base;

public interface Abonent {
    Address getAddress();
}


src/base/AccountService.java

package base;

public interface AccountService extends Abonent {
    MessageSystem getMessageSystem();
}


src/base/Address.java

package base;

import java.util.concurrent.atomic.AtomicInteger;

public class Address {
    static private AtomicInteger abonentIdCreator = new AtomicInteger();
    final private int abonentId;

    public static Address getNew(){
        return new Address();
    }
    
    public int getAbonentId() {
        return abonentId;
    }
    
    private Address(){
        this.abonentId = abonentIdCreator.incrementAndGet();
    }   
}



src/base/AddressService.java

package base;

public interface AddressService {
    
    Address getAddressAS();
    
    Address getAddressFrontend();   
}


src/base/Frontend.java

package base;

public interface Frontend extends Abonent {
    MessageSystem getMessageSystem();
}


src/base/MessageSystem.java

package base;


public interface MessageSystem {
    
    void sendMessage(Msg message);
    
    void execForAbonent(Abonent abonent);
    
    AddressService getAddressService();
}


src/base/Msg.java

package base;

public abstract class Msg {
    private Address from;
    private Address to;
    
    public Msg(Address from, Address to){
        this.from = from;
        this.to = to;
    }
    
    public Address getFrom(){
        return from;
    }
    
    public Address getTo(){
        return to;
    }
    
    public abstract void exec(Abonent abonent);
}

Пакет utils

src/utils/TimeHelper.java

package utils;

public class TimeHelper {
    public static void sleep(int period){
        try{
            Thread.sleep(period);
        } catch (InterruptedException e) {              
            e.printStackTrace();
        }
    }
}

Пакет main

src/main/Main.java

package main;

import messageSystem.MessageSystemImpl;
import org.eclipse.jetty.server.Server;
import accountService.AccountServiceImpl;
import frontend.FrontendImpl;

public class Main {
    public static void main(String[] args) throws Exception {
        MessageSystemImpl messageSystem = new MessageSystemImpl();
        
        FrontendImpl frontend = new FrontendImpl(messageSystem);
        messageSystem.addFrontend(frontend);
        
        AccountServiceImpl accountService = new AccountServiceImpl(messageSystem);
        messageSystem.addAccountService(accountService);
        
        (new Thread(frontend)).start();
        (new Thread(accountService)).start();

        Server server = new Server(8080);
        server.setHandler(frontend);
        
        server.start();
        server.join();
    }
    
    protected static void test(){
    }
    
}


src/main/PStrange.java

package main;


public class PStrange {
    public void test(){
        Main.test();
    }

}


Пакет messageSystem

src/messageSystem/AddressServiceImpl.java

package messageSystem;

import base.Address;
import base.AddressService;

public class AddressServiceImpl implements AddressService {
    private Address addressFrontend;
    private Address addressAS;
    
    public Address getAddressAS() {
        return addressAS;
    }
    public void setAddressAS(Address addressAS) {
        this.addressAS = addressAS;
    }
    public Address getAddressFrontend() {
        return addressFrontend;
    }
    public void setAddressFrontend(Address addressFrontend) {
        this.addressFrontend = addressFrontend;
    }
}


src/messageSystem/MessageSystemImpl.java

package messageSystem;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

import base.Abonent;
import base.Address;
import base.AddressService;
import base.MessageSystem;
import base.Msg;


public class MessageSystemImpl implements MessageSystem {
    private static int QUEUE_SIZE = 100;
    private Map<Address, ArrayBlockingQueue<Msg>> messages = new HashMap<Address, ArrayBlockingQueue<Msg>>();
    private AddressServiceImpl addressService = new AddressServiceImpl();
    
    public void addFrontend(Abonent abonent){
        addressService.setAddressFrontend(abonent.getAddress());
        messages.put(abonent.getAddress(), new ArrayBlockingQueue<Msg>(QUEUE_SIZE));
    }
    
    public void addAccountService(Abonent abonent){
        addressService.setAddressAS(abonent.getAddress());
        messages.put(abonent.getAddress(), new ArrayBlockingQueue<Msg>(QUEUE_SIZE));
    }
    
    public void sendMessage(Msg message){
        Queue<Msg> messageQueue = messages.get(message.getTo());
        messageQueue.add(message);      
    }
        
    public void execForAbonent(Abonent abonent){
        Queue<Msg> messageQueue = messages.get(abonent.getAddress());
        if(messageQueue == null){
            return;
        }
        while(!messageQueue.isEmpty()){
            Msg message = messageQueue.poll();
            message.exec(abonent);
        }
    }
    
    public AddressService getAddressService(){
        return addressService;
    }

}


src/messageSystem/MsgToAS.java

package messageSystem;

import base.Abonent;
import base.AccountService;
import base.Address;
import base.Msg;

public abstract class MsgToAS extends Msg{

    public MsgToAS(Address from, Address to) {
        super(from, to);        
    }

    public void exec(Abonent abonent) {
        if(abonent instanceof AccountService){
            exec((AccountService) abonent);
        }
    }

    public abstract void exec(AccountService accountService);
}


src/messageSystem/MsgToFrontend.java

package messageSystem;

import base.Abonent;
import base.Address;
import base.Frontend;
import base.Msg;

public abstract class MsgToFrontend extends Msg{

    public MsgToFrontend(Address from, Address to) {
        super(from, to);
    }

    public void exec(Abonent abonent) {
        if(abonent instanceof Frontend){
            exec((Frontend)abonent);
        }
    }
    
    public abstract void exec(Frontend frontend);
}

Пакет accountService

src/accountService/AccountServiceImpl.java

package accountService;

import base.AccountService;
import base.Address;
import base.MessageSystem;
import utils.TimeHelper;

public class AccountServiceImpl implements AccountService, Runnable{
    private Address address = Address.getNew();
    private MessageSystem messageSystem;
    
    public AccountServiceImpl(MessageSystem messageSystem){
        this.messageSystem = messageSystem;
    }
    
    public void run(){
        while(true){
            while(true){
                messageSystem.execForAbonent(this);
                TimeHelper.sleep(10);
            }
        }
    }

    public Address getAddress() {
        return address;
    }
    
    public MessageSystem getMessageSystem(){
        return messageSystem;
    }
}

Пакет frontend

src/frontend/MsgUpdateUserId.java

package frontend;

import messageSystem.MsgToFrontend;
import base.Address;
import base.Frontend;

public class MsgUpdateUserId extends MsgToFrontend {

    public MsgUpdateUserId(Address from, Address to) {
        super(from, to);
    }

    public void exec(Frontend frontend) {
        System.out.print("Address of Frontend: " + frontend.getAddress().getAbonentId() + '\n');        
    }

}


src/frontend/MsgGetUserId.java

package frontend;

import messageSystem.MsgToAS;
import base.AccountService;
import base.Address;

public class MsgGetUserId extends MsgToAS {

    public MsgGetUserId(Address from, Address to) {
        super(from, to);
    }

    public void exec(AccountService accountService) {
        System.out.print("Address of Account Service: " + accountService.getAddress().getAbonentId() + '\n');
        accountService.getMessageSystem().sendMessage(new MsgUpdateUserId(getTo(), getFrom()));
    }
}


src/frontend/FrontendImpl.java

package frontend;


import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;

import base.Address;
import base.Frontend;
import base.MessageSystem;

import utils.TimeHelper;

public class FrontendImpl extends AbstractHandler implements Frontend, Runnable{
    private static String GAME_NAME = "/test/";
    private Address address = Address.getNew();
    private MessageSystem messageSystem;
    
    public FrontendImpl(MessageSystem messageSystem){
        this.messageSystem = messageSystem;
    }
    
    public void run(){
        while(true){
            messageSystem.execForAbonent(this);
            TimeHelper.sleep(10);
        }
    }

    public Address getAddress() {
            return address;
    }

    public void handle(String target, Request baseRequest,
            HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        
        response.setContentType("text/html;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_OK);
        baseRequest.setHandled(true);
        
        if(!target.equals(GAME_NAME))
            return;
        
        response.getWriter().println("<h1>"+ Thread.currentThread().getName() +"</h1>");
        
        Address addressAS =  messageSystem.getAddressService().getAddressAS();
        messageSystem.sendMessage(new MsgGetUserId(getAddress(), addressAS));
    }
    
    public MessageSystem getMessageSystem(){
        return messageSystem;
    }
}

--
https://github.com/vitaly-chibrikov/tp_java_2013_02/tree/master/lecture4