频道栏目
首页 > 资讯 > 其他 > 正文

springMvc+spring 整合 websocket方法

18-05-07        来源:[db:作者]  
收藏   我要投稿

根据项目需求,要实现消息提醒功能,首先想到的则是websocket。浏览学习网上现在博客论坛。各种写法的都有,结合自己的项目框架,以及遇到的问题,在这写一写,供大家参考。至于websocket 是啥,原理啥的,该不多说,网上一搜一大把。直接进入主题。

一、首先介绍一下我们的框架

jdk1.8 + springMVC 4.3.8 + mybatisPlus 2.1.9 + tomcat7 + easyui

二、下面开始进入正题。

1、首先在maven的pom.xml中引入websocket依赖的jar包。(注意:spring-websocket的版本好最好跟框架的spring版本一致)

javax.websocket

javax.websocket-api

1.1

provided

org.springframework

spring-websocket

${spring.version}

2、更新web.xml中namespace.xsd的版本。(即把相应代码复制进去即可,如果有springmvc的配置文件,最好也更新一下)

xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:websocket="http://www.springframework.org/schema/websocket"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd"

id="WebApp_ID" version="3.0">

3、新建HandshakeInterceptor.java ,这个类是握手类,作用就是在连接成功前和成功后增加一些额外的功能,一般是把当前握手的用户的唯一标识记录一下,Global.java类是一个工具类,两个常量(注意:一共需要三个类,最好统一放在一个文件夹下面)

 

 

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

@Override

public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,

Map attributes) throws Exception {

System.out.println("Before Handshake--websocket 握手之前的方法");

// 解决The extension [x-webkit-deflate-frame] is not supported问题

if (request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {

request.getHeaders().set("Sec-WebSocket-Extensions",

"permessage-deflate");

}

//使用userid区分WebSocketHandler,以便定向发送消息(使用shiro获取session)

String userid = Global.userId;

if (userid == null) {

userid = "default-system";

}

attributes.put(Global.WEBSOCKET_USERID, userid);

return super.beforeHandshake(request, response, wsHandler, attributes);

}

@Override

public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,

Exception ex) {

System.out.println("After Handshake--websocket 握手之后的方法");

super.afterHandshake(request, response, wsHandler, ex);

}

}

4、新建WebsocketBusiness.java , webcocket 处理类,这个类是对消息的一些处理,比如是发给一个人,还是发给所有人,并且前端连接时触发的一些动作。(该类里面存在关于我的系统的业务模块,偷懒没有删除,可自行删除哦)

 

 

public class WebsocketBusiness extends TextWebSocketHandler {

/**

* 通知公告逻辑层

*/

@Autowired

private ISysUserreadnoticeService iSysUserreadnoticeService;

/**

*

*/

@Autowired

private ISysUserreadmsgService sysUserreadmsgService;

private static final Map users; // 这个会出现性能问题,最好用Map来存储,key用userid

static {

users = new HashMap<>();

}

/**

* 获取当前在线用户

*

* @return

*/

public static Map getUsers() {

return users;

}

/**

* 获取当前在线人数数量

*

* @return

*/

public static int getUserCount() {

return users.size();

}

/**

* 连接成功时候,会触发UI上onopen方法

*/

@Override

public void afterConnectionEstablished(WebSocketSession session) throws Exception {

System.out.println("成功链接 websocket......");

String userid = (String) session.getAttributes().get(Global.WEBSOCKET_USERID);

users.put(userid, session);

// 这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户

// 用户登录成功后,查询是否存在未读的公告内容,如果存在,则提醒用户有未读公告

EntityWrapper suEW = new EntityWrapper<>();

suEW.eq("USERID", userid);

suEW.eq("HASREAD", 0);

suEW.eq("DELFLAG", 0);

int noReadCount = iSysUserreadnoticeService.selectCount(suEW);

// 用户登录成功后,查询是否存在未读的邮件,如果存在,则提醒用户有未读邮件

EntityWrapper sumEW = new EntityWrapper<>();

sumEW.eq("USERID", userid);

sumEW.eq("HASREAD", 0);

sumEW.eq("DELFLAG", 0);

sumEW.eq("MSGFOLDER", "收件箱");

int noReadMsgCount = sysUserreadmsgService.selectCount(sumEW);

// 存在未读的则发送消息

if (noReadCount > 0 || noReadMsgCount > 0) {

JSONObject json = new JSONObject();

json.put("wdCount", noReadCount + noReadMsgCount);

json.put("content", "您有" + noReadCount + "条未读通知公告哦!");

TextMessage returnMessage = new TextMessage(json.toString());

session.sendMessage(returnMessage);

}

}

/**

* 在UI在用js调用websocket.send()时候,会调用该方法

*/

@Override

protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {

// super.handleTextMessage(session, message);

// TextMessage returnMessage = new TextMessage(message.getPayload() + " received

// at server 大圣");

// session.sendMessage(returnMessage);

sendMessageToUsers(message);

}

/**

* 给某个用户发送消息

*

* @param userid

* @param message

*/

public static void sendMessageToUser(String userid, TextMessage message) {

for (Map.Entry entry : users.entrySet()) {

if (userid.equals(entry.getKey())) {

WebSocketSession user = entry.getValue();

try {

if (user.isOpen()) {

user.sendMessage(message);

}

} catch (IOException e) {

e.printStackTrace();

}

break;

}

}

}

/**

* 给所有在线用户发送消息

*

* @param message

*/

public static void sendMessageToUsers(TextMessage message) {

WebSocketSession user = null;

for (Map.Entry entry : users.entrySet()) {

user = entry.getValue();

try {

if (user.isOpen()) {

user.sendMessage(message);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

@Override

public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

if (session.isOpen()) {

session.close();

}

String userid = (String) session.getAttributes().get(Global.WEBSOCKET_USERID);

users.remove(userid);

}

@Override

public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

String userid = (String) session.getAttributes().get(Global.WEBSOCKET_USERID);

users.remove(userid);

}

@Override

public boolean supportsPartialMessages() {

return false;

}

}

5、新建 WebSocketConfig.java ,这个类是配置类,所以需要在spring mvc配置文件中加入对这个类的扫描,第一个addHandler是对正常连接的配置,第二个是如果浏览器不支持websocket,使用socketjs模拟websocket的连接。(注意:该类一定要要扫描到才可以哦,即springmvc 的扫描)

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;

@Configuration

@EnableWebSocket

public class WebSocketConfig implements WebSocketConfigurer {

@Override

public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

registry.addHandler(websocketBusiness(),"/websocket").addInterceptors(new HandshakeInterceptor());

registry.addHandler(websocketBusiness(), "/sockjs/websocket").addInterceptors(new HandshakeInterceptor()).withSockJS();

}

@Bean

public WebSocketHandler websocketBusiness() {

return new WebsocketBusiness();

}

}

6、到此,后端的代码模块基本完成,只剩下前端页面创建请求,进行握手连接了。

7、前端JS。sockjs 可使用cdn的,也可以下载下来放入到项目中。

8、到此,整合websocket完成。测试了几次后,正常使用。OK。可以实现消息提醒。

9、遇到的小问题。引入websocket包后,功能全部正常,但是我们系统引用了Junit 做测试,Junit环境异常。如果遇到该问题,则在pom.xml 中再引入相应的包即可。

org.apache.tomcat.embed

tomcat-embed-websocket

7.0.86

10、全部结束。

相关TAG标签
上一篇:移动开发handler警告解析
下一篇:Wine中PE格式文件的加载:DLL的装入和连接教程
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站