博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring websocket在线聊天室
阅读量:4090 次
发布时间:2019-05-25

本文共 5754 字,大约阅读时间需要 19 分钟。

在线聊天室 由发表在

每天大家都在使用QQ等即时聊天工具,今天我们就使用以及websocket技术在网页端简单的实现一个在线聊天的功能。

添加maven依赖

在线聊天室使需要使用到的技术或者框架包括:

  • maven作为构建工具
  • 作为后端框架
  • spring websocket作为即时消息通讯工具
  • thymeleaf作为模板引擎
  • angular作为前端框架

因此,我们首先在pom.xml中添加上述依赖:

org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-websocket

添加登录功能

我们首先来做一个简单的登录功能,主要目的是维护一个用户列表,这里我们不考虑用户验证或者登出等问题,因此,我们只需要一个登录的地址:

@Controllerpublic class LoginController {    @Autowired private SimpMessagingTemplate messagingTemplate;    @Autowired private ParticipantRepository participantRepository;    private static final String LOGIN = "/app/chat.login";    private static final String LOGOUT = "/app/chat.logout";    @RequestMapping(value = "login", method=RequestMethod.POST)    public String login(HttpServletRequest httpRequest, User user) throws ServletException{        user.setTime(new Date());        httpRequest.getSession().setAttribute("user", user);        messagingTemplate.convertAndSend(LOGIN, user);        if(participantRepository.getActiveSessions().          containsKey(httpRequest.getSession().getId())){            messagingTemplate.convertAndSend(LOGOUT,             participantRepository.getActiveSessions().                get(httpRequest.getSession().getId()));        }        participantRepository.add(httpRequest.getSession().getId(), user);        return "redirect:/chat";    }}

需要注意的是每个登录用户在登录的时候都需要往websocket的/app/chat.login地址发送登录的信息,如果以前登录过,则往发送/app/chat.logout一个登出信息,以便客户端更新用户列表。

配置websocket

我们通过@EnableWebSocketMessageBroker标注打开websocket服务,并通过继承AbstractWebSocketMessageBrokerConfigurer对websocket进行配置,这里我们进行两个配置:

@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {    @Override    public void registerStompEndpoints(StompEndpointRegistry registry) {        registry.addEndpoint("/ws").withSockJS();    }    @Override    public void configureMessageBroker(MessageBrokerRegistry config)     {        config.setApplicationDestinationPrefixes("/app");    }}

通过registry.addEndpoint("/ws").withSockJS();使得客户端可以通过/ws地址与后台建立websocket连接。设置config.setApplicationDestinationPrefixes("/app");/app开头的地址标识为应用地址。此时,用户可以通过/ws地址与服务器建立websocket连接,并通过websocket进行通信。

添加聊天后台

这里我们为添加两个方法:

首先是聊天页面,当用户访问/chat地址时,如果未登录,则抛出AccessDeniedException错误,我们的错误处理会将用户重定向到登录页面,如果用户已登录,则显示聊天页面开始聊天。

其次我们通过websocket的/chat.participants频道提供了在线用户列表,当用户订阅/app/chat.participants时,将会获得当前在线用户的列表。

@Controllerpublic class ChatController {    @Autowired ParticipantRepository participantRepository;    @RequestMapping(value="/chat", method=RequestMethod.GET)    public String chatPage(HttpServletRequest request, Model model) throws AccessDeniedException{        if(request.getSession().getAttribute("user") == null){            throw new AccessDeniedException("login please");        }        User user = (User)request.getSession().getAttribute("user");        model.addAttribute("username", user.getUsername());        return "chat";    }    @SubscribeMapping("/chat.participants")    public Collection
retrieveParticipants() { return participantRepository.getActiveSessions().values(); }}

添加websocket客户端

系统前端主要基于angular来实现,因此我们对基本websocket操作进行了封装,包括连接、订阅、发送消息。如果有兴趣,可以参考/src/main/resources/static/js/services.js。我们的主要逻辑都在/src/main/resources/static/js/controllers.js中,因此我们主要讲解一下这个文件。

