用于netty客户端的MVC前端

时间:2014-07-27 23:37:14

标签: java swing user-interface model-view-controller netty

我已经适应了片刻的引用(QOTM),并希望构建一个GUI前端。它很简单,可以将对象从DatagramClientHandler传递给GUI。但是,GUI引用处理程序似乎很棘手。

QuotesGUI类扩展了JFrame,以利用Netbeans拖放调色板轻松添加Swing组件。它非常冗长。

显然,解决方案是:

  

嗯,这取决于有多个解决方案。一个可能是   将一个监听器注入ChannelHandler,然后通知它   一旦收到消息。另一种解决方案可能是发送   收到消息后,将事件发送到主题并注册   感兴趣的主题部分,以便他们得到通知。

https://stackoverflow.com/a/8780410/262852

DatagramClientHandler:

package net.bounceme.dur.netty;

import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
import java.util.logging.Logger;
import net.bounceme.dur.client.gui.QuotesGUI;

public class DatagramClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    private static final Logger log = Logger.getLogger(DatagramClientHandler.class.getName());
    private final QuotesGUI gui = new QuotesGUI();
    private volatile Channel channel = null;

    DatagramClientHandler() {
        log.info("starting..");
        gui.setVisible(true);
    }

    private DatagramPacket getNext() {
        DatagramPacket packet = new DatagramPacket(
                Unpooled.copiedBuffer("QOTM?", CharsetUtil.UTF_8),
                new InetSocketAddress("localhost", 4454));
        return packet;
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
        String response = msg.content().toString(CharsetUtil.UTF_8);
        log.info(response);
        gui.setQuote(response);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.severe(cause.toString());
        ctx.close();
    }
}

GUI中的示例方法。

public void setQuote(String packet) {
    text.setText(packet);
}

1 个答案:

答案 0 :(得分:1)

首先分开你的责任层......

我可能首先定义一些可以在interface的实例中注册的侦听器DatagramClientHandler。此interface将允许感兴趣的各方收到DatagramClientHandler内的更改或事件的通知,并在他们认为合适的情况下处理这些事件......

public interface MessageListener {
    public void quoteRecieved(SimpleChannelInboundHandler source, String quote);
    public void errorOccured(SimpleChannelInboundHandler source, Throwable cause);
}

然后你需要为听众提供支持......

public class DatagramClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    private static final Logger log = Logger.getLogger(DatagramClientHandler.class.getName());
    //private final QuotesGUI gui = new QuotesGUI();
    private volatile Channel channel = null;
    private List<MessageListener> listeners;

    DatagramClientHandler() {
        listeners = new ArrayList<MessageListener>(25);
        //...
    }

    public synchronized void addMessageListener(MessageListener listener) {
        listeners.add(listener);
    }

    public synchronized void removeMessageListener(MessageListener listener) {
        listeners.remove(listener);
    }

    protected synchronized void fireQuoteRecieved(String quote) {
        for (MessageListener listener : listeners) {
            listener.quoteRecieved(this, quote);
        }
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
        String response = msg.content().toString(CharsetUtil.UTF_8);
        log.info(response);
        fireQuoteRecieved(response);
    }

    //...etc...

现在,当您想要接收通知时,您将注册一个MessageListener实例,其实例为DatagramClientHandler ...

您将遇到的问题是确保您对用户界面所做的任何更新都是在EDT中正确执行的......

//...
public void quoteRecieved(SimpleChannelInboundHandler source, final String quote) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            text.setText(packet);
        }
    });
}

现在,如果你真的想,你可以进一步将代码与另一个interface解耦......

public interface QuoteFactory {
    public synchronized void addMessageListener(MessageListener listener);
    public synchronized void removeMessageListener(MessageListener listener);
}

然后由DatagramClientHandler执行此操作,您的UI将需要传递QuoteFactory的实例,以便在发生某些事情时可以注册通知...