文档章节

用 ActFramework 写一个网页聊天室是怎样的体验

罗格林
 罗格林
发布于 2018/05/05 20:28
字数 1564
阅读 762
收藏 8

看到 t-io 老谭的 用t-io来写一个网页聊天室或客服是个怎样的体验, 一时手痒, 就打算用 ActFramework 来写一个网页聊天室, 看看是什么体验.

废话少说,撸起袖子就是干。

1. 创建项目

运行下面的命令创建一个新的 ActFramework 应用项目:

mvn archetype:generate -B \
    -DgroupId=com.myproj \
    -DartifactId=chatroom \
    -DarchetypeGroupId=org.actframework \
    -DarchetypeArtifactId=archetype-quickstart \
    -DarchetypeVersion=1.8.7.3

2. 项目目录结构

运行之后可以看到如下目录结构:

.
├── pom.xml
├── run_dev
├── run_dev.bat
├── run_prod
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── myproj
    │   │           └── AppEntry.java
    │   └── resources
    │       ├── com
    │       │   └── myproj
    │       ├── conf
    │       │   ├── app.properties
    │       │   ├── prod
    │       │   │   └── app.properties
    │       │   └── uat
    │       │       └── app.properties
    │       ├── logback.xml
    │       └── rythm
    │           └── com
    │               └── myproj
    │                   └── AppEntry
    │                       └── home.html
    └── test
        └── java
            └── com
                └── myproj

3. pom.xml 文件

生成的项目 pom.xml 很简单, 打开看应该是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.myproj</groupId>
  <artifactId>chatroom</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>My Awesome Application</name>

  <parent>
    <groupId>org.actframework</groupId>
    <artifactId>act-starter-parent</artifactId>
    <version>1.8.7.1</version>
  </parent>

  <properties>
    <java.version>1.8</java.version>
    <app.entry>com.myproj.AppEntry</app.entry>
  </properties>

</project>

4. 服务端代码

就我们的聊天室应用来讲, 无需添加任何其他依赖, 直奔 com.myproj.AppEntry 文件:

package com.myproj;

import act.Act;
import act.inject.DefaultValue;
import act.util.Output;
import org.osgl.mvc.annotation.GetAction;

/**
 * A simple hello world app entry
 *
 * Run this app, try to update some of the code, then
 * press F5 in the browser to watch the immediate change
 * in the browser!
 */
@SuppressWarnings("unused")
public class AppEntry {

    /**
     * The home (`/`) endpoint.
     *
     * This will accept a query parameter named `who` and
     * render a template (resources/rythm/__package__/AppEntry/home.html),
     * where `__package__` corresponding to the package name, e.g.
     * if your package is `com.mycomp.myproj`, then `__package__`
     * is `com/mycomp/myproj`.
     *
     * @param who
     *      request query parameter to specify the hello target.
     *      default value is `World`.
     */
    @GetAction
    public void home(@DefaultValue("World") @Output String who) {
    }

    public static void main(String[] args) throws Exception {
        Act.start();
    }

}

把不需要的注释去掉, 再将 home 方法稍微改改, 去掉 who 参数, 让这个文件变得干净一点:

package com.myproj;

import act.Act;
import org.osgl.mvc.annotation.GetAction;

public class AppEntry {

    /**
     * 响应 `/` 请求. 调用 `home.html` 模板生成 HTML 页面响应
     */
    @GetAction
    public void home() {
    }

    public static void main(String[] args) throws Exception {
        Act.start();
    }

}

4.1 Websocket 消息处理方法

下面是肉戏了, 我们需要在 AppEntry 类加上一个方法来处理 websocket 请求, 也就是聊天室发送的即时消息:

    @WsAction("msg")
    public void onMessage(String message, WebSocketContext context) {
        // suppress blank lines
        if (S.notBlank(message)) {
            context.sendToPeers(message);
        }
    }

这就好了? 6 行代码搞定了服务器端的 websocket 消息处理? 我读书少所以不骗你, 真的就是这样啊. 是不是很 easy 啊? 到这里很想说 JFinal 波总 的那句 "打完收工" (感觉很酷酷的样子). 不过我们这个聊天室必须还有前端才行, 所以还没有打完, 继续看吧:

