在现在很多业务场景(比如聊天室),又或者是手机端的一些online游戏,都需要做到实时通信,那怎么来进行双向通信呢,总不见得用曾经很破旧的ajax每隔10秒或者每隔20秒来请求吧,我的天呐(

),这尼玛太坑了

跟webservice来相比,Web Socket可以做到保持长连接,或者说强连接,一直握手存在两端可以互相发送消息互相收到消息,而webservice是一次性的,你要我响应就必须要请求我一次(黄盖:“请鞭挞我吧!”)

注:浏览器需要使用高版本的chrome或者Firefox,Tomcat使用8

先来了解一下基本概念

一、WebSocket是HTML5出的,是一种协议,也就是说原版的HTTP协议没有变化的,又或者说这两者压根就是不一样的东西,HTTP本身就不支持强连接

二、Websocket是什么样的协议,具体有什么优点

首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说。

举个栗子吧,简单来说

1) HTTP的生命周期通过Request来界定,也就是一个Request 对应一个Response,或者多个Request 对应多个Response,

也就是说request对应的response数量是恒定不变的。而且这个response也是被动的,不能主动发起,必须有request才会有response

那么Websocket究竟是啥玩意呢

首先Websocket是基于HTTP协议的,或者说引用了HTTP的协议来完成一小部分的握手

简单来说,客服的发起请求到服务端,服务端找到对应的小弟(服务助理),找到好,这个小弟就会一直和老大保持联系,为老大服务

三、Websocket的作用

曾经接触WebSocket之前,我接触过ajax轮询以及long poll ,先来说说这2个概念,因为至今还有一些小项目是这么做的

ajax轮询:

原理非常简单,JS控制让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息,有的话就响应给客户端

以此循环获取后端的数据,同时浏览器又不需要刷新

简单的例子:OA首页显示流程,每个几秒刷新看看有没有需要处理的新流程出现

long poll:

long poll 其实原理跟 ajax轮询 差不多,都是采用循环的方式,不过采取的手段不太友好,是阻塞模型,客户端发起请求后,如果没响应,就一直不返回Response,直到有响应才返回,返回完之后,客户端再次建立连接,如此循环往复不亦乐乎。。。

从上面这两种方式看出他们都是在不断地建立HTTP连接,然后等待服务器处理,这样显得十分被动

那么缺点也随之而来:

这两种形式非常消耗资源,性能也不不好

好!接下来说说Websocket

Websocket的出现,使得资源不需要像之前那种方式那么浪费

它非常主动,服务端就可以主动推送信息给客户端

所以,只需建立一次HTTP请求,就可以做到源源不断的信息传送了。(就像你在手机上玩ol游戏,一开始建立连接后,你就一直保持在线,除非你断线再连)

下面贴出我的代码片段以及github地址

功能点:

spring websocket chating room

使用spring websocket实现聊天室基本功能

1.群发消息给所有人

2.悄悄话给某个人

效果:

主要代码:

pom.xml引入必要的库

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

4 4.0.0

5 com.lee

6 websocket

7 maven-spring-websocket-01

8 war

9 1.0.0-BUILD-SNAPSHOT

10

11

12

13 1.7

14 UTF-8

15 UTF-8

16

17 4.0.0.RELEASE

18

19 4.11

20

21

22 1.0.13

23 1.7.7

24

25

26

27

28

29 org.springframework

30 spring-core

31 ${spring.version}

32

33

34

35 org.springframework

36 spring-web

37 ${spring.version}

38

39

40

41 org.springframework

42 spring-webmvc

43 ${spring.version}

44

45

46

47

48 jstl

49 jstl

50 1.2

51

52

53

54

55 org.springframework

56 spring-test

57 ${spring.version}

58 test

59

60

61

62

63 org.springframework

64 spring-jdbc

65 ${spring.version}

66

67

68

69 junit

70 junit

71 4.8.2

72 test

73

74

75

76

