webSocket通信

配置路径,在项目加载的时候就开始运行:

import javax.annotation.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
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;

import com.hncy.optima.websocket.handler.MessageHandshakeInterceptor;
import com.hncy.optima.websocket.handler.MessageWebSocketHandler;

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{

@Resource
private MessageWebSocketHandler messageWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(messageWebSocketHandler,"/message.msg").addInterceptors(new MessageHandshakeInterceptor());
registry.addHandler(messageWebSocketHandler,"/sockjs/message.msg").addInterceptors(new MessageHandshakeInterceptor())
.withSockJS();
}

@Bean
public WebSocketHandler messageWebSocketHandler(){
return new MessageWebSocketHandler();
}

}

 

***************************************************从前台开始************************************

//------------------------------------------websocket---------------------------------------------

var websocket;

if ('WebSocket' in window) {
//websocket = new WebSocket("ws://${socketPath}/message.msg");
websocket = new WebSocket("ws://127.0.0.1:6060/message.msg");
} else if ('MozWebSocket' in window) {
//websocket = new MozWebSocket("ws://${socketPath}/message.msg");
websocket = new MozWebSocket("ws://127.0.0.1:6060/message.msg");
} else {
//websocket = new SockJS("ws://${socketPath}/sockjs/message.msg");
websocket = new SockJS("ws://127.0.0.1:6060/sockjs/message.msg");
}

websocket.onopen = function (evnt) {
alert("onopen");
};

websocket.onmessage = function (evnt) {
alert(evnt.data);
};

websocket.onerror = function (evnt) {
//alert("onerror:"+evnt);
//for(var name in evnt){
//    alert(name + " : " +evnt[name]);
//}
};

websocket.onclose = function (evnt) {

};

jSP页面

建立连接时websocket.onopen响应,当后台向前台发送信息时,websocket.onmessage接受信息,evnt只能是String类型,但是我们可以用JSON来传递多个参数。

********************************************************获取用户**************************

package com.hncy.optima.websocket.handler;

import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import com.optima.bedrock.utils.LoginInstance;
import com.optima.bedrock.utils.Tools;


public class MessageHandshakeInterceptor implements HandshakeInterceptor{

@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
String loginName = LoginInstance.getUser().getLoginName();
if(Tools.transNull(loginName).equals("") == false){
attributes.put("loginName", loginName);
}else{
return false;
}

//在这里如果不需要定向发送,可以设置loginName为一个定值,返回true
return true;
}

/* (non-Javadoc)
* @see org.springframework.web.socket.server.HandshakeInterceptor#afterHandshake(org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse, org.springframework.web.socket.WebSocketHandler, java.lang.Exception)
*/
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
// TODO Auto-generated method stub

}

}

 

获取用户信息为后面发送消息通信做准备

******************************响应,发送消息的方法*****************************

package com.hncy.optima.websocket.handler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.hncy.optima.websocket.service.MessageWebSocketService;


@Component
public class MessageWebSocketHandler extends TextWebSocketHandler{

protected final static Log log = LogFactory.getLog(MessageWebSocketHandler.class);

private static final Map<String, WebSocketSession> userSocketSessions;

@Autowired
private MessageWebSocketService messageWebSocketService;

static{
userSocketSessions = new HashMap<String, WebSocketSession>();
}

public List<String> getOnlineUsers(){

return new ArrayList<String>(userSocketSessions.keySet());
}

/**
* 当用户的链接成功后,获取该用户的消息数,并推送给该用户
*/
@Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
super.afterConnectionEstablished(session);
String loginName = (String)session.getAttributes().get("loginName");
if(userSocketSessions.get(loginName) == null){
userSocketSessions.put(loginName, session);
}
//获取用户的未读信息
int count = this.messageWebSocketService.getUnReadMessagesCount(loginName);

session.sendMessage(new TextMessage("连接成功"));
}

