web消息推送技术

最近在做一个web项目,有个需求是服务器向客户端发送数据,一般来讲,web是请求响应方式是无法做到服务端直接给客户端发送数据的。第一想到的是轮询方法,让客户端不断刷新访问服务器。

这种方法缺点是刷新频率不好控制,设置高了会给服务器造成很大负担,相反,消息得不到及时更新。


目前,我找到两种较优的方法。

1 . comet 技术 ——基于长连接的技术

在传统轮询方法上做的改进。

客户端和服务器保持一个长连接,当服务器向客服端发送消息,才响应数据。这种解决方案,可以说是无奈之举。

参考DWR框架

2. websocket技术 ——基于双向传输技术

html5就提供了这种技术的支持。

我就尝试了第二种方案,结合网友代码在tomcat7.0上做的例子,仅供参考!


index.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 type="text/javascript" src="js/jquery-1.11.2.js"></script>
<script type="text/javascript" src="js/socket.js"></script>

<title>Insert title here</title>
</head>
<body>
   <table>
  <tr>
    <td>Message</td>
    <td><input type="text" id="message"></td>
  </tr>
  <tr>
    <td>Name</td>
    <td><input type="text" id="othername"></td>
  </tr>
  <tr>
    <td><input id="sendbutton" type="button" value="send" onClick="click"  disabled="true">
      </input></td>
  </tr>
</table>


</body>
</html>
js/jsocket.js

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

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

if (!window.WebSocket && window.MozWebSocket)
    window.WebSocket=window.MozWebSocket;
if (!window.WebSocket)
    alert("No Support ");
var ws;

$(document).ready(function(){
    
     $("#sendbutton").attr("disabled", false);
     $("#sendbutton").click(sendMessage);

    startWebSocket();
})

function sendMessage()
{
    var othername=$("#othername").val();
    var msg="MSG\t"+username+"_"+othername+"_"+$("#message").val();
    send(msg);
}
function send(data)
{
    console.log("Send:"+data);
    ws.send(data);
}
function startWebSocket()
{    
    ws = new WebSocket("ws://" + location.host + "/web_socket/websocket/test");
    ws.onopen = function(){
        console.log("success open");
        $("#sendbutton").attr("disabled", false);
    };
     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("\t");
    var msgType=vals[0];
    switch(msgType)
    {
    case "NAME":
        var msg=vals[1];
        var mes="NAME"+"\t"+msg+"_"+ username;
        send(mes);
        break;
    case "MSG":
        var val2s=vals[1].split("_");
        var from=val2s[0];
        var message=val2s[2];
        alert(from+":"+message);
        break;
    default:
        break;
            
    }
}

web.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" 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>web_socket</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>  
      <servlet-name>wsSnake</servlet-name>  
      <servlet-class>cn.eaglestart.websocket.MyWebSocketServlet</servlet-class>  
    </servlet>  
    <servlet-mapping>  
      <servlet-name>wsSnake</servlet-name>  
      <url-pattern>/websocket/test</url-pattern>  
    </servlet-mapping>  
    
    
</web-app>

MyMessageInbound.java

package cn.eaglestart.websocket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.WsOutbound;

public class MyMessageInbound  extends MessageInbound{

	private String username;
	private Set<MyMessageInbound> users = new CopyOnWriteArraySet<MyMessageInbound>();
	
	 public static int USERNUMBER = 1;

	
	public MyMessageInbound(Set<MyMessageInbound> users) {
		super();
		this.users = users;
	}

	@Override
	protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onTextMessage(CharBuffer arg0) throws IOException {
		String data = arg0.toString();
		 System.out.println("data:" + data);
         String[] val1 = data.split("\\t");
         
         if(val1[0].equals("NAME"))
         {
             String[] val2=val1[1].split("_");
             for(MyMessageInbound user:users){
                 if (user.username.equals(val2[0])){
                     user.username=val2[1];
                 }
             }
         }
         else if(val1[0].equals("MSG"))
         {
             String[] val2=val1[1].split("_");
             for(MyMessageInbound user:users){
                 if (user.username.equals(val2[1])){
                     try {
                         CharBuffer temp=CharBuffer.wrap(data);
                         user.getWsOutbound().writeTextMessage(temp);
                     } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
             }        
         }
         else
         {
             System.out.println("ERROR");
         }

     }

	@Override
	protected void onOpen(WsOutbound outbound) {
		// TODO Auto-generated method stub
		  // this.connection=connection;
		
        this.username = "#" + String.valueOf(USERNUMBER);
        System.out.println(username);
        USERNUMBER++;
        try {
            String message = "NAME" + "\t" + this.username;
            CharBuffer buffer = CharBuffer.wrap(message);
            this.getWsOutbound().writeTextMessage(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        users.add(this);

	}
	
	 public void onMessage(String data) {
		 System.out.println("data:" + data);
         String[] val1 = data.split("\\t");
         
         if(val1[0].equals("NAME"))
         {
             String[] val2=val1[1].split("_");
             for(MyMessageInbound user:users){
                 if (user.username.equals(val2[0])){
                     user.username=val2[1];
                 }
             }
         }
         else if(val1[0].equals("MSG"))
         {
             String[] val2=val1[1].split("_");
             for(MyMessageInbound user:users){
                 if (user.username.equals(val2[1])){
                     try {
                         CharBuffer temp=CharBuffer.wrap(data);
                         user.getWsOutbound().writeTextMessage(temp);
                     } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                 }
             }        
         }
         else
         {
             System.out.println("ERROR");
         }

     }
	 @Override
     protected void onClose(int status) {
         users.remove(this);

     }


	
	

}

MyWebSocketServlet.java

package cn.eaglestart.websocket;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;

public class MyWebSocketServlet  extends WebSocketServlet{

	
	 public final Set<MyMessageInbound> users = new CopyOnWriteArraySet<MyMessageInbound>();

	    public static int USERNUMBER = 1;

	@Override
	protected StreamInbound createWebSocketInbound(String arg0,
			HttpServletRequest arg1) {
		System.out.println("=====init====");
		// TODO Auto-generated method stub
		return new MyMessageInbound(users);
	}

}

参考代码链接如下
html5利用websocket完成的推送功能


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值