- Java EE 8 Application Development
- David R. Heffelfinger
- 588字
- 2021-07-02 22:05:03
JSF WebSocket support
In typical web applications, servers always respond to requests from a browser; there is no way for a server to send data to the client browser without responding to a request. WebSocket technology provides full duplex communication between a browser and a server, allowing servers to independently send data to a client, without having to respond to a request. WebSocket technology allows a myriad of new applications to be developed for the web, including updating stock tickers, multiplayer online games, and chat applications.
Although some of these types of web applications were developed before the advent of WebSockets, they relied on hacks to work around the limitations of the HTTP protocol. With WebSockets, these hacks are no longer necessary.
Traditionally, writing applications taking advantage of the WebSocket protocol required a lot of JavaScript code. JSF 2.3 introduces WebSocket support and abstracts out most of the JavaScript plumbing, allowing us to focus on developing the business logic of our applications.
The following example illustrates a simple chat application developed using JSF 2.3 WebSocket support.
First, let's take a look at an application-scoped CDI named bean responsible for sending messages to all browser clients:
package net.ensode.javaee8book.jsfwebsocket; import java.io.Serializable; import javax.enterprise.context.ApplicationScoped; import javax.faces.push.Push; import javax.faces.push.PushContext; import javax.inject.Inject; import javax.inject.Named; @Named @ApplicationScoped public class JsfWebSocketMessageSender implements Serializable { @Inject @Push private PushContext pushContext; public void send(String message) { System.out.println("Sending message: " + message); pushContext.send(message); } }
As shown in the preceding example, in order to send data via WebSockets to the clients we need to inject an instance of an implementation of the javax.faces.push.PushContext interface, and annotate it with the @Push annotation. To actually send the message to the client, we need to invoke the send() method of the injected PushContext implementation; in our example, this is done in the send() method of our CDI named bean.
In our example, there is a session scoped CDI named bean that takes input from the user and passes it to the send() method of the preceding application scoped CDI named bean. Our session scoped CDI bean looks as follows:
package net.ensode.javaee8book.jsfwebsocket;
import java.io.Serializable; import javax.enterprise.context.SessionScoped; import javax.inject.Inject; import javax.inject.Named; @Named @SessionScoped public class JsfWebSocketController implements Serializable { @Inject
private JsfWebSocketMessageSender jsfWebSocketMessageSender; private String userName; private String message; public void sendMessage() {
jsfWebSocketMessageSender.send(String.format("%s: %s",
userName,
message));
} //setters getters and less relevant methods omitted for brevity. }
The sendMessage() method of the preceding class calls the send() method of the application scoped CDI bean we discussed earlier, passing the name of the user and the message to be broadcast to all browsers. The aforementioned sendMessage() method is invoked via Ajax when a user clicks a button on the corresponding page, as shown in the following markup:
<h:body> <f:websocket channel="pushContext"
onmessage="socketListener" /> <h:form prependId="false"> <h:panelGrid columns="2"> <h:outputLabel for="chatWindow" value="Chat
Window:"/> <textarea id="chatWindow" rows="10"/> <h:outputLabel for="chatInput" value="Type
something here:"/> <h:inputText id="chatInput" value="#{jsfWebSocketController.message}"/> <h:panelGroup/> <h:commandButton actionListener="#
{jsfWebSocketController.sendMessage()}" value="Send message"> <f:ajax execute="chatInput"
render="chatWindow"/> </h:commandButton> </h:panelGrid> </h:form> <script type="text/javascript">
function socketListener(message, channel, event) {
var textArea = document.getElementById('chatWindow');
var textAreaValue = textArea.value;
if (textAreaValue.trim() !== '') {
textAreaValue += "\n";
}
textAreaValue += message;
textArea.value = textAreaValue;
textArea.scrollTop = textArea.scrollHeight;
}
</script> </h:body>
The <f:websocket> tag in the preceding markup is needed to enable WebSocket support in our page. The value of its channel attribute links the page to the corresponding PushContext instance on the server (in our example, it is defined in the application scoped JsfWebSocketMessageSender CDI named bean). By convention, the value of the channel attribute must match the variable name on the corresponding CDI named bean (pushContext, in our example).
We're only showing the most relevant sections of the example; the complete example can be downloaded from this book's GitHub repository at https://github.com/dheffelfinger/Java-EE-8-Application-Development-Code-Samples.
After building and deploying our application we can see it in action:
- 從零開始構建企業級RAG系統
- iOS面試一戰到底
- Java入門經典(第6版)
- 深入理解Django:框架內幕與實現原理
- Building Minecraft Server Modifications
- Java 9模塊化開發:核心原則與實踐
- JavaScript程序設計(第2版)
- Python:Deeper Insights into Machine Learning
- Oracle數據庫編程經典300例
- 動手打造深度學習框架
- 從0到1:HTML5 Canvas動畫開發
- 零基礎學C語言(第4版)
- jQuery技術內幕:深入解析jQuery架構設計與實現原理
- C++ System Programming Cookbook
- 零基礎學HTML+CSS第2版