用mina+applet实现推送技术

wsd 2014-08-28

最近用到了前台推送技术,一开始用了comet4j 但是发现偶尔会断开,所以探寻了另一条出路。mina+applet实现推送技术。

分为三步:一.编写mina服务端,客户端代码。(先调试好)

                 二.将客户端类变成applet类, 进行签章等设置

                 三.实现applet 和 jsp 通信

上代码,边看代码边将:

1.服务端类MinaServer

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Collection;

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

/**
 * 服务器启动类
 * 
 * @author JiangBo
 */
public class MinaServer {
    /**
     * 单例
     */
    private static MinaServer instance = new MinaServer();
    public static MinaServer getInstance() {
        return instance;
    }
    private MinaServer() {
    }
    
    // 端口设置
    private static int PORT = 30001;
    private SocketAcceptor acceptor;
    
    /**
     * 初始化方法
     * 
     * @return
     */
    public boolean start() {
        // 创建非阻塞的server端的Socket连接
        acceptor = new NioSocketAcceptor();
        DefaultIoFilterChainBuilder filterChain = acceptor.getFilterChain();
        // 添加编码过滤器 处理乱码、编码问题
      //  filterChain.addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));

        // 设置核心消息业务处理器
        acceptor.setHandler(new ServerMessageHandler());
        // 设置session配置,30秒内无操作进入空闲状态
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30);

        try {
            // 绑定端口
            acceptor.bind(new InetSocketAddress(PORT));
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 向客户端发送(推送)消息
     */
    public void sendMessage(String host, String port, String value) {
        // 实例化一个向客户端发送的socket对象
        Collection<IoSession> sessions = acceptor.getManagedSessions().values();
        for (IoSession sess : sessions) {
            sess.write(value);
        }
    }

    /**
     * main方法
     * 
     * @param args
     */
    public static void main(String[] args) {
        //
        MinaServer server = MinaServer.getInstance();
        server.start();
        System.out.println("服务器启动成功=================");
    }
}

 2.ServerMessageHandler类

import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

/**
 * 处理服务器端消息
 * 
 * @author JiangBo
 */
public class ServerMessageHandler implements IoHandler {

    /**
     * 服务器发生异常
     */
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        System.out.println("服务器发生异常: " + cause.getMessage());
    }

    /**
     * 接收数据
     */
    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        System.out.println("服务器接收到数据:" + message);
    }

    /**
     * 发送消息
     */
    @Override
    public void messageSent(IoSession session, Object message) throws Exception {
        System.out.println("服务器发送消息: " + message);
    }

    /**
     * 关闭链接
     */
    @Override
    public void sessionClosed(IoSession session) throws Exception {
        System.out.println("关闭当前session:" + session.getId() + session.getRemoteAddress());

        CloseFuture closeFuture = session.close(true);
        closeFuture.addListener(new IoFutureListener<IoFuture>() {
            public void operationComplete(IoFuture future) {
                if (future instanceof CloseFuture) {
                    ((CloseFuture) future).setClosed();
                    System.out.println("sessionClosed CloseFuture setClosed-->" + future.getSession().getId() + ",");
                }
            }
        });
    }

    /**
     * 创建连接
     */
    @Override
    public void sessionCreated(IoSession session) throws Exception {
        System.out.println("创建一个新连接:" + session.getRemoteAddress());
        session.write("session created:" + session.getRemoteAddress());
    }

    /**
     * 空闲
     */
    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        System.out.println("当前连接" + session.getRemoteAddress() + "处于空闲状态:" + status);
    }

    /**
     * 打开一个session链接
     */
    @Override
    public void sessionOpened(IoSession session) throws Exception {
        System.out.println("打开一个session:"+ session.getId() + session.getBothIdleCount());
    }
}

 3.MinaClient客户端类

import java.applet.Applet;
import java.net.InetSocketAddress;

import netscape.javascript.JSObject;

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.SocketConnector;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import com.txsoft.ipcc.common.mina.service.CharsetCodecFactory;
 
/**
 * mina客户端
 * 
 * @author JiangBo
 */
public class MinaClient extends Applet {
    /**
     * serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    private static String IP = "192.168.1.30";
    
    private static int PORT = 30001;
    private SocketConnector connector;
    private ConnectFuture future;
    private IoSession session;
 
    public void init() {
        JSObject window= null;
        try {
            window=JSObject.getWindow(this);
            window.eval("alert('start begin!')");
        } catch (Exception e) {
            
        }
        
        // 创建一个socket连接
        connector = new NioSocketConnector();
        // 设置链接超时时间
        connector.setConnectTimeoutMillis(3000);
        // 获取过滤器链
        DefaultIoFilterChainBuilder filterChain = connector.getFilterChain();
        // 添加编码过滤器 处理乱码、编码问题
        filterChain.addLast("codec", new ProtocolCodecFilter(new CharsetCodecFactory()));
 
        // 消息核心处理器
        connector.setHandler(new ClientMessageHandlerAdapter(this));
 
        // 连接服务器,知道端口、地址
        future = connector.connect(new InetSocketAddress(IP, PORT));
        // 等待连接创建完成
        future.awaitUninterruptibly();
        // 获取当前session
        session = future.getSession();
        // 
        try {
            window.eval("alert('end!')");
        } catch (Exception e) {
            
        }
    }
 
    public void setAttribute(Object key, Object value) {
        session.setAttribute(key, value);
    }
 
    /**
     * 发送
     * @param message
     */
    public void send(String message) {
        session.write(message);
    }
    
