Mina与Spring整合

首先需要导入的包

applicationContext-mina.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        <!-- 配置地址 -->
        <bean class="com.sharp.slc.net.common.EncryptPropertyPlaceholderConfigurer">  
          <property name="order" value="1"/>  
          <property name="ignoreUnresolvablePlaceholders" value="true"/>  
          <property name="locations">  
            <list>  
                <value>classpath:ssl.properties</value>  
            </list>  
          </property>  
        </bean>
        <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
            <property name="customEditors">
                <map>
                    <!-- spring升级后此配置已失效 会报错 -->
                    <!-- <entry key="java.net.SocketAddress"> -->
                    <!-- <bean class="org.apache.mina.integration.beans.InetSocketAddressEditor"
                        /> -->
                    <!-- </entry> -->
                    <!-- 修改这里 -->
                    <entry key="java.net.SocketAddress"
                        value="org.apache.mina.integration.beans.InetSocketAddressEditor">
                    </entry>
                </map>
            </property>
        </bean>
        <!-- 配置业务处理类 -->
        <bean id="serviceHandler" class="com.sharp.slc.net.core.TCPServerHandler" />
        <!-- 配置service -->
        <bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
            init-method="bind" destroy-method="unbind">
            <property name="defaultLocalAddress" value=":2001" />
            <property name="handler" ref="serviceHandler" />
            <property name="filterChainBuilder" ref="filterChainBuilder" />
        </bean>
        <!-- 配置解码器 -->
        <bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
            <constructor-arg>
                <bean class="com.sharp.slc.net.core.codec.TextCodecFactory" />
                
    <!--     <bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" /> -->
            </constructor-arg>
        </bean>
        <!-- 配置日志拦截器 -->
        <bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
        <!-- 配置SSL拦截器 -->
        <bean id="sslFilter" class="org.apache.mina.filter.ssl.SslFilter">
            <constructor-arg ref="sslContext" />
    <!--         <property name="needClientAuth" value="true" /> -->
        </bean>
        <!-- The SSL configuration -->
        <bean id="keystoreFactory" class="org.apache.mina.filter.ssl.KeyStoreFactory">
            <property name="password">
                <value>${key_password}</value>
            </property>
        <!--     <property name="dataUrl" value="file:/d:/certs/server.jks" />  -->
            <property name="dataUrl" value="file:/usr/local/tomcat8/certs/server.jks" />
        </bean>
        <bean id="keyStore" factory-bean="keystoreFactory" factory-method="newInstance" />
        <!-- SSLContext to be used -->
        <bean id="sslContextFactory" class="org.apache.mina.filter.ssl.SslContextFactory">
            <property name="protocol" value="TLSV1.2" />
            <property name="keyManagerFactoryAlgorithm" value="SunX509" />
            <property name="keyManagerFactoryKeyStore">
                <ref local="keyStore" />
            </property>
            <property name="keyManagerFactoryKeyStorePassword">
                <value>${keyManager_password}</value>
            </property>
        </bean>
        <bean id="sslContext" factory-bean="sslContextFactory"
            factory-method="newInstance" />
        <!-- 将日志和解码器添加 -->
        <bean id="filterChainBuilder"
            class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
            <property name="filters">
                <map>
                    <entry key="sslFilter" value-ref="sslFilter" />
                    <entry key="loggingFilter" value-ref="loggingFilter" />
                    <entry key="codecFilter" value-ref="codecFilter" />
                </map>
            </property>
        </bean>
    </beans>

 

