spring-websocket 配置 websocket发送消息(群发)
来源:互联网 发布:壁纸桌面软件下载 编辑:程序博客网 时间:2024/05/18 14:45
参考:http://blog.csdn.net/heng_ji/article/details/39007227
http://blog.csdn.net/u014520745/article/details/62046396
项目结构:
所需jar包,spring-web版本需支持cors,项目中使用4.3.2+,log4j2,springmvc,jackson,servlet3.0
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zhoushun</groupId> <artifactId>tset</artifactId> <version>1.0-SNAPSHOT</version> <name>Archetype - tset</name> <url>http://maven.apache.org</url> <packaging>war</packaging> <properties> <spring.version>4.3.2.RELEASE</spring.version> <aspectj.version>1.8.9</aspectj.version> <slf4j.version>1.7.10</slf4j.version> <log4j2.version>2.3</log4j2.version> <disruptor.version>3.3.4</disruptor.version> </properties> <dependencies> <!-- spring websocket--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <!-- <version>3.1.1.RELEASE</version> --> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> <exclusions> <exclusion> <groupId>junit</groupId> <artifactId>junit</artifactId> </exclusion> </exclusions> </dependency> <!-- selenium--> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.44.0</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency> <!--<dependency>--> <!--<groupId>org.slf4j</groupId>--> <!--<artifactId>slf4j-log4j12</artifactId>--> <!--<version>1.7.12</version>--> <!--</dependency>--> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.0.23.Final</version> <exclusions> <exclusion> <groupId>io.netty</groupId> <artifactId>netty-tcnative</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-example</artifactId> <version>4.0.23.Final</version> <exclusions> <exclusion> <groupId>io.netty</groupId> <artifactId>netty-tcnative</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.9.3</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>2.6.1</version> </dependency> <!-- zookeeper--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <!-- Objenesis --> <dependency> <groupId>org.objenesis</groupId> <artifactId>objenesis</artifactId> <version>2.1</version> </dependency> <!-- CGLib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>com.dianping.dpsf</groupId> <artifactId>dpsf-net</artifactId> <version>2.7.9</version> </dependency> <dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit</artifactId> <version>2.18</version> </dependency> <dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit-core-js</artifactId> <version>2.9</version> <scope>compile</scope> </dependency> <dependency> <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> <version>1.4.01</version> </dependency> <!-- http client --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.5</version> </dependency> <!-- spring-ws--> <dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-ws-core</artifactId> <version>2.4.0.RELEASE</version> </dependency> <!-- mail --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-email</artifactId> <version>1.4</version> </dependency> <!-- redis son --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>1.2.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.5</version> </dependency> <!-- es --> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>2.3.5</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.35</version> </dependency> <!-- log4j2--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-1.2-api</artifactId> <version>${log4j2.version}</version> </dependency> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>${disruptor.version}</version> </dependency> <!-- log4j2--> </dependencies></project>
web.xml:(html等静态文件 根据servlet映射规则 优先访问,防止被springmvc 拦截)
<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><display-name>test-app</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath*:applicationContext.xml </param-value> </context-param> <!--由Sprng载入的Log4j配置文件位置 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j2.xml</param-value> </context-param> <!--Spring默认刷新Log4j配置文件的间隔,单位为毫秒 --> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>60000</param-value> </context-param> <context-param> <param-name>webAppRootKey</param-name> <param-value>testapp.root</param-value> </context-param> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>springWeb</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>springWeb</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- Welcome file lists --> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list></web-app>
配置文件:
spring :applicationContext.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:websocket="http://www.springframework.org/schema/websocket" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="websocket.socket"/> <mvc:annotation-driven/> <!--<bean id="websocket" class="websocket.socket.WebsocketEndPoint"/>--> <!--<websocket:handlers>--> <!--<websocket:mapping path="/websocket" handler="websocket"/>--> <!--<websocket:handshake-interceptors>--> <!--<bean class="websocket.socket.HandshakeInterceptor"/>--> <!--</websocket:handshake-interceptors>--> <!--</websocket:handlers>--></beans>
springmvc:spring-mvc.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:websocket="http://www.springframework.org/schema/websocket" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="websocket.controller"/> <mvc:annotation-driven/> <!--<bean id="websocket" class="websocket.socket.WebsocketEndPoint"/>--> <!--<websocket:handlers>--> <!--<websocket:mapping path="/websocket" handler="websocket"/>--> <!--<websocket:handshake-interceptors>--> <!--<bean class="websocket.socket.HandshakeInterceptor"/>--> <!--</websocket:handshake-interceptors>--> <!--</websocket:handlers>--> <!-- 对静态资源文件的访问 --> <mvc:resources mapping="/images/**" location="/images/" /></beans>
前端页面 user.html,具体效果可在chrome-console中查看
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title></head><body></body><script src="jquery.js"></script><script type="text/javascript"> var ws $(function() { console.log("abc"); $.ajax({url:"http://localhost:8080/login/4",success:function(result){ console.log(result); ws = new WebSocket("ws://localhost:8080/myHandler") ws.onopen = function () { console.log("onpen"); ws.send("{}"); } ws.onclose = function () { console.log("onclose"); } ws.onmessage = function (msg) { console.log(msg); console.log(msg.data); } }}); })</script></html>
controller:(负责用户信息数据的mock存储、消息推送、消息广播测试)
package websocket.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.socket.TextMessage;import websocket.socket.MyHandler;import javax.servlet.http.HttpSession;/** * Created by Administrator on 2017/10/16. */@Controllerpublic class SocketController { @Autowired @Qualifier("x") MyHandler handler; @RequestMapping("/login/{userId}") public @ResponseBody String login(HttpSession session, @PathVariable("userId") Integer userId) { System.out.println("登录接口,userId="+userId); session.setAttribute("userId", userId); System.out.println(session.getAttribute("userId")); return "success"; } @RequestMapping("/message") public @ResponseBody String sendMessage() { boolean hasSend = handler.sendMessageToUser(4, new TextMessage("发送一条小message")); System.out.println(hasSend); return "message"; } @RequestMapping("/broad") public @ResponseBody String broad() { boolean hasSend = handler.sendMessageToAllUsers(new TextMessage("发送一条小Broad")); System.out.println(hasSend); return "broad"; }}
websocket注册:WebSocketConfig
package websocket.socket;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;/** * Created by Administrator on 2017/10/16. */@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer { @Autowired @Qualifier("x") private MyHandler myHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler, "/myHandler").addInterceptors(new WebSocketInterceptor()); } @Bean public WebSocketHandler myHandler() { return new MyHandler(); }}
websocket拦截器:WebSocketInterceptor(监听 连接 建立及握手)
package websocket.socket;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.http.server.ServletServerHttpRequest;import org.springframework.web.socket.WebSocketHandler;import javax.servlet.http.HttpSession;import java.util.Map;/** * Created by Administrator on 2017/10/16. */public class WebSocketInterceptor implements org.springframework.web.socket.server.HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request; HttpSession session = serverHttpRequest.getServletRequest().getSession();// Map parameterMap = serverHttpRequest.getServletRequest().getParameterMap();// System.out.println(parameterMap); if (session != null) { map.put("userId", session.getAttribute("userId")); } } return true; } @Override public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { }}
处理类:MyHandler
package websocket.socket;import org.springframework.stereotype.Service;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.TextWebSocketHandler;import java.io.IOException;import java.util.HashMap;import java.util.Map;import java.util.Set;/** * Created by Administrator on 2017/10/16. */@Service("x")public class MyHandler extends TextWebSocketHandler { //在线用户列表 private static final Map<Integer, WebSocketSession> users; //用户标识 private static final String CLIENT_ID = "userId"; static { users = new HashMap<>(); } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { System.out.println("成功建立连接"); Integer userId = getClientId(session); System.out.println(userId); if (userId != null) { users.put(userId, session); session.sendMessage(new TextMessage("成功建立socket连接")); System.out.println(userId); System.out.println(session); } } @Override public void handleTextMessage(WebSocketSession session, TextMessage message) { // ... System.out.println(message.getPayload()); WebSocketMessage message1 = new TextMessage("server:"+message); try { session.sendMessage(message1); } catch (IOException e) { e.printStackTrace(); } } /** * 发送信息给指定用户 * @param clientId * @param message * @return */ public boolean sendMessageToUser(Integer clientId, TextMessage message) { if (users.get(clientId) == null) return false; WebSocketSession session = users.get(clientId); System.out.println("sendMessage:" + session); if (!session.isOpen()) return false; try { session.sendMessage(message); } catch (IOException e) { e.printStackTrace(); return false; } return true; } /** * 广播信息 * @param message * @return */ public boolean sendMessageToAllUsers(TextMessage message) { boolean allSendSuccess = true; Set<Integer> clientIds = users.keySet(); WebSocketSession session = null; for (Integer clientId : clientIds) { try { session = users.get(clientId); if (session.isOpen()) { session.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); allSendSuccess = false; } } return allSendSuccess; } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { if (session.isOpen()) { session.close(); } System.out.println("连接出错"); users.remove(getClientId(session)); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { System.out.println("连接已关闭:" + status); users.remove(getClientId(session)); } @Override public boolean supportsPartialMessages() { return false; } /** * 获取用户标识 * @param session * @return */ private Integer getClientId(WebSocketSession session) { try { Integer clientId = (Integer) session.getAttributes().get(CLIENT_ID); return clientId; } catch (Exception e) { return null; } }}
消息测试页:http://localhost:8080/user.html
根据单个用户ID推送消息(可修改controller层 message方法中的clientId):http://localhost:8080/message
广播消息推送给所有用户:http://localhost:8080/broad
阅读全文
0 0
- spring-websocket 配置 websocket发送消息(群发)
- spring配置websocket并实现群发/单独发送消息
- spring配置websocket并实现群发/单独发送消息
- spring配置websocket并实现群发/单独发送消息
- spring websocket 模拟发送消息
- spring websocket 利用注解接收和发送消息
- Spring - Websocket详细配置
- Spring中配置WebSocket
- Spring中配置WebSocket
- Spring boot websocket消息推送
- Spring WebSocket实现消息推送
- websocket(消息驱动)
- SpringBoot 实现WebSocket进行消息发送(适用于SpringMVC)
- SpringBoot中的WebSocket点对点发送消息
- Spring Boot 使用 WebSocket 实现消息推送 及 WebSocket原理
- Spring-WebSocket配置以及使用
- SpringBoot-WebSocket广播消息+单点消息(指定用户发送消息)
- Spring WebSocket
- 使用 python 的sklearn模块,训练模型时,出现 ValueError: min_samples_split must be at least 2 or in (0, 1], got 1 的
- Dlib格式与Opencv之间的转化
- 仿照火狐浏览器watch函数实现功能
- ES6 对象实现 Iterator 接口
- python django 重新建模
- spring-websocket 配置 websocket发送消息(群发)
- 程序员业余时间修炼指南
- 使用 Annotation将配置资源注入到Bean中
- Android开发知识(八):Android事件处理机制:事件分发、传递、拦截、处理机制的原理分析(中)
- cout和printf输出结果不一样
- java开发常用词汇02
- 用main调试spring
- 设计模式_16:迭代器模式
- usaco Mother's Milk