java websocket实现点对点即时聊天

算是一个入门的demo,使用的是springMVC。

必要环境:JDK1.7以上,tomcat7.0以上。以下是干货:

1、websocket的jar直接从tomcat运行库里面添加到build path里面。

2、前台聊天页面,通过ws://localhost:8080/newProject/websocketTest与后台建立连接

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>





My JSP 'socketChart.jsp' starting page




	${username}
在线人数:
0

发送对象:内容:

3、登录页面,简单的创建一个session会话模拟用户登录用作点对点聊天的唯一标识。

 

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>






My JSP 'login.jsp' starting page




username:

4、controller类,模拟登录创建会话,并向socket工具类里面传送登录用户的唯一标识。

 

 

package com.test.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.test.socket.WebSocketTest;

@Controller
@RequestMapping("chatWebsocket")
public class ChartWebsocketController {
	@RequestMapping("login")
	public void login(String username,HttpServletRequest request,HttpServletResponse response) throws Exception{
		HttpSession session=request.getSession();
		session.setAttribute("username", username);
		WebSocketTest.setHttpSession(session);
		request.getRequestDispatcher("/socketChart.jsp").forward(request, response);
	}
	@RequestMapping("loginOut")
	public void loginOut(HttpServletRequest request,HttpServletResponse response) throws Exception{
		HttpSession session=request.getSession();
		session.removeAttribute("username");
		request.getRequestDispatcher("/socketChart.jsp").forward(request, response);
	}
}

 

 

 

 

 

5、socket消息处理类,负责消息的接收与转发,作用类似于TCP的服务端,@ServerEndpoint("/websocketTest")的作用是声明websocket的连接路径。

package com.test.socket;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpSession;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import com.google.gson.Gson;

/**
 * @ServerEndpoint
 */
@ServerEndpoint("/websocketTest")
public class WebSocketTest {
	private static int onlineCount = 0;
	//存放所有登录用户的Map集合,键:每个用户的唯一标识(用户名)
	private static Map webSocketMap = new HashMap();
	//session作为用户简历连接的唯一会话,可以用来区别每个用户
	private Session session;
	//httpsession用以在建立连接的时候获取登录用户的唯一标识(登录名),获取到之后以键值对的方式存在Map对象里面
	private static HttpSession httpSession;
	
	public static void setHttpSession(HttpSession httpSession){
		WebSocketTest.httpSession=httpSession;
	}
	/**
	 * 连接建立成功调用的方法
	 * @param session
	 * 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
	 */
	@OnOpen
	public void onOpen(Session session) {
		Gson gson=new Gson();
		this.session = session;
		webSocketMap.put((String) httpSession.getAttribute("username"), this);
		addOnlineCount(); // 
		MessageDto md=new MessageDto();
		md.setMessageType("onlineCount");
		md.setData(onlineCount+"");
		sendOnlineCount(gson.toJson(md));
		System.out.println(getOnlineCount());
	}
	/**
	 * 向所有在线用户发送在线人数
	 * @param message
	 */
	public void sendOnlineCount(String message){
		for (Entry entry  : webSocketMap.entrySet()) {
			try {
				entry.getValue().sendMessage(message);
			} catch (IOException e) {
				continue;
			}
		}
	}
	
	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose() {
		for (Entry entry  : webSocketMap.entrySet()) {
			if(entry.getValue().session==this.session){
				webSocketMap.remove(entry.getKey());
				break;
			}
		}
		//webSocketMap.remove(httpSession.getAttribute("username"));
		subOnlineCount(); // 
		System.out.println(getOnlineCount());
	}

	/**
	 * 服务器接收到客户端消息时调用的方法,(通过“@”截取接收用户的用户名)
	 * 
	 * @param message
	 *            客户端发送过来的消息
	 * @param session
	 *            数据源客户端的session
	 */
	@OnMessage
	public void onMessage(String message, Session session) {
		Gson gson=new Gson();
		System.out.println("收到客户端的消息:" + message);
		StringBuffer messageStr=new StringBuffer(message);
		if(messageStr.indexOf("@")!=-1){
			String targetname=messageStr.substring(0, messageStr.indexOf("@"));
			String sourcename="";
			for (Entry entry  : webSocketMap.entrySet()) {
				//根据接收用户名遍历出接收对象
				if(targetname.equals(entry.getKey())){
					try {
						for (Entry entry1  : webSocketMap.entrySet()) {
							//session在这里作为客户端向服务器发送信息的会话,用来遍历出信息来源
							if(entry1.getValue().session==session){
								sourcename=entry1.getKey();
							}
						}
						MessageDto md=new MessageDto();
						md.setMessageType("message");
						md.setData(sourcename+":"+message.substring(messageStr.indexOf("@")+1));
						entry.getValue().sendMessage(gson.toJson(md));
					} catch (IOException e) {
						e.printStackTrace();
						continue;
					}
				}
				
			}
		}
		
	}

	/**
	 * 发生错误时调用
	 * 
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		error.printStackTrace();
	}

	/**
	 * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
	 * 
	 * @param message
	 * @throws IOException
	 */
	public void sendMessage(String message) throws IOException {
		this.session.getBasicRemote().sendText(message);
		// this.session.getAsyncRemote().sendText(message);
	}

	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		WebSocketTest.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		WebSocketTest.onlineCount--;
	}
}

6、消息封装的数据传输对象

package com.chart.dto;

public class MessageDto {
	private String messageType;
	private String data;
	public String getMessageType() {
		return messageType;
	}
	public void setMessageType(String messageType) {
		this.messageType = messageType;
	}
	public String getData() {
		return data;
	}
	public void setData(String data) {
		this.data = data;
	}
	
}

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(java)