配色: 字号:
JavaEE7+Websockets+GlassFish4打造聊天室
2016-10-11 | 阅:  转:  |  分享 
  
JavaEE7+Websockets+GlassFish4打造聊天室

JavaEE7已经发布很久了,新增加了很多新的功能和特性,如新增或更新了不少的JSR标准。其中特别受到关注的是Websockets。它的一个好处之一是减少了不必要的网络流量。它主要是用于在客户机和服务器之间建立单一的双向连接。

在客户机和服务器之间建立单一的双向连接,这就意味着客户只需要发送一个请求到服务端,那么服务端则会进行处理,处理好后则将其返回给客户端,客户端则可以在等待这个时间继续去做其他工作,整个过程是异步的。在本系列教程中,将指导用户如何在JAVAEE7的容器GlassFish4中,使用JAVAEE7中的全新的解析JsonAPI(JSR-353),以及综合运用jQuery和Bootstrap。本文要求读者有一定的HTML5Websocket的基础原理知识。

效果图

我们先来看下在完成这个教程后的效果图,如下所示:



准备工作

我们使用的是JDK7和MAVN3进行库的构建工作,首先看pom.xml中关于JaveEE7的部分:

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

${project.build.directory}/endorsed

UTF-8







javax

javaee-api

7.0

provided











org.apache.maven.plugins

maven-compiler-plugin

3.1



1.7

1.7



${endorsed.dir}









org.apache.maven.plugins

maven-war-plugin

2.3



false







org.apache.maven.plugins

maven-dependency-plugin

2.6

[..]





同时,为了能使用GlassFish4,需要增加如下的插件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20 plugin>

org.glassfish.embedded

maven-embedded-glassfish-plugin

4.0



embedded-glassfish

${basedir}/target/${project.artifactId}-${project.version}.war

true

8080

${project.artifactId}

hascode









deploy







设置Websocket的Endpoint

我们先来看服务端Websocket的代码如下,然后再做进一步解析:

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 packagecom.hascode.tutorial;

importjava.io.IOException;

importjava.util.logging.Level;

importjava.util.logging.Logger;

importjavax.websocket.EncodeException;

importjavax.websocket.OnMessage;

importjavax.websocket.OnOpen;

importjavax.websocket.Session;

importjavax.websocket.server.PathParam;

importjavax.websocket.server.ServerEndpoint;

@ServerEndpoint(value="/chat/{room}",encoders=ChatMessageEncoder.class,decoders=ChatMessageDecoder.class)

publicclassChatEndpoint{

privatefinalLoggerlog=Logger.getLogger(getClass().getName());

@OnOpen

publicvoidopen(finalSessionsession,@PathParam("room")finalStringroom){

log.info("sessionopenendwww.hunanwang.netandboundtoroom:"+room);

session.getUserProperties().put("room",room);

}

@OnMessage

publicvoidonMessage(finalSessionsession,finalChatMessagechatMessage){

Stringroom=(String)session.getUserProperties().get("room");

try{

for(Sessions:session.getOpenSessions()){

if(s.isOpen()

&&room.equals(s.getUserProperties().get("room"))){

s.getBasicRemote().sendObject(chatMessage);

}

}

}catch(IOException|EncodeExceptione){

log.log(Level.WARNING,"onMessagefailed",e);

}

}

} 下面分析下上面的代码:

使用@ServerEndpoint定义一个新的endpoint,其中的值指定了URL并且可以使用PathParams参数,就象在JAX-RS中的用法一样。

所以值“/chat/{room}”允许用户通过如下形式的URL去连接某个聊天室:ws://0.0.0.0:8080/hascode/chat/java

在大括号中的值(即room),可以通过使用javax.websocket.www.visa158.com.server.PathParam,在endpoint的生命周期回调方法中以参数的方式注入。

此外,我们要使用一个编码和解码的类,因为我们使用的是一个DTO形式的类,用于在服务端和客户端传送数据。

当用户第一次连接到服务端,输入要进入聊天室的房号,则这个房号以参数的方式注入提交,并且使用session.getUserProperties将值保存在用户的属性map中。

当一个聊天参与者通过tcp连接发送信息到服务端,则循环遍历所有已打开的session,每个session被绑定到指定的聊天室中,并且接收编码和解码的信息。

如果我们想发送简单的文本信息或和二进制格式的信息,则可以使用session.getBasicRemote().sendBinary()或session.getBasicRemote().sendText()

接下来我们看下用于代表信息传递实体(DTO:DataTransferObject)的代码,如下:

1

2

3

4

5

6

7

8

9

10

11 packagecom.hascode.tutorial;

importjava.util.Date;

publicclassChatMessage{

privateStringmessage;

privateStringsender;

privateDatereceived;

//其他getter,setter方法

} 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 packagecom.hascode.tutorial;

importjava.io.StringReader;

importjava.util.Date;

importjavax.json.Json;

importjavax.json.JsonObject;

importjavax.websocket.DecodeException;

importjavax.websocket.Decoder;

importjavax.websocket.EndpointConfig;

publicclassChatMessageDecoderimplementsDecoder.Text{

@Override

publicvoidinit(finalEndpointConfigconfig){

}

@Override

publicvoiddestroy(){

}

@Override

publicChatMessagedecode(finalStringtextMessage)throwsDecodeException{

ChatMessagechatMessage=newChatMessage();

JsonObjectobj=Json.createReader(newStringReader(textMessage))

.readObject();

chatMessage.setMessage(obj.getString("message"));

chatMessage.setSender(obj.getString("sender"));

chatMessage.setReceived(newDate());

returnchatMessage;

}

@Override

publicbooleanwillDecode(finalStrings){

returntrue;

}

} 同样再看下编码类的代码,这个类相反,是将ChatMessage类转换为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 packagecom.hascode.tutorial;

importjavax.json.Json;

importjavax.websocket.EncodeException;

importjavax.websocket.Encoder;

importjavax.websocket.EndpointConfig;

publicclassChatMessageEncoderimplementsEncoder.Text{

@Override

publicvoidinit(finalEndpointConfigconfig){

}

@Override

publicvoiddestroy(){

}

@Override

publicStringencode(finalChatMessagechatMessage)throwsEncodeException{

returnJson.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文件,代码如下:

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





[..]











Chatsignin

Nickname
class="input-block-level"placeholder="Nickname"id="nickname">



Chatroom
id="chatroom">














id="enterRoom">Signin

















Enteryourmessage..






value="Sendmessage"/>

Leave

room











在上面的代码中,要注意如下几点:

在Javascript端要调用websocket的话,要用如下的方式发起连接即可:ws://IP:PORT/CONTEXT_PATH/ENDPOINT_URLe.gws://0.0.0.0:8080/hascode/chat/java

创建一个Websocket连接的方法很简单,使用的是varwsocket=newWebSocket(‘ws://0.0.0.0:8080/hascode/chat/java'');

要获得来自服务端返回的信息,只需要在回调函数wsocket.onmessage中设置对应的获取返回信息的方法即可。

发送一个Websocket消息到服务端,使用的方法是wsocket.send(),其中可以发送的消息可以文本或者二进制数据。

关闭连接使用的是wsocket.close()。

最后,我们通过mvnpackageembedded-glassfish:run进行代码的部署,然后就可以看到本文开始部分截图的效果。



以上就是用JavaEE7、Websockets和GlassFish4实现的聊天室,希望对大家的学习有所帮助。























献花(0)
+1
(本文系白狐一梦首藏)
类似文章 更多
发表评论: