WildFly上具有AngularJS的Java EE 7和Java WebSocket API(JSR 356)

这篇博客文章描述了用于WebSocket协议Java API(JSR 356) (这是Java EE 7平台的四个最新JSR之一),并提供了部署在WildFly 8上并可以在OpenShift上在线获得的具体应用程序。

  • [FR]版本的法语( HTML或PDF )在AngularJS上发布了基于Java API的示范性演示。

阅读这篇文章后,您将能够了解Arun Gupta对WebSocket技术可以做什么的定义。

“ WebSocket通过单个TCP为您提供双向的全双工通信通道。”
— Arun Gupta(Java EE布道士Chez Oracle)–英国Devoxx 2013

Java EE 7概述

Java平台企业版20136月在版本7(Java EE 7)中发布。 与先前的两个版本(Java EE 5和Java EE 6)保持一致, Java EE 7始终建议简化开发人员的工作。 此版本用3个主要目标装饰了以前的版本:

  • 包含HTML5 (WebSocket API,JSON-P API,JAX-RS)
  • 为开发人员(JMS)提供更高的生产率
  • 满足企业需求 (批处理API,并发实用程序)
图1. Java EE 7的三个目标

图1. Java EE 7的三个目标

Java平台企业版7(JSR 342)可以总结为:

  • 4个最新规范: Java API for WebSocket 1.0 Java API for JSON Processing 1.0Batch Applications 1.0Concurrency Utilities for Java EE 1.0
  • 3个主要更新的规范: JMS 2.0JAX-RS 2.0EL 3.0
  • 和6个规范(进行了较小的更新): JPA 2.1Servlet 3.1EJB 3.2CDI 1.1JSF 2.2Bean Validation 1.1

演示:AngularJS –在WildFly 8(OpenShift)上部署HTML5 / JSR-356 API应用程序

如果要立即查看它的外观,可以访问the online application其代码将在本文中进行部分说明。 这个应用程序可以为您提供以下功能:

  • 观看(四分之一决赛美国公开赛2013年)在现场模式的一个或几个网球比赛
    • 点击您要实时访问的每个比赛
  • 下注比赛的获胜者
    • 每当用户下注相同的比赛时,计数器就会增加

您会说: “没什么特别的!” ,而您是对的:)

乍一看,这听起来像是当今许多应用程序中已经看到的东西,但是它所使用的技术确实很重要,因为,正如您将在下面看到的那样,所有内容都基于新的WebSocket协议(ws:// ou)标准。 wss://),而不是在“ HTTP hacking”上。

用于开发此应用程序的技术是:

  • 前端: HTML5CSS ,带有Bootstrap CSS和AngularJS Javascript (WebSocket API)
  • 后端: Java API for WebSocketEJBJSON-PJAX-RS
图2.美国开放应用程序-WebSocket的实现(Java API和Javascript API)

图2.美国开放应用程序– WebSocket的实现(Java API和Javascript API)

不! 该演示不是聊天应用程序:)很明显,“聊天演示”是首先想到的用于说明WebSocket技术使用的示例。 但是,还有许多其他用例,例如在线文本文档上的协作工作或JavaOne 2013主题演讲中展示的象棋这样的在线游戏。

借助RedHat的云计算PaaS产品OpenShift ,该应用程序可在云上使用。 它已部署在WildFly 8.0.0-Beta1(正常认证的Java EE 7到2013年底)上。 要在OpenShit上设置WildFly之类的应用服务器,您只需阅读Shekhar Gulati的博客文章

WebSocket(WS):不同于HTTP的新协议

HTTP是Web的标准协议,它在许多用例中非常有效,但是在交互式Web应用程序中却有一些缺点

  • 半双工 :基于请求/响应模式,客户端发送请求,服务器在发送响应之前执行处理,客户端被迫等待服务器响应
  • 详细 :在HTTP请求和HTTP响应中,与消息相关的HTTP标头中发送了大量信息
  • 为了添加服务器推送模式,您需要使用解决方法(轮询,长轮询,Comet / Ajax),因为没有标准