5. 前端页面

上面的目录结构中找到 home.html 文件, 打开看是这样的:

<!DOCTYPE html>
<html lang="en">
@args String who
<head>
  <title>Hello World - ActFramework</title>
</head>
<body>
  <h1>Hello @who</h1>
  <p>
    Powered by ActFramework @act.Act.VERSION.getVersion()
  </p>
</body>
</html>

我们需要改造一下变成一个简单的聊天室:

<html>
<head>
  <title>WebSocket Chat</title>
  <script src="/~/asset/js/jquery.js"></script>
  <script src="/~/asset/js/jquery.ext.js"></script>
  <style type="text/css">
    html,body {
      width:100%;
      height:100%;
      background-color: black;
      color: beige;
    }

    body {
      height: 80%;
    }

    input {
      padding: 8px 5px;
    }

    .center {
      margin-left: auto;
      margin-right: auto;
      width: 70%;
    }

    .chatform {
      margin-left: auto;
      margin-right: auto;
      margin-bottom: 0;
      width: 70%;
    }
    form{
      width: 100%;
    }
    label{
      display: inline;
      width: 100px;
    }
    #msg{
      display: inline;
      width: 100%;
    }

  </style>
</head>
<body>
<div class="page">
  <div class="center" >
    <h1>WebSocket @i18n("demo") - @i18n("chatroom")</h1>
    <div id="chat" style="height:100%;width: 100%; overflow: auto;">
    </div>
    <form onsubmit="return false;" class="chatform" action="">
      <label for="msg">@i18n("message")</label>
      <input type="text" name="message" id="msg"  onkeypress="if(event.keyCode==13) { send(this.form.message.value); this.value='' } " />
    </form>
  </div>
</div>
<script>
      var socket;

      function connect() {
          socket = $.createWebSocket('/msg');
          //socket = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/msg");
          socket.onmessage = function (event) {
              var home = document.getElementById('chat');
              home.innerHTML = home.innerHTML + event.data + "<br />";
          };
      }

      if (window.WebSocket) {
          connect();
      } else {
          alert("Your browser does not support Websockets. (Use Chrome)");
      }

      function send(message) {
          if (!window.WebSocket) {
              return false;
          }
          if (socket.readyState === WebSocket.OPEN) {
              socket.send(message);
          } else {
              reconnect(message);
          }
          return false;
      }

      function reconnect(message) {
          connect();
          setTimeout(function() {
            if (socket.readyState == WebSocket.OPEN) {
                socket.send(message);
            } else {
                alert("The socket is not open.");
            }
          }, 500);
      }
  </script>
</body>
</html>

注意上面的 /~/asset/js/jquery.ext.js 这是 ActFramework 自带的对 jQuery 的一点小扩展, 其中就有 $.createWebSocket() 方法用来创建客户端的 websocket client.

6. 运行项目

好了, 现在运行一把试试. 在项目目录下运行:

mvn compile act:run

