WebSocket集成XMPP网页即时通讯1:Java Web Project服务端/客户端Jetty9开发初探
Web 应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说,比如说在线游戏、在线证券、设备监控、新闻在线播报、RSS 订阅推送等等,当客户端浏览器准备呈现这些信息的时候,这些信息在服务器端可能已经过时了。所以保持客户端和服务器端的信息同步是实时 Web 应用的关键要素,对 Web 开发人员来说也是一个难题。在 WebSocket 规范出来之前,开发人员想实现这些实时的 Web 应用,不得不采用一些折衷的方案,其中最常用的就是轮询 (Polling) 和 Comet 技术(AJAX)。
但AJAX有显著缺点:
1、浏览器需要不断的向服务器发出请求,然而HTTP request 的header是非常长的,里面包含的有用数据可能只是一个很小的值,这样会占用很多的带宽。
2、客户端和服务器端的编程实现都比较复杂,在实际的应用中,为了模拟比较真实的实时效果,开发人员往往需要构造两个 HTTP 连接来模拟客户端和服务器之间的双向通讯,一个连接用来处理客户端到服务器端的数据传输,一个连接用来处理服务器端到客户端的数据传输。
WebSocket API是下一代客户端-服务器的异步通信方法。该通信取代了单个的TCP套接字,使用ws或wss(ssl加密)协议,可用于任意的客户端和服务器程序。WebSocket目前由W3C进行标准化。WebSocket已经受到Firefox 4、Chrome 4、Opera 10.70、Edge以及Safari 5等浏览器的支持。
WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内(IdleTime)的任意时刻,相互推送信息。WebSocket并不限于以Ajax(或XHR)方式通信,因为Ajax技术需要客户端发起请求,而WebSocket服务器和客户端可以彼此相互推送信息;XHR受到域的限制,而WebSocket允许跨域通信。
为方便开发,用了Jetty服务器,在网上很多例子都是基于jetty7.0的。但jetty9.0以后WebSocket的基类代码变化很多,于是自己动手开发,参考jetty官网:
http://www.eclipse.org/jetty/documentation/current/websocket-jetty.html#jetty-websocket-api
首先在Eclipse新建一个Dynamic web project
请自行下载安装jetty,另外需要在Eclipse安装Jetty工具,便于调试。

工程目录结构:

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"> <context-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</context-param> <session-config> <!-- 10 minutes -->
<session-timeout>10</session-timeout>
</session-config> <servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/wsexample</url-pattern>
</servlet-mapping> <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> </web-app>
ant用惯了,懒得去查maven的dependencies了。
build.xml
jetty.lib.dir、deploy.path请自行修改
<?xml version="1.0" encoding="UTF-8"?>
<project name="WebSocket" default="compile">
<property name="name" value="ws"/>
<property environment="env"/>
<property name="src.dir" value="src"/>
<property name="web.dir" value="WebContent" />
<property name="build.dir" location="${web.dir}/WEB-INF/classes"/>
<property name="jetty.lib.dir" location="D:/Software/jetty93/lib"/>
<property name="dist.dir" location="dist"/>
<property name="deploy.path" location="D:/Software/jetty93/webapps"/>
<path id="compile.classpath">
<fileset dir="${jetty.lib.dir}"/>
</path>
<target name="init">
<mkdir dir="${build.dir}"/>
<mkdir dir="${dist.dir}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src.dir}" destdir="${build.dir}"
includeantruntime="false">
<classpath refid="compile.classpath"/>
</javac>
<echo>Compilation completed</echo>
</target>
<target name="archive" depends="compile">
<war destfile="${dist.dir}/${name}.war" needxmlfile="false">
<fileset dir="${web.dir}"/>
</war>
<echo>Archive created</echo>
</target>
<target name="clean" depends="init">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
<echo>Cleaning completed</echo>
</target>
<target name="deploy" depends="archive">
<copy file="${dist.dir}/${name}.war" overwrite="true"
todir="${deploy.path}"/>
<echo>Archive deployed</echo>
</target>
</project>
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>你好!websocket</title>
</head>
<body>
hello,WebSocket
<script src="index.js"></script>
</body>
</html>
index.js
var ws = new WebSocket("ws://localhost:8080/ws/wsexample");
ws.onopen = function() {
document.write("WebSocket opened <br>");
ws.send("Hello Server");
};
ws.onmessage = function(evt) {
document.write("Message: " + evt.data);
};
ws.onclose = function() {
document.write("<br>WebSocket closed");
};
ws.onerror = function(err) {
document.write("Error: " + err);
};
其中 ws://localhost:8080/ws/wsexample 是WebSocket 服务器地址,是服务器端的Servelt,通过MyServlet.java实现
WebSocketServlet 类中 configure(WebSocketServletFactory factory) 用来注册socket处理类和设置连接时长,在这个时长内,保持长连接。
官网的定义:
http://www.eclipse.org/jetty/documentation/current/jetty-websocket-server-api.html
MyServlet.java
暂不理会HTTP GET请求的处理.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; @WebServlet(name = "MyServlet", urlPatterns = { "/wsexample" })
public class MyServlet extends WebSocketServlet { private static final long serialVersionUID = 1L; @Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("HTTP GET method not implemented.");
} @Override
public void configure(WebSocketServletFactory factory) {
factory.getPolicy().setIdleTimeout(10000);
factory.register(MySocket.class);
}
}
MySocket.java 是socket具体处理类,写法在jetty7和jetty9有很大的不同。
import java.io.IOException;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket; @WebSocket
public class MySocket { Session WebSession;
@OnWebSocketClose
public void onClose(int statusCode, String reason) {
System.out.println("Close: " + reason);
} @OnWebSocketError
public void onError(Throwable t) {
System.out.println("Error: " + t.getMessage());
} //客户端连接
@OnWebSocketConnect
public void onConnect(Session session) {
WebSession = session;
System.out.println("Connect: " + session.getRemoteAddress().getAddress()); try {
session.getRemote().sendString("你好!客户端。我是服务端。<br>");
} catch (IOException e) {
System.out.println("IO Exception");
}
} //接收到客户端的文本消息
@OnWebSocketMessage
public void onMessage(String message) {
System.out.println("客户端消息: " + message);
try {
WebSession.getRemote().sendString("客户端,我收到这条消息了:" + message);
} catch (IOException e) {
System.out.println("IO Exception");
}
}
}
测试一下吧

