首先需要导入的包
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;
- }
- }
Mina与Spring整合
原文:http://www.cnblogs.com/codeydt/p/5126220.html