1. 程式人生 > >(3)websocket實現單聊和群聊

(3)websocket實現單聊和群聊

2  群聊圖

  2.1 zhangsan 發給所有人的圖

     

   2.2 傳送成功後 

   zhangsan的介面如下

 lisi的介面如下

wangwu的介面如下

3 單聊圖

 3.1 zhangsan傳送資訊圖如下

 3.2傳送成功後

 zhangsan介面如下

lisi介面如下

wangwu介面如下

4 專案結構圖

5 程式碼

 5.1 ChartMessage.java

package com.web.message;

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

import com.google.gson.Gson;

public class ChartMessage {
	private int type;  // 單聊 type = 1 ,type =2 群聊
	private String from;  //由誰發的
	private List<String> to; //發給誰
	private String content; //聊天內容
	private String welcome; //進聊天室和離開聊天室提示資訊
	private List<String> usernames ; //使用者列表名字
	private List<String> sessionUsernames;//websocket session名字
	private static Gson gson = new Gson();
	
	public ChartMessage(){
		
	}
	public ChartMessage(String welcome,List<String> usernames ){
		this.welcome = welcome;
		this.usernames = usernames;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public String getFrom() {
		return from;
	}
	public void setFrom(String from) {
		this.from = from;
	}
	public List<String> getTo() {
		return to;
	}
	public void setTo(List<String> to) {
		this.to = to;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = sdf.format(new Date());
		this.content = "\r\n\r\n" +time +"\r\n" +from+" said : " + content;
	}
	
	public String getChartMessageToJson(){
		return gson.toJson(this);
	}
	public List<String> getUsernames() {
		return usernames;
	}
	public void setUsernames(List<String> usernames) {
		this.usernames = usernames;
	}
	public String getWelcome() {
		return welcome;
	}
	public void setWelcome(String welcome) {
		this.welcome = welcome;
	}
	public List<String> getSessionUsernames() {
		return sessionUsernames;
	}
	public void setSessionUsernames(List<String> sessionUsernames) {
		this.sessionUsernames = sessionUsernames;
	}
	
}


5.2 Login.java

package com.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Login extends HttpServlet {

	/**
	 * Constructor of the object.
	 */
	public Login() {
		super();
	}

	/**
	 * Destruction of the servlet. <br>
	 */
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String username = request.getParameter("username");
//		System.out.println("username = " + username);
		request.setAttribute("username", username);
		RequestDispatcher dispatcher = request.getRequestDispatcher("/chart.jsp"); 
		dispatcher.forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	
	}

	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException if an error occurs
	 */
	public void init() throws ServletException {
		// Put your code here
	}

}


5.3 EchoSocket.java

package com.webSocket.client;

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

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

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import com.web.message.ChartMessage;


@ServerEndpoint("/echo")
public class EchoSocket {
	private static List<String> usernames = new ArrayList<String>();
	private static List<Session> sessions = new ArrayList<Session>();
	private static Map<String,Session> sessionMap = new HashMap<String,Session>();
	private String username; 
	private Session session;

	@OnOpen
	public void open(Session session){ //開啟websocket
		System.out.println("userid = "+session.getId());
		String string = session.getQueryString();
		this.username = string.split("=")[1];
		this.usernames.add(this.username);
		this.sessions.add(session);
		sessionMap.put(this.username, session);
		String welcome = "歡迎"+this.username+"加入聊天室";
		ChartMessage message = new ChartMessage(welcome,this.usernames);
		this.broadcast(this.sessions,message.getChartMessageToJson());

	}
	
	@OnClose
	public void close(Session session){ //關閉websocket
		this.sessions.remove(session);
		this.usernames.remove(this.username);
		String goMsg = this.username+"已經離開聊天室";
		ChartMessage message = new ChartMessage(goMsg,this.usernames);
		sessionMap.remove(this.username);
		this.broadcast(this.sessions,message.getChartMessageToJson());
		System.out.println("websocket is close");
	}
	
	@OnMessage
	public void message(Session session,String msg){
		
		if (session.isOpen()) {
			JSONObject msgJsonObj = JSONObject.fromObject(msg);
			ChartMessage chartMessage = (ChartMessage) JSONObject.toBean(msgJsonObj, ChartMessage.class);
			chartMessage.setUsernames(this.usernames);
			if(chartMessage.getType() == 1){  // type =1 單聊
				List<Session> sessionsPrivateList = new ArrayList<Session>();
				for(int i = 0 ; i <chartMessage.getTo().size() ; i++){
					String userChartName = chartMessage.getTo().get(i);
					sessionsPrivateList.add(sessionMap.get(userChartName));
				}
				sessionsPrivateList.add(sessionMap.get(chartMessage.getFrom()));
				this.broadcast(sessionsPrivateList,chartMessage.getChartMessageToJson());
				
			}else if(chartMessage.getType() == 2){ // type = 2 群聊
				this.broadcast(this.sessions,chartMessage.getChartMessageToJson());
			}

		}
	}

	public List<String> getUsernames() {
		return usernames;
	}

	public List<Session> getSessions() {
		return sessions;
	}
	
    private  void broadcast(List<Session> sessionsList,String msg) { //廣播給其它人
    	if(sessionsList.size() > 0){
    		for(int i = 0 ; i < sessionsList.size() ; i++){
    			try {
					sessionsList.get(i).getBasicRemote().sendText(msg);
				} catch (IOException e) {
					System.out.println("EchoSocket.java broadcast method ,廣播失敗 ");
					e.printStackTrace();
				}
        	}
    	}

    }

}
5.4

