Spring和Websocket相结合实现消息的推送_java

本文主要有三个步骤

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

Websocet服务端实现

WebSocketConfig.java

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor());
registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())
.withSockJS();
}
@Bean
public WebSocketHandler systemWebSocketHandler(){
return new SystemWebSocketHandler();
}
}

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

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

@Configuration
@EnableWebMvc
@EnableWebSocket

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

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

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

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

这个是使用Sockjs的注册方法

首先SystemWebSocketHandler.java

public class SystemWebSocketHandler implements WebSocketHandler {
private static final Logger logger;
private static final ArrayList<WebSocketSession> users;
static {
users = new ArrayList<>();
logger = LoggerFactory.getLogger(SystemWebSocketHandler.class);
}
@Autowired
private WebSocketService webSocketService;
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.debug("connect to the websocket success......");
users.add(session);
String userName = (String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME);
if(userName!= null){
//查询未读消息
int count = webSocketService.getUnReadNews((String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME));
session.sendMessage(new TextMessage(count + ""));
}
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
//sendMessageToUsers();
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if(session.isOpen()){
session.close();
}
logger.debug("websocket connection closed......");
users.remove(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
logger.debug("websocket connection closed......");
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
for (WebSocketSession user : users) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
*/
public void sendMessageToUser(String userName, TextMessage message) {
for (WebSocketSession user : users) {
if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) {
try {
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
}

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

然后WebSocketHandshakeInterceptor.java

public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object
> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession(false);
if (session != null) {
//使用userName区分WebSocketHandler,以便定向发送消息
String userName = (String) session.getAttribute(Constants.SESSION_USERNAME);
attributes.put(Constants.WEBSOCKET_USERNAME,userName);
}
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}

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

用户登录建立websocket连接

index.jsp

<script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script>
<script>
var websocket;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/Origami/webSocketServer");
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8080/Origami/webSocketServer");
} else {
websocket = new SockJS("http://localhost:8080/Origami/sockjs/webSocketServer");
}
websocket.onopen = function (evnt) {
};
websocket.onmessage = function (evnt) {
$("#msgcount").html("(<font color='red'>"+evnt.data+"</font>)")
};
websocket.onerror = function (evnt) {
};
websocket.onclose = function (evnt) {
}
</script>

使用sockjs时要注意

1、这两个的写法

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

2、web.xml中

<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_1.xsd">

version

web-app_3_1.xsd

这两个的版本都要是3.0+

然后在这个servlet中加入

<async-supported>true</async-supported>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>

然后所有的filter中也加入

<async-supported>true</async-supported>

3、添加相关依赖

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.3</version>
</dependency>

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

返回用户未读的消息

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

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

服务端推送消息给用户

@Controller
public class AdminController {
static Logger logger = LoggerFactory.getLogger(AdminController.class);
@Autowired(required = false)
private AdminService adminService;
@Bean
public SystemWebSocketHandler systemWebSocketHandler() {
return new SystemWebSocketHandler();
}
@RequestMapping("/auditing")
@ResponseBody
public String auditing(HttpServletRequest request){
//无关代码都省略了
int unReadNewsCount = adminService.getUnReadNews(username);
systemWebSocketHandler().sendMessageToUser(username, new TextMessage(unReadNewsCount + ""));
return result;
}
}

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索websocket消息推送
spring消息推送
spring websocket推送、websocket 消息推送、spring 消息推送、springmvc消息推送、用websocket推送消息,以便于您获取更多的相关知识。

时间: 2024-09-14 18:50:52

Spring和Websocket相结合实现消息的推送_java的相关文章

ajax-AJAX轮询机制,消息及时推送怎么实现?

问题描述 AJAX轮询机制,消息及时推送怎么实现? 我主要想问问,我们买家登录像京东天猫这样的网站上面有买家几条消息未读, 或是邮件上面的几封信息未读等这样显示是怎么实现的?是用得消息推送机制吗? 还是买家登录后去数据库查询了一次,然后现在出来的?懂的大神求解!?谢谢. 解决方案 websocket push机制.

IOS-群组消息离线推送显示问题

问题描述 群组消息离线推送,只显示了发消息的人,并没有显示来自哪个群组?请问如何解决? 解决方案 环信离线推送的alert好像是可以自定义显示的,发送的时候在扩展里加一个字段,具体的你可以看看他们的文档.通过扩展自定义显示,应该可以实现你的需求.

Spring整合websocket整合应用示例(下)_java

在Spring整合websocket整合应用示例(上)文章中,我们已经实现了websocket,但还有一个核心的业务实现类没有实现,这里我们就实现这个业务核心类,因为老夫参与的这个系统使用websocket发送消息,所以其实现就是如何发送消息了. 7. NewsListenerImpl的实现 package cn.bridgeli.websocket; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import

Java Socket聊天室编程(一)之利用socket实现聊天之消息推送_java

相关阅读:Java Socket聊天室编程(二)之利用socket实现单聊聊天室 网上已经有很多利用socket实现聊天的例子了,但是我看过很多,多多少有一些问题存在. 这里我将实现一个比较完整的聊天例子,并解释其中的逻辑. 由于socket这一块比较大,所以我将分出几篇来写一个比较完整的socket例子. 这里我们先来实现一个最简单的,服务器与客户端通讯,实现消息推送的功能. 目的:服务器与客户端建立连接,客户端可以向服务器发送消息,服务器可以向客户端推送消息. 1,使用java建立socke

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

项目背景介绍 最近在写的项目中存在着社交模块,需要实现这样的一个功能:当发生了用户被点赞.评论.关注等操作时,需要由服务器向用户实时地推送一条消息.最终完成的项目地址为:socket-message-push,这里将介绍一下实现的思路及部分代码. 项目的流程中存在着这样的几个对象: 用 Java 实现的后端服务器 用 Node.js 实现的消息推送服务器 用户进行操作的客户端 事件处理的流程如下: 用户进行点赞操作时,后端服务器会进行处理,并向 Node.js 消息推送服务器发送一条消息 Nod

iOS消息远程推送通知_IOS

本文实例为大家分享了iOS消息推送.iOS远程通知代码,供大家参考,具体内容如下 消息推送 /* 要开发测试消息机制的程序,必须用真机测试 推送消息的类型 UIRemoteNotificationTypeNone 不接收推送消息 UIRemoteNotificationTypeBadge 接收图标数字 UIRemoteNotificationTypeSound 接收音频 UIRemoteNotificationTypeAlert 接收消息文字 UIRemoteNotificationTypeNe

Spring与Mybatis相结合实现多数据源切换功能_java

废话不多说,关键代码如下所示: 1. 代码: DbContextHolder public class DbContextHolder { //线程安全的ThreadLocal private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDbType(String dbType) { contextHolder.set(dbType

移动客服 在华为手机上收不到离线消息 就是推送收不到

问题描述 在小米手机和坚果手机上都可以在华为的手机上就是收不到推送的消息 解决方案 是离线推送么 如果是离线推送的话 参见下http://docs.easemob.com/start/200androidcleintintegration/115payloadmsg 这个链接中的内容了.如果是离线消息后再上线的问题的话,建议是直接用环信的demo换上你的appkey,测试下环信的demo能不能收到了.

您好,环信,关于收到消息,收到推送,收到用户在其他设备登陆的问题

问题描述 这几项都是通过main里面的-(void)didReceiveMessage:(EMMessage *)message和- (void)didLoginFromOtherDevice两个方法得到的 但是我如果切换到后面的界面 模态的界面以后就获取不到这两个方法了啊.求怎么解决 解决方案 确切说是我这边presentViewController到后级界面以后就收不到消息了