Web Worker позволяет JS иметь возможности многопоточности и может доставлять сложные и трудоемкие операции в потоки Worker для обработки. WebSocket позволяет веб-стороне поддерживать эффективное долгосрочное соединение со стороной сервера, чтобы сторона сервера могла активно передавать данные. Объединив их, можно полностью разделить функцию уведомления о потоке информации бизнес-системы.
Диаграмма архитектуры
JS Worker
Работник, работающий в специальной сфереDedicatedWorkerGlobalScope
, в этой области вы не можете напрямую манипулировать узлами DOM, вы не можете использоватьWindow
Методы и свойства объектов по умолчанию. При этом проблем с доступом в сеть нет.Для получения подробной информации о том, какие объекты и методы можно использовать, нажмите здесь, чтобы просмотреть
Из приведенного выше рисунка ясно видно, что Worker реализует мост слева и справа в текущей архитектуре, соединяя данные на стороне сокета вверху и распределяя данные в сокете внизу. Здесь мы сначала разбираемся с функциональной реализацией самого Worker.
- Основной поток и рабочий поток через метод
postMessage
передавать информацию друг другу - Рабочие потоки и основная нить через события
onmessage
получать сообщения друг от друга - Внедрить сторонний метод использования js в Worker
importScripts([url,])
- вызов основного потока
worker.terminate()
конец нити - Рабочий поток по вызову
this.close()
закончить свою собственную ветку
создать новыйwebworker.js
файл и напишите в нем следующий код
//author:herbert qq:464884492
onmessage = function (event) {
if (event.data.code) {
var code = event.data.code.toLowerCase();
switch (code) {
case "init":
var userId = event.data.loggedUserId;
var sessionId = event.data.sessionid;
if (!sessionId) {
this.close();
return;
}
postMessage({ code: "codeone", msg: "你好,组件1" });
postMessage({ code: "codetwo", msg: "你好,组件2" });
break;
default:
break;
}
}
}
Примечание: нельзя добавить перед onmessagevarиначе вIEВы не сможете получать сообщения. IE - разочаровывающий браузер
Создайте новую страницу index.html и напишите следующий код в блоке script для связи с webworker.js.
//author:herbert qq:464884492
var work = new Worker('webworker.js')
, textone = document.querySelector("#textone")
, textTwo = document.querySelector("#texttwo")
textAll = document.querySelector("#textAll");
work.onmessage = function (event) {
var data = event.data;
if (!!data.code) {
switch (data.code) {
case "close":
work.terminate();
case "codeone":
textone.value = textone.value + JSON.stringify(data) + "\r\n";
textAll.value = textAll.value + JSON.stringify(data) + "\r\n";
break;
case "codetwo":
textTwo.value = textTwo.value + JSON.stringify(data) + "\r\n";
textAll.value = textAll.value + JSON.stringify(data) + "\r\n";
break;
default:
textAll.value = textAll.value + JSON.stringify(data) + "\r\n";
}
}
};
work.postMessage({
code: "init",
loggedUserId: 'demo',
sessionid: 'demo'
});
JS WebSocket
WebSocket, как и Http, основан на протоколе Tcp. Разница в том, что WebSocket реализует полнодуплексную связь между сервером и клиентом. До появления Websocket, если была реализована функция проталкивания информации, то единственным решением реализовать ее через http было обучение ротации. Теперь, когда появился WebSocket, со всем легко справиться.
Далее мы начинаем устанавливать соединение WebSocket
Корень в методе представляет текущую область, которая является root=window в основном потоке и root=DedicatedWorkerGlobalScope в потоке WebWorker.
//author:herbert qq:464884492
var root = this,socket =null;
function connect(wsurl) {
if ('WebSocket' in root) {
socket = new WebSocket(wsurl);
} else if ('MozWebSocket' in root) {
socket = new MozWebSocket(wsurl);
} else {
alert("您的浏览器版本过低,将不能接收系统消息");
}
}
формат wsurlws:\\
илиwss:\\
, последнее означает зашифрованную передачу SSL. Фактические адреса, такие как:ws://localhost:8090/demo/demowebsocket
Далее нам нужно обработать события для сокета, который отвечает за получение сообщений, отправляемых сервером.
//author:herbert qq:464884492
function onOpen() {
postMessage({ code: "openConnect" });
}
function onClose() {
postMessage({ code: "closewsconnect" });
}
function onMessaage(event) {
postMessage(JSON.parse(event.data));
}
function onError(event) {
socket = null;
if (event.target.readyState == 3) {
//断线重连
setTimeout(function () {
connect(event.target.url);
initMessageEvent();
}, 1000);
}
}
function sendMessage(msg) {
if (socket == null) return;
socket.send(msg);
}
function initMessageEvent() {
socket.onopen = onOpen; //socket连接成功处理事件
socket.onclose = onClose; //socket连接关闭处理事件
socket.onmessage = onMessaage; //socket接收到新消息
socket.onerror = onError; //soket错误处理事件
}
JAVA WebSocket
Tomcat7x реализовал стандартный интерфейс WebScoket.В проекте вам нужно только написать общую аннотацию конфигурации компонента управления данными для реализации стандартного API WebSocket. Некоторые аннотации в основном используются в разработке
- @ServerEndpoint устанавливает адрес подключения WebSocket и параметры URL.
Например: @ServerEndpoint(value = "/demowebsocket/{userId}/{sessionId}"), где {userId} и {sessionId}
pathParam
Его можно получить через параметр функции @PathParam в функции onOpen - @PathParam Получить соответствующие параметры аннотации для URL-адреса
- @OnOpen устанавливает аннотацию соединения
- @OnClose закрывает аннотацию соединения
- @OnMessage получает аннотацию сообщения
- Аннотация ошибки @OnError
Функции, ограниченные аннотациями, могут произвольно выбирать необходимые параметры.Необязательными параметрами являются Session, EndpointConfig и @PathParam.Код bean-компонента на стороне сервера выглядит следующим образом.
//author:herbert qq:464884492
@ServerEndpoint(value = "/demowebsocket/{userId}/{sessionId}")
public class DemoWebSokcet {
private static final Set<DemoWebSokcet> connections = new CopyOnWriteArraySet<DemoWebSokcet>();
private Session session;
public DemoWebSokcet() {
}
@OnOpen
public void openConnection(Session session, EndpointConfig conf,
@PathParam("userId") String userId,
@PathParam("sessionId") String sessionId) {
this.session = session;
connections.add(this);
JSONObject jo = new JSONObject();
jo.put("code", "newuser");
jo.put("userid", userId);
jo.put("sessionid", sessionId);
jo.put("msg", "server:新连接用户");
sendMessage(jo);
// 测试 代码
JSONObject jo1 = new JSONObject();
jo1.put("code", "codeone");
jo1.put("userid", userId);
jo1.put("sessionid", sessionId);
jo1.put("msg", "Server:组件1你好");
sendMessage(jo1);
JSONObject jo2 = new JSONObject();
jo2.put("code", "codetwo");
jo2.put("userid", userId);
jo2.put("sessionid", sessionId);
jo2.put("msg", "server:组件2你好");
sendMessage(jo2);
}
@OnClose
public void closeConnection(@PathParam("userId") String userId,
@PathParam("sessionId") String sessionId) {
connections.remove(this);
JSONObject jo = new JSONObject();
jo.put("code", "connectionClose");
jo.put("userid", userId);
jo.put("sessionid", sessionId);
jo.put("msg", "server:连接关闭");
sendMessage(jo);
}
// 处理文本消息
@OnMessage
public void handleTextMsg(Session session, String message,
@PathParam("userId") String userId,
@PathParam("sessionId") String sessionId) {
System.out.println("userId=>" + userId + " sessionId=>" + sessionId);
// 原样转发客户端消息
sendMessage(JSONObject.parseObject(message));
}
// 处理二进制消息
@OnMessage
public void handleBinaryMsg(Session session, ByteBuffer msg,
@PathParam("userId") String userId,
@PathParam("sessionId") String sessionId) {
}
// 处理pong消息
@OnMessage
public void handlePongMsg(Session session, PongMessage msg,
@PathParam("userId") String userId,
@PathParam("sessionId") String sessionId) {
JSONObject jo = new JSONObject();
jo.put("code", "pong");
jo.put("userid", userId);
jo.put("sessionid", sessionId);
jo.put("msg", msg.getApplicationData().toString());
sendMessage(jo);
}
@OnError
public void onError(Throwable t, @PathParam("userId") String userId,
@PathParam("sessionId") String sessionId) throws Throwable {
JSONObject jo = new JSONObject();
jo.put("code", "servererror");
jo.put("userid", userId);
jo.put("sessionid", userId);
jo.put("msg", t.getMessage());
sendMessage(jo);
}
private static void sendMessage(JSONObject msg) {
for (DemoWebSokcet client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote()
.sendText(msg.toJSONString());
}
} catch (IOException e) {
JSONObject jo = new JSONObject();
jo.put("code", "servererror");
jo.put("userid",
client.session.getPathParameters().get("userid"));
jo.put("sessionid",
client.session.getPathParameters().get("sessionid"));
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
}
jo.put("msg", "server:发送消息出现异常,连接已关闭" + e.getMessage());
sendMessage(jo);
}
}
}
}
В процессе написания тестового кода вводится javax.websocket-api через pom, который всегда появляется после запускаError during WebSocket handshake: Unexpected response code: 404
Соединение неправильное.Позже проблема решается путем копирования jar соответствующей реализации tomcat под tomcat/bin непосредственно в папку bin, соответствующую веб-приложению.
Предварительный просмотр демо
Суммировать
Длина относительно длинная, и читать здесь нелегко! WebWorker и WebSocket также впервые сочетаются между собой. Я чувствую, что функции javascript сейчас действительно становятся все богаче и богаче.демонстрационный адрес, и немного инсайта.Чтобы получить новые очки знаний в разработке, во-первых, надо научиться их использовать, а во-вторых, прочитав исходный код и теоретические знания, можно более плавно их использовать, а то и менять.
Друзья, которые любят поболтать о технологиях, также могут присоединиться к группе. Если QR-код не сработает, вы можете добавить меня в WeChat, чтобы ответитьвнешний интерфейс