【工程与计算机】团队版微信智能秘书的制作

近年来,美国大学的计算机(Computer Science, CS)和电子工程(Electrical Engineering, EE)专业录取要求随着申请人数的增加逐渐水涨船高。但另一方面,国内的相关工程教育却基本是缺位的。为了弥补这种差距,陈欣老师在过去的几年里,通过我们的规划项目辅导了一批学员。通过身体力行的学习利用专业知识解决生活中的问题,他们走出了自己的舒适区。事实证明,学校对这份努力也是相当认可的。

为了帮助到更多的人,陈欣老师在此整理一些往年的成功项目经验,并同简化过的项目源代码一道与大家分享。希望能够抛砖引玉,给同学们一些思路和帮助,为之后的申请助一臂之力。毕竟短期看,CS/EE是在美国本土就业的捷径,能够较为迅速的收回教育投资;长远看,CS/EE的相关技能也能在诸多行业里起到点石成金之效。

问题

AADPS的一位学员家长在银行担任领导职务,负责的领域较为繁杂琐碎。之前,团队采用比较原始的白板、便条等方式分配工作并统筹时间安排,但是经常有遇到组员在外公干而不能得到及时通知的情况出现。在校完成了AP Computer Science的学习之后,学员对这个问题主动进行了一系列调查研究,希望能够利用自己新掌握的知识与技能让家长领导的团队可以更便利的规划日程安排。

工具

Java EE

企业版Java是一个开发部署基于网络服务的企业软件的计算平台,采用面向对象的Java编程语言。企业版Java是对标准Java的一个扩展,额外提供了在对象关系映射、分布式与多层级架构和网络服务等方面的接口。平台的设计原则主要基于应用服务的模块化组件模式。

微信企业号


微信企业号是微信为企业客户提供的移动服务,旨在提供企业移动应用入口。它可以帮助企业建立员工、上下游供应链与企业IT系统间的连接。利用企业号,企业或第三方服务商可以快速、低成本的实现高质量的企业移动轻应用,实现生产、管理、协作、运营的移动化。企业号作为企业IT移动化解决方案,相比企业自己开发APP具有明显的优势,具体为快速移动化办公、开发成本较低、零门槛使用。

Eclipse


Eclipse是日前最流行的Java集成开发环境(integrated development environment),由一个基本的工作空间和一个发达的可定制插件系统组成。Eclipse本身也由Java编写,其前身由IBM公司的团队开发,但很快就成为了一个完全开源的项目,由非营利的Eclipse基金会主导。对于本项目,需要下载用于Java EE开发的版本或在其他版本的Eclipse菜单里安装对应的软件功能包。

原理

主动调用与回调模式

微信企业号应用的基本原理是需要我们自己的应用服务器与微信服务器进行通讯。对于最基础的功能而言,微信服务器将能作为中介把我们的消息主动推送给用户,也可以转发用户发送的消息内容,适用的通信模式亦有两种。

当我们的企业号应用服务器需要主动给用户发送消息时,可以通过主动模式联络微信的服务器。主动模式是一个相对简单的两步操作:第一步,我们的服务器将访问gettoken接口,用corpid和corpsecret换取用于下一步操作的验证令牌access_token;第二步,服务器继续访问message/send接口,将消息封装到一个JSON数据结构里,使用HTML POST方法提交。如果令牌传递无误,且递交的数据没有任何问题的话,用户将能立刻在对应的企业号应用里收到新发送的消息。为了便利起见,我们用专门的Wechat类封装了这一整个过程,只需要调用sendMsg方法即可一次把消息发给对应的用户。

当然,因为我们的服务器无法预判用户会在什么时机与应用交互。因此在用户这方发送消息时,会需要微信的服务器通过回调模式进行中转。为安全起见,微信服务器使用AES算法对所有消息进行加密。我们的程序里面首先要按照微信的规范,正确的处理echostr解密,这样才能在企业号后台提交回调url并正确通过验证。通过回调模式,服务器端可以获得用户名以及消息正文,以供后续处理。如果我们的服务在回调模式时发生错误并返回错误代码,微信服务器将自动重试三次。

状态机


有限状态机(finite-state machine)是用来描述一个事物多个状态之间相互切换关系的数学模型,可以用图表或者图形来描述一个状态机。

