Spring项目中使用webservice实现h5的websocket通信

一、在项目中建立一个webservice来做后台操作。

package org.calonlan.soulpower.websocket;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

/**
 * 这里使用注释的方式来向系统指明,我的这个WebSocketTest是一个webservice。 同时指定了路径为/websocket/{uCode}
 * 其中的{uCode}是一个变化的参数,在网页端动态的输入。这样我就可以通过@PathParam("uCode")这个注释在参数中获得用户的信息等等了。
 * 
 * */
@ServerEndpoint("/websocket/{uCode}")
public class WebSocketTest {

	/**
	 * @param message
	 *            这里是客户端传来的消息,我这里只是简单的测试文本消息,消息的种类可以有很多种。
	 * @param uCode
	 *            这就是{uCode}中传来的路径参数,可以用来传递用户的信息。例如帐号。
	 * @throws Exception
	 *             偷懒的人总是抛出一个EXCEPTION
	 */
	@OnMessage
	// 当有消息传来的时候进行处理的方法
	public void onMessage(String message, @PathParam("uCode") String uCode)
			throws Exception {
		System.out.println("revived:" + message);// 输出一下接收到的消息
		String tem[] = message.split("##to##");// 消息的格式是
												// tousername##to##message,分隔以后第一个就是要发送的用户名,第二个就是消息了
		if (SessionUtils.hasConnection(tem[0])) {// 从sessionUtils中判断一下是否要发送的用户名是否已经登录,登录的话做以下操作
			/* 弄个时间开始 */
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String x = sdf.format(new Date());
			/* 弄个时间结束 */

			/*
			 * 消息的发送,可以选择AsyncRemote也可以选择
			 * BasicRemote,区别在于AsyncRemote是不会阻塞的,系统不会去管消息是否发送完成直接占用通道去发
			 * 。使用它的话要用户自己去实现控制,所以我选择BasicRemote,
			 */
			SessionUtils.get(tem[0]).getBasicRemote()
					.sendText(uCode + "##to##" + x + ":" + tem[1]);
		} else {// 没有登录的话做以下操作
			SessionUtils.get(uCode).getBasicRemote().sendText("用户不在线");
		}
	}

	/**
	 * @param uCode
	 *            同上
	 * @param session
	 *            这个是用户建立的session信息,用来唯一标识这个用户的通信
	 * @throws Exception
	 *             你懂得
	 */
	@OnOpen
	// 用户建立链接的时候执行的方法
	public void onOpen(@PathParam("uCode") String uCode, Session session)
			throws Exception {

		if (SessionUtils.hasConnection(uCode)) {// 判断缓存中是否有uCode,如果有执行括号内的方法

			SessionUtils.get(uCode).close();// 因为已经登录了,那么将已经登录的下线
			SessionUtils.remove(uCode);// 移除掉缓存中的
			SessionUtils.put(uCode, session);// 添加新的

			System.out.println(uCode + "has join server");
		} else {
			System.out.println(uCode + "has join server");
			/* 如果没有缓存相关的,那么直接添加 */
			SessionUtils.put(uCode, session);
		}

	}

	@OnClose
	//客户端断开链接时执行的方法
	public void onClose(@PathParam("uCode") String uCode) {
		System.out.println(uCode + "has left server");
		SessionUtils.remove(uCode);//直接移除就好了,session已经关闭了
		System.out.println("left deal was finished");
	}

	@OnError
	//客户端出错误的时候执行的方法
	public void onError(Throwable e, Session session) {
		
		if (SessionUtils.clients.containsValue(session)) {//移除出错的session
			SessionUtils.remove(session);
		}

	}

}

二、实现用来管理session的uti类。

package org.calonlan.soulpower.websocket;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.Session;

public class SessionUtils {
	/*的缓存*/
	public static Map clients = new ConcurrentHashMap();

	public static void put(String uCode, Session session) {//添加
		clients.put(uCode, session);
	}

	public static Session get(String uCode) {//根据uCode来获取
		return clients.get(uCode);
	}

	public static void remove(String uCode) {//根据uCode来移除
		clients.remove(uCode);
	}

	public static void remove(Session session) {//根据session来移除
		Iterator> ito = clients.entrySet()
				.iterator();
		while (ito.hasNext()) {
			java.util.Map.Entry entry = ito.next();
			if (entry.getKey().equals(session))
				remove(entry.getKey());
		}
	}

	public static boolean hasConnection(String uCode) {//根据uCode来判断是否包含对应用户名的
		return clients.containsKey(uCode);
	}
}

三、html页面实现

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

 
     
        WebSoket Demo 
         
     
     
        


四、测试。

1.登录c1

Spring项目中使用webservice实现h5的websocket通信_第1张图片


服务器端显示

Spring项目中使用webservice实现h5的websocket通信_第2张图片


2.登录c2


Spring项目中使用webservice实现h5的websocket通信_第3张图片

服务器端显示

Spring项目中使用webservice实现h5的websocket通信_第4张图片


登录完成,就可以互相发送消息了。

c1发送给c2

Spring项目中使用webservice实现h5的websocket通信_第5张图片

c2发送给c1同样的道理。


这里还看到了很多不是发送的消息,这是我在后台设置的定时任务。服务器可以定时的给客户端发送一些消息。

五、定时任务

这里我遍历sessionutils中的map,给所有用户都发送

package org.calonlan.soulpower.timertask;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.websocket.Session;

import org.calonlan.soulpower.util.ComputerUtil;
import org.calonlan.soulpower.websocket.SessionUtils;
import org.hyperic.sigar.SigarException;

public class TimerTask {

	public void printTimeStamp() throws SigarException {
		Map map = SessionUtils.clients;
		Iterator> ito = map.entrySet().iterator();
		while (ito.hasNext()) {
			Entry entry = ito.next();
			try {
				if (entry.getValue().isOpen()) {
					entry.getValue().getBasicRemote()
							.sendText(ComputerUtil.getMemory());
					entry.getValue().getBasicRemote()
							.sendText(ComputerUtil.getCPU());
					entry.getValue().getBasicRemote()
							.sendText(ComputerUtil.getDisk());
				} else {
					map.remove(entry.getKey());
				}
			} catch (Exception e) {
				System.out.println("错误");
				e.printStackTrace();
				map.remove(entry.getKey());

			}

		}
	}

	public TimerTask() {
	}

	public void doTask() throws SigarException {
		this.printTimeStamp();
	}

}


你可能感兴趣的:(java基础)