SessionCache.java

    public class SessionCache {
        private final static Log log = LogFactory.getLog(SessionCache.class);
        private static SessionCache session = null;
        /** 设备连接信息[sessions] */
        private Map<String, IoSession> sessions = new HashMap<String, IoSession>();
        private static final String value = KVStoreConfig.getIpAddress();
        /**
         * 获取唯一实例
         */
        public static SessionCache getInstance() {
            log.debug(" <<< Session单例获取 <<< ");
            if (session == null) {
                session = new SessionCache();
            }
            return session;
        }
        /**
         * 获取设备连接信息[sessions]
         *
         * @return 设备连接信息[sessions]
         */
        public Map<String, IoSession> getSessions() {
            return sessions;
        }
        /**
         * 设置设备连接信息[sessions]
         *
         * @param 设备连接信息
         *            [sessions]
         */
        public void setSessions(Map<String, IoSession> sessions) {
            this.sessions = sessions;
        }
        /**
         * 增加设备连接信息[sessions]
         *
         * @param MAC地址作为键
         *            [mac]
         * @param IoSession对象作为值
         *            [session]
         */
        public void save(String mac, IoSession session) {
            sessions.put(mac, session);
            String clientIp = session.getRemoteAddress().toString();
            KVStoreUtils.putHashmapField(mac, value);
            String kvIp = KVStoreUtils.getHashmapField(NetConstants.KV_PORT_KEY, mac);
            if (StringUtil.isNotBlank(kvIp)) {
                if (!kvIp.contains(clientIp)) {
                    String ipvalue = kvIp + ";" + clientIp;
                    KVStoreUtils.putHashmapField(NetConstants.KV_PORT_KEY, mac, ipvalue);
                }
            } else {
                KVStoreUtils.putHashmapField(NetConstants.KV_PORT_KEY, mac, clientIp);
            }
        }
        /**
         * 查找设备连接信息[sessions]
         *
         * @param MAC地址作为键
         *            [key]
         * @return 连接信息
         */
        public IoSession isExists(String key) {
            if (sessions.containsKey(key)) {
                return sessions.get(key);
            }
            return null;
        }
        /**
         * 删除设备连接信息[sessions]
         *
         * @param MAC地址作为键
         *            [mac]
         */
        public void remove(String mac, String clientIp) {
            sessions.remove(mac);
            String ipvalue = KVStoreUtils.getHashmapField(NetConstants.KV_PORT_KEY, mac);
            if (clientIp.equals(ipvalue)) {
                KVStoreUtils.removeHahmapField(mac);
                KVStoreUtils.removeHahmapField(NetConstants.KV_PORT_KEY, mac);
            } else {
                String ipvalueTemp = ipvalue.replaceAll(clientIp + ";", "");
                KVStoreUtils.putHashmapField(NetConstants.KV_PORT_KEY, mac, ipvalueTemp);
            }
        }
    }

 

