`
hbxflihua
  • 浏览: 678381 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring4+WebSocket+Socket+STOMP+Jetty构建示例

阅读更多

 

Spring 4引入了WebSocket API,浏览器和Web服务器可以根据WebSocket API通过WebSocket协议进行通信。通过这种方式,我们可以创建一个高度交互的UI和在线游戏,需要从服务器快速响应。SockJS在UI上提供类似WebSocket的对象。STOMP客户端用于通过WebSocket协议进行通信。我正在使用tomcat服务器来部署项目。下图为WebSocket通信的图表。

 

 

WebSocket协议

WebSocket是一种在浏览器和Web服务器之间进行通信的协议。WebSocket通过TCP协议工作。它在浏览器和Web服务器之间打开套接字连接并开始通信,它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。WebSocket可以轻松嵌入子协议,如STOMP。

 

STOMP协议

stomp是一个用于client之间进行异步消息传输的简单文本协议, 全称是Simple Text Oriented Messaging Protocol。STOMP使用连接,发送,订阅,断开等不同的命令进行通信。严格意义上来说STOMP并不是WebSocket的子协议,它是属于消息队列的一种协议,和AMQP/JMS一个层级。

 

SockJS

SockJS是一个java脚本库,为浏览器提供类似websocket的对象。SockJS提供跨浏览器兼容性,并支持STOMP协议与任何消息代理进行通信。SockJS的工作方式是我们需要提供URL来连接消息代理,然后让stomp客户端进行通信。

 

工程示例概览图

 

所需的jar

<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.rongdu.framework</groupId>
	<artifactId>spring-websocket-stomp-demo</artifactId>
	<version>1.0</version>
	<packaging>war</packaging>
		
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.3.18.RELEASE</spring.version>
		<jettyVersion>9.4.9.v20180320</jettyVersion>
		<jackson.version>2.7.3</jackson.version>
	</properties>
	
	<dependencies>
		
		<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
		 <dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>${jackson.version}</version>
		</dependency>

		<!-- WebSocket Tomcat插件 -->
		<!-- 
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-websocket</artifactId>
			<version>7.0.53</version>
		</dependency>
		 -->
		
		<!-- WebSocket Jetty插件 -->
		<dependency>
            <groupId>org.eclipse.jetty.websocket</groupId>
            <artifactId>websocket-api</artifactId>
            <version>${jettyVersion}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty.websocket</groupId>
            <artifactId>websocket-server</artifactId>
            <version>${jettyVersion}</version>
        </dependency>
        
		
		<dependency>
			<groupId>javax.websocket</groupId>
			<artifactId>javax.websocket-api</artifactId>
			<version>1.1</version>
		</dependency>
		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>${spring.version}</version>
        </dependency>
		<dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.0</version>
        </dependency>
        				
		
        <!-- 页面 webjar -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
            <version>0.35</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.0</version>
        </dependency>

		<!-- RabbitMQ -->
		<dependency>
			<groupId>com.rabbitmq</groupId>
			<artifactId>amqp-client</artifactId>
			<version>3.5.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.amqp</groupId>
			<artifactId>spring-rabbit</artifactId>
			<version>1.4.5.RELEASE</version>
		</dependency>
		
		<!--slf4j--> 
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-slf4j-impl</artifactId>
			<version>2.7</version>
		</dependency>
		
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<encoding>utf-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

 

 

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee"
		 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
		 version="3.0">
	
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:/config/spring/*-beans.xml</param-value>
	</context-param>

	<!-- 编码过滤器 -->
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>			
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>ASYNC</dispatcher>
	</filter-mapping>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>	
	
	<servlet>
		<servlet-name>springServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:/config/web/web-main.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
		<async-supported>true</async-supported>
	</servlet>
	<servlet-mapping>
		<servlet-name>springServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
	
</web-app>

 

 

spring的mvc-servlet.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:task="http://www.springframework.org/schema/task"  
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:websocket="http://www.springframework.org/schema/websocket"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-4.3.xsd
	http://www.springframework.org/schema/task  
    http://www.springframework.org/schema/task/spring-task-4.3.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
    http://www.springframework.org/schema/websocket
    http://www.springframework.org/schema/websocket/spring-websocket.xsd">

	<!-- 自动扫包 -->
	<context:component-scan base-package="com.huatech.controller"/>
    <!-- 提供请求分发、数据绑定、数据转换等操作 -->
	<mvc:annotation-driven/>
 	
 	<!-- 
 	application-destination-prefix 逗号分隔的前缀列表,用于匹配已处理消息的目标
	user-destination-prefix 用于标识用户目标的前缀。 不解析任何不以给定前缀开头的目的地。 默认值为:/user/
 	 -->
 	<websocket:message-broker application-destination-prefix="/app" user-destination-prefix="/queue">
        <websocket:stomp-endpoint path="/websocket-address" >
            <websocket:sockjs/>
        </websocket:stomp-endpoint>
        <websocket:simple-broker prefix="/topic,/queue"/>
    </websocket:message-broker>
    
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		 <property name="prefix" value="/js/"/>		 
		 <property name="suffix" value=".jsp"/>
         <property name="contentType" value="text/html; charset=UTF-8"/>
	</bean>
 	 	
 	<!-- webjars 静态资源 -->
 	<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" >
 		<mvc:resource-chain resource-cache="false" auto-registration="false">
 			<mvc:resolvers>
 				<bean class="org.springframework.web.servlet.resource.WebJarsResourceResolver"/>
 				<bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>
 			</mvc:resolvers>
 		</mvc:resource-chain>
 	</mvc:resources>
 	 	 	
 	<!-- 本地资源 -->
 	<mvc:resources mapping="/js/**" location="/js/"/>
 		
 	<!-- 默认首页 -->
	<mvc:view-controller path="/" view-name="index"/>
 	
 	<!-- scheduler配置 -->
 	<task:executor id="executor" pool-size="5" />      
    <task:scheduler id="scheduler" pool-size="5" />    
    <task:annotation-driven executor="executor" scheduler="scheduler" />
 	
 	
</beans>

 

添加控制器类

package com.huatech.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;

@Controller
public class TopicController {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(TopicController.class);
	
	@Autowired
	private SimpMessagingTemplate template;
	
    /*收到消息后广播推送*/
    @MessageMapping("/boardcast")
    @SendTo("/topic/boardcast")
    public String sendtousers(String s){
    	LOGGER.info(s);
        return "我是广播消息";
    }

    /*收到消息后精准投送到单个用户*/
    @MessageMapping("/precise")
    /*broadcast = false避免把消息推送到同一个帐号不同的session中*/
    @SendToUser(value = "/topic/precise",broadcast = false)
    public String sendtouser(String s){
    	LOGGER.info(s);
        return "我是精准投送消息";
    }


    /*下面2个是不用接收消息动态发送消息的方法*/
    /*Scheduled为定时任务,演示*/
    @Scheduled(fixedDelay = 1500)
    public void boardcast(){
        this.template.convertAndSend("/topic", "来自服务器广播消息");
    }

    @Scheduled(fixedDelay = 1500)
    public void precise(){
        this.template.convertAndSendToUser("abc", "/message","来自服务器精准投送消息");
    }

}

 

index.jsp示例页面

<%@ page language="java" pageEncoding="UTF-8"%>
<html>
  <head>
  	<meta charset="utf-8"/>
    <title>spring-websocket-stomp</title>
  </head>
  <body>
  <h1>spring-websocket-stomp</h1>
  <button id="btn-send">广播消息</button>
  <button id="btn-send2">精准投送消息</button>
  <button id="btn-send3">动态广播</button>
  <button id="btn-send4">动态精准投送</button>
  </body>
</html>
<script src="webjars/jquery/jquery.min.js"></script>
<script src="webjars/sockjs-client/sockjs.min.js"></script>
<script src="webjars/stomp-websocket/stomp.min.js"></script>
<script src="js/app.js"></script>

 

app.js

var stompClient = null;
var subscription = null;
$(function () {
   var ws = new SockJS("/websocket-address");
    stompClient = Stomp.over(ws);
    stompClient.connect({'client-id': 'my-client'},function () {
    });

    $("#btn-send").click(function () {
        if(subscription != null){subscription.unsubscribe();}
        subscription = stompClient.subscribe("/topic/boardcast", function(){});
        stompClient.send("/app/boardcast",{},"请求广播");
    });
    $("#btn-send2").click(function () {
        if(subscription != null){subscription.unsubscribe();}
        subscription = stompClient.subscribe("/queue/topic/precise", function(){});
        stompClient.send("/app/precise",{},"请求精准投送");
    });
    // 请求动态广播
    $("#btn-send3").click(function () {
        if(subscription != null){subscription.unsubscribe();}
        subscription = stompClient.subscribe("/topic", function(){});
    });
    // 请求精准投送
    $("#btn-send4").click(function () {
        if(subscription != null){subscription.unsubscribe();}
        subscription = stompClient.subscribe("/queue/abc/message", function(){});
    });
});

 

遇到的问题

1、spring引入webjars页面报404问题

参考:https://blog.csdn.net/chao_1990/article/details/53449494

 

2、Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.ObjectMapper.canSerialize(Ljava/lang/Class;Ljava/util/concurrent/atomic/AtomicReference;)Z

答:jackson版本冲突

 

3、@MessageMapping注解配置后不起作用

答:websocket相关的配置需通过mvc进行初始化,而不是交给IOC

参考:

https://stackoverflow.com/questions/42441837/messagemapping-does-not-work-with-spring-security-and-mvc

  • 大小: 8.8 KB
  • 大小: 14.2 KB
分享到:
评论

相关推荐

    java开发基于SpringBoot+WebSocket+Redis分布式即时通讯群聊系统.zip

    Java开发基于SpringBoot+WebSocket+Redis分布式即时通讯群聊系统。一个基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统。适用于直播间聊天、游戏内聊天、客服聊天等临时性群聊场景。 ...

    SpringBoot+SpringSecurity+WebSocket

    本项目结合这三个技术,构建了一个整合的示例,旨在展示如何在SpringBoot应用中实现安全的、基于WebSocket的实时通信。 首先,SpringBoot是由Pivotal团队提供的一个简化Spring应用初始搭建以及开发过程的框架。它...

    基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统.zip

    基于Spring Boot + WebSocket + Redis,可快速开发的分布式即时通讯群聊系统.zip 1、该资源内项目代码经过严格调试,下载即用确保可以运行! 2、该资源适合计算机相关专业(如计科、人工智能、大数据、数学、电子信息...

    spring boot+websocket

    总结,结合Spring Boot和WebSocket,我们可以轻松地构建出实时交互的Web应用。在后端,我们配置WebSocket支持,实现消息处理;在前端,使用jQuery和SockJS库来管理WebSocket连接和消息交换。这样的组合为现代Web应用...

    Spring+Netty+WebSocket实例

    在现代Web开发中,实时通信已经成为一个不可或缺的功能,Spring、Netty和WebSocket的结合为构建高性能、低延迟的实时应用提供了强大的解决方案。本实例将详细探讨如何利用这三种技术进行集成,实现高效的双向通信。 ...

    SpringBoot + Thymeleaf + WebSocket + Spring Security + SpringData-Jpa

    4. **Spring Security**: Spring Security是Spring框架的一个子项目,提供了一整套安全访问控制解决方案。它包括认证、授权等功能,可以保护Web应用免受攻击,如XSS、CSRF等。在SpringBoot中,Spring Security可以...

    spring boot+vue+websocket带token身份认证推送消息实现

    本知识点将介绍如何在Spring Boot与Vue前后端分离架构中集成WebSocket,并实现带有身份认证的消息推送功能。这是实现即时通讯、实时数据更新等应用场景的常用技术方案。 ### 1. WebSocket简介 WebSocket是一种在...

    spring+springMVC+WebSocket 的学习笔记

    这本学习笔记应该详细介绍了如何在 Spring 应用中集成 Spring MVC 和 WebSocket,包括设置项目结构、配置 Spring 容器、编写 WebSocket 处理端点类、实现客户端连接及消息交互的示例代码,并可能涉及到如何在 Spring...

    springBoot+webSocket+uniapp实现实时聊天功能

    springBoot+webSocket+uniapp实现实时聊天功能

    SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理系统.zip

    SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理系统 SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理系统 SpringBoot +Vue3 +Jwt+Editor+WebSocket+Echarts小型超市进销管理...

    spring-boot+webSocket实现向日葵远程控制

    本项目为spring-boot+webSocket实现的向日葵远程控制项目 向日葵是一款很好用的远程操作软件。 一直很好奇这种软件的基本原理是如何的? 今天带大家通过一个简单的项目来探究一下,并实现一个简单的远程操控软件 ...

    基于Vue+SpringBoot+WebSocket实现Web端聊天系统+网络通信+心跳+客户端服务端+后端java+mysql

    基于Vue+SpringBoot+WebSocket实现Web端聊天系统+网络通信+心跳+客户端服务端+后端java+mysql 项目经过严格测试,确保可以运行! 下载代码后,先配置好yml文件:数据库和微信号appid、secret(other包下面有数据库)...

    如何使用Spring Boot 3.X + WebSocket来实现推送消息功能

    如何使用Postman来发送数据到后端Spring Boot应用程序,并使用WebSocket建立实时通信通道,以便后端应用程序可以向Postman推送消息。 学会这个方法,就能缩短你的项目开发周期,以及提高你的开发效率。如果提出您的...

    Spring Boot 整合 Netty + WebSocket 实时消息推送

    2. **WebSocket Stomp协议**:在Spring Boot中,通常会使用STOMP(Simple Text Oriented Messaging Protocol)作为WebSocket的应用层协议。STOMP简化了消息的格式,使得客户端和服务器之间可以交换消息。Spring ...

    SpringBoot+nacos+websocket+redis+mysql+mybatis-plus微服务项目实战

    - SpringBoot简化了Spring应用的初始搭建以及开发过程,通过自动配置和起步依赖特性,使得创建独立的、生产级别的基于Spring的应用变得容易。 - 应用程序通常可以通过`main`方法启动,并且可以嵌入Tomcat或Jetty等...

    spring+websocket+hibernate小例子

    在本项目"spring+websocket+hibernate小例子"中,开发者通过集成Spring框架、WebSocket技术和Hibernate ORM,创建了一个小型的交互式应用。这个应用能够实现实时通信,并且能够与数据库进行数据交互,展示了现代Web...

    spring+websocketdemo

    4. **Netty的WebSocket服务器**:虽然Spring提供了WebSocket支持,但在某些场景下,我们可能需要更底层的控制,比如高性能或高度定制的需求,这时可以使用Netty。Netty是一个异步事件驱动的网络应用框架,特别适合...

    Spring4+WebSocket小示例

    在本示例中,我们将深入探讨如何在Spring4框架中集成WebSocket技术,为Web应用程序提供实时通信功能。WebSocket协议是一种在客户端和服务器之间建立长期连接的协议,它允许双向通信,使得数据能够在任意时刻从服务器...

    基于Springboot+Websocket的简单聊天室

    基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+...

Global site tag (gtag.js) - Google Analytics