WebSocket Java Programming入門-1(annotated)
阿新 • • 發佈:2018-12-25
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版本以上才可以2.2、開發環境:(不做強制要求,根據個人的愛好,我只是列舉一下我的開發環境)
Maven:3.0.4 IDE:Intellij IDEA3、第一個基於註解的WebSocket Demo
好了,一切準備就緒,我們來看看下面的程式碼吧,然後我再一一說明其中的一些細節
3.1、 Maven的POM
其中我們引入了javax websocket的標準api介面,並且將其的scope設定成provided(tomcat容器已經自帶了這個包,我們不需要重複釋出,指定為provided的目的就是為了在編寫程式碼的過程中使用而已)。<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>
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);