160601、Websocet服务端实现

今天是六一儿童节,祝愿小朋友们节日快乐!大朋友们事事顺心!

Websocet服务端实现

WebSocketConfig.Java

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@Configuration

@EnableWebMvc

@EnableWebSocket

public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {

    @Override

    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

        registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(newWebSocketHandshakeInterceptor());

        registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(newWebSocketHandshakeInterceptor())

                .withSockJS();

    }

    @Bean

    public WebSocketHandler systemWebSocketHandler(){

        return new SystemWebSocketHandler();

    }

}

不要忘记在springmvc的配置文件中配置对此类的自动扫描

?


1

<context:component-scan base-package="com.ldl.origami.websocket" />

@Configuration

@EnableWebMvc
@EnableWebSocket
这三个大致意思是使这个类支持以@Bean的方式加载bean,并且支持springmvc和websocket,不是很准确大致这样,试了一下@EnableWebMvc不加也没什么影响,@Configuration本来就支持springmvc的自动扫描

?


1

registry.addHandler(systemWebSocketHandler(),"/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())

用来注册websocket server实现类,第二个参数是访问websocket的地址

?


1

2

3

registry.addHandler(systemWebSocketHandler(), "/sockjs/webSocketServer").addInterceptors(new WebSocketHandshakeInterceptor())

                .withSockJS();

    }

这个是使用Sockjs的注册方法

首先SystemWebSocketHandler.java

?


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

public class SystemWebSocketHandler implements WebSocketHandler {

    private static final Logger logger;

    private static final ArrayList<WebSocketSession> users;

    static {

        users = new ArrayList<>();

        logger = LoggerFactory.getLogger(SystemWebSocketHandler.class);

    }

    @Autowired

    private WebSocketService webSocketService;

    @Override

    public void afterConnectionEstablished(WebSocketSession session) throws Exception {

        logger.debug("connect to the websocket success......");

        users.add(session);

        String userName = (String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME);

        if(userName!= null){

            //查询未读消息

            int count = webSocketService.getUnReadNews((String) session.getAttributes().get(Constants.WEBSOCKET_USERNAME));

            session.sendMessage(new TextMessage(count + ""));

        }

    }

    @Override

    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {

        //sendMessageToUsers();

    }

    @Override

    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

        if(session.isOpen()){

            session.close();

        }

        logger.debug("websocket connection closed......");

        users.remove(session);

    }

    @Override

    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

        logger.debug("websocket connection closed......");

        users.remove(session);

    }

    @Override

    public boolean supportsPartialMessages() {

        return false;

    }

    /**

     * 给所有在线用户发送消息

     *

     * @param message

     */

    public void sendMessageToUsers(TextMessage message) {

        for (WebSocketSession user : users) {

            try {

                if (user.isOpen()) {

                    user.sendMessage(message);

                }

            catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    /**

     * 给某个用户发送消息

     *

     * @param userName

     * @param message

     */

    public void sendMessageToUser(String userName, TextMessage message) {

        for (WebSocketSession user : users) {

            if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) {

                try {

                    if (user.isOpen()) {

                        user.sendMessage(message);

                    }

                catch (IOException e) {

                    e.printStackTrace();

                }

                break;

            }

        }

    }

}

相关内容大家一看就能明白,就不多解释了

然后WebSocketHandshakeInterceptor.java

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {

    private static Logger logger = LoggerFactory.getLogger(HandshakeInterceptor.class);

    @Override

    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object

                > attributes) throws Exception {

        if (request instanceof ServletServerHttpRequest) {

            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;

            HttpSession session = servletRequest.getServletRequest().getSession(false);

            if (session != null) {

                //使用userName区分WebSocketHandler,以便定向发送消息

                String userName = (String) session.getAttribute(Constants.SESSION_USERNAME);

                attributes.put(Constants.WEBSOCKET_USERNAME,userName);

            }

        }

        return true;

    }

    @Override

    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

    }

}

这个的主要作用是取得当前请求中的用户名,并且保存到当前的WebSocketHandler中,以便确定WebSocketHandler所对应的用户,具体可参考HttpSessionHandshakeInterceptor

