前言


  QQ这类即时通讯工具多数是以桌面应用的方式存在。在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户端的流量。而websocket的出现,则完美的解决了这些问题。

spring boot对websocket进行了封装,这对实现一个websocket网页即时通讯应用来说,变得非常简单。

一、准备工作


pom.xml引入

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

完整的pom.xml文件代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId>
<artifactId>spring-boot-16</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>spring-boot-16</name>
<description>Demo project for Spring Boot</description> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

pom.xml

二、代码编写


1.创建名为“WebSocketConfig.java”的类来配置websocket,并继承抽象类“AbstractWebSocketMessageBrokerConfigurer”

此类声明“@EnableWebSocketMessageBroker”的注解

package com.example;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
} @Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/my-websocket").withSockJS();
} }

这里配置了以“/app”开头的websocket请求url。和名为“my-websocket”的endpoint(端点)

2.编写一个DTO类来承载消息:

package com.example;

public class SocketMessage {

    public String message;

    public String date;

}

3.创建App.java类,用于启用spring boot和用于接收、发送消息的控制器。

package com.example;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; @Controller
@EnableScheduling
@SpringBootApplication
public class App { public static void main(String[] args) {
SpringApplication.run(App.class, args);
} @Autowired
private SimpMessagingTemplate messagingTemplate; @GetMapping("/")
public String index() {
return "index";
} @MessageMapping("/send")
@SendTo("/topic/send")
public SocketMessage send(SocketMessage message) throws Exception {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
message.date = df.format(new Date());
return message;
} @Scheduled(fixedRate = 1000)
@SendTo("/topic/callback")
public Object callback() throws Exception {
// 发现消息
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
messagingTemplate.convertAndSend("/topic/callback", df.format(new Date()));
return "callback";
}
}

“send”方法用于接收客户端发送过来的websocket请求。

@EnableScheduling注解为:启用spring boot的定时任务,这与“callback”方法相呼应,用于每隔1秒推送服务器端的时间。

4.在“resources/templates”目录下创建index.html文件:

<!DOCTYPE html>
<html>
<head>
<title>玩转spring boot——websocket</title>
<script src="//cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
/*<![CDATA[*/ var stompClient = null; var app = angular.module('app', []);
app.controller('MainController', function($rootScope, $scope, $http) { $scope.data = {
//连接状态
connected : false,
//消息
message : '',
rows : []
}; //连接
$scope.connect = function() {
var socket = new SockJS('/my-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
// 注册发送消息
stompClient.subscribe('/topic/send', function(msg) {
$scope.data.rows.push(JSON.parse(msg.body));
$scope.data.connected = true;
$scope.$apply();
});
// 注册推送时间回调
stompClient.subscribe('/topic/callback', function(r) {
$scope.data.time = '当前服务器时间:' + r.body;
$scope.data.connected = true;
$scope.$apply();
}); $scope.data.connected = true;
$scope.$apply();
});
}; $scope.disconnect = function() {
if (stompClient != null) {
stompClient.disconnect();
}
$scope.data.connected = false;
} $scope.send = function() {
stompClient.send("/app/send", {}, JSON.stringify({
'message' : $scope.data.message
}));
}
});
/*]]>*/
</script>
</head>
<body ng-app="app" ng-controller="MainController"> <h2>玩转spring boot——websocket</h2>
<h4>
出处:刘冬博客 <a href="http://www.cnblogs.com/goodhelper">http://www.cnblogs.com/goodhelper</a>
</h4> <label>WebSocket连接状态:</label>
<button type="button" ng-disabled="data.connected" ng-click="connect()">连接</button>
<button type="button" ng-click="disconnect()"
ng-disabled="!data.connected">断开</button>
<br />
<br />
<div ng-show="data.connected">
<label>{{data.time}}</label> <br /> <br /> <input type="text"
ng-model="data.message" placeholder="请输入内容..." />
<button ng-click="send()" type="button">发送</button>
<br /> <br /> 消息列表: <br />
<table>
<thead>
<tr>
<th>内容</th>
<th>时间</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in data.rows">
<td>{{row.message}}</td>
<td>{{row.date}}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

除了引用angular.js的CDN文件外,还需要引用sockjs和stomp。

完整的项目结构,如下图所示:

三、运行效果


点击“连接”按钮,出现发送消息的输入框。并接收到服务器端的时间推送。

输入发送内容并点击“发送”按钮后,页面显示出刚才发送的消息。

点击“断开”按钮,则服务器端不会再推送消息。

总结


在开发一个基于web的即时通讯应用的过程中,我们还需考虑session的机制。

还需要一个集合来承载当前的在线用户,并做一个定时任务,其目的是用轮询的方式定时处理在线用户的状态,有哪些用户在线,又有哪些用户离线。

