build.gradle文件配置以下html
buildscript {
ext {
springBootVersion = '1.5.9.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.data:spring-data-redis')
compile group: 'com.alibaba', name: 'fastjson', version: '1.1.15'
runtime('mysql:mysql-connector-java')
compile("org.springframework.boot:spring-boot-starter-websocket")
compile("org.webjars:webjars-locator-core")
compile("org.webjars:sockjs-client:1.0.2")
compile("org.webjars:stomp-websocket:2.3.3")
testCompile('org.springframework.boot:spring-boot-starter-test')
}
复制代码
服务将接受包含STOMP消息中名称的消息,该消息的主体是JSON对象。若是给出的名称是“Test”,那么该消息可能以下所示:前端
{
"username ": "Test"
}
复制代码
为了建模带有名称的消息,可使用username 属性和相应的getUsername()方法建立一个普通的旧Java对象:java
public class ReceiveBean {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "UserBeans{" +
"username='" + username + '\'' + '}'; } } 复制代码
在收到消息并提取名称后,服务将经过建立问候语并在客户端订阅的单独队列上发布该问候语来处理它。问候语也将是一个JSON对象,可能看起来像这样:mysql
{
"content": "Hello, Test!"
}
复制代码
为了建模问候表示,能够添加另外一个具备content属性和相应getContent()方法的普通旧Java对象:web
public class ServerStatus {
private String content;
public ServerStatus() {}
public ServerStatus (String content) {
this.content = content;
}
public String getContent () {
return content;
}
}
复制代码
Spring将使用Jackson JSON库自动将类型实例编组
Greeting
为JSON。 接下来,建立一个控制器来接收serverStatus消息并发送问候消息。 #####建立消息处理控制器 在Spring使用STOMP消息传递的方法中,STOMP消息能够映射到到@Controller
类。例如,它ServerStatusController
被映射为处理消息到目的地“/serverStatus”redis
@Controller
@EnableScheduling
public class ServerStatusController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
//当浏览器向服务端发送请求时,经过@MessageMapping映射的地址,相似于@RequestMapping
@MessageMapping("/serverStatus")
@SendTo("/receive/message") //广播全部用户
//传递的参数会自动的被注入到userbean中
public ServerStatus serverStatus (ReceiveBean receiveBean) throws InterruptedException {
// 返回值被广播给全部订户,如@SendTo注释中所指定的"/receive/message" 。请注意,来自输入消息的名称已被清理,由于在这种状况下,它将被回显并从新呈如今客户端的浏览器DOM中。
return new ServerStatus((int) (Math.random() * 10 + 50));
}
@Scheduled(fixedRate = 5000) //每一个5秒提取一次
@SendTo("/receive/message") //广播全部用户
public Object sendAllMessage () {
// 发现消息
simpMessagingTemplate.convertAndSend("/receive/message", new ServerStatus((int) (Math.random() * 10 + 50)));
return "callback";
}
}
复制代码
配置Spring以启用WebSocket和STOMP消息传递。spring
/**
* 为STOMP消息传递配置Spring
* WebSocketConfig被注释@Configuration为代表它是一个Spring配置类。
* @EnableWebSocketMessageBroker: @EnableWebSocketMessageBroker启用WebSocket消息处理,由消息代理支持。
*/
@Configuration //@Configuration注解代表它是一个Spring配置类
@EnableWebSocketMessageBroker //经过@EnableWebSocketMessageBroker 注解启用WebSocket消息处理,由消息代理支持。
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer{
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
/*
* 该registerStompEndpoints()方法注册“/serverStatus”端点,
* 启用SockJS后备选项,以便在WebSocket不可用时可使用替代传输。
* SockJS客户端将尝试链接到“/serverStatus”并使用可用的最佳传输(websocket,xhr-streaming,xhr-polling等)。
* setAllowedOrigins: 容许跨域
*/
registry.addEndpoint("/serverStatus").setAllowedOrigins("*").withSockJS();
}
/**
* 配置消息代理
* @param registry
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/receive"); // 调用enableSimpleBroker()一个简单的基于内存的消息代理,将问候消息带回以“/ receive”为前缀的客户端
// registry.setApplicationDestinationPrefixes("/app"); //为绑定了@MessageMapping注解方法的消息指定“/ app”前缀,该前缀将用于定义全部消息映射
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
}
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
}
@Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
return false;
}
}
复制代码
SockJS是一个浏览器JavaScript库,提供了一个相似WebSocket的对象。SockJS为您提供了一个连贯的,跨浏览器的JavaScript API,它在浏览器和Web服务器之间建立了一个低延迟,全双工,跨域的通讯通道。 在底层SockJS首先尝试使用本地WebSocket。若是失败了,它可使用各类浏览器特定的传输协议,并经过WebSocket相似的抽象方式呈现它们。sql
npm install sockjs-client
复制代码
经过在WebSocket 之上使用 STOMP协议,来为浏览器 和 server 间的 通讯增长适当的消息语义。(STOMP—— Simple Text Oriented Message Protocol——面向消息的简单文本协议)npm
npm install @stomp/stompjs websocket --save
复制代码
const SockJS = require('sockjs-client')
const Stomp = require('@stomp/stompjs')
const socket = new SockJS('http://127.0.0.1:8080/serverStatus')
const stompClient = Stomp.over(socket) //建立STOMP客户端
stompClient.connect({}, (frame) => { //链接到服务器
let bean = {
username: 'Test'
}
stompClient.send('/serverStatus', {}, JSON.stringify(bean)) //发送信息
stompClient.subscribe('/receive/message', (receive) => { //订阅并接收消息
console.log('greeting', JSON.parse(receive.body))
})
})
复制代码
#####效果如图: json