spell 发表于 2017-1-24 08:49:47

基于Tomcat的WebSocket

  原文地址:http://redstarofsleep.iteye.com/blog/1488639
 
2014年2月更新: 此API为Tomcat私有,当时Java没有标准API,现在Java有标准API,JSR536,此API不建议使用,新的用法请参照: http://redstarofsleep.iteye.com/blog/1974620
 
之前大概的看过WebSocket,当时Tomcat还不支持WebSocket,所以当时写了一篇基于Jetty的WebSocket实现,地址如下:
http://redstarofsleep.iteye.com/blog/1307608
 
现在Tomcat7.0.27发布了,从这个版本开始Tomcat就支持WebSocket了。
Tomcat的WebSocket和Jetty的大致上差不多,大同小异,这里就简单的贴两个类吧(此例子未考虑多线程的情况):
 
第一个类,这个和Jetty一样,需要一个Servlet来处理WebSocket请求:
Java代码  


[*]package lhc.websocket;  
[*]  
[*]import org.apache.catalina.websocket.StreamInbound;  
[*]import org.apache.catalina.websocket.WebSocketServlet;  
[*]  
[*]public class MyWebSocketServlet extends WebSocketServlet {  
[*]  
[*]    private static final long serialVersionUID = -7178893327801338294L;  
[*]  
[*]    @Override  
[*]    protected StreamInbound createWebSocketInbound(String arg0) {  
[*]System.out.println("##########");  
[*]        return new MyMessageInbound();  
[*]    }  
[*]  
[*]}  

这个Servlet继承自WebSocketServlet,实现createWebSocketInbound方法。该方法返回第二个类的实例。
 
第二个类,处理每一次具体的WebSocket任务:
Java代码  


[*]package lhc.websocket;  
[*]  
[*]import java.io.IOException;  
[*]import java.nio.ByteBuffer;  
[*]import java.nio.CharBuffer;  
[*]  
[*]import lhc.init.InitServlet;  
[*]  
[*]import org.apache.catalina.websocket.MessageInbound;  
[*]import org.apache.catalina.websocket.WsOutbound;  
[*]  
[*]public class MyMessageInbound extends MessageInbound {  
[*]  
[*]    @Override  
[*]    protected void onBinaryMessage(ByteBuffer arg0) throws IOException {  
[*]        // TODO Auto-generated method stub  
[*]          
[*]    }  
[*]  
[*]    @Override  
[*]    protected void onTextMessage(CharBuffer msg) throws IOException {  
[*]        for (MessageInbound messageInbound : InitServlet.getSocketList()) {  
[*]            CharBuffer buffer = CharBuffer.wrap(msg);  
[*]            WsOutbound outbound = messageInbound.getWsOutbound();  
[*]            outbound.writeTextMessage(buffer);  
[*]            outbound.flush();  
[*]        }  
[*]          
[*]    }  
[*]  
[*]    @Override  
[*]    protected void onClose(int status) {  
[*]        InitServlet.getSocketList().remove(this);  
[*]        super.onClose(status);  
[*]    }  
[*]  
[*]    @Override  
[*]    protected void onOpen(WsOutbound outbound) {  
[*]        super.onOpen(outbound);  
[*]        InitServlet.getSocketList().add(this);  
[*]    }  
[*]      
[*]      
[*]  
[*]}  

 
 这个类继承自MessageInbound类,必须实现onBinaryMessage和onTextMessage方法。Jetty中只有一个onMessage方法,而Tomcat细化成了2个方法。
 
还要一个初始化的Servlet
Java代码  


[*]package lhc.init;  
[*]  
[*]import java.util.ArrayList;  
[*]import java.util.List;  
[*]  
[*]import javax.servlet.ServletConfig;  
[*]import javax.servlet.ServletException;  
[*]import javax.servlet.http.HttpServlet;  
[*]  
[*]import org.apache.catalina.websocket.MessageInbound;  
[*]  
[*]public class InitServlet extends HttpServlet {  
[*]  
[*]    private static final long serialVersionUID = -3163557381361759907L;  
[*]      
[*]    private static List<MessageInbound> socketList;    
[*]      
[*]    public void init(ServletConfig config) throws ServletException {    
[*]        InitServlet.socketList = new ArrayList<MessageInbound>();    
[*]        super.init(config);    
[*]        System.out.println("Server start============");    
[*]    }    
[*]        
[*]    public static List<MessageInbound> getSocketList() {    
[*]        return InitServlet.socketList;    
[*]    }    
[*]}  

 
 
最后,web.xml中进行一下Servlet的配置。
Xml代码  


[*]<?xml version="1.0" encoding="UTF-8"?>  
[*]<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">  
[*]  <display-name>wsoc</display-name>  
[*]  <welcome-file-list>  
[*]    <welcome-file>index.jsp</welcome-file>  
[*]  </welcome-file-list>  
[*]    
[*]  <servlet>  
[*]    <servlet-name>mywebsocket</servlet-name>  
[*]    <servlet-class>lhc.websocket.MyWebSocketServlet</servlet-class>  
[*]  </servlet>  
[*]  <servlet-mapping>  
[*]    <servlet-name>mywebsocket</servlet-name>  
[*]    <url-pattern>*.do</url-pattern>  
[*]  </servlet-mapping>  
[*]    
[*]  <servlet>  
[*]    <servlet-name>initServlet</servlet-name>  
[*]    <servlet-class>lhc.init.InitServlet</servlet-class>  
[*]    <load-on-startup>1</load-on-startup>  
[*]  </servlet>  
[*]</web-app>  

 
 
页面的话,就是标准的HTML5的websocket,这个和服务器是否是Tomcat或者Jetty是无关的:
Html代码  


[*]<%@ page language="java" contentType="text/html; charset=UTF-8"  
[*]    pageEncoding="UTF-8"%>  
[*]<!DOCTYPE html>  
[*]<html>  
[*]<head>  
[*]<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
[*]<title>Index</title>  
[*]<script type="text/javascript">  
[*]var ws = null;  
[*]function startWebSocket() {  
[*]    if ('WebSocket' in window)  
[*]        ws = new WebSocket("ws://localhost:8080/wsoc/mywebsocket.do");  
[*]    else if ('MozWebSocket' in window)  
[*]        ws = new MozWebSocket("ws://localhost:8080/wsoc/mywebsocket.do");  
[*]    else  
[*]        alert("not support");  
[*]      
[*]      
[*]    ws.onmessage = function(evt) {  
[*]        alert(evt.data);  
[*]    };  
[*]      
[*]    ws.onclose = function(evt) {  
[*]        alert("close");  
[*]    };  
[*]      
[*]    ws.onopen = function(evt) {  
[*]        alert("open");  
[*]    };  
[*]}  
[*]  
[*]function sendMsg() {  
[*]    ws.send(document.getElementById('writeMsg').value);  
[*]}  
[*]</script>  
[*]</head>  
[*]<body onload="startWebSocket();">  
[*]<input type="text" id="writeMsg"></input>  
[*]<input type="button" value="send" onclick="sendMsg()"></input>  
[*]</body>  
[*]</html>  
页: [1]
查看完整版本: 基于Tomcat的WebSocket