参考:

http://spring.io/guides/gs/scheduling-tasks/
http://spring.io/guides/gs/messaging-stomp-websocket/

代码地址:

https://github.com/carter659/spring-boot-16

如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。

有可能就是你的一点打赏会让我的博客写的更好:)

返回玩转spring boot系列目录

玩转spring boot——websocket的更多相关文章

  1. spring boot websocket stomp 实现广播通信和一对一通信聊天

    一.前言 玩.net的时候,在asp.net下有一个叫 SignalR 的框架,可以在ASP .NET的Web项目中实现实时通信.刚接触java寻找相关替代品,发现 java 体系中有一套基于stom ...

  2. 玩转spring boot——快速开始

    开发环境: IED环境:Eclipse JDK版本:1.8 maven版本:3.3.9 一.创建一个spring boot的mcv web应用程序 打开Eclipse,新建Maven项目 选择quic ...

  3. 玩转spring boot——开篇

    很久没写博客了,而这一转眼就是7年.这段时间并不是我没学习东西,而是园友们的技术提高的非常快,这反而让我不知道该写些什么.我做程序已经有十几年之久了,可以说是彻彻底底的“程序老炮”,至于技术怎么样?我 ...

  4. 玩转spring boot——结合redis

    一.准备工作 下载redis的windows版zip包:https://github.com/MSOpenTech/redis/releases 运行redis-server.exe程序 出现黑色窗口 ...

  5. 玩转spring boot——AOP与表单验证

    AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...

  6. 玩转spring boot——结合JPA入门

    参考官方例子:https://spring.io/guides/gs/accessing-data-jpa/ 接着上篇内容 一.小试牛刀 创建maven项目后,修改pom.xml文件 <proj ...

  7. 玩转spring boot——结合JPA事务

    接着上篇 一.准备工作 修改pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...

  8. 玩转spring boot——结合AngularJs和JDBC

    参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...

  9. 玩转spring boot——结合jQuery和AngularJs

    在上篇的基础上 准备工作: 修改pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...

随机推荐

  1. MyEclipse修改项目名称后,部署到tomcat问题。

    1.问题描述: 修改项目名称后,部署到tomcat server,部署出来的文件夹名还是旧的名称. 2.解决方案: 光把项目重命名是不够的,还要修改一下Myeclipse里面的配置. a). 工程名- ...

  2. Servlet,过滤器,监听器,拦截器的区别

    1.过滤器 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml ...

  3. 广义后缀树(GST)算法的简介

    导言 最近软件安全课上,讲病毒特征码的提取时,老师讲了一下GST算法.这里就做个小总结. 简介 基本信息  广义后缀树的英文为Generalized Suffix Tree,简称GST. 算法目的   ...

  4. 浅谈 Java Xml 底层解析方式

    XML 使用DTD(document type definition)文档类型来标记数据和定义数据,格式统一且跨平台和语言,已成为业界公认的标准. 目前 XML 描述数据龙头老大的地位渐渐受到 Jso ...

  5. Visual Studio 2017 针对移动开发的新特性介绍

    欢迎大家持续关注葡萄城控件技术团队博客,更多更好的原创文章尽在这里~~ Visual Studio是世界上最好的IDE之一,如果是 .NET世界,那就没有之一了(^_^),而最近推出的Visual S ...

  6. 使用PostProcessBuild设定Unity产生的Xcode Project

    简单来说就是unity提供一套api去修改xcode项目工程配置以及修改plist文件内容(当unity build结束后, 会自动回调OnPostProcessBuild). 以下是一些用到的配置处 ...

  7. Factoextra R Package: Easy Multivariate Data Analyses and Elegant Visualization

    factoextra is an R package making easy to extract and visualize the output of exploratory multivaria ...

  8. “织梦”CMS注入高危漏洞情况

    "织梦"CMS注入高危漏洞情况 作者:    时间:2014-04-17   "织梦"CMS是由上海卓卓网络科技有限公司研发的一款网站建站系统软件,又称&quo ...

  9. 原生js实现图片网格式渐显、渐隐效果

    写正文前先吐槽一下:端午放假完第一天去某千人以上公司面试前端工程师,第一轮是我应聘职位的部门小领导,谈的不错,面试主要围绕要用到的技术来:第二轮来了我要说的正主,我了个去,问的问题一个和前端无关,问我 ...

  10. JavaSE教程-03Java中分支语句与四种进制转换

    一.分支语句 计算机源于生活,程序模拟现实生活,从而服务生活 行为模式 1,起床,刷牙,洗脸,吃早餐,上课,回家,睡觉(顺序性) 2,如果时间不太够,打个滴滴快车,如果时间够,坐个地铁(选择性) 3, ...