客户端运行结果:

完整源代码下载 : source code
WebSocket集成XMPP网页即时通讯1:Java Web Project服务端/客户端Jetty9开发初探的更多相关文章
- WebSocket集成XMPP网页即时通讯3:二进制文件收发
WebSocket支持二进制的发送,见jetty官网: http://www.eclipse.org/jetty/documentation/current/jetty-websocket-api-s ...
- Java Tomcat SSL 服务端/客户端双向认证
借花献佛:http://www.blogjava.net/icewee/archive/2012/06/04/379947.html
- Android基于XMPP的即时通讯3-表情发送
这篇博文主要讲表情发送的一些东西. 参考:Android基于XMPP的即时通讯1-基本对话 1.准备好资源文件 采用的是emoji的表情,我打包好了,下载地址:http://files.cnblogs ...
- Android基于XMPP的即时通讯2-文件传输
本文是在上一篇博文Android基于XMPP的即时通讯1-基本对话的基础上,添加新的功能,文件传输 1.初始化文件传输管理类 public static FileTransferManager get ...
- JAVA WEBSERVICE服务端&客户端的配置及调用(基于JDK)
前言:我之前是从事C#开发的,因公司项目目前转战JAVA&ANDROID开发,由于对JAVA的各种不了解,遇到的也是重重困难.目前在做WEBSERVICE提供数据支持,看了网上相关大片的资料也 ...
- 如何实现从Java入门到服务端项目开发的进阶?
对于打算入门或者刚刚入门学习Java的人来说,刚开始接触这门学科,往往会觉得不知所措,也会觉得很迷茫.结合前人经验,就从入门到进阶对于Java的学习而言,应该对于学习时间.目标和内容规划有一个清晰的定 ...
- [转载]Java创建WebService服务及客户端实现
Java创建WebService服务及客户端实现 Java创建WebService服务及客户端实现
- Java实现:服务端登录系统并跳转到系统内的指定页面(不调用浏览器)
Java实现:服务端登录系统并跳转到系统内的指定页面(不调用浏览器) 1,思路:根据爬虫思想: 2,代码: /** * ClassName:AuthFr * Function: TODO * Reas ...
- gprc-java与golang分别实现服务端,客户端,跨语言通信(一.java实现)
1.在pom中引入 <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty< ...
随机推荐
- 【转】Centos 7 修改主机名hostname
在CentOS中,有三种定义的主机名:静态的(static),瞬态的(transient),和灵活的(pretty).“静态”主机名也称为内核主机名,是系统在启动时从/etc/hostname自动初始 ...
- poj-2777(区间线段树,求种类数模板)
题目链接:http://poj.org/problem?id=2777 参考文章:https://blog.csdn.net/heucodesong/article/details/81038360 ...
- n维向量空间W中有子空间U,V,如果dim(U)=r dim(V)=n-r U交V !={0},那么U,V的任意2组基向量的组合必定线性相关
如题取U交V中的向量p (p!=0), 那么p可以由 U中的某一组基线性组合成(系数不全是零),同时,-p也可以由V中的某一组基线性组合成(系数不全为零) 考察p+(-p)=0 可知道,U中的这组基跟 ...
- VC调试小结
本机调试F5: 开始调试Shift+F5: 停止调试F10: 调试到下一句,这里是单步跟踪 F11: 调试到下一句,跟进函数内部Shift+F11: 从当前函数中跳出F9: 设置(取消)断点Outpu ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记七之铭文升级版
铭文一级: 第五章:实战环境搭建 Spark源码编译命令:./dev/make-distribution.sh \--name 2.6.0-cdh5.7.0 \--tgz \-Pyarn -Phado ...
- (转)php语法(符号用法)
转自:http://blog.unvs.cn/archives/php-equal-bracket.html 学习PHP过程中,会常碰到一些特殊的符号,比如:=.==.===.->.=>. ...
- 第75讲:模式匹配下的For循环
今天学习了模式匹配下的for循环内容.让我们从代码实战角度出发. for(i<-List(1,2,3,4,5)) println(i)//实际上调用的是foreach for(in ...
- python_条件语句
条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. Python程序语言指定任何非0和非空(null)值为true,0 或者 null为fals ...
- brctl命令
有五台主机.其中一台主机装有linux ,安装了网桥模块,而且有四块物理网卡,分别连接同一网段的其他主机.我们希望其成为一个网桥,为其他四台主机(IP分别为192.168.1.2 ,192.168.1 ...
- 6.python3爬虫之urllib库
# 导入urllib.request import urllib.request # 向指定的url发送请求,并返回服务器响应的类文件对象 response = urllib.request.urlo ...