77 org.springframework

78 spring-websocket

79 ${spring.version}

80

81

82 org.springframework

83 spring-messaging

84 ${spring.version}

85

86

87

88

89 com.fasterxml.jackson.core

90 jackson-databind

91 2.3.0

92

93

94

95 commons-fileupload

96 commons-fileupload

97 1.2.2

98

99

100 commons-io

101 commons-io

102 2.2

103

104

105

106

107 org.slf4j

108 slf4j-api

109 ${slf4j.version}

110 compile

111

112

113 ch.qos.logback

114 logback-classic

115 ${logback.version}

116 runtime

117

118

119

120

121 com.alibaba

122 druid

123 1.0.4

124

125

126

127

128 mysql

129 mysql-connector-java

130 5.1.29

131

132

133

134

135

136

137

138 org.apache.maven.plugins

139 maven-compiler-plugin

140

141 1.7

142 1.7

143

144

145

146

147

148

主要结构

HandshakeInterceptor.java

1 packagecom.lee.websocket;2

3 importjava.util.Map;4

5 importjavax.servlet.http.HttpSession;6

7 importorg.springframework.http.server.ServerHttpRequest;8 importorg.springframework.http.server.ServerHttpResponse;9 importorg.springframework.http.server.ServletServerHttpRequest;10 importorg.springframework.web.socket.WebSocketHandler;11

12 public class HandshakeInterceptor implementsorg.springframework.web.socket.server.HandshakeInterceptor {13

14 //进入hander之前的拦截

15 @Override16 public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map map) throwsException {17 if (request instanceofServletServerHttpRequest) {18 ServletServerHttpRequest servletRequest =(ServletServerHttpRequest) request;19

20 String clientName = (String)servletRequest.getServletRequest().getParameter("name");21 System.out.println(clientName);22

23 HttpSession session = servletRequest.getServletRequest().getSession(true);24 //String userName = "lee";

25 if (session != null) {26 //使用userName区分WebSocketHandler,以便定向发送消息27 //String clientName = (String) session.getAttribute("WEBSOCKET_USERNAME");

28 map.put("WEBSOCKET_USERNAME", clientName);29 }30 }31 return true;32 }33

34 @Override35 public voidafterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {36

37 }38

39 }

HomeController.java

1 packagecom.lee.websocket;2

3 importjava.text.DateFormat;4 importjava.util.Date;5 importjava.util.Locale;6

7 importorg.slf4j.Logger;8 importorg.slf4j.LoggerFactory;9 importorg.springframework.stereotype.Controller;10 importorg.springframework.ui.Model;11 importorg.springframework.web.bind.annotation.RequestMapping;12 importorg.springframework.web.bind.annotation.RequestMethod;13

14 /**

15 * Handles requests for the application home page.16 */

17 @Controller18 public classHomeController {19

20 private static final Logger logger = LoggerFactory.getLogger(HomeController.class);21

22 /**

23 * Simply selects the home view to render by returning its name.24 */

25 @RequestMapping(value = "/", method =RequestMethod.GET)26 publicString home(Locale locale, Model model) {27 logger.info("Welcome home! The client locale is {}.", locale);28

29 Date date = newDate();30 DateFormat dateFormat =DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);31

32 String formattedDate =dateFormat.format(date);33

34 model.addAttribute("serverTime", formattedDate );35

36 return "home";37 }38

39 @RequestMapping(value = "/chat", method =RequestMethod.GET)40 publicString chat(Locale locale, Model model) {41 return "chat";42 }43

44 }

WebSocketConfig.java

1 packagecom.lee.websocket;2

3 importorg.springframework.context.annotation.Configuration;4 importorg.springframework.web.socket.config.annotation.EnableWebSocket;5 importorg.springframework.web.socket.config.annotation.WebSocketConfigurer;6 importorg.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;7

8 @Configuration9 @EnableWebSocket//开启websocket