该协议并未针对在实时双向通信方面有重大需求的大型应用进行优化。 这就是为什么新的WebSocket协议比HTTP提供更多高级功能的原因,因为它是:

  • 基于1 unique TCP connection between 2 peers (而每个HTTP请求/响应都需要一个新的TCP连接)
  • bidirectionnal :客户端可以向服务器发送消息,服务器也可以向客户端发送消息
  • full-duplex :客户端可以将多个消息发送到服务器,也可以将服务器发送到客户端,而无需等待彼此的响应

术语“ 客户端”仅用于定义启动连接的客户端 建立连接后,客户端和服务器将成为具有相同容量的对等端。

WebSocket协议原本打算成为HTML5规范的一部分,但是随着HTML5将于2014年正式发布,WebSocket协议以及HTTP协议最终都由IETF规范和RFC 6455设置 。

如下图所示, WebSocket协议在两个阶段起作用

  1. handshake (打开和关闭)
  2. data transfer
图3. WebSocket协议如何工作

图3. WebSocket协议如何工作

开幕握手

打开握手阶段是发起连接的一个请求 (对等客户端)和对等服务器之间的唯一HTTP请求/响应 。 此HTTP交换是特定的,因为它使用HTTP规范中定义升级概念。 原理很简单: 升级HTTP允许客户端要求服务器更改通信协议,从而确保客户端和服务器可以使用HTTP以外的协议进行讨论。

例子1. HTTP握手示例请求

GET /usopen/matches/1234 HTTP/1.1     
Host: wildfly-mgreau.rhcloud.com:8000  
Upgrade: websocket  
Connection: Upgrade
Origin: http://wildfly-mgreau.rhcloud.com
Sec-WebSocket-Key:0EK7XmpTZL341oOh7x1cDw==
Sec-WebSocket-Version:13

第1行:需要HTTP GET方法和HTTP 1.1版本
第2行:用于WebSocket连接的主机
第3行:请求升级到WebSocket协议 第4行:请求从HTTP升级到另一个协议

例子2. HTTP握手响应样本

HTTP/1.1 101 Switching Protocols 
Connection:Upgrade
Sec-WebSocket-Accept:SuQ5/hh0kStSr6oIzDG6gRfTx2I=
Upgrade:websocket

第1行:HTTP响应代码101:服务器兼容并接受通过其他协议发送消息
第4行:接受升级到WebSocket协议

当端点服务器批准了从HTTP到WebSocket协议的升级请求时,就不再可以使用HTTP通信,所有交换都必须通过WebSocket协议进行。

数据传输

一旦握手被批准,就可以使用WebSocket协议。 在对等服务器端以及对等客户端端都有一个开放的连接,调用回调处理程序以启动通信。

现在可以开始数据传输 ,因此两个对等方可以双向和全双工通信方式交换消息。

如图3所示 ,对peer server可以发送多条消息( 在此示例中:每个得分点1条消息,每次用户在此游戏下注时每条消息1条,比赛结束时每条消息1条消息 ),而无需发送任何消息peer client响应,对等客户端也可以随时发送消息( 在此示例中:押注比赛获胜者 )。 每个对等方都可以发送特定的消息以关闭连接。

使用Java EE7平台,对peer server side代码是用Java编写的,而对peer client side代码是用Java或Javascript编写的。

关闭握手

这个阶段可以由双方发起 。 想要关闭通信的对等方需要发送一个关闭控制帧,并且它也会收到一个关闭控制帧作为响应。

WebSocket Javascript API(客户端)

