JavaEE7+Websockets+GlassFish4打造聊天室。本站提示廣大學習愛好者:(JavaEE7+Websockets+GlassFish4打造聊天室)文章只能為提供參考,不一定能成為您想要的結果。以下是JavaEE7+Websockets+GlassFish4打造聊天室正文
在客戶機和辦事器之間樹立單一的雙向銜接,這就意味著客戶只須要發送一個要求到辦事端,那末辦事端則會停止處置,處置好後則將其前往給客戶端,客戶端則可以在期待這個時光持續去做其他任務,全部進程是異步的。在本系列教程中,將指點用戶若何在JAVA EE 7的容器GlassFish 4中,應用JAVA EE 7中的全新的解析Json API(JSR-353),和綜合應用jQuery和Bootstrap。本文請求讀者有必定的HTML 5 Websocket的基本道理常識。
後果圖
我們先來看下在完成這個教程後的後果圖,以下所示:
預備任務
我們應用的是JDK 7 和MAVN 3停止庫的構建任務,起首看pom.xml中關於Jave EE 7的部門:
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
[..]
</plugin>
</plugins>
</build>
同時,為了能應用GlassFish 4,須要增長以下的插件:
plugin>
<groupId>org.glassfish.embedded</groupId>
<artifactId>maven-embedded-glassfish-plugin</artifactId>
<version>4.0</version>
<configuration>
<goalPrefix>embedded-glassfish</goalPrefix>
<app>${basedir}/target/${project.artifactId}-${project.version}.war</app>
<autoDelete>true</autoDelete>
<port>8080</port>
<name>${project.artifactId}</name>
<contextRoot>hascode</contextRoot>
</configuration>
<executions>
<execution>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
設置Websocket的Endpoint
我們先來看辦事端Websocket的代碼以下,然後再做進一步解析:
package com.hascode.tutorial;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/chat/{room}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class)
public class ChatEndpoint {
private final Logger log = Logger.getLogger(getClass().getName());
@OnOpen
public void open(final Session session, @PathParam("room") final String room) {
log.info("session openend and bound to room: " + room);
session.getUserProperties().put("room", room);
}
@OnMessage
public void onMessage(final Session session, final ChatMessage chatMessage) {
String room = (String) session.getUserProperties().get("room");
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& room.equals(s.getUserProperties().get("room"))) {
s.getBasicRemote().sendObject(chatMessage);
}
}
} catch (IOException | EncodeException e) {
log.log(Level.WARNING, "onMessage failed", e);
}
}
}
上面剖析下下面的代碼:
應用@ ServerEndpoint界說一個新的endpoint,個中的值指定了URL而且可使用PathParams參數,就象在JAX-RS中的用法一樣。
所以值“/chat/{room}”許可用戶經由過程以下情勢的URL去銜接某個聊天室:ws://0.0.0.0:8080/hascode/chat/java
在年夜括號中的值(即room),可以經由過程應用javax.websocket.server.PathParam,在endpoint的性命周期回調辦法中以參數的方法注入。
另外,我們要應用一個編碼息爭碼的類,由於我們應用的是一個DTO情勢的類,用於在辦事端和客戶端傳送數據。
當用戶第一次銜接到辦事端,輸出要進入聊天室的房號,則這個房號以參數的方法注入提交,而且應用session.getUserProperties將值保留在用戶的屬性map中。
當一個聊天介入者經由過程tcp銜接發送信息到辦事端,則輪回遍歷一切已翻開的session,每一個session被綁定到指定的聊天室中,而且吸收編碼息爭碼的信息。
假如我們想發送簡略的文本信息或和二進制格局的信息,則可使用session.getBasicRemote().sendBinary() 或session.getBasicRemote().sendText()
接上去我們看下用於代表信息傳遞實體(DTO:Data Transfer Object)的代碼,以下:
package com.hascode.tutorial;
import java.util.Date;
public class ChatMessage {
private String message;
private String sender;
private Date received;
// 其他getter,setter辦法
}
聊天新聞的轉換
在這個運用中,將編寫一個編碼息爭碼類,用於在聊天信息和JSON格局間停止轉換。
先來看下解碼類的完成,這將會把傳遞到辦事真個聊天信息轉換為ChatMessage實體類。在這裡,應用的是Java API for JSON Processing(JSR353)標准去將JSON格局的信息轉換為實體類,代碼以下,個中重寫的willDecode辦法,這裡默許前往為true。
package com.hascode.tutorial;
import java.io.StringReader;
import java.util.Date;
import javax.json.Json;
import javax.json.JsonObject;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
public class ChatMessageDecoder implements Decoder.Text<ChatMessage> {
@Override
public void init(final EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public ChatMessage decode(final String textMessage) throws DecodeException {
ChatMessage chatMessage = new ChatMessage();
JsonObject obj = Json.createReader(new StringReader(textMessage))
.readObject();
chatMessage.setMessage(obj.getString("message"));
chatMessage.setSender(obj.getString("sender"));
chatMessage.setReceived(new Date());
return chatMessage;
}
@Override
public boolean willDecode(final String s) {
return true;
}
}
異樣再看下編碼類的代碼,這個類相反,是將ChatMessage類轉換為Json格局,代碼以下:
package com.hascode.tutorial;
import javax.json.Json;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
public class ChatMessageEncoder implements Encoder.Text<ChatMessage> {
@Override
public void init(final EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public String encode(final ChatMessage chatMessage) throws EncodeException {
return Json.createObjectBuilder()
.add("message", chatMessage.getMessage())
.add("sender", chatMessage.getSender())
.add("received", chatMessage.getReceived().toString()).build()
.toString();
}
}
這裡可以看到JSR-353的壯大威力,只須要挪用Json.createObjectBuilder便可以隨意馬虎把一個DTO對象轉化為JSON了。
經由過程Bootstrap、Javacsript搭建簡略單純客戶端
最初,我們綜合應用有名的Bootstrap、jQuery框架和Javascript設計一個簡略單純的客戶端。我們在src/main/weapp目次下新樹立index.html文件,代碼以下:
<!DOCTYPE html>
<html lang="en">
<head>
[..]
<script>
var wsocket;
var serviceLocation = "ws://0.0.0.0:8080/hascode/chat/";
var $nickName;
var $message;
var $chatWindow;
var room = '';
function onMessageReceived(evt) {
//var msg = eval('(' + evt.data + ')');
var msg = JSON.parse(evt.data); // native API
var $messageLine = $('<tr><td class="received">' + msg.received
+ '</td><td class="user label label-info">' + msg.sender
+ '</td><td class="message badge">' + msg.message
+ '</td></tr>');
$chatWindow.append($messageLine);
}
function sendMessage() {
var msg = '{"message":"' + $message.val() + '", "sender":"'
+ $nickName.val() + '", "received":""}';
wsocket.send(msg);
$message.val('').focus();
}
function connectToChatserver() {
room = $('#chatroom option:selected').val();
wsocket = new WebSocket(serviceLocation + room);
wsocket.onmessage = onMessageReceived;
}
function leaveRoom() {
wsocket.close();
$chatWindow.empty();
$('.chat-wrapper').hide();
$('.chat-signin').show();
$nickName.focus();
}
$(document).ready(function() {
$nickName = $('#nickname');
$message = $('#message');
$chatWindow = $('#response');
$('.chat-wrapper').hide();
$nickName.focus();
$('#enterRoom').click(function(evt) {
evt.preventDefault();
connectToChatserver();
$('.chat-wrapper h2').text('Chat # '+$nickName.val() + "@" + room);
$('.chat-signin').hide();
$('.chat-wrapper').show();
$message.focus();
});
$('#do-chat').submit(function(evt) {
evt.preventDefault();
sendMessage()
});
$('#leave-room').click(function(){
leaveRoom();
});
});
</script>
</head>
<body>
<div class="container chat-signin">
<form class="form-signin">
<h2 class="form-signin-heading">Chat sign in</h2>
<label for="nickname">Nickname</label> <input type="text"
class="input-block-level" placeholder="Nickname" id="nickname">
<div class="btn-group">
<label for="chatroom">Chatroom</label> <select size="1"
id="chatroom">
<option>arduino</option>
<option>java</option>
<option>groovy</option>
<option>scala</option>
</select>
</div>
<button class="btn btn-large btn-primary" type="submit"
id="enterRoom">Sign in</button>
</form>
</div>
<!-- /container -->
<div class="container chat-wrapper">
<form id="do-chat">
<h2 class="alert alert-success"></h2>
<table id="response" class="table table-bordered"></table>
<fieldset>
<legend>Enter your message..</legend>
<div class="controls">
<input type="text" class="input-block-level" placeholder="Your message..." id="message" />
<input type="submit" class="btn btn-large btn-block btn-primary"
value="Send message" />
<button class="btn btn-large btn-block" type="button" id="leave-room">Leave
room</button>
</div>
</fieldset>
</form>
</div>
</body>
</html>
在下面的代碼中,要留意以下幾點:
在Javascript端要挪用websocket的話,要用以下的方法提議銜接便可:ws://IP:PORT/CONTEXT_PATH/ENDPOINT_URL e.g ws://0.0.0.0:8080/hascode/chat/java
創立一個Websocket銜接的辦法很簡略,應用的是var wsocket = new WebSocket(‘ws://0.0.0.0:8080/hascode/chat/java');
要取得來自辦事端前往的信息,只須要在回調函數wsocket.onmessage中設置對應的獲得前往信息的辦法便可。
發送一個Websocket新聞到辦事端,應用的辦法是wsocket.send(),個中可以發送的新聞可以文本或許二進制數據。
封閉銜接應用的是wsocket.close()。
最初,我們經由過程mvn package embedded-glassfish:run停止代碼的安排,然後便可以看到本文開端部門截圖的後果。
以上就是用JavaEE7、Websockets和GlassFish4完成的聊天室,願望對年夜家的進修有所贊助。
nt.getRoundX(),lyjCirclePoint.getRoundY(), lyjCirclePoint.getRadiu(),circlePaint); } } //繪制用bitmap創立出來的畫布 @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap, 0, 0, null); } }如許便可以獲得以下界面後果(固然反編譯百度錢包,並沒有百度錢包中的圖片,只好隨意找了一張圖片):
以上就是本文的全體內容,願望對年夜家進修Android有所贊助。