10 public class WebSocketConfig implementsWebSocketConfigurer {11 @Override12 public voidregisterWebSocketHandlers(WebSocketHandlerRegistry registry) {13 registry.addHandler(new WebSocketHander(),"/echo").addInterceptors(new HandshakeInterceptor()); //支持websocket 的访问链接

14 registry.addHandler(new WebSocketHander(),"/sockjs/echo").addInterceptors(new HandshakeInterceptor()).withSockJS(); //不支持websocket的访问链接

15 }16 }

WebSocketHander.java

1 packagecom.lee.websocket;2

3 importjava.io.IOException;4 importjava.util.ArrayList;5

6 importorg.slf4j.Logger;7 importorg.slf4j.LoggerFactory;8 importorg.springframework.web.socket.CloseStatus;9 importorg.springframework.web.socket.TextMessage;10 importorg.springframework.web.socket.WebSocketHandler;11 importorg.springframework.web.socket.WebSocketMessage;12 importorg.springframework.web.socket.WebSocketSession;13

14 public class WebSocketHander implementsWebSocketHandler {15 private static final Logger logger = LoggerFactory.getLogger(WebSocketHander.class);16

17 private static final ArrayList users = new ArrayList<>();18

19 //初次链接成功执行

20 @Override21 public void afterConnectionEstablished(WebSocketSession session) throwsException {22 logger.debug("链接成功......");23 users.add(session);24 String userName = (String) session.getHandshakeAttributes().get("WEBSOCKET_USERNAME");25 if(userName!= null){26 session.sendMessage(new TextMessage("欢迎来到Nathan的聊天室,我们开始聊天吧!~"));27 }28 }29

30 //接受消息处理消息

31 @Override32 public void handleMessage(WebSocketSession session, WebSocketMessage> webSocketMessage) throwsException {33 String clientName = (String) session.getHandshakeAttributes().get("WEBSOCKET_USERNAME");34

35 clientName = "" + clientName + "";36

37 String msg =webSocketMessage.getPayload().toString();38 String charter = "";39

40 String msgs[] = msg.split("\\|");41 if (msgs.length > 1) {42 msg = msgs[1];43 charter = msgs[0];44 sendMessageToUser(charter, new TextMessage(clientName + " 悄悄地对你说 :" +msg));45 } else{46 sendMessageToUsers(new TextMessage(clientName + " 说:" +msg));47 }48

49 }50

51 @Override52 public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throwsException {53 if(webSocketSession.isOpen()){54 webSocketSession.close();55 }56 logger.debug("链接出错,关闭链接......");57 users.remove(webSocketSession);58 }59

60 @Override61 public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throwsException {62 logger.debug("链接关闭......" +closeStatus.toString());63 users.remove(webSocketSession);64 }65

66 @Override67 public booleansupportsPartialMessages() {68 return false;69 }70

71 /**

72 * 给所有在线用户发送消息73 *74 *@parammessage75 */

76 public voidsendMessageToUsers(TextMessage message) {77 for(WebSocketSession user : users) {78 try{79 if(user.isOpen()) {80 user.sendMessage(message);81 }82 } catch(IOException e) {83 e.printStackTrace();84 }85 }86 }87

88 /**

89 * 给某个用户发送消息90 *91 *@paramuserName92 *@parammessage93 */

94 public voidsendMessageToUser(String userName, TextMessage message) {95 for(WebSocketSession user : users) {96 if (user.getHandshakeAttributes().get("WEBSOCKET_USERNAME").equals(userName)) {97 try{98 if(user.isOpen()) {99 user.sendMessage(message);100 }101 } catch(IOException e) {102 e.printStackTrace();103 }104 break;105 }106 }107 }108 }

Person.java

1 packagecom.lee.websocket.entity;2

