前言

目前,公司的项目部署方式还是使用的原始的方式,通过手动运行脚本去部署。每次全部服务器部署一遍,需要耗费的时间很长,如果遇到错误,也不能立刻进行回滚,只能将错误解决提交或者将备份代码进行还原。

在持续集成大行其道的今天,这种原始的方式实在是不应该再使用了!在调研了 Jekins 等开源持续集成工具之后,发现对于我们公司而言,比如 Jekins 的上手难度还是较高的,配置也比较复杂繁琐,也就没有采用。

于是想着自己能不能也搞一个简化版适用于公司的自动化部署系统呢?于是在开发的过程中,遇到了本文的问题,为了实时展示服务器命令输出情况,我使用了 WebSocket 技术来实现,同时使用 SpringBoot 框架进行快速搭建项目,该部署系统目前未开发完成,姑且作为一个练手项目。

WebSocket 介绍

对于 WebSocket 就不多说什么了,直接引用维基百科的解释。

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。 在WebSocket API中,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

易于理解的版本,可以看看阮一峰的 WebSocket 教程

下面讲解 WebSocket 与 SpringBoot 的集成使用。

服务端环境准备

  1. SpringBoot 项目引入 WebSocket 依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
  2. 新建 WebSocketHandler, 用于处理请求,以及向客户端发送消息

    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
    @Component
    public class WebSocketHandler extends AbstractWebSocketHandler {
    private static CopyOnWriteArraySet<WebSocketSession> webSocketSet = new CopyOnWriteArraySet<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    // 接收到WebSocket会触发
    System.out.println(session.getUri().getQuery());
    webSocketSet.add(session);
    session.sendMessage(new TextMessage("欢迎!!!"));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
    // 关闭WebSocket会触发
    System.out.println("关闭WebSocket会触发");
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    exception.printStackTrace();
    }

    /**
    * 广播消息
    */
    public void sendMessage() throws IOException {
    for (WebSocketSession session : webSocketSet) {
    session.sendMessage(new TextMessage("欢迎你来啦!"));
    }
    }
    }
  3. 新建 Config 类,用于接收 WebSocket 请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Configuration
    @EnableWebSocket
    public class WebSocketConfig implements WebSocketConfigurer {

    @Autowired
    private WebSocketHandler webSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
    webSocketHandlerRegistry.addHandler(webSocketHandler,"/webSocket");
    }
    }

客户端环境准备

  1. 新建页面

    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
    <!DOCTYPE html> <!--标准HTML5-->
    <html lang="zh-CN">
    <body>
    <h1>Hello World!</h1>
    </body>
    <script type="text/javascript">
    var websocket = null;
    if('WebSocket' in window) {
    websocket = new WebSocket('ws://localhost:8080/webSocket?code=abcd');
    <!--此处的地址即第二步指定的接口地址,可以传递参数-->
    }else {
    alert('该浏览器不支持websocket!');
    }
    websocket.onopen = function (event) {
    alert('建立连接');
    }
    websocket.onclose = function (event) {
    alert('连接关闭');
    }
    websocket.onmessage = function (event) {
    alert('收到消息:' + event.data)
    }
    websocket.onerror = function () {
    alert('websocket通信发生错误!');
    }
    window.onbeforeunload = function () {
    websocket.close();
    }
    </script>

    注意:如果websocket 的 url写的是localhost:8080,则当前页面的地址也应是localhost:8080域名下,不可以是127.0.0.1:8080 ,否则会提示 403,如果用真实域名也同理。

  2. 新建 Controller 跳转到该页面

    1
    2
    3
    4
    5
    6
    7
    8
    @Controller
    public class HomeController {

    @GetMapping(value = "/home")
    public ModelAndView home() {
    return new ModelAndView("home");
    }
    }

进行测试

  1. 启动项目
  2. 访问 http://localhost:8080/home
  3. 浏览器控制台打印结果:

应用

  • 服务器向浏览器发送通知可以使用 WebSocket
  • 聊天室

资源下载

参考