在线聊天室
一.需求分析:
实现web版在线聊天室
(1)进入登录页面;
(2)登录成功之后,进入该系统主页面;
(3)在主页面中可以查看到当前所有的频道列表;
(4)点击某个频道列表,可以查看到该频道列表中的信息;
(5)点击某个频道,可以发送消息,此时其它用户也可以查看到该消息;
二.相关技术
webSocket介绍:webSocket是应用在Web浏览器和服务器之间进行任意的双向数据传输的一种技术。
1.消息推送:
在HTML 5之前,消息推送基本上都是使用HTTP请求的,但HTTP请求只能在客户端发起请求之后服务端才会返回消息。不能实现在客户端未发送请求时,服务端主动推送消息给客户端。
2.基于Http实现消息推送的方式包括:
- 轮询方式
- 长轮询
- 长连接
- WebSocket
3.WebSccket原理:
WebSocket协议是基于TCP协议实现的。包含初始的握手过程,以及后续的多次数据帧双向传输的过程;其目的是在WebSoccket应用和webSocket服务器进行频繁的双向通讯时,可以使服务器避免打开多个Http连接进行工作来节约资源,提高了工作效率和资源利用率。
4.使用:
使用Tomcat中内置的websocket库,在pom.xml中添加相关依赖:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
5.后端实现:使用继承或者注解的方式;
(6)注解成员数据介绍
- @OnClose——连接关闭时的调用方法;
- @OnOpen——有连接时进行调用的方法;
- @OnMessage——收到消息进行调用的函数;
- Session ----每个Session代表了两个web socket断点的会话;
当websocket握手成功后,websocket就会提供一个打开的Session,可以通过这个 Session来对另一个端点发送数据;如果Session关闭后发送数据将会报错。
- Session.getBasicRemote().sendText("message") -------向该Session连接的用户发送字符串数据。
- @OnError发生意外错误时调用的函数。
三、接口设计
1.用户管理相关接口设计
接口模块 | 接口名称 | 接口类型 | 接口说明 |
用户管理模块 | register | 内部接口 | 注册 |
login | 内部接口 | 登录 | |
logout | 内部接口 | 注销 |
2.频道管理相关接口设计
接口模块 | 接口名称 | 接口类型 | 接口说明 |
频道管理模块 | channel | 内部接口 | 频道相关操作接口 |
四、具体实现
1.数据库设计
(1)用户表user:
create table user (userId int primary key auto_increment,
name varchar(50) unique,
password varchar(50),
nickName varchar(50),
iconPath varchar(2048),
signature varchar(100),
lastLogout DateTime
);
insert into user values(null, 'test', '123', '张三', '', '我擅长唱', now());
(2)频道表channel
create table channel (channelId int primary key auto_increment,
channelName varchar(50)
);
insert into channel values(null, '体坛赛事');
insert into channel values(null, '娱乐八卦');
insert into channel values(null, '时事新闻');
insert into channel values(null, '午夜情感');
(3)消息表mesage
create table message (messageId int primary key auto_increment,
userId int,
channelId int
content text,
sendTime DateTime
);
insert into message values (null, 1, 1, 'hehe1', now());
2.model层实现——创建实体类
(1)User类表示一个用户:
public class User {
int userId;
String name;
String password;
String nickName;
String iconPath;
String signature;
java.sql.TimeStamp lastLogout; }
(2)Channel类表示一个频道:
public class Channel {
private int channelId;
private String channelName; }
(3)Message类表示一条消息:
public class Message {
private int messageId;
private int userId;
private String nickName; // 这个字段只是为了前后端交互方便, 表中没这个.
private int channelId;
private String content;
private java.sql.TimeStamp sendTime;
}
3.dao层实现——对数据的相关操作;
(1)实现UserDao:具体包括:实现新增用户、按名字查询、按id查询等功能;
实现新增用户
public void add(User user) throws ChatroomException {
Connection connection = DBUtil.getConnection();
String sql = "insert into user values(null, ?, ?, ?, ?, ?, now())";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1, user.getName());
statement.setString(2, user.getPassword());
statement.setString(3, user.getNickName());
statement.setString(4, user.getIconPath());
statement.setString(5, user.getSignature());
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw new ChatroomException("插入用户失败");
} finally {
DBUtil.close(connection, statement, null);
}
}
实现按名字查找
public User selectByName(String name) throws ChatroomException {
Connection connection = DBUtil.getConnection();
String sql = "select * from user where name = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1, name);
resultSet = statement.executeQuery();
if (resultSet.next()) {
User user = new User();
user.setUserId(resultSet.getInt("userId"));
user.setName(resultSet.getString("name"));
user.setPassword(resultSet.getString("password"));
user.setNickName(resultSet.getString("nickName"));
user.setIconPath(resultSet.getString("iconPath"));
user.setSignature(resultSet.getString("signature"));
user.setLastLogin(resultSet.getTimestamp("lastLogout"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
throw new ChatroomException("通过姓名查找用户失败");
} finally {
DBUtil.close(connection, statement, resultSet);
}
return null; }
实现按id查找
public User selectById(int userId) throws ChatroomException {
Connection connection = DBUtil.getConnection();
String sql = "select * from user where userId = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1, userId);
resultSet = statement.executeQuery();
if (resultSet.next()) {
User user = new User();
user.setUserId(resultSet.getInt("userId"));
user.setName(resultSet.getString("name"));
user.setPassword(resultSet.getString("password"));
user.setNickName(resultSet.getString("nickName"));
user.setIconPath(resultSet.getString("iconPath"));
user.setSignature(resultSet.getString("signature"));
user.setLastLogin(resultSet.getTimestamp("lastLogout"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
throw new ChatroomException("通过 id 查找用户失败");
} finally {
DBUtil.close(connection, statement, resultSet);
}
return null; }
(2)实现ChannelDao:包括实现新增频道、删除频道、查看所有频道等功能;
(3)实现MessageDao:包括实现新增消息,按时间获取消息等功能;