用户登录建立websocket连接

index.jsp

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script>

        <script>

            var websocket;

            if (‘WebSocket‘ in window) {

                websocket = new WebSocket("ws://localhost:8080/Origami/webSocketServer");

            else if (‘MozWebSocket‘ in window) {

                websocket = new MozWebSocket("ws://localhost:8080/Origami/webSocketServer");

            else {

                websocket = new SockJS("http://localhost:8080/Origami/sockjs/webSocketServer");

            }

            websocket.onopen = function (evnt) {

            };

            websocket.onmessage = function (evnt) {

                $("#msgcount").html("(<font color=‘red‘>"+evnt.data+"</font>)")

            };

            websocket.onerror = function (evnt) {

            };

            websocket.onclose = function (evnt) {

            }

        </script>

使用sockjs时要注意

1、这两个的写法

?


1

<script type="text/javascript" src="http://localhost:8080/Origami/websocket/sockjs-0.3.min.js"></script>

?


1

websocket = new SockJS("http://localhost:8080/Origami/sockjs/webSocketServer");

2、web.xml中

?


1

2

3

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd">

?


1

version

?


1

web-app_3_1.xsd

这两个的版本都要是3.0+

然后在这个servlet中加入

?


1

<async-supported>true</async-supported>

?


1

2

3

4

5

6

7

8

9

10

<servlet>

        <servlet-name>appServlet</servlet-name>

        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>classpath*:servlet-context.xml</param-value>

        </init-param>

        <load-on-startup>1</load-on-startup>

        <async-supported>true</async-supported>

    </servlet>

然后所有的filter中也加入

?


1

<async-supported>true</async-supported>

3、添加相关依赖

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<dependency>

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-annotations</artifactId>

            <version>2.3.0</version>

        </dependency>

        <dependency>

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-core</artifactId>

            <version>2.3.1</version>

        </dependency>

        <dependency>

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-databind</artifactId>

            <version>2.3.3</version>

        </dependency>

好了,现在websocket可以正常建立起来了

返回用户未读的消息

当连接建立后,会进入SystemWebSocketHandler的afterConnectionEstablished方法,代码看上边,取出WebSocketHandshakeInterceptor中保存的用户名

查询信息后使用session.sendMessage(new TextMessage(count + ""));返回给用户,从哪来回哪去

服务端推送消息给用户

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@Controller

public class AdminController {

    static Logger logger = LoggerFactory.getLogger(AdminController.class);

    @Autowired(required = false)

    private AdminService adminService;

    @Bean

    public SystemWebSocketHandler systemWebSocketHandler() {

        return new SystemWebSocketHandler();

    }

    @RequestMapping("/auditing")

    @ResponseBody

    public String auditing(HttpServletRequest request){

        //无关代码都省略了

        int unReadNewsCount = adminService.getUnReadNews(username);

        systemWebSocketHandler().sendMessageToUser(username, new TextMessage(unReadNewsCount + ""));

        return result;

    }

}

在这里可以使用sendMessageToUser给某个用户推送信息,也可以使用sendMessageToUsers给所有用户推送信息

时间: 2024-10-01 22:01:14

160601、Websocet服务端实现的相关文章

Spring Cloud官方文档中文版-服务发现:Eureka服务端

官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR3/#spring-cloud-eureka-server 文中例子我做了一些测试在:http://git.oschina.net/dreamingodd/spring-cloud-preparation Service Discovery: Eureka Server 服务发现:Eureka服务端 How to Include Eureka Server 如何创建Eurek

ssh 服务端安全配置

更改ssh服务端配置文件 [[email protected] ~]# vi /etc/ssh/sshd_config Port 59118                 #ssh 连接默认端口为22 ,更改后提高安全级别 PermitRootLogin no         #禁止root用户远程登录 PermitEmptyPasswords no    #禁止空密码登录 UseDNS no                  #不使用DNS GSSAPIAuthentication no  

Android客户端与PHP服务端交互(一)---框架概述

背景 作为一个普通上班族,总是想做一些自认为有意义的事情,于是乎准备成立一个工作室,尽管目前正在筹备阶段,但是之前有些朋友提出一些需求的时候,我发现自己的能力还是有限,直到最近和一些技术牛朋友聊起这事儿,大家不谋而合,也准备加入小团队.只是我作为工作室的“业务员”,感觉有必要都了解一下,这样才好和客户沟通,提出解决方案,也方便大家讨论订方案.譬如之前有商家提出的在线订单,要求客户可以使用APP直接下单,商家处理订单.当时我不是很懂,自己接不了,现在和朋友交流后,准备学习一下. 框架 ① 客户提交

基于NIO的消息路由的实现(四) 服务端通讯主线程(2)断包和粘包的处理

本来我打算单独开一章,专门说明粘包和断包,但是觉得这个事儿我在做的时候挺头疼的,但是对于别人或许不那么重要,于是就在这里写吧. 那么何谓粘包.何谓断包呢? 粘包:我们知道客户端在写入报文给服务端的时候,首先要将需要写入的内容写入Buffer,以ByteBuffer为例,如果你Buffer定义的足够大,并且你发送的报文足够快,此时就会产生粘包现象,举例来说 你发送一个 报文" M|A",然后你有发送了一个"M|B",如果产生粘包,服务端从缓冲区里面读出的就是"

头像服务端设计思路

思路 一 把图片上传到服务端.命名以用户的(用户名md5)作为文件名.要是以前有文件,覆盖以前的文件 二编写一个servlet处理获取头像请求. servlet接收一个用户名md5+大小的参数 根据 用户名md5+大小生成对应的图片 例如 用户名为ada 上传到服务端的位置为 /gravatar/ada.jpg 请求地址:/webstore/headimg/ada.jpg?s=120 对应的服务端文件地址 /gravatar/ada.jpg(原图片) /gravatar/ada/120.jpg

一步一步学会http获取tomcat服务端的图片,在android客户端显示

最简单的利用服务端来下载图片到客户端上面,刚开始接触,记录一下,同时希望帮助到新人. 在看本篇文章之前,你可以先看下这两篇文章 加载web项目时报的错误:Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modul http://blog.csdn.net/harryweasley/article/details/45723443 Eclipse无法启动tomcat http://blog.csdn.ne

Android客户端与PHP服务端交互(一)

背景 作为一个普通上班族,总是想做一些自认为有意义的事情,于是乎准备成立一个工作室,尽管目前正在筹备阶段,但是之前有些朋友提出一些需求的时候,我发现自己的能力还是有限,直到最近和一些技术牛朋友聊起这事儿,大家不谋而合,也准备加入小团队.只是我作为工作室的"业务员",感觉有必要都了解一下,这样才好和客户沟通,提出解决方案,也方便大家讨论订方案.譬如之前有商家提出的在线订单,要求客户可以使用APP直接下单,商家处理订单.当时我不是很懂,自己接不了,现在和朋友交流后,准备学习一下. 框架 ①

Java小项目点餐系统(二)之服务端

服务端详解: 服务端的主要功能就是无限监听一个端口号,对客户端发来的连接请求给予回应,然后开辟新线程处理客户端.界面做的比较简单就是显示在线的用户,分为商家和学生. 一.监听客户端的socket连接请求 <span style="font-family:KaiTi_GB2312;font-size:18px;">package mainjframe; import java.awt.Dimension; import java.awt.GridLayout; import

小程序服务端集成微信支付

摘要: 换取openid->统一下单->发起支付,三步走,其中二次签名比较坑人. 该demo源码已托管到码云:http://git.oschina.net/dotton/lendoo-wx,欢迎下载. 理论上集成微信支付的全部工作可以在小程序端完成,因为小程序js有访问网络的能力,但是为了安全,不暴露敏感key,而且可以使用官方提供的现成php demo更省力,于是在服务端完成签名与发起请求,小程序端只做一个wx.requestPayment(OBJECT)接口的对接. 整体集成过程与JSAP