DemeConfig.java

package com.webSocket.config;

import java.util.Set;

import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;

public class DemeConfig implements ServerApplicationConfig{
	//註解的方式 啟動
	public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scan) {
		System.out.println("-------------websoket start-----------------");
		System.out.println("scan.size() = " + scan.size());
		
		return scan; //必須要返回scan,否則會造成連線失敗
	}

	//介面方式啟動
	public Set<ServerEndpointConfig> getEndpointConfigs(
			Set<Class<? extends Endpoint>> arg0) {
	
		return null;
	}

}

5.5 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>Login</servlet-name>
    <servlet-class>com.web.servlet.Login</servlet-class>
  </servlet>

 <servlet-mapping>
    <servlet-name>Login</servlet-name>
    <url-pattern>/servlet/Login</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
  </welcome-file-list>
</web-app>

5.6 chart.jsp

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    
    
    <title>My JSP 'index.jsp' starting page</title>
	
  </head>
  
  <body>
   <script type="text/javascript">
    
     var ws=null; 
     var target = "ws://"+window.location.host+"/webSocketTest/echo?username=${requestScope.username}"; // 開啟管道  ,ws://localhost:8080/專案名/@ServerEndpoint名字
      window.onload=function(){
       if(ws==null){
          if ('WebSocket' in window) {
                ws = new WebSocket(target);
            } else if ('MozWebSocket' in window) {
                ws = new MozWebSocket(target);
            } else {
                alert('WebSocket is not supported by this browser.');
                return;
         }
           ws.onmessage = function (event) { //建立websocket同時,接收伺服器發給客服端的訊息
         		if(event!=null){
         		//將json字串轉為物件
         		 eval("var msg="+event.data+";"); 
         		 //得到物件裡面的值
         		 var welcome = msg.welcome;
         		 var content = msg.content;
         		 var usernames = msg.usernames;
         		 //為聊天區teaxarea賦值
         		 var textArea = document.getElementById("content");
         		 if(undefined!=welcome){
         		   textArea.value = textArea.value  + "\r\n"+welcome;
         		 }
         		  if(undefined!=content){
         		   textArea.value = textArea.value  + "\r\n"+content;
         		 }
         		
         		 //為使用者列表區TD賦值
         		 var userListTD = document.getElementById("userList");
         		 userListTD.innerHTML="";
         		 for(var i = 0 ; i < usernames.length; i++){
         		  	if(undefined!=usernames[i]){
         		  	if("${requestScope.username}" == usernames[i]){
         		  	  userListTD.innerHTML += "\r\n  <input name='msgCheckBox' disabled='true' type='checkbox' value='"+usernames[i]+"'> <span style='color: red'>" +  usernames[i]+"</span></br>";
         		  	}else{
         		  	  userListTD.innerHTML += "\r\n  <input name='msgCheckBox' type='checkbox' value='"+usernames[i]+"'>" +  usernames[i]+"</br>";
         		  	}
         		  	 
         		  	}
         			
         		 }
         		 
         		 
         		}
         	  };
       
       
       }
       

     };
    
     
     sendMessage = function(){ //傳送資訊
      if(ws!=null){
       var checkNumber = 0 ; // 被選中複選框的個數
       var checkedUsernameArray = new Array();  // 被選中的複選框名字
       var checkBoxs =  document.getElementsByName("msgCheckBox");
       for(var i = 0 ; i < checkBoxs.length ; i++ ){ 
      	  var checkbox = checkBoxs[i];
         if(checkbox.checked == true){
         	checkNumber ++;
         	checkedUsernameArray.push(checkbox.value) ;
         }
      }
    //  alert("checkedUsernameArray = " + checkedUsernameArray);
      var type; // 單聊 type = 1 ,type =2 群聊
      if(checkNumber > 0 ) { // 單聊 type = 1 
        type = 1;
      }else{ //群聊
        type = 2; 
      }
       var sendMessageInput = document.getElementById("sendMessageTextArea");
       var msg = sendMessageInput.value; 
     
       /*
        1 傳送物件有哪些
        2 傳送的型別  單聊/群聊
        3 內容
       
       */
       var msgObj={
         type:type,
         from:'${requestScope.username}',
         to:checkedUsernameArray,
         content:msg
       };
     //將msgOjb物件轉為json
         var json = JSON.stringify(msgObj);
         ws.send(json);
       	 sendMessageInput.value ="";
       	
       }
       else{
         alert("websocket is null , please create a websocket");
       }
     }
   </script>
   
    <table cellpadding="0" cellspacing="0"  border="1" width="500px" height="400px">
      <tr>
        <td>
          <textarea id="content" rows="10" cols=50">
          </textarea>
         </td>
        <td id="userList" width="150px" align="center">
            
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <textarea id="sendMessageTextArea" rows="5" cols=50">
          </textarea>
          <button onclick="sendMessage()">傳送</button>
        </td>
        
      </tr>
    
    </table>
 
   
  </body>
</html>

5.7 login.jsp

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
   
    
    <title>login</title>
    


  </head>

  <body>
      <form action="<%=request.getContextPath()%>/servlet/Login" method="get">
                       使用者名稱:<input type="text" name="username"/>
         <input type="submit" value="登入"/>
      </form>
    
  </body>
</html>