1、前言
一直没有怎么做过前端的东西,但是最近的项目中,前端人员奇缺,公司又不安排新的人员进入,所以我这个后台开发人员只能拉过来坐前端了,前段的东西感觉一大堆,CSS,js自不必说,HTML生态圈就有很多的技术要去学习,好吧,那就一个一个的学习整理啦,先来说说最近这个项目的前端用到什么技术吧。
1、Restful:DropWizard这个很简单,两天基本上就能拿下
2、Js Framework :AngularJS 这个JS库的确很酷,最近学习的过程中越来越喜欢这个东西了,打算以后再整理一些AngularJS的学习笔记和过程
3、前端和后端的通讯的方式不是那种request和response的方式,而是采用HTML5的WebSocket。
4、其他技术我就不一一列举了
在学习websocket的过程中我阅读了一下tomcat的websocket examples当然最重要的是阅读了一本比较不错的系统化的WEBSOCKET书,推荐给大家《JAVA WEBSOCKET PROGRAMMING》然后我尽力将自己学到的东西,尽可能通俗的详细地介绍一下,方便和大家交流。
2、环境配置
网上关于Websocket是什么的文章多如牛毛,我这里也就不用挨个去摘抄,先直接来一个比较直观的例子,本文中采用的是基于注解的方式,来演示一个Echo Server的实例
2.1、运行环境要求:
Tomcat版本必须在7.0.47版本以上才可以
JDK必须在1.7版本以上才可以
2.2、开发环境:(不做强制要求,根据个人的爱好,我只是列举一下我的开发环境)
Maven:3.0.4
IDE:Intellij IDEA
3、第一个基于注解的WebSocket Demo
好了,一切准备就绪,我们来看看下面的代码吧,然后我再一一说明其中的一些细节
3.1、 Maven的POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <parent> <artifactId>websocket</artifactId> <groupId>websocket</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>websocket-anotation</artifactId> <packaging>war</packaging> <name>websocket-anotation Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>websocket-anotation</finalName> </build> </project>
其中我们引入了javax websocket的标准api接口,并且将其的scope设置成provided(tomcat容器已经自带了这个包,我们不需要重复发布,指定为provided的目的就是为了在编写代码的过程中使用而已)。
3.2、服务段代码:
package com.wangwenjun.websocket.annotation; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint(value = "/hello") public class HelloWorldServer { @OnMessage public String sayHello(String incomingMessage) { return "I got this(" + incomingMessage + ") so I am sending it back to you!"; } @OnOpen public void open(Session session) { System.out.println("On Open---" + session.getBasicRemote()); } @OnClose public void close() { System.out.println("Close."); } }
其实这个例子中只要有一个方法被@OnMessage注解即可,其他的open和close 暂时可以忽略掉,Websocket的方式不仅可以和服务段传递文本信息也可以交互二进制的形式(InputStream),不仅可以返回字符串,也可以返回二进制流(OutputStream),而且还可以得到整个回话的引用如Session,也就意味着我们下面的方法都是合理的
@OnMessage public void test1(String test){ //do nothing. } @OnMessage public void test2(InputStream inputStream){ //do nothing. } @OnMessage public OutputStream test3(InputStream inputStream){ //do nothing. return null; } @OnMessage public void test4(String text,Session session){ //do nothing. }
等等诸如此类吧,都是可行的,好了我们说会刚才那个方法sayHello,该方法接受一个文本字符串,并且返回一个文本字符串,注解为OnMessage,表示它接受来自客户端的信息并且处理之。
3.3、客户端代码
<!DOCTYPE HTML> <html> <head> <title>WebSocket Learning Example(Hello World)</title> <script type="text/javascript"> var ws; function init() { outputArea = document.getElementById("output"); } function sayHello() { var url = "ws://localhost:8080/websocket-anotation/hello"; writeMessageToScreen("Connecting to " + url); ws = new WebSocket(url); ws.onopen = function (event) { writeMessageToScreen("Connected."); var message=document.getElementById("message").value; doSend(message); } ws.onmessage = function (event) { writeMessageToScreen("Received message: " + event.data); ws.close(); } ws.onerror = function (event) { writeMessageToScreen("Occur Error:<span style='color:red'>" + event.data + "</span>"); ws.close(); } } function doSend(message) { ws.send(message); writeMessageToScreen("Sent message: " + message); } function writeMessageToScreen(message) { var p = document.createElement("p"); p.style.wordWrap = "break-word"; p.innerHTML = message; outputArea.appendChild(p); } this.addEventListener("load", init, false); </script> </head> <body> <h1>Hello World Server</h1> <div style="text-align:left"> <form action="#"> <input type="text" id="message" placeholder="Please enter your name."/> <input type="button" id="sender" value="PressMeToSend" onclick="sayHello()"/> </form> </div> <div id="output"> </div> </body> </html>
客户端的代码关于DOM的操作我用的是最元生的处理方式,并没有采用Jquery等对Dom支持特别好的第三方库,想必大家都能看得明白,我就不做更多的解释了,关键来说说WebSocket对象,websocket对象在JS宿主(浏览器)中并不是都被支持,IE就从第十个版本才开始支持的,如果你做的是一个互联网应用,没有办法强制让客户试用统一支持websocket对象的浏览器,你最好能够判断一下js环境是否支持websocket的对象,判断的方法也是非常简单,如下的几种方式都可以
//method 1 if(window.WebSocket){ } //method 2 if("WebSocket" in window) { } //method 3 if(window["WebSocket"]){ }
好了,我们来说一下上面JS代码中的几个关键部分吧
var url = "ws://localhost:8080/websocket-anotation/hello";
定义了Websocket ServerEndpoint的地址,记住协议是WS哦,不要像我一样第一次学习的习惯性的用http,最后的那个URI/hello是我们在我们的HelloWorldServer中用@ServerEnmdpoint注解的Value值,应该不难理解吧。
ws = new WebSocket(url);
创建一个WebSocket的对象,如果能够创建成功就可以使用我们的WebSocket了,不过更加严谨的做法应该是像我在前面所说的那样应该判断JS宿主环境是否支持WebSocket,否则下面的代码都会出现错误的。
WebSocket最美的地方有很多回调函数在里面,当发生相关的事情会被自动调用,如下面的代码就是注册相关的回调函数
ws.onopen = function (event) { writeMessageToScreen("Connected."); var message=document.getElementById("message").value; doSend(message); } ws.onmessage = function (event) { writeMessageToScreen("Received message: " + event.data); ws.close(); } ws.onerror = function (event) { writeMessageToScreen("Occur Error:<span style='color:red'>" + event.data + "</span>"); ws.close(); }
第一个当成功连接之后会被调用,第二个是收到了来自ServerEndpoint的消息之后的回调,第三个是发生了错误会被回调,怎么样很爽吧。
最后一个比较关键的方法就是发送消息到服务端,但是不得不承认真的很简单,简单到就一行
ws.send(message);
4、发布
就这么简单,寥寥几行代码就可以实现一个最基本的客户端与服务端通讯的小程序,写到这里我们应该发布一下,看看运新多个效果如何,运行
mvn clean package命令,将web项目打包成一个war包 ,然后拷贝到你的tomcat webapps目录下面,当然你也可以安装tomcat自动部署插件,运行命令即可自动将war包发布到webapps下面去,感兴趣的可以自己尝试,我在这里就不做演示了,然后访问页面:http://localhost:8080/websocket-anotation/ 自己玩一把吧。
5、简单总结
Http是一个非持续连接协议,也就是说每一次的和服务器交互都是一个新的连接,我们可以理解为一个基于TCP的短连接协议,但是Websocket的出现,给Web开发人员多了一个长连接的选择,我们可以和服务端始终保持回话,并且接受来自服务端的信息,在互联网中,基于Websocket的应用越来越多了,学习掌握是很有必要的,在接下来还会继续进行更新,再说一遍《JAVA WEBSOCKET PROGRAMMING》这本书真的很好,而且只有两百多页,看完之后加以练习,相信你会精通WebSocket的使用的。