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,WebSocketMessage>message)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;
}
}
|
|