Mina聊天服务端实现思路:在用户登录的时候,连接服务端并且验证登录用户,如果成功,则将IoSession保存到map<账号,IoSession>中,并且通知该用户的好友上线,然
后再请求好友列表;若不成功,则断开连接。
自定义协议格式:包头+包体
包头(10字节):包头长度(short)+ 消息类型(byte)+ 内容类型(byte) + 消息命令(short)+ 包体长度(int)
包体:JSON字符串
自定义编码解码:由于数据在网络传输过程中都是以二进制传输的,所以我们可以自定义自己的编码解码格式,详细实现代码可以看下面的
ChatServerDecode和ChatServerEncode
数据库(chat):三张表 用户表(user),好友表(friends),分类表(category)
/* Navicat MySQL Data Transfer Source Server : bufoon Source Server Version : 50527 Source Host : localhost:3306 Source Database : chat Target Server Type : MYSQL Target Server Version : 50527 File Encoding : 65001 Date: 2014-06-29 23:30:28 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for category -- ---------------------------- DROP TABLE IF EXISTS `category`; CREATE TABLE `category` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) DEFAULT NULL, `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `FK_CATEGOFY_USER_ID` (`user_id`), CONSTRAINT `FK_CATEGOFY_USER_ID` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- ---------------------------- -- Records of category -- ---------------------------- INSERT INTO `category` VALUES ('1', '1', '我的好友', '2014-06-29 19:00:25'); INSERT INTO `category` VALUES ('3', '2', '我的好友', '2014-06-29 19:00:55'); INSERT INTO `category` VALUES ('4', '3', '我的好友', '2014-06-29 19:01:00'); INSERT INTO `category` VALUES ('5', '1', '同学', '2014-06-29 20:39:04'); -- ---------------------------- -- Table structure for friends -- ---------------------------- DROP TABLE IF EXISTS `friends`; CREATE TABLE `friends` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) DEFAULT NULL, `friend_id` int(11) DEFAULT NULL, `category_id` int(11) DEFAULT NULL, `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `FK_FRIENDS_USER_ID` (`user_id`), KEY `FK_FRIENDS_CATEGORY_ID` (`category_id`), KEY `FK_FRIENDS_FUSER_ID` (`friend_id`), CONSTRAINT `FK_FRIENDS_CATEGORY_ID` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE, CONSTRAINT `FK_FRIENDS_FUSER_ID` FOREIGN KEY (`friend_id`) REFERENCES `user` (`id`) ON DELETE CASCADE, CONSTRAINT `FK_FRIENDS_USER_ID` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- ---------------------------- -- Records of friends -- ---------------------------- INSERT INTO `friends` VALUES ('1', '1', '2', '1', '2014-06-21 23:35:16'); INSERT INTO `friends` VALUES ('2', '1', '3', '1', '2014-06-21 23:35:22'); INSERT INTO `friends` VALUES ('3', '2', '1', '3', '2014-06-22 02:09:24'); INSERT INTO `friends` VALUES ('4', '3', '1', '4', '2014-06-22 02:09:29'); -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, `user_num` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL, `password` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, `regist_time` datetime DEFAULT NULL, `sex` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `signature` varchar(300) COLLATE utf8_unicode_ci DEFAULT NULL, `head_pic_path` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, `is_online` varchar(1) COLLATE utf8_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', '张三', '12345', '12345', '2014-06-20 23:32:26', '男', null, null, '0'); INSERT INTO `user` VALUES ('2', '李四', '123456', '123456', '2014-06-20 23:32:31', '女', null, null, '1'); INSERT INTO `user` VALUES ('3', '王二', '1234567', '1234567', '2014-06-21 11:29:41', '男', null, null, '1');
项目目录结构:
需要的jar包:
ChatServer.java
package com.bufoon.main; import java.io.IOException; import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.keepalive.KeepAliveFilter; import org.apache.mina.filter.keepalive.KeepAliveMessageFactory; import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler; import org.apache.mina.filter.logging.LogLevel; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import com.bufoon.codeFactory.ChatServerCodecFactory; import com.bufoon.handle.ChatServerHandle; import com.bufoon.handle.KeepAliveMessageFactoryImpl; import com.bufoon.handle.KeepAliveRequestTimeoutHandlerImpl; public class ChatServer { private static final int PORT = 7073; //30秒后超时 private static final int IDELTIMEOUT = 30; //15秒发送一次心跳包 private static final int HEARTBEATRATE = 15; private static SocketAcceptor acceptor; public static SocketAcceptor getAcceptor(){ if(null==acceptor){ // 创建非阻塞的server端的Socket连接 acceptor = new NioSocketAcceptor(); } return acceptor; } public static boolean serverStart() { DefaultIoFilterChainBuilder filterChain = getAcceptor().getFilterChain(); // 添加编码过滤器 处理乱码、编码问题 filterChain.addLast("codec", new ProtocolCodecFilter(new ChatServerCodecFactory())); LoggingFilter loggingFilter = new LoggingFilter(); loggingFilter.setMessageReceivedLogLevel(LogLevel.INFO); loggingFilter.setMessageSentLogLevel(LogLevel.INFO); // 添加日志过滤器 filterChain.addLast("loger", loggingFilter); // 设置核心消息业务处理器 getAcceptor().setHandler(new ChatServerHandle()); KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl(); KeepAliveRequestTimeoutHandler heartBeatHandler = new KeepAliveRequestTimeoutHandlerImpl(); KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory,IdleStatus.BOTH_IDLE, heartBeatHandler); // 是否回发 heartBeat.setForwardEvent(true); // 发送频率 heartBeat.setRequestInterval(HEARTBEATRATE); // getAcceptor().getFilterChain().addLast("heartbeat", heartBeat); getAcceptor().getSessionConfig().setBothIdleTime(30); // 设置session配置,30秒内无操作进入空闲状态 getAcceptor().getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, IDELTIMEOUT); try { // 绑定端口7033 getAcceptor().bind(new InetSocketAddress(PORT)); return true; } catch (IOException e) { e.printStackTrace(); } return false; } public static void main(String[] args) { ChatServer.serverStart(); System.out.println("服务器启动..."); } }
package com.bufoon.handle; import java.sql.ResultSet; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.chat.ChatProtocolHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.bufoon.model.CategoryModel; import com.bufoon.model.FriendsModel; import com.bufoon.model.LoginModel; import com.bufoon.model.PackageHead; import com.bufoon.model.SendModel; import com.bufoon.model.UserModel; import com.bufoon.util.BaseDAO; import com.bufoon.util.DBUtil; import com.bufoon.util.MessageType; public class ChatServerHandle extends IoHandlerAdapter { private final static Logger logger = LoggerFactory.getLogger(ChatProtocolHandler.class); public static Map<String, IoSession> sessionMap = new HashMap<String, IoSession>(); @Override public void sessionCreated(IoSession session) throws Exception { logger.info("创建连接"); } @Override public void sessionOpened(IoSession session) throws Exception { logger.info("打开连接"); } @Override public void sessionClosed(IoSession session) throws Exception { logger.info("关闭连接"); String userNum = (String) session.getAttribute("userNum"); String sql = "update user set is_online=1 where user_num like'" + userNum + "'"; DBUtil.getInstance().executeUpdate(sql); sessionMap.remove(userNum); //修改下线,通知 String userSql = "select * from user where user_num like '" + userNum + "'"; UserModel userModel = BaseDAO.getInstance().findUserModel(userSql); String friendListSql = "select * from friends where user_id=" + userModel.getId(); List<FriendsModel> list = BaseDAO.getInstance().findFriendsList(friendListSql); for (FriendsModel friendsModel : list) { String fUserSql = "select * from user where id=" + friendsModel.getFriendId(); UserModel userModel2 = BaseDAO.getInstance().findUserModel(fUserSql); IoSession is = sessionMap.get(userModel2.getUserNum()); if (is != null) { PackageHead ph = new PackageHead(); Map<String, Object> object = new HashMap<String, Object>(); object.put("userNum", userModel2.getUserNum()); object.put("status", 1); //下线 String content = JSONObject.fromObject(object).toString(); ph.setPackageHeadLength(10); ph.setMessageCommand(MessageType.USER_ON_OFF_LINE_NOTICE); ph.setContentType(MessageType.CONTENT_TYPE_OBJECT); ph.setMessageType(MessageType.MESSAGE_TYPE_PUSH); ph.setPackageBodyLength(content.getBytes().length); ph.setPackageBodyContent(content); is.write(ph); } } } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { logger.info("进入空闲"); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.warn("异常.", cause); session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { System.out.println(message); PackageHead ph = (PackageHead) message; System.out.println("还有没有这个session:" + sessionMap.size()); switch (ph.getMessageCommand()) { case MessageType.LOGIN_VERIFY: //登录请求 LoginModel loginModel = (LoginModel)JSONObject.toBean(JSONObject.fromObject(ph.getPackageBodyContent()), LoginModel.class); String username = loginModel.getUsername(); IoSession is = sessionMap.get(username); Map<String, Object> map = new HashMap<String, Object>(); if (!DBUtil.getInstance().isExit("user", "user_num", username)) { System.out.println("用户不存在"); map.put("status", 1); map.put("info", "用户不存在"); map.put("username", username); } else if (is != null && is.isConnected()) { System.out.println("用户已登录"); map.put("status", 2); map.put("info", "用户已登录"); map.put("username", username); } else if (!DBUtil.getInstance().isExit("user", new String[]{"user_num", "password"}, new Object[]{username, loginModel.getPassword()})) { System.out.println("用户密码错误"); map.put("status", 3); map.put("info", "用户密码错误"); map.put("username", username); } else if (DBUtil.getInstance().isExit("user", new String[]{"user_num", "password"}, new Object[]{username, loginModel.getPassword()})) { String sql = "select * from user where user_num like '" + username + "'"; ResultSet rs = DBUtil.getInstance().executeQuery(sql); UserModel vo = null; while (rs.next()) { vo = new UserModel(); vo.setId(rs.getInt("id")); vo.setUsername(rs.getString("name")); vo.setUserNum(rs.getString("user_num")); vo.setPassword(rs.getString("password")); vo.setSex(rs.getString("sex")); vo.setSignature(rs.getString("signature")); vo.setIsOnline(rs.getInt("is_online")); break; } if (vo != null) { map.put("username", vo.getUsername()); } map.put("status", 0); map.put("info", "成功"); map.put("userNum", username); map.put("userVO", vo); session.setAttribute("userNum", username); sessionMap.put(username, session); } String onLinesql = "update user set is_online=0 where user_num like'" + username + "'"; DBUtil.getInstance().executeUpdate(onLinesql); String content = JSONObject.fromObject(map).toString(); ph.setMessageCommand(MessageType.LOGIN_VERIFY_ACK); ph.setContentType(MessageType.CONTENT_TYPE_OBJECT); ph.setMessageType(MessageType.MESSAGE_TYPE_REQUEST); ph.setPackageBodyLength(content.getBytes().length); ph.setPackageBodyContent(content); session.write(ph); String friendSql = "select * from user where user_num like '" + username + "'"; ResultSet rs1 = DBUtil.getInstance().executeQuery(friendSql); Map<String, Object> object = new HashMap<String, Object>(); object.put("userNum", username); object.put("status", 0); content = JSONObject.fromObject(object).toString(); ph.setMessageCommand(MessageType.USER_ON_OFF_LINE_NOTICE); ph.setContentType(MessageType.CONTENT_TYPE_OBJECT); ph.setMessageType(MessageType.MESSAGE_TYPE_PUSH); ph.setPackageBodyLength(content.getBytes().length); ph.setPackageBodyContent(content); while (rs1.next()) { String sql1 = "select * from friends where user_id=" + rs1.getInt("id"); ResultSet rs2 = DBUtil.getInstance().executeQuery(sql1); while(rs2.next()){ String sql2 = "select * from user where id=" + rs2.getInt("friend_id"); ResultSet rs3 = DBUtil.getInstance().executeQuery(sql2); while(rs3.next()){ IoSession iso = sessionMap.get(rs3.getString("user_num")); if(iso != null){ iso.write(ph); } } } } break; case MessageType.FRIEND_LIST: //好友列表请求 JSONObject obj = JSONObject.fromObject(ph.getPackageBodyContent()); String userId = obj.getString("userId"); String friendListSql = "select * from friends where user_id=" + userId; List<FriendsModel> friendList = BaseDAO.getInstance().findFriendsList(friendListSql); String categorySql = "select * from category where user_id=" + userId; List<CategoryModel> categoryList = BaseDAO.getInstance().findCategoryList(categorySql); for (CategoryModel categoryModel : categoryList) { for (FriendsModel friendModel : friendList) { if (categoryModel.getId() == friendModel.getCategoryId()) { String userSql = "select * from user where id=" + friendModel.getFriendId(); categoryModel.getList().add(BaseDAO.getInstance().findUserModel(userSql)); } } } String friends = JSONArray.fromObject(categoryList).toString(); System.out.println("frends:" + friends); ph.setMessageCommand(MessageType.FRIEND_LIST_ACK); ph.setContentType(MessageType.CONTENT_TYPE_ARRAY); ph.setMessageType(MessageType.MESSAGE_TYPE_REQUEST); ph.setPackageBodyLength(friends.getBytes().length); ph.setPackageBodyContent(friends); session.write(ph); break; case MessageType.SEND_MESSAGE: //消息发送 SendModel sendModel = (SendModel)JSONObject.toBean(JSONObject.fromObject(ph.getPackageBodyContent()), SendModel.class); ph.setMessageType(MessageType.SEND_MESSAGE_ACK); session.write(ph); ph.setMessageCommand(MessageType.SEND_MESSAGE_ACK_NOTICE); String sendStr = JSONObject.fromObject(sendModel).toString(); ph.setPackageBodyLength(sendStr.getBytes().length); ph.setPackageBodyContent(sendStr); ph.setMessageType(MessageType.MESSAGE_TYPE_PUSH); ph.setContentType(MessageType.CONTENT_TYPE_OBJECT); sessionMap.get(sendModel.getReceiverNum()).write(ph); break; //查找好友 //注册 //添加好友 } } @Override public void messageSent(IoSession session, Object message) throws Exception { logger.info("发送消息: " + message); } }
package com.bufoon.codeFactory; import java.nio.charset.Charset; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolEncoder; public class ChatServerCodecFactory implements ProtocolCodecFactory{ private static final Charset charset = Charset.forName("UTF-8"); @Override public ProtocolEncoder getEncoder(IoSession session) throws Exception { return new ChatServerEncode(charset); } @Override public ProtocolDecoder getDecoder(IoSession session) throws Exception { return new ChatServerDecode(charset); } }ChatServerDecode.java
package com.bufoon.codeFactory; import java.nio.ByteOrder; import java.nio.charset.Charset; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.AttributeKey; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolDecoder; import org.apache.mina.filter.codec.ProtocolDecoderOutput; import com.bufoon.model.PackageHead; public class ChatServerDecode implements ProtocolDecoder { private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context"); private final Charset charset; private int maxPackLength = 100; public ChatServerDecode() { this(Charset.defaultCharset()); } public ChatServerDecode(Charset charset) { this.charset = charset; } public int getMaxLineLength() { return maxPackLength; } public void setMaxLineLength(int maxLineLength) { if (maxLineLength <= 0) { throw new IllegalArgumentException("maxLineLength: " + maxLineLength); } this.maxPackLength = maxLineLength; } private ChatContext getContext(IoSession session) { ChatContext ctx; ctx = (ChatContext) session.getAttribute(CONTEXT); if (ctx == null) { ctx = new ChatContext(charset); session.setAttribute(CONTEXT, ctx); } return ctx; } @Override public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { final int packHeadLength = 10; // 先获取上次的处理上下文,其中可能有未处理完的数据 in.order(ByteOrder.LITTLE_ENDIAN); ChatContext ctx = getContext(session); // 先把当前buffer中的数据追加到Context的buffer当中 ctx.append(in); // 把position指向0位置,把limit指向原来的position位置 IoBuffer buf = ctx.getBuffer(); buf.flip(); // 然后按数据包的协议进行读取 if (buf.remaining() >= packHeadLength) { buf.mark(); // 读取消息头部分 PackageHead message = new PackageHead(); message.setPackageHeadLength(buf.getShort()); message.setMessageType(buf.get()); message.setContentType(buf.get()); message.setMessageCommand(buf.getShort()); int bodyLen = buf.getInt(); message.setPackageBodyLength(bodyLen); // 读取正常的消息包,并写入输出流中,以便IoHandler进行处理 if (bodyLen > 0 && buf.remaining() >= bodyLen) { message.setPackageBodyContent(buf.getString(bodyLen, charset.newDecoder())); } else { //buf.clear(); } out.write(message); } if (buf.hasRemaining()) { // 将数据移到buffer的最前面 IoBuffer temp = IoBuffer.allocate(maxPackLength) .setAutoExpand(true); temp.put(buf); temp.flip(); buf.clear(); buf.put(temp); } else {// 如果数据已经处理完毕,进行清空 buf.clear(); } } @Override public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { } @Override public void dispose(IoSession session) throws Exception { ChatContext ctx = (ChatContext) session.getAttribute(CONTEXT); if (ctx != null) { session.removeAttribute(CONTEXT); } } }
package com.bufoon.codeFactory; import java.nio.ByteOrder; import java.nio.charset.Charset; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoderAdapter; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import com.bufoon.model.PackageHead; public class ChatServerEncode extends ProtocolEncoderAdapter { private Charset charset = null; public ChatServerEncode(Charset charset) { this.charset = charset; } @Override public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { if (message instanceof PackageHead) { PackageHead ph = (PackageHead) message; IoBuffer buf = IoBuffer.allocate(ph.getPackageHeadLength() + ph.getPackageBodyLength()); buf.order(ByteOrder.LITTLE_ENDIAN); //buf.setAutoExpand(true); buf.putShort((short) ph.getPackageHeadLength()); buf.put((byte) ph.getMessageType()); buf.put((byte) ph.getContentType()); buf.putShort((short) ph.getMessageCommand()); buf.putInt((int) ph.getPackageBodyLength()); if (ph.getPackageBodyLength() > 0) { buf.putString(ph.getPackageBodyContent(), charset.newEncoder()); } buf.flip(); out.write(buf); out.flush(); buf.free(); } } }ChatContext.java
package com.bufoon.codeFactory; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import org.apache.mina.core.buffer.IoBuffer; public class ChatContext { private final CharsetDecoder decoder; private IoBuffer buf; private int matchCount = 0; private int overflowPosition = 0; public ChatContext(Charset charset) { decoder = charset.newDecoder(); buf = IoBuffer.allocate(80).setAutoExpand(true); buf.order(ByteOrder.LITTLE_ENDIAN); } public CharsetDecoder getDecoder() { return decoder; } public IoBuffer getBuffer() { return buf; } public int getOverflowPosition() { return overflowPosition; } public int getMatchCount() { return matchCount; } public void setMatchCount(int matchCount) { this.matchCount = matchCount; } public void reset() { overflowPosition = 0; matchCount = 0; decoder.reset(); } public void append(IoBuffer in) { getBuffer().put(in); } }
package com.bufoon.util; public class MessageType { /**登录验证请求消息类型**/ public final static int LOGIN_VERIFY = 0x0000; /**登录验证响应消息类型**/ public final static int LOGIN_VERIFY_ACK = 0x0001; /**心跳请求消息类型**/ public final static int HEART_BEAT = 0x0002; /**心跳响应消息类型**/ public final static int HEART_BEAT_ACK = 0x0003; /**好友列表请求消息类型**/ public final static int FRIEND_LIST = 0x0004; /**好友列表响应消息类型**/ public final static int FRIEND_LIST_ACK = 0x0005; /**发送消息请求**/ public final static int SEND_MESSAGE = 0x0006; /**发送消息响应**/ public final static int SEND_MESSAGE_ACK = 0x0007; /**发送消息通知响应**/ public final static int SEND_MESSAGE_ACK_NOTICE = 0x1000; /**通知用户上下线**/ public final static int USER_ON_OFF_LINE_NOTICE = 0X1001; /**包头大小**/ public final static int HEAD_LENGTH = 10; /**返回的消息类型 0服务端推送**/ public final static int MESSAGE_TYPE_PUSH = 0; /**返回的消息类型 1请求响应**/ public final static int MESSAGE_TYPE_REQUEST = 1; /**返回的内容类型 0 JsonObject**/ public final static int CONTENT_TYPE_OBJECT = 0; /**返回的内容类型 1 JsonArray**/ public final static int CONTENT_TYPE_ARRAY = 1; }DBUtil.java
package com.bufoon.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * 数据库 连接类 * @author AllenYe * */ public class DBUtil { private static final DBUtil uniqueInstance = new DBUtil(); private DBUtil(){ //加载mysql-jdbc桥接器: try{ Class.forName("com.mysql.jdbc.Driver"); }catch(ClassNotFoundException e){} } public static DBUtil getInstance() { return uniqueInstance; } //公共的connection private Connection conn=null; private Connection getConnection() throws Exception { if(conn == null) { //设置connection的url,账号,密码 conn=DriverManager.getConnection( "jdbc:mysql://localhost:3306/chat?useUnicode=true&characterEncoding=UTF-8" ,"root" ,"root"); } return conn; } public ResultSet executeQuery(String sql) { try { Statement statement = getConnection().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); ResultSet rs = statement.executeQuery(sql); return rs; } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } public int executeUpdate(String sql) { try { PreparedStatement statement = getConnection().prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); int result = statement.executeUpdate(); return result; } catch (SQLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return -1; } public boolean isExit(String table, String column, String value){ String sql = "select * from " + table + " where " + column + " like '" + value + "'"; ResultSet rs = this.executeQuery(sql); boolean flag = false; try { while (rs.next()) { flag = true; break; } } catch (SQLException e) { e.printStackTrace(); } return flag; } public boolean isExit(String table, String column[], Object value[]){ StringBuffer sb = new StringBuffer("select * from " + table + " where 1=1"); for(int i = 0; i < column.length; i++){ sb.append(" and " + column[i] + " like '" + value[i] + "'"); } ResultSet rs = this.executeQuery(sb.toString()); boolean flag = false; try { while (rs.next()) { flag = true; break; } } catch (SQLException e) { e.printStackTrace(); } return flag; } }
package com.bufoon.util; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.bufoon.model.CategoryModel; import com.bufoon.model.FriendsModel; import com.bufoon.model.UserModel; public class BaseDAO { private static final BaseDAO uniqueInstance = new BaseDAO(); private BaseDAO(){ } public static BaseDAO getInstance() { return uniqueInstance; } public UserModel findUserModel(String sql){ UserModel vo = null; try { ResultSet rs = DBUtil.getInstance().executeQuery(sql); while(rs.next()){ vo = new UserModel(); vo.setId(rs.getInt("id")); vo.setUsername(rs.getString("name")); vo.setUserNum(rs.getString("user_num")); vo.setPassword(rs.getString("password")); vo.setIsOnline(rs.getInt("is_online")); vo.setSignature(rs.getString("signature")); vo.setSex(rs.getString("sex")); } } catch (SQLException e) { e.printStackTrace(); } return vo; } public List<FriendsModel> findFriendsList(String sql){ List<FriendsModel> list = new ArrayList<FriendsModel>(); try { ResultSet rs = DBUtil.getInstance().executeQuery(sql); FriendsModel vo = null; while(rs.next()){ vo = new FriendsModel(); vo.setId(rs.getInt("id")); vo.setUserId(rs.getInt("user_id")); vo.setFriendId(rs.getInt("friend_id")); vo.setCategoryId(rs.getInt("category_id")); vo.setCreateTime(Util.formatTime(rs.getDate("create_time"))); list.add(vo); } } catch (SQLException e) { e.printStackTrace(); } return list; } public List<CategoryModel> findCategoryList(String sql){ List<CategoryModel> list = new ArrayList<CategoryModel>(); CategoryModel vo = null; ResultSet rs = DBUtil.getInstance().executeQuery(sql); try { while(rs.next()){ vo = new CategoryModel(); vo.setId(rs.getInt("id")); vo.setUserId(rs.getInt("user_id")); vo.setName(rs.getString("name")); vo.setCreateTime(Util.formatTime(rs.getDate("create_time"))); list.add(vo); } } catch (SQLException e) { e.printStackTrace(); } return list; } }
package com.bufoon.model; import java.io.Serializable; public class PackageHead implements Serializable { private static final long serialVersionUID = 3965541808116510722L; private int id; //id private int packageHeadLength; //包头长度 short 2个字节 长度为10 private int messageType; //消息类型 byte 1字节 private int contentType; //内容类型 1字节 private int messageCommand; //消息命令 short 2字节 private int packageBodyLength; //包体长度 消息int 4字节 private String packageBodyContent; //包体内容 大小 为packageBodyLength public int getId() { return id; } public void setId(int id) { this.id = id; } public int getPackageHeadLength() { return packageHeadLength; } public void setPackageHeadLength(int packageHeadLength) { this.packageHeadLength = packageHeadLength; } public int getMessageType() { return messageType; } public void setMessageType(int messageType) { this.messageType = messageType; } public int getContentType() { return contentType; } public void setContentType(int contentType) { this.contentType = contentType; } public int getMessageCommand() { return messageCommand; } public void setMessageCommand(int messageCommand) { this.messageCommand = messageCommand; } public int getPackageBodyLength() { return packageBodyLength; } public void setPackageBodyLength(int packageBodyLength) { this.packageBodyLength = packageBodyLength; } public String getPackageBodyContent() { return packageBodyContent; } public void setPackageBodyContent(String packageBodyContent) { this.packageBodyContent = packageBodyContent; } @Override public String toString() { return "Messeage is: command=" + getMessageCommand() + ", type=" + getMessageType() + ", contentLength=" + getPackageBodyLength() + ", content=" + getPackageBodyContent(); } }
Mina airQQ聊天 服务端篇(二),布布扣,bubuko.com
原文:http://blog.csdn.net/songanling/article/details/35862657