    /**
     * 发送信息到JSP
     * @param message
     */
    public void sendJsp(String message) {
        // 获取JavaScript窗口句柄,引用当前文档窗口
        JSObject window = JSObject.getWindow(MinaClient.this);
        // 调用页面上的js方法 show(message)
        Object obj[] = new Object[1];
        obj[0] = message;
        window.call("show", obj);// 参数用数组的形势表示。
    }
 
    public boolean close() {
        CloseFuture future = session.getCloseFuture();
        future.awaitUninterruptibly(1000);
        connector.dispose();
        return true;
    }
 
    public SocketConnector getConnector() {
        return connector;
    }
 
    public IoSession getSession() {
        return session;
    }
}

 4.ClientMessageHandlerAdapter类

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
 
/**
 * 客户端消息处理类
 * @author JiangBo
 */
public class ClientMessageHandlerAdapter extends IoHandlerAdapter {
    private MinaClient minaClient = null;
    public ClientMessageHandlerAdapter(MinaClient minaClient) {
        this.minaClient = minaClient;
    }
    /**
     * 接收到消息
     */
    public void messageReceived(IoSession session, Object message) throws Exception {
        // 接到消息无处理
        System.out.println("messageSent服务端发送到客户端的消息:" + message);
        if (null != this.minaClient) {
            try {
                this.minaClient.sendJsp(message.toString());
            } catch (Exception e) {
            }
        }
    }
    
    public void messageSent(IoSession session , Object message) throws Exception{
        System.out.println("messageSent 客户端发送消息:" + message);
    }
    
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        System.out.println("服务器发生异常: {}" + cause.getMessage());
    }
}

5. jsp文件

<%@ page contentType="text/html; charset=utf-8"%>
<html>
 <head>
  <title> test mina push </title>
 </head>
 
 <body>
    <applet name = "testapplet" code = 'com.txsoft.ipcc.common.mina.client.MinaClient.class' 
          archive = 'minaClient.jar' width = 100 height = 50 MAYSCRIPT>
    </applet>
    <script type="text/javascript">
         function show(message){
             alert(message);
         }
     </script>
 </body>
</html>

 注意:例子中要把代码打包放在跟目录下,例子中jar包名叫:minaClient.jar。jar包还需要密码的支持所以打包时候还要把mima的支持包打进去。把下面3个包放在跟minaClient.jar同级目录下。

          1.mina-core-2.0.7.jar

           2.slf4j-api-1.7.6.jar

           3.slf4j-jdk14-1.7.7.jar

打包时候我是通过MANIFEST.MF文件选择了密码支持的3个包

MANIFEST.MF内容:

Manifest-Version: 1.0
Class-Path: mina-core-2.0.7.jar slf4j-api-1.7.6.jar slf4j-jdk14-1.7.7.jar

由于是Applet所以需要生成证书及签名所以在服务端cmd调出命令框 执行授权:
       1、keytool -genkey -keystore pepper.store -alias pepper
  这个命令用来产生一个密匙库,执行完毕后应该在c:/admin中产生一个pepper.store的文件,这里的pepper是我自己的名字,你可以对它进行修改。另外在执行命令的时候还有提示你输入密匙库的密码,这里你一定要记住,否则后面要用的时候无法输入。

2、keytool -export -keystore pepper.store -alias pepper -file pepper.cert
  这个命令用来产生签名时所要用的证书,同样这里的pepper也可以换成你自己需要的名字。这个命令执行完后在c:/admin中产生一个pepper.cert的文件。

3、 jarsigner -keystore pepper.store E:\workspace_IPCC\IPCC\WebRoot\minaClient.jar pepper
  这个命令用上面产生的证书将我们的jar文件进行了签名。(可以写绝对路径)

 在客户端设置security

 C:\Program Files (x86)\Java\jre6\lib\security\java.policy

在最下面添加这句,是允许所有IP 所有端口的权限,让然你可以可以指定IP 和端口

permission java.net.SocketPermission "*:*","accept,connect,resolve";

好了 小伙伴们 快去试试吧~

 需要的jar包:

相关推荐

lionelf / 0评论 2020-07-28