虽然无状态(stateless)的模型在很多时候能极大的简化编程并降低出错的可能性。但是在实际操作中,熟练掌握状态机并用它来描述所期待的应用行为是非常有必要的。就我们自己的微信智能秘书而言,会需要根据与用户对话的上下文来进行状态的切换,并处理对应的关键字。具体而言,一开始是没有特定状态的,用户可以输入“用户名”确认自己的内部用户名,也可以输入“添加事件”(状态1)或“查找事件”(状态2)得到对应后续操作的提示并进入相应的状态。对于添加事件,用户可以逐一按格式增加新事件,回复e的话则会退出模式并将状态清除。查找事件也大同小异,重点是在查找以后又有选项可以进入状态代码为3的编辑/删除模式。

在服务端的程序中,我们使用Java的哈希映射(HashMap)来在内存中存储每个用户自己的状态,这样可以兼顾储存空间的大小和访问效率。这一块没有做下面提到的持久化是因为用户的微信应用状态不是一个非常关键的量。比如在进入查找模式以后,隔着一两天不再访问,再次使用应用的话,是否还在查找模式相对就不很重要了。

持久化

对于我们实现的用于响应来自微信回调模式的Java EE Servlet,相关信息本身在Servlet的生命周期里都是直接以Java对象的形式存储在内存里。但是考虑到以下因素:

  • Tomcat在Servlet有一段时间不活跃以后,会自动终止应用以节省服务器资源
  • 服务器端可能需要不定期升级Tomcat和Java,在这种情况下Servlet也必须暂时中断
  • 服务器整体可能因维护而需要重启

另一方面,很多网络服务本身都必须定期重启,以防止出现内存泄漏(memory leak)等一系列最终会导致服务器无法正常工作的状况。

由此我们明白,一直将企业诸如日程安排之类的重要数据存储在内存里不是长久之计。需要通过一些方法,将数据保存到硬盘等持久存储介质(persistent storage),待需要使用时再读取回来。在我们的EventList这个数据类里,简单实现了将日程列表转化为字符串的方法。而在另一个Event数据类里,也实现了从字符串到日程的构造函数(constructor)。那么在实现Servlet的Receiver类里,我们就在日程有变化时做一次保存操作,将字符串写入到磁盘文件里。而在初始化的init函数里,我们又可以读取该文件的最新内容,恢复原本的EventList。

示例


上图展示了项目开发环境和服务器端管理界面。注意为让示例代码可以正常工作,需要正确配置自己的服务器以及微信企业号,并将相关参数填写到代码的相应位置。在服务端和本地开发机上均需要安装Tomcat 7。示例项目已经关联了所需的微信消息解密库。

在完成开发后,项目上点击右键,即可在菜单中选择导出到WAR文件,然后就能在服务器端管理界面上传部署。

思考

  1. 对于示例程序,目前只提供了日程查询和管理功能。那么是否有可能让使用者在日程活动即将开始前得到来自服务器端的主动提醒?这一功能该如何设计?(提示:cron)
  2. 当前我们使用简单的文本文件读取和写入来将日程持久化,但这一方式在使用人数和频度急剧增加以后,会在效率和可靠性上带来一系列的问题。当前使用一种数据库管理系统来储存网络应用的数据是一个很通用的做法,如何在此应用里实现这一点?
  3. 对于管理员,如何更加方便的将企业员工导入到应用里并随后进行管理?
  4. 标准Java在编程时很容易在本地开发机器上进行调试。但企业版Java的代码在某些情况下由于种种限制(比如微信企业号只许可预先设定的回调地址),必须运行在服务器上。在这个前提下,怎样提高开发效率并迅速定位可能出现的编程错误?

以上就是我们今天分享的案例,欢迎大家登陆网站后下载项目源码,通过实践来加深理解。简单的疑问可以评论在文章下,陈欣老师将会在有空时予以解答。如果对我们的服务项目感兴趣,希望获取陈欣老师一对一指导的,可以加上小助手微信号aadps1。

重要通知

本文为AADPS原创,原始发布地址是https://aadps.net/2019/11667.html。我们每年夏季会更新最新美国大学本科申请文书题目和权威院校指南,欢迎把网站加入浏览器收藏夹。

因屡次出现我们学员家长将盗用我方的推文发到我们自己的服务群里,严重影响了AADPS的正常经营秩序。AADPS决定禁止对我们专业资讯的一切形式转载或再利用(包括但不限于同行或留学生家长在任何媒体平台的公众号、资讯号、私人号中非法利用我方内容)。一经发现,我方将可能采用一切合法手段维权,不再另行通知,创业不易,望谅解。

发布者

陈 欣

陈 欣

AADPS创始人

发表评论