本文主要有三个步骤 1、用户登录后建立websocket连接,默认选择websocket连接,如果浏览器不支持,则使用sockjs进行模拟连接 2、建立连接后,服务端返回该用户的未读消息 3、服务端进行相关操作后,推送给某一个用户或者所有用户新消息 相关环境 Spring4.0.6(要选择4.0+),tomcat7.0.5

Websocet服务端实现

WebSocketConfig.java

  1. @Configuration
  2. @EnableWebMvc
  3. @EnableWebSocket
  4. public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
  5. @Override
  6. public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
  7. registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor());
  8. registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
  9. .withSockJS();
  10. }
  11. @Bean
  12. public WebSocketHandler systemWebSocketHandler(){
  13. return new SystemWebSocketHandler();
  14. }
  15. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

不要忘记在springmvc的配置文件中配置对此类的自动扫描

  1. <context:component-scan base-package="com.ldl.origami.websocket" />
  • 1

@Configuration

@EnableWebMvc 
@EnableWebSocket 
这三个大致意思是使这个类支持以@Bean的方式加载bean,并且支持springmvc和websocket,不是很准确大致这样,试了一下@EnableWebMvc不加也没什么影响,@Configuration本来就支持springmvc的自动扫描

  1. registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
  • 1

用来注册websocket server实现类,第二个参数是访问websocket的地址

  1. registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
  2. .withSockJS();
  3. }
  • 1
  • 2
  • 3

这个是使用Sockjs的注册方法 
首先SystemWebSocketHandler.java

  1. public class SystemWebSocketHandler implements WebSocketHandler {
  2. private static final Logger logger;
  3. private static final ArrayList<WebSocketSession> users;
  4. static {
  5. users = new ArrayList<>();
  6. logger = LoggerFactory.getLogger(SystemWebSocketHandler.class);
  7. }
  8. @Autowired
  9. private WebSocketService webSocketService;
  10. @Override
  11. public void afterConnectionEstablished(WebSocketSession session) throws Exception {
  12. logger.debug("connect to the websocket success......");
  13. users.add(session);
  14. String userName = (String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME);
  15. if(userName!= null){
  16. //查询未读消息
  17. int count = webSocketService.getUnReadNews((String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME));
  18. session.sendMessage(new TextMessage(count + ""));
  19. }
  20. }
  21. @Override
  22. public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
  23. //sendMessageToUsers();
  24. }
  25. @Override
  26. public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
  27. if(session.isOpen()){
  28. session.close();
  29. }
  30. logger.debug("websocket connection closed......");
  31. users.remove(session);
  32. }
  33. @Override
  34. public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
  35. logger.debug("websocket connection closed......");
  36. users.remove(session);
  37. }
  38. @Override
  39. public boolean supportsPartialMessages() {
  40. return false;
  41. }
  42. /**
  43. * 给所有在线用户发送消息
  44. *
  45. * @param message
  46. */
  47. public void sendMessageToUsers(TextMessage message) {
  48. for (WebSocketSession user : users) {
  49. try {
  50. if (user.isOpen()) {
  51. user.sendMessage(message);
  52. }
  53. } catch (IOException e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. }
  58. /**
  59. * 给某个用户发送消息
  60. *
  61. * @param userName
  62. * @param message
  63. */
  64. public void sendMessageToUser(String userName, TextMessage message) {
  65. for (WebSocketSession user : users) {
  66. if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) {
  67. try {
  68. if (user.isOpen()) {
  69. user.sendMessage(message);
  70. }
  71. } catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74. break;
  75. }
  76. }
  77. }
  78. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

相关内容大家一看就能明白,就不多解释了

然后WebSocketHandshakeInterceptor.java

  1. public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
  2. private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);
  3. @Override
  4. public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object
  5. > attributes) throws Exception {
  6. if (request instanceof ServletServerHttpRequest) {
  7. ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
  8. HttpSession session = servletRequest.getServletRequest().getSession(false);
  9. if (session != null) {
  10. //使用userName区分WebSocketHandler,以便定向发送消息
  11. String userName = (String) session.getAttribute(Constants.SESSION_USERNAME);
  12. attributes.put(Constants.WEBSOCKET_USERNAME,userName);
  13. }
  14. }
  15. return true;
  16. }
  17. @Override
  18. public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
  19. }
  20. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