首先我们来看看initStompClient方法,该方法与服务器建立了websocket连接,同时订阅了我们所需要用到的几个频道:

  • /app/chat.participants 该频道由服务器提供服务,订阅后,服务器会返回当前的用户列表
  • /topic/chat.login 当有用户登录,服务器会往该频道发送一个信息,客户端接收信息后将该用户添加进在线用户列表
  • /app/chat.logout 当有用户登出,服务器会会往该频道发送一个信息,客户端接收信息后将该用户移出在线用户列表
  • /app/chat.typing 当用户在进行输入时,会往该频道广播一个信息,客户端接收消息后在前端显示该用户正在编辑
  • /app/chat.message 用户发送消息时,会往该频道广播一条消息,客户端接收该消息,并展示该消息

var initStompClient = function() {    chatSocket.init('/ws');    chatSocket.connect(function(frame) {        chatSocket.subscribe("/app/chat.participants", function(message) {            $scope.participants = JSON.parse(message.body);        });        chatSocket.subscribe("/app/chat.login", function(message) {            $scope.participants.unshift({                username: JSON.parse(message.body).username,                 typing : false});        });        chatSocket.subscribe("/app/chat.logout", function(message) {            var username = JSON.parse(message.body).username;            for(var index in $scope.participants) {                if($scope.participants[index].username == username) {                    $scope.participants.splice(index, 1);                }            }        });        chatSocket.subscribe("/app/chat.typing", function(message) {            var parsed = JSON.parse(message.body);            if(parsed.username == $scope.username) return;            for(var index in $scope.participants) {                var participant = $scope.participants[index];                if(participant.username == parsed.username) {                    $scope.participants[index].typing = parsed.typing;                }              }         });        chatSocket.subscribe("/app/chat.message", function(message) {            $scope.messages.unshift(JSON.parse(message.body));        });    }, function(error) {        toaster.pop('error', 'Error', 'Connection error ' + error);    });};

向websocket广播消息

广播消息其实很简单,只需要向某个固定频道发送消息,这样所有订阅了该频道的用户都能接收到相应的信息,具体代码如下:

$scope.sendMessage = function() {    chatSocket.send(        "/app/chat.message",         {},         JSON.stringify({            message: $scope.newMessage,            username: $scope.username        }));    $scope.newMessage = '';};

更多文章请访问

你可能感兴趣的文章
太赞了,《快乐学 Pandas》中文教程已正式开源!
查看>>
未来 10 年,软件开发技术的 8 个发展趋势
查看>>
GitHub 标星 2.3w+!这个开源的 Java 网络通信框架究竟有多牛逼...
查看>>
GitHub 热榜:用 Zoom 开会很无聊?赶紧试下这个会议换脸神器!
查看>>
写一个开源的 macOS 软件可以赚多少钱?
查看>>
太强了!成功打入 RTC 2020 编程挑战赛决赛圈的选手,到底有多秀...
查看>>
又一神书面世:《无需计算机的计算机科学》!
查看>>
微信支付的软件架构究竟有多牛逼...
查看>>
聊聊 5G 技术的那些事儿...
查看>>
微软当年挖下大坑,现砸重金买下危险域名 corp.com 来填!
查看>>
学不会数据结构与算法,是因为你还没看过这个图文并茂的算法中文课!
查看>>
这张「二维码」在 GitHub 上火了:扫一扫,打破系统边界,文件秒传
查看>>
霸榜 GitHub,一款开源的 Linux 神器!
查看>>
我不信这些技术名词的发音你都能读对!
查看>>
太赞了,亚马逊免费对外开放计算机编程课!
查看>>
如何画出一张优秀的架构图?
查看>>
论文代码不开源,应该被直接拒稿?
查看>>
教你一招搞定 Homebrew 下载加速!
查看>>
一个神奇的开源项目:让照片快速 3D 化!
查看>>
你肯定没用过这个全新的 Git 客户端工具!
查看>>