基于Tomcat7的websocket的应用实现

这几天想做一个单对单的在线聊天模块,所以研究了一下websocket,以下就来分享一下基于tomcat7的websocket实现的小例子。

1.WebSocket是什么


WebSocket protocol 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。

它摒弃了以轮询为主要方式的传统的即时通讯技术,真正实现了一个浏览器与服务器之间的全双工通讯,通过一个握手的动作,使得浏览器与服务器之间形成一条通道,实现数据的互相传送。

2.WebSocket在Tomcat7中的java实现

2.1 demo实现效果图
  1)先看看这个小demo实现后的效果,一访问先要注册用户名
  
  2)我这里一共打开了三个窗口注册了三个用户分别为user0,user1,suer2
  确定之后
  
  3)在user0里面向user1发送消息
  
  4)user1的窗口就收到信息
  
2.2 demo的实现过程
 1) 首先在eclipse新建一个J2EE工程,此处为websocketDemo
  
 2)新建一个名为WebSocketServer的java类,它继承于WebSocketServlet。(Tomcat7中显示WebSocketServlet已过期,本文后面再作解释)
 1 import java.util.Set;
 2 import java.util.concurrent.CopyOnWriteArraySet;
 3 
 4 import javax.servlet.http.HttpServletRequest;
 5 
 6 import org.apache.catalina.websocket.StreamInbound;
 7 import org.apache.catalina.websocket.WebSocketServlet;
 8 
 9 
10 public class WebSocketServer extends WebSocketServlet {
11 
12     public final Set<ChatWebSocket> users = new CopyOnWriteArraySet<ChatWebSocket>();
13     
14     @Override
15     protected StreamInbound createWebSocketInbound(String arg0,
16             HttpServletRequest arg1) {
17         // TODO Auto-generated method stub
18         return new ChatWebSocket(users);
19     }
21 }

  浏览器的每一次连接都会经过WebSocketServer 的createWebSocketInbound方法,这里返回一个ChatWebSocket实例(文章接下来会实现),这里还维护了一个每一个连接对象users。

  关于CopyOnWriteArraySet可以看这里http://ifeve.com/tag/copyonwritearrayset/

 3)ChatWebSocket.java

 1 import java.io.IOException;
 2 import java.nio.ByteBuffer;
 3 import java.nio.CharBuffer;
 4 import java.util.Set;
 5 import java.util.concurrent.CopyOnWriteArraySet;
 6 
 7 import org.apache.catalina.websocket.MessageInbound;
 8 import org.apache.catalina.websocket.WsOutbound;
 9 
10 public class ChatWebSocket extends MessageInbound {
11 
12     public Set<ChatWebSocket> users = new CopyOnWriteArraySet<ChatWebSocket>();
13     private String username;
14 
15     public ChatWebSocket() {
16     }
17 
18     public ChatWebSocket(Set<ChatWebSocket> users) {
19         this.users = users;
20     }
21 
22     /**
23      * 此方法会接收浏览器的二进制消息
24      */
25     @Override
26     protected void onBinaryMessage(ByteBuffer message) throws IOException {
27         // TODO Auto-generated method stub
28         System.out.println("binary:"+message);
29     }
30 
31     /**
32      * 此方法接收浏览器的文本消息,以下的for循环是用来查找名字实现单对单聊天用的
33      */
34     @Override
35     protected void onTextMessage(CharBuffer message) throws IOException {
36         // TODO Auto-generated method stub
37         System.out.println("text:"+message);
38         String mes = String.valueOf(message);
39         if(mes.indexOf("username:")==0) {
40             this.username = mes.substring(9);
41             System.out.println(username);
42         } else {
43             String[] str = mes.split("_123");
44             String name = str[0];
45             for(ChatWebSocket user :users) {
46                 if(user.username.equals(name)) {
47                     CharBuffer ch = CharBuffer.wrap(this.username+":123"+str[1]);
48                     System.out.println("find");
49                     user.getWsOutbound().writeTextMessage(ch);
50                     break;
51                 }
52             }
53         }
54         
55     }
56 
57     /**
58      * 关闭连接会经过此方法
59      */
60     @Override
61     protected void onClose(int status) {
62         // TODO Auto-generated method stub        
63         System.out.println("----");
64         System.out.println("close");
65         users.remove(this);
66     }
67 
68     /**
69      * 浏览器连接会经过此方法
70      */
71     @Override
72     protected void onOpen(WsOutbound outbound) {
73         // TODO Auto-generated method stub
74 
75         System.out.println("open");        
76         users.add(this);
77     }
78 
79     public String getUsername() {
80         return username;
81     }
82 
83     public void setUsername(String username) {
84         this.username = username;
85     }     
89 }

 

 4) 当然还要在web.xml上配置这个servlet  

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">


    <servlet>
        <servlet-name>websocketserver</servlet-name>
        <servlet-class>WebSocketServer1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>websocketserver</servlet-name>
        <url-pattern>/webchat</url-pattern>
    </servlet-mapping>
    
    <session-config>    
        <session-timeout>30</session-timeout>
    </session-config>

</web-app>

 

  至此,服务器端已搭建结束。

  5 )浏览器的jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="js/socket.js"></script>
<title>webClient</title>
</head>

<body>
<table id="mes"> 
  <tr>
    <td>名字</td>
    <td><input type="text" id="othername"></td>
  </tr>
  <tr>
    <td>消息</td>
    <td><input type="text" id="message"></td>
  </tr>
  <tr>
    <td><input id="sendbutton" type="button" value="send" onClick="click"  disabled="true">
      </input></td>
  </tr>
</table>
<div id="record">
</div>

</body>
</html>

  以下是页面引入的soket.js

var username = window.prompt("输入你的名字:");

document.write("Welcome<p id=\"username\">" + username + "</p>");

/**
 * 判断浏览器是否支持websocket
 */
if (!window.WebSocket && window.MozWebSocket)
    window.WebSocket = window.MozWebSocket;
if (!window.WebSocket)
    alert("No Support ");
var ws;

$(document).ready(function() {

    $("#sendbutton").click(sendMessage);
    startWebSocket();
});

function sendMessage() {
    var othername = $("#othername").val();
    var msg = othername + "_123" + $("#message").val();
    send(msg);
};

function send(data) {
    //alert(data);
    ws.send(data);
};

function startWebSocket() {
    ws = new WebSocket("ws://localhost:8080/websocketDemo/webchat");
    
    //浏览器连接会自动执行这个open方法
    ws.onopen = function() {
        console.log("success open");
        send("username:"+username);
    };
    
    //服务端向浏览器发送消息会经过此方法
    ws.onmessage = function(event) {
        console.log("RECEIVE:" + event.data);        
        handleData(event.data);
    };
    
    //浏览器关闭连接会经过此方法
    ws.onclose = function(event) {
        console.log("Client notified socket has closed", event);
    };

};

function handleData(data) {
    var vals = data.split(":123");
    var name = vals[0];
    var mess = vals[1];
    $("#record").append("<p>" + name+":" +mess+ "</p>");
}

 

3.后记

 


在tomcat8以后,已经出现了新的支持websocket的方式了,可以直接用注解的方式去代替本例子中的继承,注解的方式为@ServerEndpoint(value="/") ,@OnOpen,@OnMessage,@OnClose等等

由于我的eclipse版本没支持tomcat8,所以本文章就只写了基于tomcat7的实现。理解了本例子,相信用注解的方式也是很容易的了。

 
  

转载于:https://www.cnblogs.com/detoAndy/p/5079788.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值