/**
* 当关闭链接后,将用户从用户池中移除
*/
@Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus status) throws Exception {
// TODO Auto-generated method stub
super.afterConnectionClosed(session, status);
Iterator<Entry<String, WebSocketSession>> it = userSocketSessions.entrySet().iterator();
while(it.hasNext()){
Entry<String,WebSocketSession> entry = it.next();
if(entry.getValue().getId().equals(session.getId())){
userSocketSessions.remove(entry.getKey());
break;
}
}
System.out.println("关闭连接");

}

/**
* 消息处理,在客户端通过WebSocket API发送的消息会进过这里,然后进行相应的处理
*/
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
// TODO Auto-generated method stub
super.handleTextMessage(session, message);
//如果客户端发送的消息为空,那么直接返回
if(message.getPayloadLength() == 0)
return;
}

public void sendMessageToUser(String loginName,TextMessage message) throws IOException{
WebSocketSession session = userSocketSessions.get(loginName);
if(session != null && session.isOpen()){
session.sendMessage(message);
}
}

/**
* 消息传输错误处理
*/
@Override
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception {
if(session.isOpen()){
session.close();
}
Iterator<Entry<String,WebSocketSession>> it = userSocketSessions.entrySet().iterator();
while(it.hasNext()){
Entry<String,WebSocketSession> entry = it.next();
if(entry.getValue().getId().equals(session.getId())){
userSocketSessions.remove(entry.getKey());
break;
}
}
}

/**
* 向所有在线用户发送消息
* @param message
* @throws IOException
*/
public void sendMessageToAllOnlinUsers(final TextMessage message) throws IOException{
Iterator<Entry<String,WebSocketSession>> it = userSocketSessions.entrySet().iterator();
while(it.hasNext()){
final Entry<String,WebSocketSession> entry = it.next();
//采用多线程的方式发送消息
if(entry.getValue().isOpen()){
new Thread(new Runnable() {

@Override
public void run() {
try{
if(entry.getValue().isOpen()){
entry.getValue().sendMessage(message);
}
}catch(IOException e){
log.error("多线程发送消息给用户错误,用户:" + entry.getKey(), e);
}
}
}).start();
}
}
System.out.println("发送成功");
}

/**
* 将消息发送给指定的用户集合
* @param loginNames
* @param message
* @throws IOException
*/
public void sendMessageToUsers(List<String> loginNames,final TextMessage message) throws IOException{
for(String loginName : loginNames){
final WebSocketSession session = userSocketSessions.get(loginName);
if(session != null && session.isOpen()){
new Thread(new Runnable() {

@Override
public void run() {
try{
if(session.isOpen()){
session.sendMessage(message);
}
}catch(IOException e){
log.error("多线程发送消息给用户错误,用户:" + session.getAttributes().get("loginName"), e);
}
}
}).start();
}
}
}
}

 

我们可以修改其中的内容

**********************************************

package com.hncy.optima.websocket.service;


public interface MessageWebSocketService {

int getUnReadMessagesCount(String loginName);

}

 

package com.hncy.optima.websocket.service.impl;

import org.springframework.stereotype.Component;

import com.hncy.optima.websocket.service.MessageWebSocketService;


@Component
public class MessageWebSocketManagerImpl implements MessageWebSocketService{

/* (non-Javadoc)
* @see com.optima.websocket.service.MessageWebSocketService#getUnReadMessagesCount(java.lang.String)
*/
@Override
public int getUnReadMessagesCount(String loginName) {
return 0;
}

}

 

*********************************调用发送信息*******************************

try {
messageWebSocketHandler.sendMessageToAllOnlinUsers(new TextMessage("hello"));
} catch (IOException e) {
e.printStackTrace();
}

 

*********************************注意事项****************************

之前我用的是spring4.12但是报错了,后来我全部换成了4.16后就不在报错,为了保险起见,建议使用全家福,web,webSocket是必须要的。

在前台jsp页面,我们可以用http://<%= request.getServerName() %>:<%=request.getServerPort()%>来获取到地址与端口号,我之上写的地址一定要和调用地址相同,不然是不能达成连接的,不过最好的方法就是使用http://<%= request.getServerName() %>:<%=request.getServerPort()%>,就不会再担心这些问题了。

 

posted @ 2017-04-13 20:52  handbang  阅读(522)  评论(0编辑  收藏  举报