个的主要作用是取得当前请求中的用户名,并且保存到当前的WebSocketHandler中,以便确定WebSocketHandler所对应的用户,具体可参考HttpSessionHandshakeInterceptor

用户登录建立websocket连接

index.jsp

  1. <script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script>
  2. <script>
  3. var websocket;
  4. if ('WebSocket' in window) {
  5. websocket = new WebSocket("ws://localhost:8080/Origami/webSocketServer");
  6. } else if ('MozWebSocket' in window) {
  7. websocket = new MozWebSocket("ws://localhost:8080/Origami/webSocketServer");
  8. } else {
  9. websocket = new SockJS("http://localhost:8080/Origami/sockjs/webSocketServer");
  10. }
  11. websocket.onopen = function (evnt) {
  12. };
  13. websocket.onmessage = function (evnt) {
  14. $("#msgcount").html("(<font color='red'>"+evnt.data+"</font>)")
  15. };
  16. websocket.onerror = function (evnt) {
  17. };
  18. websocket.onclose = function (evnt) {
  19. }
  20. </script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

使用sockjs时要注意

1、这两个的写法

  1. <script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script>
  • 1
  1. websocket = new SockJS("http://localhost:8080/Origami/sockjs/webSocketServer");
  • 1

2、web.xml中

  1. <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">
  • 1
  • 2
  • 3
  1. version
  • 1
  1. web-app_3_1.xsd
  • 1

这两个的版本都要是3.0+

然后在这个servlet中加入

  1. <async-supported>true</async-supported>
  • 1
  1. <servlet>
  2. <servlet-name>appServlet</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <init-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>classpath*:servlet-context.xml</param-value>
  7. </init-param>
  8. <load-on-startup>1</load-on-startup>
  9. <async-supported>true</async-supported>
  10. </servlet>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后所有的filter中也加入

  1. <async-supported>true</async-supported>
  • 1

3、添加相关依赖

  1. <dependency>
  2. <groupId>com.fasterxml.jackson.core</groupId>
  3. <artifactId>jackson-annotations</artifactId>
  4. <version>2.3.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.fasterxml.jackson.core</groupId>
  8. <artifactId>jackson-core</artifactId>
  9. <version>2.3.1</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.fasterxml.jackson.core</groupId>
  13. <artifactId>jackson-databind</artifactId>
  14. <version>2.3.3</version>
  15. </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

好了,现在websocket可以正常建立起来了

返回用户未读的消息

当连接建立后,会进入SystemWebSocketHandler的afterConnectionEstablished方法,代码看上边,取出WebSocketHandshakeInterceptor中保存的用户名

查询信息后使用session.sendMessage(new TextMessage(count + “”));返回给用户,从哪来回哪去