TCPServerHandler.java

    /**
     * 服务端业务处理类
     *
     * @author Pactera.He
     */
    public class PurifierTCPServerHandler extends IoHandlerAdapter {
        private final static Log log = LogFactory.getLog(TCPServerHandler.class);
        private final static Map<String, String> firstHeartBeatMap = new HashMap<String, String>();
        public TCPServerHandler() {
        }
        @Override
        public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
            log.error(session.getRemoteAddress().toString() + " : " + cause.toString());
        }
        @Override
        public void messageReceived(IoSession session, Object message) throws Exception {
            // 消息内容
            String text = message.toString();
            // 获取客户端发过来的消息内容
            log.info("接收消息内容 : " + text);
            if (StringUtil.isNotBlank(text)) {
                // 解析XML文件
                readXML(text, session);
            } else {
                // 返回错误信息
                session.write("error heartbeat");
            }
        }
        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            log.debug("发送消息内容 : \n" + message.toString());
        }
        @Override
        public void sessionCreated(IoSession session) throws Exception {
            log.debug("连接创建 : " + session.getRemoteAddress().toString());
        }
        @Override
        public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
            log.info(MessageFormat.format("连接Idle [{0}] from {1} ", status, session.getRemoteAddress()));
            if (status == IdleStatus.READER_IDLE) {
                session.close(true);
            }
        }
        @Override
        public void sessionOpened(IoSession session) throws Exception {
            if (checkIsBlocked(session)) {
                session.close(true);
                return;
            }
            log.info("连接打开:" + session.getRemoteAddress().toString());
        }
        @Override
        public void sessionClosed(IoSession session) throws Exception {
            if (checkIsBlocked(session)) {
                return;
            }
            log.info("连接关闭 : " + session.getRemoteAddress().toString());
            // 关闭通知
            if (session.getAttribute("mac") != null) {
                String mac = session.getAttribute("mac").toString();
                firstHeartBeatMap.remove(mac);
                this.notifyWeChat(mac, session.getRemoteAddress().toString());
            }
        }
        /**
         * session关闭通知WeChat
         */
        private void notifyWeChat(String mac, String clientIp) {
            log.info("连接关闭:" + mac + ",通知微信 . . .");
            if (StringUtil.isNotBlank(mac)) {
                // 清除信息
                SessionCache.getInstance().remove(mac, clientIp);
            }
        }
        /**
         * 解析XML文件
         *
         * @param contents
         *            解析数据内容
         * @param session
         *            处理对象
         */
        private void readXML(String contents, IoSession session) throws DocumentException {
            Document readDoc = DocumentHelper.parseText(contents);
            Element rootNode = readDoc.getRootElement();
            String mac = "";
            // 匹配节点:tcp_msg
            if (NetConstants.NODE_TCP_MSG.equals(rootNode.getName())) {
                // 匹配节点(msg)内容
                if (NetConstants.MSG_VALUE_HEARTBEAT.equals(rootNode.elementTextTrim(NetConstants.NODE_MSG))) {
                    // mac address
                    Element node = rootNode.element(NetConstants.NODE_DATA);
                    mac = node.elementTextTrim(NetConstants.NODE_MAC_ADDRESS);
                    // 生成所需XML文件
                    createXML(mac, session, wifiVersion);
                }
            }
        }
        /**
         * 生成XML文件
         *
         * @param mac
         *            MAC地址
         * @param session
         *            处理对象
         */
        private void createXML(String mac, IoSession session, String wifiVersion) {
            log.info("当前处理Mac地址 : " + mac);
            if (StringUtil.isNotBlank(mac)) {
                // 保存客户端的会话session
                SessionCache.getInstance().save(mac, session);
                // DocumentHelper提供了创建Document对象的方法
                Document writeDoc = DocumentHelper.createDocument();
                // 添加节点:tcp_msg
                Element root = writeDoc.addElement(NetConstants.NODE_TCP_MSG);
                // 添加节点:msg
                Element msg = root.addElement(NetConstants.NODE_MSG);
                // 设置节点信息
                msg.setText(NetConstants.MSG_VALUE_HEARTBEATRES);
                // 添加节点:cmd
                Element cmd = root.addElement(NetConstants.NODE_CMD);
                // 不再检查每个心跳包
                cmd.setText(NetConstants.VALUE_NULL);
                // 添加节点:data
                Element data = root.addElement(NetConstants.NODE_DATA);
                // 添加节点:server_time
                Element server_time = data.addElement(NetConstants.NODE_SERVER_TIME);
                // 设置节点信息
                server_time.setText(String.valueOf(System.currentTimeMillis()));
                // 将document文档对象直接转换成字符串
                log.debug("发送内容: " + writeDoc.asXML());
                session.write(writeDoc.asXML());
            }
        }
        /**
         * 检查对面地址是否在黑名单中
         *
         * @param session
         *            连接session
         * @return 是:true,否:false
         */
        private boolean checkIsBlocked(IoSession session) {
            boolean ret = false;
            String[] blockList = {};
            for (String blocked : blockList) {
                if (session.getRemoteAddress().toString().indexOf(blocked) > 0) {
                    ret = true;
                    break;
                }
            }
            return ret;
        }
    }

 

posted on 2016-01-13 09:16  全心全意做开发  阅读(1854)  评论(1编辑  收藏  举报

导航