国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - JavaEE7+Websockets+GlassFish4打造聊天室

JavaEE7+Websockets+GlassFish4打造聊天室

2020-01-05 14:55lijiao JAVA教程

Java EE 7已經(jīng)發(fā)布很久了,新增加了很多新的功能和特性,如新增或更新了不少的JSR標(biāo)準(zhǔn)。其中特別受到關(guān)注的是Websockets。它的一個好處之一是減少了不必要的網(wǎng)絡(luò)流量。它主要是用于在客戶機和服務(wù)器之間建立單一的雙向連接。

在客戶機和服務(wù)器之間建立單一的雙向連接,這就意味著客戶只需要發(fā)送一個請求到服務(wù)端,那么服務(wù)端則會進(jìn)行處理,處理好后則將其返回給客戶端,客戶端則可以在等待這個時間繼續(xù)去做其他工作,整個過程是異步的。在本系列教程中,將指導(dǎo)用戶如何在JAVA EE 7的容器GlassFish 4中,使用JAVA EE 7中的全新的解析Json API(JSR-353),以及綜合運用jQuery和Bootstrap。本文要求讀者有一定的HTML 5 Websocket的基礎(chǔ)原理知識。

效果圖

我們先來看下在完成這個教程后的效果圖,如下所示:

JavaEE7+Websockets+GlassFish4打造聊天室

準(zhǔn)備工作

我們使用的是JDK 7 和MAVN 3進(jìn)行庫的構(gòu)建工作,首先看pom.xml中關(guān)于Jave EE 7的部分:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<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,需要增加如下的插件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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>

設(shè)置Websocket的Endpoint

我們先來看服務(wù)端Websocket的代碼如下,然后再做進(jìn)一步解析:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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參數(shù),就象在JAX-RS中的用法一樣。

所以值“/chat/{room}”允許用戶通過如下形式的URL去連接某個聊天室:ws://0.0.0.0:8080/hascode/chat/java

在大括號中的值(即room),可以通過使用javax.websocket.server.PathParam,在endpoint的生命周期回調(diào)方法中以參數(shù)的方式注入。

此外,我們要使用一個編碼和解碼的類,因為我們使用的是一個DTO形式的類,用于在服務(wù)端和客戶端傳送數(shù)據(jù)。

當(dāng)用戶第一次連接到服務(wù)端,輸入要進(jìn)入聊天室的房號,則這個房號以參數(shù)的方式注入提交,并且使用session.getUserProperties將值保存在用戶的屬性map中。

當(dāng)一個聊天參與者通過tcp連接發(fā)送信息到服務(wù)端,則循環(huán)遍歷所有已打開的session,每個session被綁定到指定的聊天室中,并且接收編碼和解碼的信息。

如果我們想發(fā)送簡單的文本信息或和二進(jìn)制格式的信息,則可以使用session.getBasicRemote().sendBinary() 或session.getBasicRemote().sendText()

接下來我們看下用于代表信息傳遞實體(DTO:Data Transfer Object)的代碼,如下:

?
1
2
3
4
5
6
7
8
9
10
11
package com.hascode.tutorial;
 
import java.util.Date;
 
public class ChatMessage {
 private String message;
 private String sender;
 private Date received;
 
 // 其他getter,setter方法
}

聊天消息的轉(zhuǎn)換

在這個應(yīng)用中,將編寫一個編碼和解碼類,用于在聊天信息和JSON格式間進(jìn)行轉(zhuǎn)換。

先來看下解碼類的實現(xiàn),這將會把傳遞到服務(wù)端的聊天信息轉(zhuǎn)換為ChatMessage實體類。在這里,使用的是Java API for JSON Processing(JSR353)規(guī)范去將JSON格式的信息轉(zhuǎn)換為實體類,代碼如下,其中重寫的willDecode方法,這里默認(rèn)返回為true。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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類轉(zhuǎn)換為Json格式,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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的強大威力,只需要調(diào)用Json.createObjectBuilder就可以輕易把一個DTO對象轉(zhuǎn)化為JSON了。

通過Bootstrap、Javacsript搭建簡易客戶端

最后,我們綜合運用著名的Bootstrap、jQuery框架和Javascript設(shè)計一個簡易的客戶端。我們在src/main/weapp目錄下新建立index.html文件,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!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" style="height:60px"/>
     <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端要調(diào)用websocket的話,要用如下的方式發(fā)起連接即可:ws://IP:PORT/CONTEXT_PATH/ENDPOINT_URL e.g ws://0.0.0.0:8080/hascode/chat/java

創(chuàng)建一個Websocket連接的方法很簡單,使用的是var wsocket = new WebSocket(‘ws://0.0.0.0:8080/hascode/chat/java');

要獲得來自服務(wù)端返回的信息,只需要在回調(diào)函數(shù)wsocket.onmessage中設(shè)置對應(yīng)的獲取返回信息的方法即可。

發(fā)送一個Websocket消息到服務(wù)端,使用的方法是wsocket.send(),其中可以發(fā)送的消息可以文本或者二進(jìn)制數(shù)據(jù)。

關(guān)閉連接使用的是wsocket.close()。

最后,我們通過mvn package embedded-glassfish:run進(jìn)行代碼的部署,然后就可以看到本文開始部分截圖的效果。

JavaEE7+Websockets+GlassFish4打造聊天室

以上就是用JavaEE7、Websockets和GlassFish4實現(xiàn)的聊天室,希望對大家的學(xué)習(xí)有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久久精品综合 | 日韩3级在线观看 | 色婷婷久久一区二区三区麻豆 | 国产精品久久精品 | 亚洲一区电影 | 国产成人免费 | 国产精品免费av | 久久尤物免费一区二区三区 | 黄色毛片在线视频 | 一区二区精品视频 | 黄色网日本 | 国产a视频| 亚洲男人天堂网 | 黄色一级片看看 | 国产伦精品一区二区三区高清 | 亚洲欧美日韩精品久久奇米色影视 | 瑟瑟视频网站 | 婷婷五月色综合 | 黄网免费看 | 天天爱天天操 | 午夜网址 | 亚洲综合视频在线观看 | 在线观看av网站永久 | 欧美日韩不卡 | 榴莲视频成人在线观看 | 亚洲a在线观看 | 美国理论 | 亚洲国内精品 | 欧美在线观看一区 | 日本一区二区三区四区 | 免费一级性片 | 欧美亚洲综合久久 | 国产一区二区三区免费观看 | 国产精品网站在线观看 | 亚洲视频中文字幕 | 在线小视频 | 五月天伊人| 久久综合国产 | 成人国产精品久久久 | 中文字幕免费播放 | 亚洲综合色视频在线观看 |