要使用WebSocket协议从Web应用程序与服务器进行通信,必须使用客户端Javascript API 。 定义此API是W3C的角色。 JavaScript WebSocket API的W3C规范正在最终确定。 WebSocket接口提供以下功能:

  • 一个属性,用于定义到服务器端点的连接URL( url
  • 知道连接状态的属性( readyState :CONNECTING,OPEN,CLOSING,CLOSED)
  • 与WebSocket生命周期有关的一些事件处理程序 ,例如:
    • 当新连接打开时,将调用事件处理程序onopen
  • 可以将不同类型的流(文本,二进制)发送到端点服务器的方法( send(DOMString data)send(Blob data)

例子3.来自http://websocket.org的 JavaScript源代码例子

var wsUri = "ws://echo.websocket.org/";function testWebSocket() {websocket = new WebSocket(wsUri);websocket.onopen = function(evt) { onOpen(evt) };websocket.onclose = function(evt) { onClose(evt) };websocket.onmessage = function(evt) { onMessage(evt) };websocket.onerror = function(evt) { onError(evt) }; }
}function onOpen(evt) {writeToScreen("CONNECTED");doSend("WebSocket rocks");
}
function onClose(evt) {writeToScreen("DISCONNECTED");
}
function onMessage(evt) {writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');websocket.close();
}function onError(evt) {writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message) {writeToScreen("SENT: " + message);websocket.send(message);
}

JSR 386:用于WebSocket协议的Java API

由于W3C定义了如何在Javascript中使用WebSocket,因此Java Communitee Process(JCP)通过JSR 386在Java世界中进行了相同的操作。JSR356 为WebSocket协议定义了Java API,该协议是Java EE Web Profile的一部分,并提供了有能力 :

  • 创建一个WebSocket Endpoint (服务器或客户端),该名称是可以通过WebSocket协议进行通信的Java组件的名称
  • 注释或程序化方法的选择
  • 通过此协议发送和使用消息控件,文本或二进制
    • 将消息作为完整消息或部分消息序列进行管理
  • 配置和管理WebSocket会话 (超时,Cookie…)

开源JSR-356 RI(参考实现)是Tyrus项目

WebSocket服务器端点

将普通旧Java对象(PO​​JO)转换为服务器WebSocket端点 (即能够处理来自同一URI的不同客户的请求) 非常容易,因为您只需用@ServerEndpoint注释Java类,并用@注释一种方法即可。 OnMessage

import javax.websocket.OnMessage;
import javax.websocket.ServerEndpoint;@ServerEndpoint("/echo") 
public class EchoServer {@OnMessage public String handleMessage(String message){return "Thanks for the message: " + message;}}

第04行:@ServerEndpoint将此POJO转换为WebSocket端点,为将访问URI设置为此端点,必须使用value属性
第07行:将为每个收到的消息调用handleMessage方法

注解

此Java API提供了几种与WebSocket协议完全兼容的注释:

注解 角色
@ServerEndpoint 声明服务器端点
@ClientEndpoint 声明客户端端点
@OnOpen 声明此方法处理打开事件
@OnMessage 声明此方法处理Websocket消息
@OnError 声明此方法处理错误
@OnClose 声明此方法处理WebSocket关闭事件

@ServerEndpoint属性在下面列出:

    • 相对URI或模板URI(例如:“ / echo”,“ / matches / {match-id}”)
  • 解码器
    • 消息解码器类名列表
  • 编码器
    • 消息编码器类名列表
  • 子协议
    • 支持的子协议的名称列表(例如:http://wamp.ws)

编码器和解码器

如本文前面所述,端点服务器可以接收消息中不同类型的内容:文本格式(JSON,XML…)或二进制格式的数据。

为了有效地管理来自对等客户端或应用程序业务代码中的对等客户端的消息,可以创建Encoders和Decoders Java类。

无论采用哪种转换算法,都可以进行转换:

  • 业务POJO以所需的通信格式(JSON,XML,Binary…)流动
  • 以特定格式(JSON,XML ..)流入业务POJO

因此,应用程序代码的结构使得业务逻辑不受对等服务器对等客户端流之间交换的消息的类型和格式的影响。

本文后面将提供一个具体示例。

WebSocket客户端端点

该Java API还提供了对创建客户端Java端点的支持。

例子4. Java客户端端点样本

@ClientEndpoint
public class HelloClient {@OnMessagepublic String message(String message){// code}
}WebSocketContainer c = ContainerProvider.getWebSocketContainer();
c.connectToServer(HelloClient.class, "hello");

美国公开赛

该示例应用程序被部署为使用Apache Maven构建的WAR结果。 除了传统的管理WebSocket生命周期,发送消息的工作流程还如下:

  • 每个对等客户端可以连接1或4个实时比赛
  • 每个对等客户端都可以断开匹配
  • 在比赛的每个点,连接到该比赛的客户端将接收数据(得分,服务…)
  • 等客户可能会发送一条消息,押注比赛的获胜者
  • 每次一个对等客户下注一场比赛,所有其他在相同比赛中下注的对等客户都会收到一条消息,其中包含投注者总数
  • 在比赛结束时, 对等客户押注这场比赛,会收到一条消息,其中包含获胜者的姓名和一条特定消息

所有消息均以JSON格式交换

项目布局如下:

例子5. Maven项目结构

+ src/main/java|+ com.mgreau.wildfly.websocket|+ decoders|- MessageDecoder.java   |+ encoders       |- BetMessageEncoder.java|- MatchMessageEncoder.java|+ messages       |- BetMessage.java|- MatchMessage.java|- Message.java|+ rest       |- RestApplication.java|- TournamentREST.java|- MatchEndpoint.java    |- StarterService.java   |- TennisMatch.java      
+ src/main/resources
+ scr/main/webapp|+ css|+ images|+ js|+ live    |- app.js|- controllers.js|- directives.js|- services.js|- websocket.js  |+ templates|- bet.html|- match.html|- msg.html|- index.html|- live.html
pom.xml

第04行:解码从对等客户端 (关于获胜者的赌注)发送到POJO( BetMessage )的JSON消息
第05行:以JSON格式编码(通过JSON-P),有关获胜者的所有消息以及对等客户端的比赛详细信息
第08行:POJO处理对等体之间发送的消息 第12行:REST端点,列出所有比赛的比赛 第15行:应用程序WebSocket服务器端点( 对等服务器 ) 第16行:EJB @Startup,以便在部署时初始化此应用程序 第17行:POJO处理有关比赛的信息 第23行:AngularJS文件通过REST和WebSocket调用处理多个匹配项(live.html) 第28行:包含用于WebSocket协议的Javascript API实现的文件,用于处理简单情况下的客户端通信(index.html)

Java EE 7 API的Maven依赖关系

例子6.带有Java EE 7依赖关系的pom.xml

<project>
...
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- Java EE 7 --><javaee.api.version>7.0</javaee.api.version>
</properties<dependencies><dependency><groupId>javax</groupId> <artifactId>javaee-api</artifactId><version>${javaee.api.version}</version><scope>provided</scope></dependency>
</dependencies>
...
</project>

第11行:使用Java EE 7依赖关系以便能够在多个Java EE应用程序服务器(WildFly,Glassfish…)中部署同一应用程序而无需更改代码,这一点很重要

添加服务器端点

该端点可以接收有关下注比赛获胜者的消息(由match-id标识),并且还可以向对等客户端发送有关比赛过程和下注的所有信息。

例子7.服务器端点:MatchEndpoint.java

@ServerEndpoint(value = "/matches/{match-id}",  decoders = { MessageDecoder.class }, encoders = { MatchMessageEncoder.class, BetMessageEncoder.class } )
public class MatchEndpoint {private static final Logger logger = Logger.getLogger("MatchEndpoint");/** All open WebSocket sessions */static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());/** Handle number of bets by match */static Map<String, AtomicInteger> nbBetsByMatch = new ConcurrentHashMap<>();@Inject StarterService ejbService;@OnOpenpublic void openConnection(Session session,@PathParam("match-id") String matchId) { session.getUserProperties().put(matchId, true);peers.add(session);//Send live result for this matchsend(new MatchMessage(ejbService.getMatches().get(matchId)), matchId);}public static void send(MatchMessage msg, String matchId) {try {/* Send updates to all open WebSocket sessions for this match */for (Session session : queue) {if (Boolean.TRUE.equals(session.getUserProperties().get(matchId))){if (session.isOpen()){session.getBasicRemote().sendObject(msg);        }}}} catch (IOException | EncodeException e) {logger.log(Level.INFO, e.toString());}}public static void sendBetMessage(Session session, BetMessage betMsg, String matchId){try {betMsg.setNbBets(nbBetsByMatch.get(matchId).get());session.getBasicRemote().sendObject(betMsg);logger.log(Level.INFO, "BetMsg Sent: {0}", betMsg.toString());} catch (IOException | EncodeException e) {logger.log(Level.SEVERE, e.toString());}}@OnMessagepublic void message(final Session session, BetMessage msg,    @PathParam("match-id") String matchId) {session.getUserProperties().put("bet", msg.getWinner());//Send betMsg with bet countif (!nbBetsByMatch.containsKey(matchId)){nbBetsByMatch.put(matchId, new AtomicInteger());}nbBetsByMatch.get(matchId).incrementAndGet();sendBetMessages(null, matchId, false);}@OnClosepublic void closedConnection(Session session,@PathParam("match-id") String matchId) {if (session.getUserProperties().containsKey("bet")){nbBetsByMatch.get(matchId).decrementAndGet();sendBetMessages(null, matchId, false);}/* Remove this connection from the queue */peers.remove(session);}
...
}

第02行:由于应用程序上下文根为/ usopen ,因此访问此端点的URI的最终URL如下所示: ws://<host>:<port>/usopen/matches/1234
第03行: MessageDecoder将传入的JSON流(约等于赢家的赌注)转换为POJO BetMessage
第4行:这2个编码器增加了将MatchMessage POJO和BetMessage POJO转换为JSON格式消息的功能 第20行: @PathParam批注允许提取WebSocket请求的一部分并将值(id匹配)作为方法的参数传递,对于每个匹配,可以管理多个客户端进行的多个匹配。 第34行:向连接的对等方发送有关比赛过程的消息。 多亏了MatchMessageEncoder对象,只需传递MatchMessage对象即可。 第55行:由于使用了MessageDecoder对象,因此可以处理接收到的有关赢家押注的消息 ,该方法的参数之一是BetMessage对象。

编码和解码消息

要对同位体之间交换的消息进行编码或解码,只需根据消息类型(文本,二进制)和处理方向(编码,解码)实现适当的接口,然后重新定义关联的方法。

在下面的示例中,它是MatchMessage POJO到JSON格式的编码器 。 用于执行此处理的API也是Java EE 7发行的新API: 用于JSON Processiong(JSON-P)的Java API

例子8.文本编码器:MatchMessageEncoder.java

public class MatchMessageEncoder implements Encoder.Text<MatchMessage> {@Overridepublic String encode(MatchMessage m) throws EncodeException {StringWriter swriter = new StringWriter();try (JsonWriter jsonWrite = Json.createWriter(swriter)) {JsonObjectBuilder builder = Json.createObjectBuilder();builder.add("match",Json.createObjectBuilder().add("serve", m.getMatch().getServe()).add("title", m.getMatch().getTitle())...}jsonWrite.writeObject(builder.build());}return swriter.toString();}
}

HTML5 Web客户端(单个匹配– index.html)

此应用程序的index.html页面加载websocket.js文件以实现Javascript WebSocket API,从而与Java Server Endpoint进行交互。 此页面仅处理一次匹配。

例子9.在websocket.js中实现的API Javascript

var wsUrl;
if (window.location.protocol == 'https:') {  wsUrl = 'wss://' + window.location.host + ':8443/usopen/matches/1234';
} else {wsUrl = 'ws://' + window.location.host + ':8000/usopen/matches/1234';
}function createWebSocket(host) {if (!window.WebSocket) {    ...} else {socket = new WebSocket(host);   socket.onopen = function() {document.getElementById("m1-status").innerHTML = 'CONNECTED...';};socket.onclose = function() {document.getElementById("m1-status").innerHTML = 'FINISHED';};...socket.onmessage = function(msg) {try {console.log(data);var obj = JSON.parse(msg.data);     if (obj.hasOwnProperty("match")){   //titlem1title.innerHTML = obj.match.title;// commentsm1comments.value = obj.match.comments;// serveif (obj.match.serve === "player1") {m1p1serve.innerHTML = "S";m1p2serve.innerHTML = "";} else {m1p1serve.innerHTML = "";m1p2serve.innerHTML = "S";}..}...} catch (exception) {data = msg.data;console.log(data);}}}
}

第02行:根据当前使用的HTTP协议(是否安全)选择适当的WebSocket协议
第09行:检查浏览器是否支持WebSocket API
第12行:创建WebSocket对象 第23行:尝试将对等服务器发送的JSON消息解析为onmessage Event Handler调用的函数 第24行:检查接收到的对象类型(MatchMessage或BetMessage)以对DOM进行适当处理

要了解哪些浏览器与WebSocket API兼容, 请访问网站caniuse.com 。 如今,除了Android和Opera Mini浏览器外,所有最新版本的浏览器都兼容,二者仅占Web流量的3%。

AngularJS客户端(几个匹配项– live.html)

正如我们在本文开头所看到的,用于处理多次匹配的版本是在客户端使用AngularJS开发的。 因此,有4个JS文件包含:

  • app.js :仅定义TennisApp角度应用程序
  • controllers.js :TournamentCtrl控制器
  • directives.js
    • bet指令和bet.html模板以显示投注者数量和当前投注
  • services.js
    • WebSocketService:通过回调处理WebSocket生命周期

这篇文章不是有关AngularJS的教程,因为这是我第一个使用此框架的应用程序。 但这是在客户端处理多个匹配项的快速解决方案。 您可以阅读以下3篇文章,以更好地理解JS代码: 法语的 指令以及AngularJS 指令的重构和AngularJS WebSocket服务示例

Github上的源代码

您可以在https://github.com/mgreau/javaee7-websocket Github分叉此项目

该示例应用程序是基本的,可能会有很多改进,例如在其他条件上下注...

从技术上讲,一个有趣的功能是根据每个获胜点的坐标创建一种新的下注类型。 只需通过HTML5 Canvas API绘制背景并管理用户选择的坐标(例如获胜点),然后与获胜者的实际坐标进行比较即可。

构建和部署WAR

先决条件:

  • JDK 7
  • Apache Maven 3.0.4以上
  • Java EE 7应用服务器(WildFly 8)

为了构建WAR,您只需执行以下Maven命令即可;

mvn clean package

如果您的应用服务器是WildFly,则可以使用以下命令快速部署WAR(必须启动WildFly):

mvn jboss-as:deploy

然后可以在以下位置找到usopen应用程序:

  • http:// localhost:8080 / usopen /仅使用本机Javascript的简单情况
  • http:// localhost:8080 / usopen / matches用于具有多次匹配和AngularJS的版本

WildFly 8使用其Web Server called UndertowWeb Server called Undertow来代替Tomcat。

我没有在Glassfish 4上测试此应用程序,但是由于我仅使用Java EE 7 API依赖项,因此它可以与相同的代码一起使用而不会出现问题。 让我知道您是否对GlassFish有麻烦。

基准测试:WebSocket VS REST

为了获得有关此新协议性能的一些指标,Arun Gupta开发了一个应用程序,该应用程序可以比较 WebSocket代码和REST代码执行的相同处理的执行时间 。

每个终结点(REST终结点和WebSocket终结点)都只是执行“回显”,因此它们仅返回接收到的流。 应用程序的Web界面允许您定义消息的大小以及在测试结束之前必须发送消息的次数。

如下所示的基准测试结果非常雄辩:

请求 总执行时间
REST端点
总执行时间
WebSocket端点
发送10个1字节的消息 220毫秒(63毫秒)* 7毫秒(29毫秒)*
发送10个字节的100条消息 986毫秒(587毫秒)* 57毫秒(74毫秒)*
发送100个字节的1000条消息 10210毫秒(4 636毫秒)* 179毫秒(288毫秒)*
发送1000个字节的5000条消息 54449毫秒(18049毫秒)* 1202毫秒(2862毫秒)*

()*之间的值表示在具有默认配置的WildFly 8.0.0-beta1的笔记本电脑(MacBook Pro 2013 i5 – 8Go – 128SSD)上进行的相同测试。

关于WebSocket的参考

我特别推荐Arun Gupta的会议,这些会议使您可以在不到1小时的时间内发现并了解WebSocket技术以及适用于WebSocket的Java API。

有关更多高级信息,理想的是IETF,W3C和Java规范。

  • RFC 6455:WebSocket协议 – IETF规范
  • W3C:WebSocket API – W3C规范 (候选推荐)
  • JSR 356:用于WebSocket协议的Java API – Java规范
  • 采用JSR – JSR 356
  • Java EE 7和WebSocket API – Arun Gupta的会议@ SF (从第46分钟开始)
  • WebSocket和SSE入门 – 2013年Devoxx UK的Arun Gupta会议

本文的结构是基于英国2013 Devoxx会议。

结论

本文通过一个具体示例介绍了随Java EE 7一起发布的WebSocket协议,HTML5 WebSocket API和用于WebSocket的Java API 。 已经可以将WebSocket与Java框架(如Atmosphere)一起使用,但缺乏标准。

如今,所有标准都已完成或即将完成 ,这项新技术满足了特定需求,并且在性能方面很有前途。 要大量使用该协议,将需要在通常仅允许HTTP协议的企业中使用该协议。

参考:我们的JCG合作伙伴 Maxime Greau在http://mgreau.com/blog.html博客上发布了WildFly上带有AngularJS的Java EE 7和Java WebSocket API for Java(JSR 356) 。

翻译自: https://www.javacodegeeks.com/2014/01/java-ee-7-and-websocket-api-for-java-jsr-356-with-angularjs-on-wildfly.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

日期加减加1天_2小时整理了13个时间日期函数,动图演示简单易学,收藏备用吧...

Hello&#xff0c;大家好&#xff0c;今天跟大家整理汇总了13个工作中经常用到的日期与时间函数的使用方法&#xff0c;学会它们几乎可以解决所有工作中遇到的&#xff0c;关于日期与时间提取与转换的问题。话不多说&#xff0c;让我们直接开始吧一、了解时间与日期的本质工作中…

点云数据显示_vispy 显示 kitti 点云数据

国内博客找了一圈&#xff0c;居然没有发现有用 vispy 做可视化的代码&#xff0c;这里做一个简单的示例&#xff0c;代码大部分来自官方。import numpy as np import vispy.scene from vispy.scene import visuals import sys# Make a canvas and add simple view canvas vis…

Webpack 常用命令总结以及常用打包压缩方法

前言&#xff1a;Webpack是一款基于node的前端打包工具&#xff0c;它可以将很多静态文件打包起来&#xff0c;自动处理依赖关系后&#xff0c;生成一个.js文件&#xff0c;然后让html来引用&#xff0c;不仅可以做到按需加载&#xff0c;而且可以减少HTTP请求&#xff0c;节约…

CSS3 Filter详解(改变模糊度 亮度 透明度等方法)

文章目录 1.模糊2.灰度3.亮度4.对比度5.饱和度6.色相旋转7.反色8.阴影9.透明度10.褐色CSS3 Filter&#xff08;滤镜&#xff09;属性提供了提供模糊和改变元素颜色的功能。CSS3 Fitler 常用于调整图像的渲染、背景或边框显示效果。 -webkit-filter是css3的一个属性&#xff0c;…

laravel中使用offsetSet

首先不用offsetSet方法&#xff0c;使用laravel的硬添加属性如下&#xff1a; 下边使用offsetSet 转载于:https://www.cnblogs.com/qaing123/p/9672241.html

转3d视图快捷键_最全Solidworks快捷键,值得收藏!

SOLIDWORKS软件提供了很多实用的快捷键&#xff0c;如果我们熟练掌握这些快捷键无疑可以减轻工作强度和提高工作效率。当然我们也可以点击【工具】-【自定义】-【键盘】&#xff0c;自己定义一些快捷键。本文为大家整理一些常用的快捷键&#xff0c;多使用快捷键可以帮助我们节…

构建前端自动化工作流环境

目标&#xff1a;建一个自动化工作流环境 自动编译 自动合并 自动刷新 自动部署 工作流&#xff1a; 1 全局安装webpack 执行命令&#xff1a; npm install webpack webpack-cli -g 其中webpack-cil 是命令接口工具 2 初始化当前项目&#xff1a;npm init 然后一路回车…

大型布线:Java云应用程序缺少的技术

您是否曾经想过&#xff0c;为什么大多数Java框架中的依赖项注入仅用于本地进程内服务而不是分布式服务&#xff1f; 我最近在2013年EMC世界大会上遇到了Paul Maritz的主题演讲 &#xff08;跳至第32分钟&#xff09;&#xff0c;这使我在云平台的背景下思考了这个问题。 主题…

java cpu过高排查_涨薪秘籍:JAVA项目排查cpu负载过高

背景我负责的其中一个项目在空负载的情况下&#xff0c;CPU占用率依然保持着100%左右&#xff0c;线上、测试、开发的服务都一样&#xff1b;是什么导致的呢&#xff1f;在开发环境我查看了请求流量&#xff0c;这个流量可以忽略但CPU占用率一直在60%-100%之间浮动。分析问题流…

巧用css的border属性完成对图片编辑功能的性能优化

一、需求场景&#xff1a; 最近闲来无事&#xff0c;boss提出了一个要求&#xff0c;研究相关代码并完成一个关于编辑图片功能的性能优化&#xff0c;该功能的主要界面展示如下&#xff1a; 通过了几分钟的短暂试用&#xff0c;发现就是一个简单的裁剪并保存用户选择并上传的图…

求数的绝对值一定是正数_人教版初中数学七年级上册绝对值公开课优质课课件教案视频...

绝对值&#xff08;习题课&#xff09;导学案&#xff08;教师版&#xff09;【教学目标】1、能利用绝对值的性质求值。 2、通过复习绝对值&#xff0c;让学生对绝对值的理解更加深透。 3、通过复习&#xff0c;让学生掌握利用绝对值的代数和几何意义&#xff0c;并学会灵活运用…

使用Java EE安全性和JBoss AS 7.x保护JSF应用程序的安全

企业应用程序的常见要求是在登录页面后面保护所有JSF页面。 有时&#xff0c;您甚至希望在应用程序内部具有保护区&#xff0c;只有拥有特定角色的用户才能访问这些保护区。 Java EE标准附带实现受某些安全性约束保护的Web应用程序所需的所有方法。 在此博客文章中&#xff0c;…

java 十六进制转十进制_JAVA知识-分析JAVA中的重点和难点

Java中有很多内容在开发项目的过程中并不常用&#xff0c;但是却是很重要的部分&#xff0c;为了避免忘记&#xff0c;今天重新温习了一遍Java中的重点和难点&#xff0c;借此机会记录一下方便以后查找。本文主要分为以下几个部分&#xff1a;1.进制的相互转换2.Java中位运算符…

java运算符知识整理

赋值运算符: int a 0;a 2;System.out.println("a0"""".."a);int b 0;b2;System.out.println("b0""b2"".."b);int c 0;c-2;System.out.println("c0""c-2"".."c);int d 1;d*2;S…

开放才能进步!Angular和Wijmo一起走过的日子

Angular 已成为广受欢迎的前端框架。去年9月份&#xff0c;期待已久的 Angular2 的正式版发布之后&#xff0c;Angular 又迎来了新一轮热潮。伴随着 Angular 这一路走来&#xff0c;Wijmo 一直都是第一个全面支持各种版本 Angular 的JS控件库&#xff0c;为 Angular 用户提供着…

windows 检查cuda安装_Windows云主机GPU驱动-CUDA安装使用

IE安全相关配置如果打开浏览器无法正常下载&#xff0c;则需要设置Internet Explorer增强的安全配置。设置如下&#xff1a;打开"服务器管理器";点击"本地服务器"&#xff1b;"IE增强的安全配置"&#xff1b;选择"关闭"&#xff1b; 之…

镜像镜像–使用反射在运行时查看JVM内部

开发人员&#xff1a;Takipi会告诉您何时新代码在生产中中断– 了解更多 我们都习惯于在我们的日常工作中直接或通过利用反射的框架来运用反射。 它是Java和Scala编程的主要方面&#xff0c;它使我们使用的库可以与我们的代码进行交互&#xff0c;而无需对其进行硬编码的知识。…

UnicodeMath数学公式编码_翻译(Unicode Nearly Plain - Text Encoding of Mathematics Version 3)

目录 完整目录1. 简介2. 编码简单数学表达式2.1 分数2.2 上标和下标2.3 空白&#xff08;空格&#xff09;字符使用3. 编码其他数学表达式3.1 分隔符强烈推荐本文简明版UnicodeMath编码教程 本文为UnicodeMath官方文档的翻译&#xff0c;原文看这。翻译如有不准还请谅解&#x…

antd 表格树如何展开_如何分析工作,找出规律,使用excel大幅度提高工作效率...

在职场中&#xff0c;掌握一定的excel知识&#xff0c;有时候可以极大的提高工作效率&#xff0c;减少加班次数。但是有的人可能不知道如何去做&#xff0c;下面我使用一个我前几天遇到的工作场景&#xff0c;一步一步的来给大家展示一下&#xff0c;如何使用excel提高工作效率…

Wijmo 更优美的jQuery UI部件集:复合图表(CompositeChart)

Wijmo的CompositeChart控件允许您使用一个Chart来分析和展现复杂的数据。相同的数据可以使用不同的可视化效果&#xff0c;不同的图表类型展现在一个图表内&#xff0c;使得用户可以从不同的角度&#xff0c;了解分析这组数据所表达的内容 。 本文将介绍如何使用Wijmo的Composi…