服务端推送消息给用户

  1. @Controller
  2. public class AdminController {
  3. static Logger logger = LoggerFactory.getLogger(AdminController.class);
  4. @Autowired(required = false)
  5. private AdminService adminService;
  6. @Bean
  7. public SystemWebSocketHandler systemWebSocketHandler() {
  8. return new SystemWebSocketHandler();
  9. }
  10. @RequestMapping("/auditing")
  11. @ResponseBody
  12. public String auditing(HttpServletRequest request){
  13. //无关代码都省略了
  14. int unReadNewsCount = adminService.getUnReadNews(username);
  15. systemWebSocketHandler().sendMessageToUser(username, new TextMessage(unReadNewsCount + ""));
  16. return result;
  17. }
  18. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在这里可以使用sendMessageToUser给某个用户推送信息,也可以使用sendMessageToUsers给所有用户推送信息

原文地址:https://my.oschina.net/ldl123292/blog/304360

【转】Spring+Websocket实现消息的推送的更多相关文章

  1. Spring+Websocket实现消息的推送

    http://my.oschina.net/ldl123292/blog/304360

  2. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

  3. 基于 WebSocket 的 MQTT 移动推送方案

    WebSphere MQ Telemetry Transport 简介 WebSphere MQ Telemetry Transport (MQTT) 是一项异步消息传输协议,是 IBM 在分析了他们 ...

  4. 基于HTTP协议之WEB消息实时推送技术原理及实现

    很早就想写一些关于网页消息实时推送技术方面的文章,但是由于最近实在忙,没有时间去写文章.本文主要讲解基于 HTTP1.1 协议的 WEB 推送的技术原理及实现.本人曾经在工作的时候也有做过一些用到网页 ...

  5. 利用socket.io实现消息实时推送

    最近在写的项目中存在着社交模块,需要实现这样的一个功能:当发生了用户被点赞.评论.关注等操作时,需要由服务器向用户实时地推送一条消息.最终完成的项目地址为:socket-message-push,这里 ...

  6. RabbitMQ 延迟队列,消息延迟推送

    目录 应用场景 消息延迟推送的实现 测试结果 应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给 ...

  7. #研发中间件介绍#异步消息可靠推送Notify

    郑昀 基于朱传志的设计文档 最后更新于2014/11/11 关键词:异步消息.订阅者集群.可伸缩.Push模式.Pull模式 本文档适用人员:研发   电商系统为什么需要 NotifyServer? ...

  8. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制

    2013年10月06日最新整理. PHP版微信公共平台消息主动推送,突破订阅号一天只能发送一条信息限制 微信公共平台消息主动推送接口一直是腾讯的私用接口,相信很多朋友都非常想要用到这个功能. 通过学习 ...

  9. Swift - 本地消息的推送通知(附样例)

    使用UILocalNotification可以很方便的实现消息的推送功能.我们可以设置这个消息的推送时间,推送内容等. 当推送时间一到,不管用户在桌面还是其他应用中,屏幕上方会都显示出推送消息. 1, ...

随机推荐

  1. java基础学习笔记五(抽象类)

    java基础学习总结——抽象类 抽象类介绍

  2. sql 实现分页+分组并取出分组内的前n条数据

    一.建表 if exists (select * from sysobjects where id = OBJECT_ID('[test]') and OBJECTPROPERTY(id, 'IsUs ...

  3. hdu 4609 3-idiots(FFT+去重处理)

    3-idiots Problem Description King OMeGa catched three men who had been streaking in the street. Look ...

  4. MailUtils

    /** *包名:com.thinkgem.jeesite.test *描述:package com.thinkgem.jeesite.test; */ package com.thinkgem.jee ...

  5. paper 135:关于C#泛型的一些讲解

    计划着要用一个月的时间把  C#语言Windows程序设计 搞定,现在是零零散散的知识点,日积月累吧!朋友们,看这里咯~呵呵 原文地址:http://www.blogjava.net/Jack2007 ...

  6. Docker Machine 管理-管理machine(17)

    用 docker-machine 创建 machine 的过程很简洁,非常适合多主机环境.除此之外,Docker Machine 也提供了一些子命令方便对 machine 进行管理.其中最常用的就是无 ...

  7. gokit 统计分析 M2M接入服务 OTA固件升级 硬件社交化

    统计分析 M2M接入服务  OTA固件升级 硬件社交化 统计分析 为智能硬件定制的统计分析服务.只需添加入一行代码的集成工作,多维度的设备使用和用户行为数据就能自动统计出来. 演示 特色一:设备上线情 ...

  8. java.lang.IllegalAccessException: Class XXXcan not access xxx with modifiers "private"

    field 或者 method 是 provate的 field.setAccessible(true); method.setAccessible(true); 有时候是因为 newinstance ...

  9. XSS注入方式和逃避XSS过滤的常用方法(整理)

    (转自黑吧安全网http://www.myhack58.com/) web前端开发常见的安全问题就是会遭遇XSS注入,而常见的XSS注入有以下2种方式: 一.html标签注入 这是最常见的一种,主要入 ...

  10. 实用maven笔记一概念&构建

    maven,作为我现在每天都会使用的工具,却发现我还有很多地方了解的迷迷糊糊.老大就曾说过我的一个问题在于,做事情不够精细.大概就是太浮于表面吧.最近突然非常想把maven撸一遍.豆瓣搜了下高分书籍, ...