配色: 字号:
Spring和Websocket相结合实现消息的推送
2016-10-14 | 阅:  转:  |  分享 
  
Spring和Websocket相结合实现消息的推送

这篇文章主要介绍了Spring和Websocket相结合实现消息的推送的相关资料,本文介绍的非常详细具有参考借鉴价值,感兴趣的朋友一起学习吧

本文主要有三个步骤

1、用户登录后建立websocket连接,默认选择websocket连接,如果浏览器不支持,则使用sockjs进行模拟连接

2、建立连接后,服务端返回该用户的未读消息

3、服务端进行相关操作后,推送给某一个用户或者所有用户新消息相关环境Spring4.0.6(要选择4.0+),tomcat7.0.55

Websocet服务端实现

WebSocketConfig.java

@Configuration

@EnableWebMvc

@EnableWebSocket

publicclassWebSocketConfigextendsWebMvcConfigurerAdapterimplementsWebSocketConfigurer{

@Override

publicvoidregisterWebSocketHandlers(WebSocketHandlerRegistryregistry){

registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(newWebSocketHandshakeInterceptor());

registry.addHandler(systemWebSocketHandler(),"/sockjs/webSocketServer").addInterceptors(newWebSocketHandshakeInterceptor())

.withSockJS();

}

@Bean

publicWebSocketHandlersystemWebSocketHandler(){

returnnewSystemWebSocketHandler();

}

}

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

?

1

@Configuration

@EnableWebMvc

@EnableWebSocket

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

?

1 registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(newWebSocketHandshakeInterceptor())

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

?

1

2

3 registry.addHandler(systemWebSocketHandler(),"/sockjs/webSocketServer").addInterceptors(newWebSocketHandshakeInterceptor())

.withSockJS();

}

这个是使用Sockjs的注册方法

首先SystemWebSocketHandler.java

publicclassSystemWebSocketHandlerimplementsWebSocketHandler{

privatestaticfinalLoggerlogger;

privatestaticfinalArrayListusers;

static{

users=newArrayList<>();

logger=LoggerFactory.getLogger(SystemWebSocketHandler.class);

}

@Autowired

privateWebSocketServicewebSocketService;

@Override

publicvoidafterConnectionEstablished(WebSocketSessionsession)throwsException{

logger.debug("connecttothewebsocketsuccess......");

users.add(session);

StringuserName=(String)session.getAttributes().get(Constants.WEBSOCKET_USERNAME);

if(userName!=null){

//查询未读消息

intcount=webSocketService.getUnReadNews((String)session.getAttributes().get(Constants.WEBSOCKET_USERNAME));

session.sendMessage(newTextMessage(count+""));

}

}

@Override

publicvoidhandleMessage(WebSocketSessionsession,WebSocketMessagemessage)throwsException{

//sendMessageToUsers();

}

@Override

publicvoidhandleTransportError(WebSocketSessionsession,Throwableexception)throwsException{

if(session.isOpen()){

session.close();

}

logger.debug("websocketconnectionclosed......");

users.remove(session);

}

@Override

publicvoidafterConnectionClosed(WebSocketSessionsession,CloseStatuscloseStatus)throwsException{

logger.debug("websocketconnectionclosed......");

users.remove(session);

}

@Override

publicbooleansupportsPartialMessages(){

returnfalse;

}

/

给所有在线用户发送消息



@parammessage

/

publicvoidsendMessageToUsers(TextMessagemessage){

for(WebSocketSessionuser:users){

try{

if(user.isOpen()){

user.sendMessage(message);

}

}catch(IOExceptione){

e.printStackTrace();

}

}

}

/

给某个用户发送消息



@paramuserName

@parammessage

/

publicvoidsendMessageToUser(StringuserName,TextMessagemessage){

for(WebSocketSessionuser:users){

if(user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)){

try{

if(user.isOpen()){

user.sendMessage(message);

}

}catch(IOExceptione){

e.printStackTrace();

}

break;

}

}

}

}

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

然后WebSocketHandshakeInterceptor.java

publicclassWebSocketHandshakeInterceptorimplementsHandshakeInterceptor{

privatestaticLoggerlogger=LoggerFactory.getLogger(HandshakeInterceptor.class);

@Override

publicbooleanbeforeHandshake(ServerHttpRequestrequest,ServerHttpResponseresponse,WebSocketHandlerwsHandler,Map
>attributes)throwsException{

if(requestinstanceofServletServerHttpRequest){

ServletServerHttpRequestservletRequest=(ServletServerHttpRequest)request;

HttpSessionsession=servletRequest.getServletRequest().getSession(false);

if(session!=null){

//使用userName区分WebSocketHandler,以便定向发送消息

StringuserName=(String)session.getAttribute(Constants.SESSION_USERNAME);

attributes.put(Constants.WEBSOCKET_USERNAME,userName);

}

}

returntrue;

}

@Override

publicvoidafterHandshake(ServerHttpRequestrequest,ServerHttpResponseresponse,WebSocketHandlerwsHandler,Exceptionexception){

}

}

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

用户登录建立websocket连接

index.jsp





使用sockjs时要注意

1、这两个的写法

?

1

2

websocket=newSockJS(//localhost:8080/Origami/sockjs/webSocketServer);

2、web.xml中


xmlns:xsi=".w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="//java.sun.com/xml/ns/javaee//java.sun.com/xml/ns/javaee/web-app_3_1.xsd">

version

web-app_3_1.xsd

这两个的版本都要是3.0+

然后在这个servlet中加入

true



appServlet

org.springframeworkwww.visa158.com.web.servlet.DispatcherServlet



contextConfigLocation

classpath:servlet-context.xml



1

true



然后所有的filter中也加入

1 true

3、添加相关依赖



com.fasterxml.www.hunanwang.net.jackson.core

jackson-annotations

2.3.0





com.fasterxml.jackson.core

jackson-core

2.3.1





com.fasterxml.jackson.core

jackson-databind

2.3.3



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

返回用户未读的消息

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

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

服务端推送消息给用户

@Controller

publicclassAdminController{

staticLoggerlogger=LoggerFactory.getLogger(AdminController.class);

@Autowired(required=false)

privateAdminServiceadminService;

@Bean

publicSystemWebSocketHandlersystemWebSocketHandler(){

returnnewSystemWebSocketHandler();

}

@RequestMapping("/auditing")

@ResponseBody

publicStringauditing(HttpServletRequestrequest){

//无关代码都省略了

intunReadNewsCount=adminService.getUnReadNews(username);

systemWebSocketHandler().sendMessageToUser(username,newTextMessage(unReadNewsCount+""));

returnresult;

}

}























献花(0)
+1
(本文系白狐一梦首藏)