运行上面的命令之后差不多能看到下面的控制台消息

   ___   _  _     _     _____   ___    ___     ___    __  __ 
  / __| | || |   /_\   |_   _| | _ \  / _ \   / _ \  |  \/  |
 | (__  | __ |  / _ \    | |   |   / | (_) | | (_) | | |\/| |
  \___| |_||_| /_/ \_\   |_|   |_|_\  \___/   \___/  |_|  |_|
                                                             
                          powered by ActFramework r1.8.7-2f28

 version: v1.0-SNAPSHOT-180505_2214
scan pkg: com.myproj
base dir: /home/luog/p/greenlaw110/chatroom
     pid: 20757
 profile: dev
    mode: DEV

     zen: Readability counts.

2018-05-05 22:14:54,447 INFO  a.Act@[main] - loading application(s) ...
2018-05-05 22:14:54,459 INFO  a.a.App@[main] - App starting ....
2018-05-05 22:14:54,639 WARN  a.h.b.ResourceGetter@[main] - URL base not exists: META-INF/resources/webjars
2018-05-05 22:14:54,653 WARN  a.a.DbServiceManager@[main] - DB service not initialized: No DB plugin found
2018-05-05 22:14:55,379 WARN  a.m.MailerConfig@[main] - smtp host configuration not found, will use mock smtp to send email
2018-05-05 22:14:55,831 INFO  a.a.App@[main] - App[chatroom] loaded in 1372ms
2018-05-05 22:14:55,837 INFO  a.a.ApiManager@[jobs-thread-3] - start compiling API book
2018-05-05 22:14:55,857 INFO  o.xnio@[main] - XNIO version 3.3.8.Final
2018-05-05 22:14:55,885 INFO  o.x.nio@[main] - XNIO NIO Implementation Version 3.3.8.Final
2018-05-05 22:14:56,003 INFO  a.Act@[main] - network client hooked on port: 5460
2018-05-05 22:14:56,004 INFO  a.Act@[main] - CLI server started on port: 5461
2018-05-05 22:14:56,005 INFO  a.Act@[main] - app is ready at: http://192.168.1.2:5460
2018-05-05 22:14:56,005 INFO  a.Act@[main] - it takes 2269ms to start the app

现在是检验成果的时候了, 直奔浏览器, 打开 http://localhost:5460/ 可以开始玩了:

结果演示

打完收工!

7. 总结

到这里我们可以来总结一下这个项目了. 我们的项目非常简单, 只有一个主程序 AppEntry, 提供了两个请求处理方法:

  • home() - 接受发送到 / 的 GET 请求, 加载 home.html 模板生成 HTML 响应
  • onMessage() - 接受发送到 /msg 的 WS 请求, 转发消息到所有连接到这个服务端口的客户端

两个方法都非常简单 (可以用波总的极简么?), 全部项目的源代码统计如下:

luog@luog-X510UQR:~/p/greenlaw110/chatroom$ cloc src
       7 text files.
       7 unique files.                              
       4 files ignored.

http://cloc.sourceforge.net v 1.60  T=0.03 s (99.6 files/s, 8069.1 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
HTML                             1             10             17             93
XML                              1             17              3             72
Java                             1              6              4             21
-------------------------------------------------------------------------------
SUM:                             3             33             24            186
-------------------------------------------------------------------------------

这就是 ActFramework 用 21 行代码实现的极简网页聊天室后端. 整个项目源码只能在 gitee 上获取:

https://gitee.com/greenlaw110/act-chatroom/

7. 结束语

这是一个非常简单的网页聊天室应用, 没有谭总的那个功能丰富, 不过写起来貌似要比 t-io 稍微容易一点哦. 以后有时间加上用户登录认证, 就等下回分解了

更多关于 ActFramework 的情况, 请关注

© 著作权归作者所有

罗格林

罗格林

粉丝 309
博文 46
码字总数 49389
作品 4
其他
架构师
私信 提问
加载中

评论(6)

罗格林
罗格林 博主

引用来自“超级大黑猫”的评论

问个问题 act框架能和dubbo整合吗��
现在还没有 dubbo 整合插件. 你可以去提个需求
国产大熊猫
国产大熊猫
问个问题 act框架能和dubbo整合吗��
罗格林
罗格林 博主

引用来自“talent-tan”的评论

1、先赞一下罗总把产品视为自己小孩的态度。

2、同时我也要向 @红薯 举报,罗总有点模仿我,哈哈哈

3、最后我来说一下,那个是想作为项目脚手架写的,有好些东西不是作为demo必须的

引用来自“罗格林”的评论

先进的东西必须学习啊, 为了蹭 t-io 的热度, 我也是拼了 😆

引用来自“talent-tan”的评论

得了,我觉得你手够痒,而且手速还够快
哈哈, 敲键盘的速度还行
talent-tan
talent-tan

引用来自“talent-tan”的评论

1、先赞一下罗总把产品视为自己小孩的态度。

2、同时我也要向 @红薯 举报,罗总有点模仿我,哈哈哈

3、最后我来说一下,那个是想作为项目脚手架写的,有好些东西不是作为demo必须的

引用来自“罗格林”的评论

先进的东西必须学习啊, 为了蹭 t-io 的热度, 我也是拼了 😆
得了,我觉得你手够痒,而且手速还够快
罗格林
罗格林 博主

引用来自“talent-tan”的评论

1、先赞一下罗总把产品视为自己小孩的态度。

2、同时我也要向 @红薯 举报,罗总有点模仿我,哈哈哈

3、最后我来说一下,那个是想作为项目脚手架写的,有好些东西不是作为demo必须的
先进的东西必须学习啊, 为了蹭 t-io 的热度, 我也是拼了 😆
talent-tan
talent-tan
1、先赞一下罗总把产品视为自己小孩的态度。

2、同时我也要向 @红薯 举报,罗总有点模仿我,哈哈哈

3、最后我来说一下,那个是想作为项目脚手架写的,有好些东西不是作为demo必须的
ActFramework R1.4.0 带来 WebSocket 支持

ActFramework R1.4.0 发布了,R1.4.0版最重要的更新是 WebSocket 的支持 #17 WebSocket 支持 ActFramework 终于支持 WebSocket 了 聊天室应用: Echo 应用: 关于更详细的 websocket 支持, 可参...

罗格林
2017/06/13
1K
3
ActFramework 1.8.12 系列更新,高性能 Java Web 框架

ActFramework 是一款高效能(对程序员)和高性能(对运行系统)的 Java Web 应用和服务框架. 本次更新的主要内容: 热加载失效 Hot-reload issue caused by `StackOverflowError` on `AppConfig....

罗格林
2018/11/20
1K
14
Act starter 1.8.8.4 发布,更完善的 E2E 自动化测试方案

act-starters-1.8.8.4 基于最新的 act-1.8.8-RC8 版本, 提供了多个插件的更新, 包括: act-sql-common-1.4.0 act-jpa-common-1.4.0 act-ebean-1.7.0 act-ebean-java7-1.7.0 act-eclipselink-1......

罗格林
2018/05/31
427
14
Act 1.8.22 发布 - 强大易用的 Java MVC 框架

Act 1.8.22 更新内容 * 命令行命令 `route.print` 不能正确处理 keyword 匹配的路由 #1136 提供配置选项禁止 JSON body patch #1134 API 文档 - 特殊标记 session 变量 #1133 API 文档 - 字段...

罗格林
05/21
0
0
ActFramework 1.2.0 - 代码简洁之道上新的里程碑

ActFramework 是一个功能强大易用的 Java 全栈 Web 开发框架. 依托于 undertow 提供的网络层服务, ActFramework 摈弃了老式难用的 Servlet 框架, 并提供了开发时热加载特性, 非常便于开发. A...

罗格林
2017/04/25
2.7K
16

没有更多内容

加载失败,请刷新页面

加载更多

Java基础-Queue

Queue实现 1、没有实现阻塞接口的 LinkedList:实现了java.util.Queue接口和java.util.AbstractQueue接口   内置的不阻塞队列:PriorityQueue和ConcurrentLinkedQueue   PriorityQueue和...

MyOldTime
24分钟前
1
0
阿里云应用高可用 AHAS 正式商用,可一键提升云上应用可用性

在分布式架构环境下,服务间的依赖日益复杂,可能没有人能说清单个故障对整个系统的影响,构建一个高可用的分布式系统面临着很大挑战。 7月17日,阿里云应用高可用服务AHAS 正式商用,包含架...

阿里云云栖社区
28分钟前
0
0
Audio 和 Video的简单介绍

HTML多媒体 , 主要分为Audio 音频和 Video 视频。 1:Audio 基本语法 src 指定当前播放的音频文件,controls播放控制器,loop歌曲循环,autoplay自动播放 (chrome66之后被禁止)主流浏览器已...

凌兮洛
41分钟前
4
0
【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)

工作中遇到需要生成PDF。最终选择了iText。其他也有通过html再生成。感觉不太适合就用了代码实现。 使用iText 5.5.13.1版本。纯Java代码实现 1.自定义表格合并指定行列完成数据填充 2.自定义...

小帅帅丶
43分钟前
10
0
Redis HyperLogLog

关于 Redis HyperLogLog 在说明 HyperLogLog 之前,我们需要先了解一个概念:基数统计。维基百科中的解释是: cardinality of a set is a measure of the “number of elements“ of the set...

xiaomin0322
43分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部