3 public classPerson {4

5 private intage;6 privateString name;7 privateString sex;8

9 public intgetAge() {10 returnage;11 }12 public void setAge(intage) {13 this.age =age;14 }15 publicString getName() {16 returnname;17 }18 public voidsetName(String name) {19 this.name =name;20 }21 publicString getSex() {22 returnsex;23 }24 public voidsetSex(String sex) {25 this.sex =sex;26 }27

28 }

chat.jsp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

webSocket测试

16

17 varchater;18

19 $(function(){20

21 varwebsocket;22 functionconnectServer() {23 var clientName = $("#client_name").val();24 if ("WebSocket" inwindow) {25 websocket = new WebSocket("ws://127.0.0.1:8080/websocket/echo?name=" +clientName);26 } else if ("MozWebSocket" inwindow) {27 alert("MozWebSocket");28 websocket = new MozWebSocket("ws://echo");29 } else{30 alert("SockJS");31 websocket = new SockJS("http://127.0.0.1:8080/websocket/sockjs/echo");32 }33 }34

35 //websocket.onopen = function (evnt) {

36 //$("#tou").html("链接服务器成功!")

37 //};

38 //websocket.onmessage = function (evnt) {

39 //$("#msg").html($("#msg").html() + "
" + evnt.data);

40 //};

41 //websocket.onerror = function (evnt) {

42 //};

43 //websocket.onclose = function (evnt) {

44 //$("#tou").html("与服务器断开了链接!")

45 //}

46

47 $("#conncet_server").bind("click", function() {48 connectServer();49

50 websocket.onopen = function(evnt) {51 $("#tou").html("链接服务器成功!")52 };53 websocket.onmessage = function(evnt) {54 $("#msg").html($("#msg").html() + "
" +evnt.data);55 };56 websocket.onerror = function(evnt) {57 };58 websocket.onclose = function(evnt) {59 $("#tou").html("与服务器断开了链接!")60 }61 });62

63 $("#send").bind("click", function() {64 send();65 });66

67 functionsend(){68 if (websocket != null) {69 var message = document.getElementById("message").value;70

71 if ($.trim(chater) != "") {72 message = chater + "|" +message;73 }74

75 websocket.send(message);76 } else{77 alert("未与服务器链接.");78 }79 }80 });81

82 functionchangeChater(e) {83 chater =$(e).html();84 alert("您将和" + chater + "进行聊天...");85 }86

87

88

89

90

91

webSocket及时聊天Demo程序

92

93

94

95

96

97 连接服务器

98

99

100

101

102

103

104

105

106

107

108 发送

109

110

111

112

113

114

java聊天服务器架构_基于Spring 4.0 的 Web Socket 聊天室/游戏服务端简单架构相关推荐

  1. 基于Spring 4.0 的 Web Socket 聊天室/游戏服务端简单架构

    跟webservice来相比,Web Socket可以做到保持长连接,或者说强连接,一直握手存在两端可以互相发送消息互相收到消息,而webservice是一次性的,你要我响应就必须要请求我一次(黄盖: ...

  2. 浅谈游戏服务端开发-架构

    网络游戏程序分为客户端和服务端.客户端负责图形渲染.交互和一些简单校验处理,服务端负责业务逻辑处理.数据存储. 我们开发一个游戏demo,服务端程序可以是一个单线程的服务进程.它包含网络通信.业务逻辑 ...

  3. java aop管理权限_基于spring aop 权限管理系统原型 - andyj2ee - BlogJava

    此权限管理系统把待访问的业务层方法做为权限管理中的资源,通过spring aop 对接口方法进行拦截,来实现权限的管理,可以实现细粒度的权限控制. 在上文体验了spring aop 一些特性,aop ...

  4. java http 服务器搭建_基于http.server搭建局域网服务器过程解析

    不知道大家有没有遇到过这样的情况, 在做项目或者研发的时候,迫切想要将一个文件传输给另一台电脑,却找不到u盘,于是麻烦的通过登陆qq.微信等社交软件 ,或者邮箱等工具进行传输,十分麻烦,让人苦恼.都说 ...

  5. paho架构_基于paho springboot集成mqtt实现消息的发布订阅 - 人人都是架构师

    1.首先添加pom依赖 org.springframework.boot spring-boot-starter-integration org.springframework.integration ...

  6. java开源springboot项目_使用Spring Boot的10多个免费开源项目

    这是一个真实的应用程序,为  Spring.io  网站提供支持.它正在生产中,每天都有成千上万的用户使用. 我强烈建议这个项目,你将学习有关Spring框架生态系统,Elasticsearch,Gr ...

  7. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  8. java项目-第99期基于spring+springmvc+hibernate的在线问卷答题系统-计算机毕业设计

    java项目-第99期基于spring+springmvc+hibernate的在线问卷答题系统[毕业设计] [源码请到下载专栏下载] 1.项目简述 今天分享的项目是<在线问卷答题系统>, ...

  9. Mongodb网页管理工具,基于Spring Boot2.0,前端采用layerUI实现

    源码:https://github.com/a870439570/Mongodb-WeAdmin 项目介绍 Mongodb网页管理工具,基于Spring Boot2.0,前端采用layerUI实现. ...

  10. 基于滴滴云的棋牌游戏服务端架构设计

    现在小团队开发的棋牌游戏有很多,棋牌行业的相互攻击是非常普遍的现象,同行之间往往会采取 DDOS.CC 等攻击的手段来打击对手,这是目前棋牌运营商们面临的比较严峻的一个问题,那么在设计棋牌游戏服务端架 ...

最新文章

  1. 关于web.xml3.0启动报错
  2. ue4 怎么传递变量到另一个蓝图_资深建模教你放置UE4蓝图节点,所以你就不要偷懒啦,认真点学...
  3. .Net程序员安卓学习之路5:使用xutils注入View和事件以及图片的显示
  4. famous javascript library.
  5. HTTP之Cookie和Session(C++ Qt框架实现)
  6. NOIP 2015 提高组 Day2
  7. Oracle技术之索引与Null值对于Hints及执行计划的影响
  8. SQL 游标使用实例
  9. Linux进程间通信——消息队列
  10. 一个果农儿子的心声,你倾听一下吧?
  11. android 图片合成pdf文件,怎样将图片转换成pdf文件时将它们合并成一个pdf文件?...
  12. linux下载git并为git配置连接ssh
  13. android 9.0极光推送闪退,极光推送集成Module中遇到的坑
  14. linux命令报错,在Linux执行命令报错”Arg list too long”的原因分析 – 运维派
  15. 尝试编写一个加密程序,加密方法将明文的字母变成其后的第4个字母,**字母表首尾相连。非字母符号** 不加密。 例如输入“China“, 输出密文“Glmre“, 输入 “ab123“, 输出 “ef1
  16. 初学JavaScript:BOM(浏览器对象模型)介绍
  17. 遥感深度学习数据集汇总(更新中)
  18. 猿创征文|一文吃透JAVA初学者的开发工具
  19. 海外用户用不了鸿蒙系统,鸿蒙系统国内遇冷海外好评 技术壁垒依然存在
  20. 计算机科学与技术毕业设计源码,计算机科学与技术专业(毕业论文)基于网络的同学录设计与实现源代码.doc...

热门文章

  1. Python 标准库 xml 详解
  2. Windows server2012r2安装密钥
  3. 资讯美国悬赏1000万美元追捕勒索黑客、能源行业成为网络钓鱼攻击“重灾区”|11月8日全球网络安全热点
  4. ogg格式怎么转换为mp3?
  5. JAVA正则表达式语法大全
  6. 电商后台管理系统分享
  7. Mac系统搭建C语言开发环境
  8. DNS与NS、NS记录
  9. 【avx2】VitrualBox 安装centos7 支持avx2
  10. 群晖系统服务器设置,私人云搭建 篇二:群晖系统搭建和初步设置的不正确指北...