准备
导入依赖
compile group: 'org.springframework', name: 'spring-messaging', version: '4.3.3.RELEASE'
compile group: 'org.springframework', name: 'spring-websocket', version: '4.3.3.RELEASE'
方式一
<bean id="websocket" class="net.rock.projects.orp.web.websocket.WebsocketEndPoint" />
<websocket:handlers allowed-origins="*">
<websocket:mapping path="/websocket" handler="websocket"/>
<websocket:handshake-interceptors>
<bean class="com.up.websocket.HandshakeInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
其中,path对应的路径就是前段通过ws协议调的接口路径
创建握手接口(拦截器)
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
HttpSession session = servletRequest.getSession(false);
User user = (User) session.getAttribute("token");
if(user!=null){
attributes.put("token", user);
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
super.afterHandshake(request, response, wsHandler, ex);
}
}
创建处理类
@Component
public class WebsocketEndPoint extends TextWebSocketHandler {
@Autowired
IProjectDeliverService iProjectDeliverService;
@Autowired
IProjectDeliverReplyService iProjectDeliverReplyService;
@Autowired
private IUserService iUserService;
/**
* 所有的用户
*/
private static final Map<Integer , WebSocketSession > users ;
static{
users = new HashMap<>();
}
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
super.handleTextMessage(session, message);
session.sendMessage(message);
}
@Override
public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
User user = (User) session.getAttributes().get("token");
if(user != null)
users.put(user.getId() , session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
User user = (User) session.getAttributes().get("token");
// 如果用户对象还存在内存中,那么不进行退出记录
if(user != null){
iUserService.exit(DateUtils.dateToString(new Date()),user.getId());
System.out.println(user.getNickName()+" exits from the system ! Connection Closed!");
}
}
/**
* 发送给指定用户
* @param userIds 用户编号数组,不传(长度=0) 默认发送给所有用户
* @param message 消息内容
*/
public static void sendToUser( TextMessage message , List<Integer> userIds){
try {
// 如果没有传用户编号 , 默认发送给所有用户
if(userIds == null || userIds.size() == 0){
if(users.keySet() != null && users.keySet().size() > 0 ){
for (Integer key : users.keySet()) {
if(users.get(key).isOpen())
users.get(key).sendMessage(message);
}
}
}else{ // 发送给指定的用户
for (Integer id : userIds) {
if(users.containsKey(id) && users.get(id).isOpen()){
users.get(id).sendMessage(message);
}
}
}
}catch (IOException e){
e.printStackTrace();
}
}
}
用户页面连接(sockjs-0.3.min.js自行下载)
<script src="<%=resourcePath%>js/sockjs-0.3.min.js"></script>
<script>
var ws = null;
var url = "ws://<%=basePath.replace("http://","")%>/msgcenter?uid=20125";
function socketConnection(){
if (!url) {
alert('Select whether to use W3C WebSocket or SockJS');
return;
}
ws = new WebSocket(url); //申请一个WebSocket对象
ws.onopen = function () {
console.info("连接已经打开。。。。。。");
};
ws.onmessage = function (event) {
console.info("你接受到消息是:"+event.data);
}
}
};
ws.onclose = function (event) {
console.info("连接已经断开。。。。。" );
};
}
$(function(){
socketConnection();
});
</script>
后台调用sendToUser给指定用户发送信息
.................................................................................................
方式二
websocket入口
@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//setAllowedOrigins("*") 解决跨域问题
registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()).setAllowedOrigins("*");
registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor()).withSockJS();
}
@Bean
public WebSocketHandler systemWebSocketHandler(){
return new SystemWebSocketHandler();
}
}
拦截器,beforeHandshake在调用handler前处理方法。常用在注册用户信息,绑定WebSocketSession,在handler里根据用户信息获取WebSocketSession发送消息。
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
@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,以便定向发送消息
attributes.put("userId",session.getAttribute("userId"));
}
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
}
handle处理器
public class SystemWebSocketHandler implements WebSocketHandler {
private static final Map<String,WebSocketSession> users;
static {
users = new HashMap<>();
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String userId = (String) session.getAttributes().get("userId");
if(userId !=null){
users.put(userId,session);
}
session.sendMessage(new TextMessage("hello world"));
System.out.println("建立连接");
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
System.out.println("连接被关闭");
for (Map.Entry<String, WebSocketSession> entry : users.entrySet()) {
if(entry.getValue().equals(session)){
users.remove(entry.getKey());
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
System.out.println("连接被关闭");
users.remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* 给某个用户发送消息
*
* @param userId
* @param message
*/
public static void sendMessageToUser(String userId, TextMessage message) throws IOException {
Set<Map.Entry<String, WebSocketSession>> entries = users.entrySet();
for (Map.Entry<String, WebSocketSession> entry : entries) {
if(entry.getKey().equals(userId))
entry.getValue().sendMessage(message);
}
}
}
用户建立socket连接(sockjs-0.3.min.js自行下载)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path;
String url = request.getServerName()+":"+request.getServerPort()+path;
%>
<html>
<head>
<title>index</title>
</head>
<body>
<h3 align="center">
消息通知:<span id="msg"></span>
</h3>
</body>
</html>
<script src="<%=basePath%>/js/jquery-1.9.1.min.js"></script>
<script src="<%=basePath%>/js/sockjs-0.3.min.js"></script>
<script>
var websocket;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://<%=url%>/webSocketServer?userId=1");
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://<%=url%>/webSocketServer?userId=1");
} else {
websocket = new SockJS("http://<%=url%>/sockjs/webSocketServer?userId=1");
}
websocket.onopen = function (evnt) {
console.info("连接已建立")
};
websocket.onmessage = function (evnt) {
console.info("本次推送内容是:"+evnt.data);
$("#msg").html(evnt.data)
};
websocket.onerror = function (evnt) {
console.info("连接已断开")
};
websocket.onclose = function (evnt) {
console.info("连接已断开")
}
</script>
调用 sendMessageToUser推送信息
/**
* 消息推送
* @param msg 消息内容
* @param userId 推送用户id
*/
@RequestMapping(value = "pushMsg",method = RequestMethod.POST)
@ResponseBody
public String pushMsg(String userId, String msg) {
System.out.println("用户id:"+userId+" 推送的消息:"+msg);
try {
SystemWebSocketHandler.sendMessageToUser(userId,new TextMessage(msg));
return new Gson().toJson("success");
} catch (Exception e) {
System.out.println(e.getMessage()+"................");
e.printStackTrace();
return new Gson().toJson("fail:"+e);
}
}
相关链接
http://www.bridgeli.cn/archives/262
https://my.oschina.net/ldl123292/blog/304360
http://www.cnblogs.com/nosqlcoco/p/5860730.html